Buscape_Fcontrol - Version 0.1.0

Version Notes

Buscapé Fcontrol é compatível com Magento Enterprise Edition 1.7.0.0 ou superior, Professional Edition 1.9.0.0 ou superior, e Magento Community Edition 1.3.3.0 ou superior.

Download this release

Release Info

Developer Adriano Aguiar
Extension Buscape_Fcontrol
Version 0.1.0
Comparing to
See all releases


Version 0.1.0

app/code/community/Buscape/Fcontrol/Block/Adminhtml/Sales/Order.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
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 suporte.developer@buscape-inc.com so we can send you a copy immediately.
14
+ *
15
+ * @category Buscape
16
+ * @package Buscape_Fcontrol
17
+ * @copyright Copyright (c) 2010 Buscapé Company (http://www.buscapecompany.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Buscape_Fcontrol_Block_Adminhtml_Sales_Order extends Mage_Adminhtml_Block_Sales_Order
22
+ {
23
+
24
+ public function __construct()
25
+ {
26
+ if(intval(Mage::helper('fcontrol')->getConfig('type_service')) !== Buscape_Fcontrol_Model_Api::FRAME) {
27
+
28
+ $this->_addButton('capturelist', array(
29
+ 'label' => Mage::helper('sales')->__('Sincronizar captura com FControl'),
30
+ 'onclick' => 'setLocation(\'' . $this->getCaptureUrl() .'\')',
31
+ 'class' => 'add',
32
+ ));
33
+ }
34
+
35
+ parent::__construct();
36
+ }
37
+
38
+ public function getCaptureUrl()
39
+ {
40
+ return $this->getUrl('*/sales_order/capturelist');
41
+ }
42
+ }
app/code/community/Buscape/Fcontrol/Block/Adminhtml/Sales/Order/Grid.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
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 suporte.developer@buscape-inc.com so we can send you a copy immediately.
14
+ *
15
+ * @category Buscape
16
+ * @package Buscape_Fcontrol
17
+ * @copyright Copyright (c) 2010 Buscapé Company (http://www.buscapecompany.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Buscape_Fcontrol_Block_Adminhtml_Sales_Order_Grid extends Mage_Adminhtml_Block_Sales_Order_Grid
22
+ {
23
+
24
+ /*
25
+ * @Buscape_Fcontrol_Block_Adminhtml_Sales_Order_View_Info
26
+ *
27
+ * Implementação somente para o uso de Frame
28
+ */
29
+ protected function _prepareMassaction()
30
+ {
31
+ parent::_prepareMassaction();
32
+
33
+ if(intval(Mage::helper('fcontrol')->getConfig('type_service')) !== Buscape_Fcontrol_Model_Api::FRAME) {
34
+
35
+ $this->getMassactionBlock()->addItem('sendlist_order', array(
36
+ 'label'=> Mage::helper('sales')->__('Enfileirar no F-Control'),
37
+ 'url' => $this->getUrl('*/sales_order/sendlist'),
38
+ ));
39
+ }
40
+ }
41
+ }
app/code/community/Buscape/Fcontrol/Block/Adminhtml/Sales/Order/View/Info.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
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 suporte.developer@buscape-inc.com so we can send you a copy immediately.
14
+ *
15
+ * @category Buscape
16
+ * @package Buscape_Fcontrol
17
+ * @copyright Copyright (c) 2010 Buscapé Company (http://www.buscapecompany.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Buscape_Fcontrol_Block_Adminhtml_Sales_Order_View_Info extends Mage_Adminhtml_Block_Sales_Order_Abstract
22
+ {
23
+
24
+ /*
25
+ * @Buscape_Fcontrol_Block_Adminhtml_Sales_Order_View_Info
26
+ *
27
+ * Implementação somente para o uso de Frame
28
+ */
29
+ public function getScore()
30
+ {
31
+ if ($this->getOrder()) {
32
+ Mage::getModel('fcontrol/observer')->frameOrder($this, true);
33
+ }
34
+ }
35
+ }
app/code/community/Buscape/Fcontrol/Helper/Data.php ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
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 suporte.developer@buscape-inc.com so we can send you a copy immediately.
14
+ *
15
+ * @category Buscape
16
+ * @package Buscape_Fcontrol
17
+ * @copyright Copyright (c) 2010 Buscapé Company (http://www.buscapecompany.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Buscape_Fcontrol_Helper_Data extends Mage_Core_Helper_Abstract
22
+ {
23
+ const CORE = 'Buscape_Core';
24
+
25
+ /**
26
+ * log facility for fcontrol
27
+ *
28
+ * @param string $message
29
+ * @param integer $level
30
+ * @param string $file
31
+ */
32
+
33
+ /* type file generate in log */
34
+ const LOG_TYPE_DEFAULT = '';
35
+ const LOG_TYPE_EXCEPTION = 'exception_';
36
+ const LOG_TYPE_MESSAGE_SEND = 'send_';
37
+ const LOG_TYPE_MESSAGE_RETURN = 'return_';
38
+
39
+ const LOG_TYPE_CHECK_RETURN = 'return_check_';
40
+ const LOG_TYPE_CHECK_EXCEPTION = 'exception_check_';
41
+
42
+ const LOG_TYPE_QUEUE_RETURN = 'return_queue_';
43
+ const LOG_TYPE_QUEUE_EXCEPTION = 'exception_queue_';
44
+
45
+ /**
46
+ *
47
+ * @param string $message
48
+ * @param integer $level
49
+ * @param const $file
50
+ * @param Hipxik_Bpag_Helper_Data $type
51
+ * @return void|void
52
+ */
53
+ public static function log($message, $level=null, $file = '', $type = self::LOG_TYPE_DEFAULT)
54
+ {
55
+ static $loggers = array();
56
+
57
+ $level = is_null($level) ? Zend_Log::DEBUG : $level;
58
+
59
+ if (empty($file)) {
60
+ $file = Mage::getStoreConfig('dev/log/file');
61
+
62
+ $file = empty($file) ? $type . 'system.log' : $type . $file;
63
+ }
64
+
65
+ try {
66
+ if (!isset($loggers[$file])) {
67
+ $logFile = Mage::getBaseDir('var').DS.'log'.DS.'fcontrol'.DS.$file;
68
+ $logDir = Mage::getBaseDir('var').DS.'log'.DS.'fcontrol';
69
+
70
+ if (!is_dir(Mage::getBaseDir('var').DS.'log'.DS.'fcontrol')) {
71
+ mkdir(Mage::getBaseDir('var').DS.'log'.DS.'fcontrol', 0777);
72
+ }
73
+
74
+ if (!file_exists($logFile)) {
75
+ file_put_contents($logFile,'');
76
+ chmod($logFile, 0777);
77
+ }
78
+ $format = "================================================= \n";
79
+ // Define title for this option
80
+ switch($type)
81
+ {
82
+ default:
83
+ // general
84
+ case self::LOG_TYPE_DEFAULT:
85
+ $format .= "F-Control: \n";
86
+ $format .= "DATE: %timestamp% %priorityName% (%priority%): " . PHP_EOL . "\n";
87
+ $format .= "MSG: \n %message% \n";
88
+ break;
89
+ case self::LOG_TYPE_MESSAGE_SEND:
90
+ $format .= "Novo envio ao F-Control: \n";
91
+ $format .= "DATE: %timestamp% %priorityName% (%priority%): " . PHP_EOL . "\n";
92
+ $format .= "MSG Enviada: \n %message% \n";
93
+ break;
94
+ case self::LOG_TYPE_MESSAGE_RETURN:
95
+ $format .= "Retorno do F-Control: \n";
96
+ $format .= "DATE: %timestamp% %priorityName% (%priority%): " . PHP_EOL . "\n";
97
+ $format .= "MSG Retorno: \n %message% \n";
98
+ break;
99
+ // check
100
+ case self::LOG_TYPE_CHECK_RETURN:
101
+ $format .= "Return Check do F-Control: \n";
102
+ $format .= "DATE: %timestamp% %priorityName% (%priority%): " . PHP_EOL . "\n";
103
+ $format .= "MSG Retorno: \n %message% \n";
104
+ break;
105
+ case self::LOG_TYPE_CHECK_EXCEPTION:
106
+ $format .= "Exception Check do F-Control: \n";
107
+ $format .= "DATE: %timestamp% %priorityName% (%priority%): " . PHP_EOL . "\n";
108
+ $format .= "MSG Retorno: \n %message% \n";
109
+ break;
110
+ // queue
111
+ case self::LOG_TYPE_QUEUE_RETURN:
112
+ $format .= "Return Queue do F-Control: \n";
113
+ $format .= "DATE: %timestamp% %priorityName% (%priority%): " . PHP_EOL . "\n";
114
+ $format .= "MSG Retorno: \n %message% \n";
115
+ break;
116
+ case self::LOG_TYPE_QUEUE_EXCEPTION:
117
+ $format .= "Exception Queue do F-Control: \n";
118
+ $format .= "DATE: %timestamp% %priorityName% (%priority%): " . PHP_EOL . "\n";
119
+ $format .= "MSG Retorno: \n %message% \n";
120
+ break;
121
+ }
122
+ $format .= "================================================= \n \n";
123
+
124
+ $formatter = new Zend_Log_Formatter_Simple($format);
125
+ $writer = new Zend_Log_Writer_Stream($logFile);
126
+ $writer->setFormatter($formatter);
127
+ $loggers[$file] = new Zend_Log($writer);
128
+ }
129
+
130
+ if (is_array($message) || is_object($message)) {
131
+ $message = print_r($message, true);
132
+ }
133
+
134
+ $loggers[$file]->log($message, $level);
135
+ }
136
+ catch (Exception $e){
137
+
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Return the config value for the passed key
143
+ */
144
+ public function getConfig($key)
145
+ {
146
+
147
+ $modules = array_keys((array)Mage::getConfig()->getNode('modules')->children());
148
+
149
+ sort($modules);
150
+
151
+ $path = 'sales/fcontrol/' . $key;
152
+
153
+ if(in_array(self::CORE, $modules)) {
154
+
155
+ $modules = Mage::getConfig()->getNode('modules')->children();
156
+
157
+ /* Precisa verificar se o modulo esta habilitado para fazer migração dos nodes (melhoria prevista) */
158
+ if($modules->Buscape_Core->active->xmlentities() == 'true') {
159
+ // $path = 'buscape/fcontrol/' . $key;
160
+ }
161
+ }
162
+
163
+ return Mage::getStoreConfig($path, Mage::app()->getStore());
164
+ }
165
+
166
+ /**
167
+ * Check if the extension has been disabled in the system configuration
168
+ *
169
+ * @return boolean
170
+ */
171
+ public function moduleActive()
172
+ {
173
+ return (!(bool) $this->getConfig('active')); // || (!(bool) parent::getConfig('disable_ext'));
174
+ }
175
+
176
+ /**
177
+ * Return true if the reqest is made via the api
178
+ *
179
+ * @return boolean
180
+ */
181
+ public function isRequest()
182
+ {
183
+ return Mage::app()->getRequest()->getModuleName() === 'api';
184
+ }
185
+ }
app/code/community/Buscape/Fcontrol/Model/Adapter/Payment.php ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
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 suporte.developer@buscape-inc.com so we can send you a copy immediately.
14
+ *
15
+ * @category Buscape
16
+ * @package Buscape_Fcontrol
17
+ * @copyright Copyright (c) 2010 Buscapé Company (http://www.buscapecompany.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Buscape_Fcontrol_Model_Adapter_Payment extends Varien_Object
22
+ {
23
+
24
+ protected static $_service = array(
25
+ 'ccsave' => true,
26
+ 'checkmo' => true,
27
+ 'free' => true,
28
+ 'purchaseorder' => true,
29
+ 'authorizenet_directpost' => false,
30
+ 'authorizenet' => false,
31
+ 'googlecheckout' => false,
32
+ 'paypal_standard' => false,
33
+ 'paypal_express' => false,
34
+ 'paypal_direct' => false,
35
+ 'paypaluk_direct' => false,
36
+ 'paypaluk_express' => false,
37
+ 'verisign' => false,
38
+ 'payflow_link' => false,
39
+ 'hosted_pro' => false,
40
+ 'paypal_billing_agreement' => false,
41
+ 'pagamentodigital_standard' => false,
42
+ 'pagseguro_standard' => false,
43
+ 'pagseguro' => false,
44
+ 'brunoassarisse_pagseguro' => false,
45
+ 'cobredireto' => false,
46
+ );
47
+
48
+ /* Verifica se a forma de pagamento pode ser utilizada com o FControl */
49
+ public function validate($payment = null)
50
+ {
51
+ if(in_array($payment->getMethod(), self::$_service)) {
52
+ if(self::$_service[$payment->getMethod()]) {
53
+ return true;
54
+ }
55
+ }
56
+
57
+ return false;
58
+ }
59
+
60
+ public function filter($payment = null, Buscape_Fcontrol_Model_Api_Abstract $api = null)
61
+ {
62
+ if($api && in_array($payment->getMethod(), self::$_service)) {
63
+
64
+ switch($payment->getMethod())
65
+ {
66
+ case 'ccsave':
67
+
68
+ if(intval(Mage::helper('fcontrol')->getConfig('type_service')) === Buscape_Fcontrol_Model_Api::FRAME) {
69
+ $api->metodoPagamento = 1;
70
+ } else {
71
+ $api->metodoPagamento = 'CartaoCredito';
72
+ }
73
+
74
+ $api->valorPedido = number_format($payment->getAmountOrdered(), 2, ".", "");
75
+
76
+ $api->nomeBancoEmissor = $payment->getCcType();
77
+
78
+ $api->numeroCartao = $payment->getCcNumber();
79
+
80
+ $api->dataValidadeCartao = $payment->getCcExpMonth() . '/' . $payment->getCcExpYear();
81
+
82
+ $api->nomeTitularCartao = $payment->getCcOwner();
83
+
84
+ $api->quatroUltimosDigitosCartao = $payment->getCcLast4();
85
+ break;
86
+ case 'checkmo':
87
+
88
+ if(intval(Mage::helper('fcontrol')->getConfig('type_service')) === Buscape_Fcontrol_Model_Api::FRAME) {
89
+ $api->metodoPagamento = 15;
90
+ } else {
91
+ $api->metodoPagamento = 'Deposito';
92
+ }
93
+
94
+ $api->valorPedido = number_format($payment->getAmountOrdered(), 2, ".", "");
95
+ break;
96
+ case 'free':
97
+ case 'purchaseorder':
98
+
99
+ if(intval(Mage::helper('fcontrol')->getConfig('type_service')) === Buscape_Fcontrol_Model_Api::FRAME) {
100
+ $api->metodoPagamento = 18;
101
+ } else {
102
+ $api->metodoPagamento = 'ValePresente';
103
+ }
104
+
105
+ $api->valorPedido = number_format($payment->getAmountOrdered(), 2, ".", "");
106
+ break;
107
+ }
108
+ }
109
+
110
+ $api->numeroParcelas = 1;
111
+
112
+ return $api;
113
+ }
114
+ }
app/code/community/Buscape/Fcontrol/Model/Adapter/Shipping.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
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 suporte.developer@buscape-inc.com so we can send you a copy immediately.
14
+ *
15
+ * @category Buscape
16
+ * @package Buscape_Fcontrol
17
+ * @copyright Copyright (c) 2010 Buscapé Company (http://www.buscapecompany.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Buscape_Fcontrol_Model_Adapter_Shipping extends Varien_Object
22
+ {
23
+
24
+ }
app/code/community/Buscape/Fcontrol/Model/Api.php ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
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 suporte.developer@buscape-inc.com so we can send you a copy immediately.
14
+ *
15
+ * @category Buscape
16
+ * @package Buscape_Fcontrol
17
+ * @copyright Copyright (c) 2010 Buscapé Company (http://www.buscapecompany.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Buscape_Fcontrol_Model_Api extends Buscape_Fcontrol_Model_Api_Abstract
22
+ {
23
+
24
+ protected $_urlFrame = 'https://secure.fcontrol.com.br/validatorframe/validatorframe.aspx';
25
+
26
+ public function analisaFrame()
27
+ {
28
+ $url = $this->_urlFrame;
29
+
30
+ $url .= '?login=' . $this->getUser();
31
+ $url .= '&senha=' . $this->getPassword();
32
+ $url .= '&nomeComprador=' . $this->compradorNome;
33
+ $url .= '&ruaComprador=' . $this->compradorRua;
34
+ $url .= '&numeroComprador=' . $this->compradorNumero;
35
+ $url .= '&cidadeComprador=' . $this->compradorCidade;
36
+ $url .= '&ufComprador=' . $this->compradorEstado;
37
+ $url .= '&paisComprador=' . $this->compradorPais;
38
+ $url .= '&cepComprador=' . $this->compradorCep;
39
+ $url .= '&dddComprador=' . $this->compradorDddTelefone1;
40
+ $url .= '&telefoneComprador=' . $this->compradorTelefone1;
41
+ $url .= '&cpfComprador=' . $this->compradorCpfCnpj;
42
+ $url .= '&emailComprador=' . $this->compradorEmail;
43
+ $url .= '&nomeEntrega=' . $this->entregaNome;
44
+ $url .= '&ruaEntrega=' . $this->entregaRua;
45
+ $url .= '&numeroEntrega=' . $this->entregaNumero;
46
+ $url .= '&cidadeEntrega=' . $this->entregaCidade;
47
+ $url .= '&ufEntrega=' . $this->entregaEstado;
48
+ $url .= '&paisEntrega=' . $this->entregaPais;
49
+ $url .= '&cepEntrega=' . $this->entregaCep;
50
+ $url .= '&dddEntrega=' . $this->entregaDddTelefone1;
51
+ $url .= '&telefoneEntrega=' . $this->entregaTelefone1;
52
+ $url .= '&codigoPedido=' . $this->codigoPedido;
53
+ $url .= '&quantidadeItensDistintos=' . $this->itensDistintos;
54
+ $url .= '&quantidadeTotalItens=' . $this->itensTotal;
55
+ $url .= '&valorTotalCompra=' . ($this->valorTotalCompra * 100);
56
+ $url .= '&dataCompra=' . $this->dataCompra;
57
+ $url .= '&metodoPagamentos=' . $this->metodoPagamento;
58
+ $url .= '&numeroParcelasPagamentos=' . $this->numeroParcelas;
59
+ $url .= '&valorPagamentos=' . ($this->valorPedido * 100);
60
+
61
+ echo '<iframe height="115" frameborder="0" width="300" src="'. $url .'"></iframe>';
62
+ }
63
+
64
+ /* Proposta */
65
+ public function analisaFrame2()
66
+ {
67
+ try {
68
+ $client = new Zend_Http_Client();
69
+
70
+ $url = $this->_urlFrame;
71
+
72
+ $client->setUri($this->_urlFrame); // verify if exist problem with https, if exist please change for http
73
+
74
+ $client->resetParameters();
75
+
76
+ $client->setParameterGet('login', $this->getUser());
77
+ $client->setParameterGet('senha', $this->getPassword());
78
+ $client->setParameterGet('nomeComprador', $this->compradorNome);
79
+ $client->setParameterGet('ruaComprador', $this->compradorRua);
80
+ $client->setParameterGet('numeroComprador', $this->compradorNumero);
81
+ $client->setParameterGet('cidadeComprador', $this->compradorCidade);
82
+ $client->setParameterGet('ufComprador', $this->compradorEstado);
83
+ $client->setParameterGet('paisComprador', $this->compradorPais);
84
+ $client->setParameterGet('cepComprador', $this->compradorCep);
85
+ $client->setParameterGet('cpfComprador', $this->compradorCpfCnpj);
86
+ $client->setParameterGet('emailComprador', $this->compradorEmail);
87
+ $client->setParameterGet('nomeEntrega', $this->entregaNome);
88
+ $client->setParameterGet('ruaEntrega', $this->entregaRua);
89
+ $client->setParameterGet('numeroEntrega', $this->entregaNumero);
90
+ $client->setParameterGet('cidadeEntrega', $this->entregaCidade);
91
+ $client->setParameterGet('ufEntrega', $this->entregaEstado);
92
+ $client->setParameterGet('paisEntrega', $this->entregaPais);
93
+ $client->setParameterGet('cepEntrega', $this->entregaCep);
94
+ $client->setParameterGet('dddEntrega', $this->entregaDddTelefone1);
95
+ $client->setParameterGet('telefoneEntrega', $this->entregaTelefone1);
96
+ $client->setParameterGet('codigoPedido', $this->codigoPedido);
97
+ $client->setParameterGet('quantidadeItensDistintos', $this->itensDistintos);
98
+ $client->setParameterGet('quantidadeTotalItens', $this->itensTotal);
99
+ $client->setParameterGet('valorTotalCompra', ($this->valorTotalCompra * 100));
100
+ $client->setParameterGet('dataCompra', $this->dataCompra);
101
+ $client->setParameterGet('metodoPagamentos', $this->metodoPagamento);
102
+ $client->setParameterGet('numeroParcelasPagamentos', $this->numeroParcelas);
103
+ $client->setParameterGet('valorPagamentos', ($this->valorPedido * 100));
104
+
105
+ $content = $client->request();
106
+
107
+ $body = $content->getBody();
108
+
109
+ $images = array();
110
+
111
+ preg_match_all('/(img|src)\=(\"|\')[^\"\'\>]+/i', $body, $media);
112
+
113
+ preg_match_all('/BACKGROUND-IMAGE:[\s]*url\(.*.gif\);/', $body, $background_images);
114
+
115
+ $data_images = preg_replace('/(img|src)(\"|\'|\=\"|\=\')(.*)/i', "$3", $media[0]);
116
+
117
+ // images
118
+ foreach($data_images as $url)
119
+ {
120
+ $body = preg_replace("~$url~", "https://secure.fcontrol.com.br/validatorframe/{$url}", $body);
121
+ }
122
+
123
+ foreach($background_images[0] as $background)
124
+ {
125
+ $background = str_replace("BACKGROUND-IMAGE: url(", "", $background);
126
+ $background = str_replace(");", "", $background);
127
+ $body = preg_replace("~$background~", "https://secure.fcontrol.com.br/validatorframe/{$background}", $body);
128
+ }
129
+
130
+ echo $body;
131
+
132
+ } catch(Exception $e) {
133
+ return;
134
+ }
135
+ }
136
+ }
app/code/community/Buscape/Fcontrol/Model/Api/Abstract.php ADDED
@@ -0,0 +1,1358 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
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 suporte.developer@buscape-inc.com so we can send you a copy immediately.
14
+ *
15
+ * @category Buscape
16
+ * @package Buscape_Fcontrol
17
+ * @copyright Copyright (c) 2010 Buscapé Company (http://www.buscapecompany.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ require_once 'Buscape/Fcontrol/lib/nusoap.php';
22
+
23
+ abstract class Buscape_Fcontrol_Model_Api_Abstract extends Varien_Object
24
+ {
25
+
26
+ /* Tipo de Serviço */
27
+
28
+ const FRAME = 1;
29
+
30
+ const FILA_LOJISTA_UNICO = 2;
31
+
32
+ const FILA_LOJISTA_PASSAGENS = 3;
33
+
34
+ const FILA_VARIOS_LOJISTAS = 4;
35
+
36
+ const RECARGA_WEBSERVICE = 5;
37
+
38
+ /* Status */
39
+
40
+ const STATUS_PENDENTE = 1;
41
+
42
+ const STATUS_ENVIADO = 2;
43
+
44
+ const STATUS_CANCELADO = 3;
45
+
46
+ const STATUS_AGUARDANDO_DOCUMENTACAO = 5;
47
+
48
+ const STATUS_CANCELADO_POR_SUSPEITA = 6;
49
+
50
+ const STATUS_APROVADA = 7;
51
+
52
+ const STATUS_EM_ESPERA = 8;
53
+
54
+ const STATUS_SOLICITADA_SUPERVISAO = 9;
55
+
56
+ const STATUS_FRAUDE_CONFIRMADA = 10;
57
+
58
+ const STATUS_EM_RECUPERACAO_DE_PERDA = 11;
59
+
60
+ const STATUS_RECUPERADO = 12;
61
+
62
+ const STATUS_REPROVADO_OPERADORA_CARTAO = 13;
63
+
64
+ const STATUS_DESCANCELADO = 14;
65
+
66
+ const STATUS_AGUARDANDO_DOCUMENTACAO_FILA = 17;
67
+
68
+ const STATUS_SOLICITAR_CONTATO = 18;
69
+
70
+ const STATUS_CONTATO_EFETUADO = 19;
71
+
72
+ const STATUS_APROVADO_OPERADORA_CARTAO = 23;
73
+
74
+ public static $acaoAprovar = array(
75
+ self::STATUS_ENVIADO,
76
+ self::STATUS_APROVADA,
77
+ self::STATUS_RECUPERADO,
78
+ self::STATUS_DESCANCELADO,
79
+ self::STATUS_APROVADO_OPERADORA_CARTAO
80
+ );
81
+
82
+ public static $acaoCancelar = array(
83
+ self::STATUS_CANCELADO,
84
+ self::STATUS_CANCELADO_POR_SUSPEITA,
85
+ self::STATUS_FRAUDE_CONFIRMADA,
86
+ self::STATUS_REPROVADO_OPERADORA_CARTAO
87
+ );
88
+
89
+ public static $acaoIndefinida = array(
90
+ self::STATUS_PENDENTE,
91
+ self::STATUS_ENVIADO,
92
+ self::STATUS_AGUARDANDO_DOCUMENTACAO,
93
+ self::STATUS_EM_ESPERA,
94
+ self::STATUS_SOLICITADA_SUPERVISAO,
95
+ self::STATUS_EM_RECUPERACAO_DE_PERDA,
96
+ self::STATUS_REPROVADO_OPERADORA_CARTAO,
97
+ self::STATUS_AGUARDANDO_DOCUMENTACAO_FILA,
98
+ self::STATUS_SOLICITAR_CONTATO,
99
+ self::STATUS_CONTATO_EFETUADO
100
+ );
101
+
102
+ public $_paymentMethod = array(
103
+ 1 => 'CartaoCredito',
104
+ 2 => 'CartaoVisa',
105
+ 3 => 'CartaoMasterCard',
106
+ 4 => 'CartaoDiners',
107
+ 5 => 'CartaoAmericanExpress',
108
+ 6 => 'CartaoHiperCard',
109
+ 7 => 'CartaoAura',
110
+ 10 => 'PagamentoEntrega',
111
+ 11 => 'DebitoTransferenciaEletronica',
112
+ 12 => 'BoletoBancario',
113
+ 13 => 'Financiamento',
114
+ 14 => 'Cheque',
115
+ 15 => 'Deposito',
116
+ 18 => 'ValePresente',
117
+ 21 => 'OiPaggo',
118
+ 25 => 'CartaoSoroCred',
119
+ 27 => 'BoletoAPrazo',
120
+ 34 => 'TransferenciaEletronicaBancoBrasil',
121
+ 35 => 'TransferenciaEletronicaBradesco',
122
+ 36 => 'TransferenciaEletronicaItau'
123
+ );
124
+
125
+ public $_levelRisk = array(
126
+ 0 => 'Baixo Risco',
127
+ 1 => 'Médio Risco',
128
+ 2 => 'Alto Risco'
129
+ );
130
+
131
+ public $_statusOrderReturned = array(
132
+ 2 => 'Enviado',
133
+ 3 => 'Cancelado',
134
+ 6 => 'Cancelado por Suspeita',
135
+ 7 => 'Aprovada',
136
+ 10 => 'Fraude Confirmada',
137
+ 13 => 'Não Aprovado pela operadora do cartão'
138
+ );
139
+
140
+ /**
141
+ * Parameter $_wsdl
142
+ *
143
+ * @var Buscape_Fcontrol_Model_Api
144
+ */
145
+ private $_wsdl = "http://secure.fcontrol.com.br/WSFControl2/WSFControl2.asmx?wsdl";
146
+
147
+ /**
148
+ * Parameter $usuario
149
+ *
150
+ * @var Buscape_Fcontrol_Model_Api
151
+ */
152
+ public $usuario;
153
+
154
+ /**
155
+ * Parameter $senha
156
+ *
157
+ * @var Buscape_Fcontrol_Model_Api
158
+ */
159
+ public $senha;
160
+
161
+ /**
162
+ * Parameter $compradorNome
163
+ *
164
+ * @var Buscape_Fcontrol_Model_Api
165
+ */
166
+ public $compradorNome;
167
+
168
+ /**
169
+ * Parameter $compradorPais
170
+ *
171
+ * @var Buscape_Fcontrol_Model_Api
172
+ */
173
+ public $compradorPais;
174
+
175
+ /**
176
+ * Parameter $compradorCep
177
+ *
178
+ * @var Buscape_Fcontrol_Model_Api
179
+ */
180
+ public $compradorCep;
181
+
182
+ /**
183
+ * Parameter $compradorRua
184
+ *
185
+ * @var Buscape_Fcontrol_Model_Api
186
+ */
187
+ public $compradorRua;
188
+
189
+ /**
190
+ * Parameter $compradorNumero
191
+ *
192
+ * @var Buscape_Fcontrol_Model_Api
193
+ */
194
+ public $compradorNumero;
195
+
196
+ /**
197
+ * Parameter $compradorComplemento
198
+ *
199
+ * @var Buscape_Fcontrol_Model_Api
200
+ */
201
+ public $compradorComplemento;
202
+
203
+ /**
204
+ * Parameter $compradorBairro
205
+ *
206
+ * @var Buscape_Fcontrol_Model_Api
207
+ */
208
+ public $compradorBairro;
209
+
210
+ /**
211
+ * Parameter $compradorCidade
212
+ *
213
+ * @var Buscape_Fcontrol_Model_Api
214
+ */
215
+ public $compradorCidade;
216
+
217
+ /**
218
+ * Parameter $compradorEstado
219
+ *
220
+ * @var Buscape_Fcontrol_Model_Api
221
+ */
222
+ public $compradorEstado;
223
+
224
+ /**
225
+ * Parameter $compradorCpfCnpj
226
+ *
227
+ * @var Buscape_Fcontrol_Model_Api
228
+ */
229
+ public $compradorCpfCnpj;
230
+
231
+ /**
232
+ * Parameter $compradorDddTelefone1
233
+ *
234
+ * @var Buscape_Fcontrol_Model_Api
235
+ */
236
+ public $compradorDddTelefone1;
237
+
238
+ /**
239
+ * Parameter $compradorTelefone1
240
+ *
241
+ * @var Buscape_Fcontrol_Model_Api
242
+ */
243
+ public $compradorTelefone1;
244
+
245
+ /**
246
+ * Parameter $compradorDddCelular
247
+ *
248
+ * @var Buscape_Fcontrol_Model_Api
249
+ */
250
+ public $compradorDddCelular;
251
+
252
+ /**
253
+ * Parameter $compradorCelular
254
+ *
255
+ * @var Buscape_Fcontrol_Model_Api
256
+ */
257
+ public $compradorCelular;
258
+
259
+ /**
260
+ * Parameter $compradorIp
261
+ *
262
+ * @var Buscape_Fcontrol_Model_Api
263
+ */
264
+ public $compradorIp;
265
+
266
+ /**
267
+ * Parameter $compradorEmail
268
+ *
269
+ * @var Buscape_Fcontrol_Model_Api
270
+ */
271
+ public $compradorEmail;
272
+
273
+ /**
274
+ * Parameter $compradorSenha
275
+ *
276
+ * @var Buscape_Fcontrol_Model_Api
277
+ */
278
+ public $compradorSenha;
279
+
280
+ /**
281
+ * Parameter $compradorSexo
282
+ *
283
+ * @var Buscape_Fcontrol_Model_Api
284
+ */
285
+ public $compradorSexo;
286
+
287
+ /**
288
+ * Parameter $compradorDddTelefone2
289
+ *
290
+ * @var Buscape_Fcontrol_Model_Api
291
+ */
292
+ public $compradorDddTelefone2;
293
+
294
+ /**
295
+ * Parameter $compradorTelefone2
296
+ *
297
+ * @var Buscape_Fcontrol_Model_Api
298
+ */
299
+ public $compradorTelefone2;
300
+
301
+ /**
302
+ * Parameter $compradorDataNascimento
303
+ *
304
+ * @var Buscape_Fcontrol_Model_Api
305
+ */
306
+ public $compradorDataNascimento = '2000-01-01';
307
+
308
+ /**
309
+ * Parameter $prazoEntrega
310
+ *
311
+ * @var Buscape_Fcontrol_Model_Api
312
+ */
313
+ public $entregaPais;
314
+
315
+ /**
316
+ * Parameter $prazoEntrega
317
+ *
318
+ * @var Buscape_Fcontrol_Model_Api
319
+ */
320
+ public $entregaCep;
321
+
322
+ /**
323
+ * Parameter $prazoEntrega
324
+ *
325
+ * @var Buscape_Fcontrol_Model_Api
326
+ */
327
+ public $entregaRua;
328
+
329
+ /**
330
+ * Parameter $prazoEntrega
331
+ *
332
+ * @var Buscape_Fcontrol_Model_Api
333
+ */
334
+ public $entregaNumero;
335
+
336
+ /**
337
+ * Parameter $prazoEntrega
338
+ *
339
+ * @var Buscape_Fcontrol_Model_Api
340
+ */
341
+ public $entregaComplemento;
342
+
343
+ /**
344
+ * Parameter $prazoEntrega
345
+ *
346
+ * @var Buscape_Fcontrol_Model_Api
347
+ */
348
+ public $entregaBairro;
349
+
350
+ /**
351
+ * Parameter $prazoEntrega
352
+ *
353
+ * @var Buscape_Fcontrol_Model_Api
354
+ */
355
+ public $entregaCidade;
356
+
357
+ /**
358
+ * Parameter $prazoEntrega
359
+ *
360
+ * @var Buscape_Fcontrol_Model_Api
361
+ */
362
+ public $entregaEstado;
363
+
364
+ /**
365
+ * Parameter $prazoEntrega
366
+ *
367
+ * @var Buscape_Fcontrol_Model_Api
368
+ */
369
+ public $entregaDddTelefone1;
370
+
371
+ /**
372
+ * Parameter $prazoEntrega
373
+ *
374
+ * @var Buscape_Fcontrol_Model_Api
375
+ */
376
+ public $entregaNome;
377
+
378
+ /**
379
+ * Parameter $prazoEntrega
380
+ *
381
+ * @var Buscape_Fcontrol_Model_Api
382
+ */
383
+ public $entregaTelefone1;
384
+
385
+ /**
386
+ * Parameter $prazoEntrega
387
+ *
388
+ * @var Buscape_Fcontrol_Model_Api
389
+ */
390
+ public $entregaDddCelular;
391
+
392
+ /**
393
+ * Parameter $prazoEntrega
394
+ *
395
+ * @var Buscape_Fcontrol_Model_Api
396
+ */
397
+ public $entregaCelular;
398
+
399
+ /**
400
+ * Parameter $prazoEntrega
401
+ *
402
+ * @var Buscape_Fcontrol_Model_Api
403
+ */
404
+ public $entregaDddTelefone2;
405
+
406
+ /**
407
+ * Parameter $prazoEntrega
408
+ *
409
+ * @var Buscape_Fcontrol_Model_Api
410
+ */
411
+ public $entregaTelefone2;
412
+
413
+ /**
414
+ * Parameter $prazoEntrega
415
+ *
416
+ * @var Buscape_Fcontrol_Model_Api
417
+ */
418
+ public $entregaCpfCnpj;
419
+
420
+ /**
421
+ * Parameter $prazoEntrega
422
+ *
423
+ * @var Buscape_Fcontrol_Model_Api
424
+ */
425
+ public $entregaSexo;
426
+
427
+ /**
428
+ * Parameter $prazoEntrega
429
+ *
430
+ * @var Buscape_Fcontrol_Model_Api
431
+ */
432
+ public $entregaDataNascimento = '2000-01-01';
433
+
434
+ /**
435
+ * Parameter $prazoEntrega
436
+ *
437
+ * @var Buscape_Fcontrol_Model_Api
438
+ */
439
+ public $entregaEmail;
440
+
441
+ /**
442
+ * Parameter $prazoEntrega
443
+ *
444
+ * @var Buscape_Fcontrol_Model_Api
445
+ */
446
+ public $metodoPagamento = 'CartaoCredito';
447
+
448
+ /**
449
+ * Parameter $nomeBancoEmissor
450
+ *
451
+ * @var Buscape_Fcontrol_Model_Api
452
+ */
453
+ public $nomeBancoEmissor;
454
+
455
+ /**
456
+ * Parameter $prazoEntrega
457
+ *
458
+ * @var Buscape_Fcontrol_Model_Api
459
+ */
460
+ public $numeroCartao;
461
+
462
+ /**
463
+ * Parameter $prazoEntrega
464
+ *
465
+ * @var Buscape_Fcontrol_Model_Api
466
+ */
467
+ public $dataValidadeCartao;
468
+
469
+ /**
470
+ * Parameter $prazoEntrega
471
+ *
472
+ * @var Buscape_Fcontrol_Model_Api
473
+ */
474
+ public $nomeTitularCartao;
475
+
476
+ /**
477
+ * Parameter $cpfTitularCartao
478
+ *
479
+ * @var Buscape_Fcontrol_Model_Api
480
+ */
481
+ public $cpfTitularCartao;
482
+
483
+ /**
484
+ * Parameter $bin
485
+ *
486
+ * @var Buscape_Fcontrol_Model_Api
487
+ */
488
+ public $bin;
489
+
490
+ /**
491
+ * Parameter $prazoEntrega
492
+ *
493
+ * @var Buscape_Fcontrol_Model_Api
494
+ */
495
+ public $quatroUltimosDigitosCartao;
496
+
497
+ /**
498
+ * Parameter $prazoEntrega
499
+ *
500
+ * @var Buscape_Fcontrol_Model_Api
501
+ */
502
+ public $bin2;
503
+
504
+ /**
505
+ * Parameter $prazoEntrega
506
+ *
507
+ * @var Buscape_Fcontrol_Model_Api
508
+ */
509
+ public $binBanco;
510
+
511
+ /**
512
+ * Parameter $prazoEntrega
513
+ *
514
+ * @var Buscape_Fcontrol_Model_Api
515
+ */
516
+ public $binPais;
517
+
518
+ /**
519
+ * Parameter $prazoEntrega
520
+ *
521
+ * @var Buscape_Fcontrol_Model_Api
522
+ */
523
+ public $pagadorDddTelefone;
524
+
525
+ /**
526
+ * Parameter $prazoEntrega
527
+ *
528
+ * @var Buscape_Fcontrol_Model_Api
529
+ */
530
+ public $pagadorTelefone;
531
+
532
+ /**
533
+ * Parameter $prazoEntrega
534
+ *
535
+ * @var Buscape_Fcontrol_Model_Api
536
+ */
537
+ public $valorPedido;
538
+
539
+ /**
540
+ * Parameter $prazoEntrega
541
+ *
542
+ * @var Buscape_Fcontrol_Model_Api
543
+ */
544
+ public $numeroParcelas;
545
+
546
+ /**
547
+ * Parameter $prazoEntrega
548
+ *
549
+ * @var Buscape_Fcontrol_Model_Api
550
+ */
551
+ public $codigoPedido;
552
+
553
+ /**
554
+ * Parameter $prazoEntrega
555
+ *
556
+ * @var Buscape_Fcontrol_Model_Api
557
+ */
558
+ public $dataCompra;
559
+
560
+ /**
561
+ * Parameter $prazoEntrega
562
+ *
563
+ * @var Buscape_Fcontrol_Model_Api
564
+ */
565
+ public $itensDistintos;
566
+
567
+ /**
568
+ * Parameter $prazoEntrega
569
+ *
570
+ * @var Buscape_Fcontrol_Model_Api
571
+ */
572
+ public $itensTotal;
573
+
574
+ /**
575
+ * Parameter $prazoEntrega
576
+ *
577
+ * @var Buscape_Fcontrol_Model_Api
578
+ */
579
+ public $valorTotalCompra;
580
+
581
+ /**
582
+ * Parameter $prazoEntrega
583
+ *
584
+ * @var Buscape_Fcontrol_Model_Api
585
+ */
586
+ public $valorTotalFrete;
587
+
588
+ /**
589
+ * Parameter $prazoEntrega
590
+ *
591
+ * @var Buscape_Fcontrol_Model_Api
592
+ */
593
+ public $prazoEntrega;
594
+
595
+ /**
596
+ * Parameter $formaEntrega
597
+ *
598
+ * @var Buscape_Fcontrol_Model_Api
599
+ */
600
+ public $formaEntrega;
601
+
602
+ /**
603
+ * Parameter $observacao
604
+ *
605
+ * @var Buscape_Fcontrol_Model_Api
606
+ */
607
+ public $observacao;
608
+
609
+ /**
610
+ * Parameter $canalVenda
611
+ *
612
+ * @var Buscape_Fcontrol_Model_Api
613
+ */
614
+ public $canalVenda;
615
+
616
+ /**
617
+ * Parameter $extra1
618
+ *
619
+ * @var Buscape_Fcontrol_Model_Api
620
+ */
621
+ public $extra1;
622
+
623
+ /**
624
+ * Parameter $extra2
625
+ *
626
+ * @var Buscape_Fcontrol_Model_Api
627
+ */
628
+ public $extra2;
629
+
630
+ /**
631
+ * Parameter $extra3
632
+ *
633
+ * @var Buscape_Fcontrol_Model_Api
634
+ */
635
+ public $extra3;
636
+
637
+ /**
638
+ * Parameter $extra4
639
+ *
640
+ * @var Buscape_Fcontrol_Model_Api
641
+ */
642
+ public $extra4;
643
+
644
+ /**
645
+ * Parameter $produtoCodigo
646
+ *
647
+ * @var Buscape_Fcontrol_Model_Api
648
+ */
649
+ public $produtoCodigo;
650
+
651
+ /**
652
+ * Parameter $produtoDescricao
653
+ *
654
+ * @var Buscape_Fcontrol_Model_Api
655
+ */
656
+ public $produtoDescricao;
657
+
658
+ /**
659
+ * Parameter $produtoQtde
660
+ *
661
+ * @var Buscape_Fcontrol_Model_Api
662
+ */
663
+ public $produtoQtde;
664
+
665
+ /**
666
+ * Parameter $produtoValor
667
+ *
668
+ * @var Buscape_Fcontrol_Model_Api
669
+ */
670
+ public $produtoValor;
671
+
672
+ /**
673
+ * Parameter $produtoCategoria
674
+ *
675
+ * @var Buscape_Fcontrol_Model_Api
676
+ */
677
+ public $produtoCategoria;
678
+
679
+ /**
680
+ * Parameter $produtoListaCasamento
681
+ *
682
+ * @var Buscape_Fcontrol_Model_Api
683
+ */
684
+ public $produtoListaCasamento;
685
+
686
+ /**
687
+ * Parameter $produtoParaPresente
688
+ *
689
+ * @var Buscape_Fcontrol_Model_Api
690
+ */
691
+ public $produtoParaPresente;
692
+
693
+ /**
694
+ * Parameter $status
695
+ *
696
+ * @var Buscape_Fcontrol_Model_Api
697
+ */
698
+ public $status;
699
+
700
+ /**
701
+ * Parameter $comentario
702
+ *
703
+ * @var Buscape_Fcontrol_Model_Api
704
+ */
705
+ public $comentario;
706
+
707
+ /**
708
+ * Parameter $compartilharComentario
709
+ *
710
+ * @var Buscape_Fcontrol_Model_Api
711
+ */
712
+ public $compartilharComentario = false;
713
+
714
+ public function __construct()
715
+ {
716
+ $this->usuario = $this->getUser();
717
+
718
+ $this->senha = $this->getPassword();
719
+
720
+ $this->compradorPais = $this->getCountry();
721
+
722
+ $this->entregaPais = $this->getCountry();
723
+
724
+ $this->canalVenda = Mage::app()->getStore()->getName();
725
+
726
+ $this->prazoEntrega = 0;
727
+ }
728
+
729
+ public function preparaTransacao($order)
730
+ {
731
+ switch(Mage::helper('fcontrol')->getConfig('type_service')) {
732
+ case self::FRAME:
733
+ /* @required */
734
+ $this->compradorNome = $order->getBillingAddress()->getFirstname() . ' ' . $order->getBillingAddress()->getLastname();
735
+
736
+ /* @required */
737
+ $this->compradorCep = str_replace("-", "", preg_replace('/[^(\x20-\x7F)\x0A]*/', '', $order->getBillingAddress()->getPostcode()));
738
+
739
+ /* @required */
740
+ $this->compradorRua = utf8_decode($order->getBillingAddress()->getStreet1());
741
+
742
+ /* @required */
743
+ $this->compradorNumero = ($order->getBillingAddress()->getStreet2()) ? $order->getBillingAddress()->getStreet2() : 'SN';
744
+
745
+ $this->compradorComplemento = $order->getBillingAddress()->getStreet3();
746
+
747
+ $this->compradorBairro = $order->getBillingAddress()->getStreet4();
748
+
749
+ /* @required */
750
+ $this->compradorCidade = utf8_decode($order->getBillingAddress()->getCity());
751
+
752
+ /* @required */
753
+ $this->compradorEstado = utf8_decode($order->getBillingAddress()->getRegion());
754
+
755
+ $telBilling = preg_replace("/[^0-9]/","", $order->getBillingAddress()->getTelephone());
756
+
757
+ $telBilling = trim($telBilling);
758
+
759
+ switch(strlen($telBilling))
760
+ {
761
+ case 8:
762
+ $telephoneBilling = $telBilling;
763
+ $dddTelephoneBilling = '';
764
+ break;
765
+ case 10:
766
+ $telephoneBiling = substr($telBilling, -8);
767
+ $dddTelephoneBilling = substr($telBilling, -10, 2);
768
+ break;
769
+ case 12:
770
+ $telephoneBiling = substr($telBilling, -8);
771
+ $dddTelephoneBilling = substr($telBilling, -10, 2);
772
+ break;
773
+ }
774
+
775
+ $this->compradorDddTelefone1 = $dddTelephoneBilling;
776
+
777
+ $this->compradorTelefone1 = $telephoneBiling;
778
+
779
+ /* @required */
780
+ $this->compradorCpfCnpj = preg_replace("/[^0-9]/","", $order->getCustomerTaxvat());
781
+
782
+ $telShipping = preg_replace("/[^0-9]/","", $order->getShippingAddress()->getTelephone());
783
+
784
+ $telShipping = trim($telShipping);
785
+
786
+ switch(strlen($telShipping))
787
+ {
788
+ case 8:
789
+ $telephoneShipping = $telShipping;
790
+ $dddTelephoneShipping = '';
791
+ break;
792
+ case 10:
793
+ $telephoneShipping = substr($telShipping, -8);
794
+ $dddTelephoneShipping = substr($telShipping, -10, 2);
795
+ break;
796
+ case 12:
797
+ $telephoneShipping = substr($telShipping, -8);
798
+ $dddTelephoneShipping = substr($telShipping, -10, 2);
799
+ break;
800
+ }
801
+
802
+ /* @required */
803
+ $this->compradorEmail = (is_null($order->getBillingAddress()->getEmail())) ? $order->getCustomerEmail() : $order->getBillingAddress()->getEmail();
804
+
805
+ $this->entregaCep = str_replace("-", "", preg_replace('/[^(\x20-\x7F)\x0A]*/', '', $order->getShippingAddress()->getPostcode()));
806
+
807
+ $this->entregaRua = utf8_decode($order->getShippingAddress()->getStreet1());
808
+
809
+ $this->entregaNumero = ($order->getShippingAddress()->getStreet2()) ? $order->getShippingAddress()->getStreet2() : 'SN';
810
+
811
+ $this->entregaBairro = $order->getShippingAddress()->getStreet4();
812
+
813
+ $this->entregaCidade = utf8_decode($order->getShippingAddress()->getCity());
814
+
815
+ $this->entregaEstado = utf8_decode($order->getShippingAddress()->getRegion());
816
+
817
+ /* @required */
818
+ $this->entregaNome = $order->getShippingAddress()->getFirstname() . ' ' . $order->getShippingAddress()->getLastname();
819
+
820
+ $this->entregaDddTelefone1 = $dddTelephoneShipping;
821
+
822
+ $this->entregaTelefone1 = $telephoneShipping;
823
+
824
+ $this->entregaCpfCnpj = preg_replace("/[^0-9]/","", $order->getCustomerTaxvat());
825
+
826
+ $this->entregaEmail = $order->getShippingAddress()->getEmail();
827
+
828
+ /* @required */
829
+ $adapter_payment = Mage::getModel('fcontrol/adapter_payment');
830
+
831
+ $adapter_payment->filter($order->getPayment(), $this);
832
+
833
+ /* @required */
834
+ $this->valorPedido = number_format($order->getPayment()->getAmountOrdered(), 2, ".", "");
835
+
836
+ /* @required */
837
+ $this->numeroParcelas = 1;
838
+
839
+ $this->codigoPedido = $order->getIncrementId();
840
+
841
+ /* @required; @format: ISO 8601 */
842
+ $this->dataCompra = str_replace(" ", "+", $order->getCreatedAt());
843
+
844
+ $this->itensTotal = 0;
845
+
846
+ if($order->getAllItems()) {
847
+ foreach($order->getAllItems() as $items) {
848
+ if(is_null($items->getParentItemId())) {
849
+ $this->itensTotal += intval($items->getQtyOrdered());
850
+ }
851
+ }
852
+ }
853
+
854
+ $this->itensDistintos = count($order->getAllItems());
855
+
856
+ $this->valorTotalCompra = number_format($order->getPayment()->getAmountOrdered(), 2, ".", "");
857
+ break;
858
+ case self::FILA_LOJISTA_UNICO:
859
+ case self::FILA_LOJISTA_PASSAGENS:
860
+ case self::FILA_VARIOS_LOJISTAS:
861
+ case self::RECARGA_WEBSERVICE:
862
+
863
+ /* @required */
864
+ $this->compradorNome = $order->getBillingAddress()->getFirstname() . ' ' . $order->getBillingAddress()->getLastname();
865
+
866
+ /* @required */
867
+ $this->compradorCep = str_replace("-", "", preg_replace('/[^(\x20-\x7F)\x0A]*/', '', $order->getBillingAddress()->getPostcode()));
868
+
869
+ /* @required */
870
+ $this->compradorRua = utf8_decode($order->getBillingAddress()->getStreet1());
871
+
872
+ /* @required */
873
+ $this->compradorNumero = ($order->getBillingAddress()->getStreet2()) ? $order->getBillingAddress()->getStreet2() : 'SN';
874
+
875
+ $this->compradorComplemento = $order->getBillingAddress()->getStreet3();
876
+
877
+ $this->compradorBairro = $order->getBillingAddress()->getStreet4();
878
+
879
+ /* @required */
880
+ $this->compradorCidade = utf8_decode($order->getBillingAddress()->getCity());
881
+
882
+ /* @required */
883
+ $this->compradorEstado = utf8_decode($order->getBillingAddress()->getRegion());
884
+
885
+ /* @required */
886
+ $this->compradorCpfCnpj = preg_replace("/[^0-9]/","", $order->getCustomerTaxvat());
887
+
888
+ /* @required */
889
+ $this->compradorTelefone1 = str_replace("-", "", $order->getBillingAddress()->getTelephone());
890
+
891
+ $this->compradorCelular = str_replace("-", "", $order->getBillingAddress()->getTelephone());
892
+
893
+ if($order->getRemoteIp()) {
894
+ $this->compradorIp = $order->getRemoteIp();
895
+ }
896
+
897
+ /* @required */
898
+ $this->compradorEmail = (is_null($order->getBillingAddress()->getEmail())) ? $order->getCustomerEmail() : $order->getBillingAddress()->getEmail();
899
+
900
+ if($order->getCustomerGender()) {
901
+ $this->compradorSexo = (intval($order->getCustomerGender()) === 123) ? 'M' : 'F';
902
+ }
903
+
904
+ if($order->getCustomerDob()) {
905
+ $dob = new DateTime($order->getCustomerDob());
906
+
907
+ $this->compradorDataNascimento = $dob->format('c');
908
+ }
909
+
910
+ $this->entregaCep = str_replace("-", "", preg_replace('/[^(\x20-\x7F)\x0A]*/', '', $order->getShippingAddress()->getPostcode()));
911
+
912
+ $this->entregaRua = utf8_decode($order->getShippingAddress()->getStreet1());
913
+
914
+ $this->entregaNumero = ($order->getShippingAddress()->getStreet2()) ? $order->getShippingAddress()->getStreet2() : 'SN';
915
+
916
+ $this->entregaComplemento = $order->getShippingAddress()->getStreet3();
917
+
918
+ $this->entregaBairro = $order->getShippingAddress()->getStreet4();
919
+
920
+ $this->entregaCidade = utf8_decode($order->getShippingAddress()->getCity());
921
+
922
+ $this->entregaEstado = utf8_decode($order->getShippingAddress()->getRegion());
923
+
924
+ /* @required */
925
+ $this->entregaNome = $order->getShippingAddress()->getFirstname() . ' ' . $order->getShippingAddress()->getLastname();
926
+
927
+ $this->entregaCpfCnpj = preg_replace("/[^0-9]/","", $order->getCustomerTaxvat());;
928
+
929
+ if($order->getCustomerGender()) {
930
+ $this->entregaSexo = (intval($order->getCustomerGender()) === 123) ? 'M' : 'F';
931
+ }
932
+
933
+ if($order->getCustomerDob()) {
934
+ $dob = new DateTime($order->getCustomerDob());
935
+
936
+ $this->entregaDataNascimento = $dob->format('c');;
937
+ }
938
+
939
+ $this->entregaEmail = (is_null($order->getShippingAddress()->getEmail())) ? $order->getCustomerEmail() : $order->getShippingAddress()->getEmail();
940
+
941
+ $adapter_payment = Mage::getModel('fcontrol/adapter_payment');
942
+
943
+ $adapter_payment->filter($order->getPayment(), $this);
944
+
945
+ $this->cpfTitularCartao = preg_replace("/[^0-9]/","", $order->getCustomerTaxvat());
946
+
947
+ $this->codigoPedido = $order->getIncrementId();
948
+
949
+ $created_at = new DateTime($order->getPayment()->getCreatedAt());
950
+
951
+ /* @required; @format: ISO 8601 */
952
+ $this->dataCompra = $created_at->format('c');
953
+
954
+ $this->itensDistintos = count($order->getAllItems());
955
+
956
+ $this->itensTotal = 0;
957
+
958
+ $this->valorTotalCompra = number_format($order->getPayment()->getAmountOrdered(), 2, ".", "");
959
+
960
+ $this->valorTotalFrete = number_format($order->getBaseShippingAmount(), 2, ".", "");
961
+
962
+ $items_index = 0;
963
+
964
+ if($order->getAllItems()) {
965
+ foreach($order->getAllItems() as $items) {
966
+ if(is_null($items->getParentItemId())) {
967
+ $this->produtoCodigo[$items_index] = utf8_decode($items->getProductId());
968
+ $this->produtoDescricao[$items_index] = utf8_decode(str_replace("&", "", $items->getName()));
969
+ $this->produtoQtde[$items_index] = number_format($items->getQtyOrdered(), 0, "", "");
970
+ $this->produtoValor[$items_index] = number_format($items->getPrice(), 2, ".", "");
971
+
972
+ $this->itensTotal += intval($items->getQtyOrdered());
973
+
974
+ $item_data = Mage::getModel('catalog/product')->load($items->getProductId());
975
+
976
+ $this->produtoCategoria[$items_index] = implode(";", $item_data->getCategoryIds());
977
+ $this->produtoListaCasamento[$items_index] = 'false';
978
+ $this->produtoParaPresente[$items_index] = 'false';
979
+ $items_index++;
980
+ }
981
+ }
982
+ }
983
+
984
+ break;
985
+ }
986
+ }
987
+
988
+ public function analisarTransacao()
989
+ {
990
+ $client = new Zend_Soap_Client($this->_wsdl,
991
+ array(
992
+ 'soap_version' => SOAP_1_1,
993
+ 'encoding' => 'ISO-8859-1'
994
+ )
995
+ );
996
+
997
+ $data = array(
998
+ 'pedido' => array(
999
+ 'DadosUsuario' => array(
1000
+ 'Login' => $this->usuario,
1001
+ 'Senha' => $this->senha
1002
+ ),
1003
+ 'DadosComprador' => array(
1004
+ 'NomeComprador' => $this->compradorNome,
1005
+ 'Endereco' => array(
1006
+ 'Pais' => $this->compradorPais,
1007
+ 'Cep' => $this->compradorCep,
1008
+ 'Rua' => $this->xmlentities($this->compradorRua),
1009
+ 'Numero' => $this->compradorNumero,
1010
+ 'Complemento' => $this->xmlentities($this->compradorComplemento),
1011
+ 'Bairro' => $this->xmlentities($this->compradorBairro),
1012
+ 'Cidade' => $this->xmlentities($this->compradorCidade),
1013
+ 'Estado' => $this->compradorEstado
1014
+ ),
1015
+ 'CpfCnpj' => $this->compradorCpfCnpj,
1016
+ 'DddTelefone' => $this->compradorDddTelefone1,
1017
+ 'NumeroTelefone' => $this->compradorTelefone1,
1018
+ 'DddCelular' => $this->compradorDddCelular,
1019
+ 'NumeroCelular' => $this->compradorCelular,
1020
+ 'IP' => $this->compradorIp,
1021
+ 'Email' => $this->compradorEmail,
1022
+ 'Senha' => $this->compradorSenha,
1023
+ 'Sexo' => $this->compradorSexo,
1024
+ 'DddTelefone2' => $this->compradorDddTelefone2,
1025
+ 'NumeroTelefone2' => $this->compradorTelefone2,
1026
+ 'DataNascimento' => $this->compradorDataNascimento
1027
+ ),
1028
+ 'DadosEntrega' => array(
1029
+ 'Endereco' => array(
1030
+ 'Pais' => $this->entregaPais,
1031
+ 'Cep' => $this->entregaCep,
1032
+ 'Rua' => $this->xmlentities($this->entregaRua),
1033
+ 'Numero' => $this->entregaNumero,
1034
+ 'Complemento' => $this->xmlentities($this->entregaComplemento),
1035
+ 'Bairro' => $this->xmlentities($this->entregaBairro),
1036
+ 'Cidade' => $this->xmlentities($this->entregaCidade),
1037
+ 'Estado' => $this->entregaEstado
1038
+ ),
1039
+ 'DddTelefone' => $this->entregaDddTelefone1,
1040
+ 'NumeroTelefone' => $this->entregaTelefone1,
1041
+ 'NomeEntrega' => $this->entregaNome,
1042
+ 'DddCelular' => $this->entregaDddCelular,
1043
+ 'NumeroCelular' => $this->entregaCelular,
1044
+ 'DddTelefone2' => $this->entregaDddTelefone2,
1045
+ 'NumeroTelefone2' => $this->entregaTelefone2,
1046
+ 'CpfCnpj' => $this->entregaCpfCnpj,
1047
+ 'Sexo' => $this->entregaSexo,
1048
+ 'DataNascimento' => $this->entregaDataNascimento,
1049
+ 'Email' => $this->entregaEmail
1050
+ ),
1051
+ 'Pagamentos' => array(
1052
+ 'WsPagamento' => array(
1053
+ 'MetodoPagamento' => $this->metodoPagamento,
1054
+ 'Cartao' => array(
1055
+ 'NomeBancoEmissor' => $this->nomeBancoEmissor,
1056
+ 'NumeroCartao' => $this->numeroCartao,
1057
+ 'DataValidadeCartao' => $this->dataValidadeCartao,
1058
+ 'NomeTitularCartao' => $this->nomeTitularCartao,
1059
+ 'CpfTitularCartao' => $this->cpfTitularCartao,
1060
+ 'Bin' => $this->bin,
1061
+ 'quatroUltimosDigitosCartao' => $this->quatroUltimosDigitosCartao,
1062
+ 'Bin_payment' => $this->bin2,
1063
+ 'BinBanco' => $this->binBanco,
1064
+ 'BinPais' => $this->binPais,
1065
+ 'DddTelefone2' => $this->pagadorDddTelefone,
1066
+ 'NumeroTelefone2' => $this->pagadorTelefone
1067
+ ),
1068
+ 'Valor' => $this->format($this->valorPedido),
1069
+ 'NumeroParcelas' => $this->numeroParcelas
1070
+ )
1071
+ ),
1072
+ 'CodigoPedido' => $this->codigoPedido,
1073
+ 'DataCompra' => $this->dataCompra,
1074
+ 'QuantidadeItensDistintos' => $this->itensDistintos,
1075
+ 'QuantidadeTotalItens' => $this->itensTotal,
1076
+ 'ValorTotalCompra' => $this->format($this->valorTotalCompra),
1077
+ 'ValorTotalFrete' => $this->format($this->valorTotalFrete),
1078
+ 'PedidoDeTeste' => false,
1079
+ 'PrazoEntregaDias' => $this->prazoEntrega,
1080
+ 'FormaEntrega' => $this->formaEntrega,
1081
+ 'Observacao' => $this->observacao,
1082
+ 'CanalVenda' => $this->canalVenda
1083
+ )
1084
+ );
1085
+
1086
+ $data['Produtos'] = array();
1087
+
1088
+ for($i=0; $i < count($this->produtoCodigo); $i++ ) {
1089
+ $data['Produtos']['WsProduto3'] = array(
1090
+ 'Codigo' =>$this->produtoCodigo[$i],
1091
+ 'Descricao' => $this->produtoDescricao[$i],
1092
+ 'Quantidade' => $this->produtoQtde[$i],
1093
+ 'ValorUnitario' => $this->format($this->produtoValor[$i]),
1094
+ 'Categoria' => $this->produtoCategoria[$i],
1095
+ 'ListaDeCasamento' => $this->produtoListaCasamento[$i],
1096
+ 'ParaPresente' => $this->produtoParaPresente[$i]
1097
+ );
1098
+ }
1099
+
1100
+ $data['DadosExtra'] = array(
1101
+ 'Extra1' => $this->extra1,
1102
+ 'Extra2' => $this->extra2,
1103
+ 'Extra3' => $this->extra3,
1104
+ 'Extra4' => $this->extra4
1105
+ );
1106
+
1107
+ $result = $client->analisarTransacao($data);
1108
+
1109
+ return $result;
1110
+ }
1111
+
1112
+ /* @decrepted, i think that we can use the Zend_Soap_Client */
1113
+ public function enfileirarTransacao()
1114
+ {
1115
+ $xml = <<<EOT
1116
+ <enfileirarTransacao3 xmlns="http://tempuri.org/">
1117
+ <pedido>
1118
+ <DadosUsuario>
1119
+ <Login>{$this->usuario}</Login>
1120
+ <Senha>{$this->senha}</Senha>
1121
+ </DadosUsuario>
1122
+ <DadosComprador>
1123
+ <NomeComprador>{$this->compradorNome}</NomeComprador>
1124
+ <Endereco>
1125
+ <Pais>{$this->compradorPais}</Pais>
1126
+ <Cep>{$this->compradorCep}</Cep>
1127
+ <Rua>{$this->xmlentities($this->compradorRua)}</Rua>
1128
+ <Numero>{$this->compradorNumero}</Numero>
1129
+ <Complemento>{$this->xmlentities($this->compradorComplemento)}</Complemento>
1130
+ <Bairro>{$this->xmlentities($this->compradorBairro)}</Bairro>
1131
+ <Cidade>{$this->xmlentities($this->compradorCidade)}</Cidade>
1132
+ <Estado>{$this->compradorEstado}</Estado>
1133
+ </Endereco>
1134
+ <CpfCnpj>{$this->compradorCpfCnpj}</CpfCnpj>
1135
+ <DddTelefone>{$this->compradorDddTelefone1}</DddTelefone>
1136
+ <NumeroTelefone>{$this->compradorTelefone1}</NumeroTelefone>
1137
+ <DddCelular>{$this->compradorDddCelular}</DddCelular>
1138
+ <NumeroCelular>{$this->compradorCelular}</NumeroCelular>
1139
+ <IP>{$this->compradorIp}</IP>
1140
+ <Email>{$this->compradorEmail}</Email>
1141
+ <Senha>{$this->compradorSenha}</Senha>
1142
+ <Sexo>{$this->compradorSexo}</Sexo>
1143
+ <DddTelefone2>{$this->compradorDddTelefone2}</DddTelefone2>
1144
+ <NumeroTelefone2>{$this->compradorTelefone2}</NumeroTelefone2>
1145
+ <DataNascimento>{$this->compradorDataNascimento}</DataNascimento>
1146
+ </DadosComprador>
1147
+ <DadosEntrega>
1148
+ <Endereco>
1149
+ <Pais>{$this->entregaPais}</Pais>
1150
+ <Cep>{$this->entregaCep}</Cep>
1151
+ <Rua>{$this->xmlentities($this->entregaRua)}</Rua>
1152
+ <Numero>{$this->entregaNumero}</Numero>
1153
+ <Complemento>{$this->xmlentities($this->entregaComplemento)}</Complemento>
1154
+ <Bairro>{$this->xmlentities($this->entregaBairro)}</Bairro>
1155
+ <Cidade>{$this->xmlentities($this->entregaCidade)}</Cidade>
1156
+ <Estado>{$this->entregaEstado}</Estado>
1157
+ </Endereco>
1158
+ <DddTelefone>{$this->entregaDddTelefone1}</DddTelefone>
1159
+ <NumeroTelefone>{$this->entregaTelefone1}</NumeroTelefone>
1160
+ <NomeEntrega>{$this->entregaNome}</NomeEntrega>
1161
+ <DddCelular>{$this->entregaDddCelular}</DddCelular>
1162
+ <NumeroCelular>{$this->entregaCelular}</NumeroCelular>
1163
+ <DddTelefone2>{$this->entregaDddTelefone2}</DddTelefone2>
1164
+ <NumeroTelefone2>{$this->entregaTelefone2}</NumeroTelefone2>
1165
+ <CpfCnpj>{$this->entregaCpfCnpj}</CpfCnpj>
1166
+ <Sexo>{$this->entregaSexo}</Sexo>
1167
+ <DataNascimento>{$this->entregaDataNascimento}</DataNascimento>
1168
+ <Email>{$this->entregaEmail}</Email>
1169
+ </DadosEntrega>
1170
+ <Pagamentos>
1171
+ <WsPagamento>
1172
+ <MetodoPagamento>{$this->metodoPagamento}</MetodoPagamento>
1173
+ <Cartao>
1174
+ <NomeBancoEmissor>{$this->nomeBancoEmissor}</NomeBancoEmissor>
1175
+ <NumeroCartao>{$this->numeroCartao}</NumeroCartao>
1176
+ <DataValidadeCartao>{$this->dataValidadeCartao}</DataValidadeCartao>
1177
+ <NomeTitularCartao>{$this->nomeTitularCartao}</NomeTitularCartao>
1178
+ <CpfTitularCartao>{$this->cpfTitularCartao}</CpfTitularCartao>
1179
+ <Bin>{$this->bin}</Bin>
1180
+ <quatroUltimosDigitosCartao>{$this->quatroUltimosDigitosCartao}</quatroUltimosDigitosCartao>
1181
+ <Bin_payment>{$this->bin2}</Bin_payment>
1182
+ <BinBanco>{$this->binBanco}</BinBanco>
1183
+ <BinPais>{$this->binPais}</BinPais>
1184
+ <DddTelefone2>{$this->pagadorDddTelefone}</DddTelefone2>
1185
+ <NumeroTelefone2>{$this->pagadorTelefone}</NumeroTelefone2>
1186
+ </Cartao>
1187
+ <Valor>{$this->format($this->valorPedido)}</Valor>
1188
+ <NumeroParcelas>{$this->numeroParcelas}</NumeroParcelas>
1189
+ </WsPagamento>
1190
+ </Pagamentos>
1191
+ <CodigoPedido>{$this->codigoPedido}</CodigoPedido>
1192
+ <DataCompra>{$this->dataCompra}</DataCompra>
1193
+ <QuantidadeItensDistintos>{$this->itensDistintos}</QuantidadeItensDistintos>
1194
+ <QuantidadeTotalItens>{$this->itensTotal}</QuantidadeTotalItens>
1195
+ <ValorTotalCompra>{$this->format($this->valorTotalCompra)}</ValorTotalCompra>
1196
+ <ValorTotalFrete>{$this->format($this->valorTotalFrete)}</ValorTotalFrete>
1197
+ <PedidoDeTeste>false</PedidoDeTeste>
1198
+ <PrazoEntregaDias>{$this->prazoEntrega}</PrazoEntregaDias>
1199
+ <FormaEntrega>{$this->formaEntrega}</FormaEntrega>
1200
+ <Observacao>{$this->observacao}</Observacao>
1201
+ <CanalVenda>{$this->canalVenda}</CanalVenda>
1202
+ <Produtos>
1203
+ EOT;
1204
+ for ($i=0; $i < count($this->produtoCodigo); $i++ ) {
1205
+ $xml .= "
1206
+ <WsProduto3>
1207
+ <Codigo>{$this->produtoCodigo[$i]}</Codigo>
1208
+ <Descricao>{$this->produtoDescricao[$i]}</Descricao>
1209
+ <Quantidade>{$this->produtoQtde[$i]}</Quantidade>
1210
+ <ValorUnitario>{$this->format($this->produtoValor[$i])}</ValorUnitario>
1211
+ <Categoria>{$this->produtoCategoria[$i]}</Categoria>
1212
+ <ListaDeCasamento>{$this->produtoListaCasamento[$i]}</ListaDeCasamento>
1213
+ <ParaPresente>{$this->produtoParaPresente[$i]}</ParaPresente>
1214
+ </WsProduto3>";
1215
+ }
1216
+
1217
+ $xml .= "\n";
1218
+
1219
+ $xml .= <<<EOT
1220
+ </Produtos>
1221
+ <DadosExtra>
1222
+ <Extra1>{$this->extra1}</Extra1>
1223
+ <Extra2>{$this->extra2}</Extra2>
1224
+ <Extra3>{$this->extra3}</Extra3>
1225
+ <Extra4>{$this->extra4}</Extra4>
1226
+ </DadosExtra>
1227
+ </pedido>
1228
+ </enfileirarTransacao3>
1229
+ EOT;
1230
+
1231
+ $client = new nusoap_client($this->_wsdl, true);
1232
+
1233
+ $client->soap_defencoding = 'ISO-8859-1';
1234
+
1235
+ $result = $client->call('enfileirarTransacao3', $xml);
1236
+
1237
+ return $result;
1238
+ }
1239
+
1240
+ public function alterarStatus()
1241
+ {
1242
+ $data = array(
1243
+ 'login' => $this->usuario,
1244
+ 'senha' => $this->senha,
1245
+ 'codigoPedido' => $this->codigoPedido,
1246
+ 'status' => $this->status,
1247
+ 'comentario' => $this->comentario,
1248
+ 'compartilharComentario' => $this->compartilharComentario
1249
+ );
1250
+
1251
+ $client = new Zend_Soap_Client($this->_wsdl,
1252
+ array(
1253
+ 'soap_version' => SOAP_1_1,
1254
+ 'encoding' => 'ISO-8859-1'
1255
+ )
1256
+ );
1257
+
1258
+ $result = $client->alterarStatus($data);
1259
+
1260
+ return $result;
1261
+ }
1262
+
1263
+ public function capturarResultados()
1264
+ {
1265
+ $data = array(
1266
+ 'login' => $this->usuario,
1267
+ 'senha' => $this->senha
1268
+ );
1269
+
1270
+ $client = new Zend_Soap_Client($this->_wsdl,
1271
+ array(
1272
+ 'soap_version' => SOAP_1_1,
1273
+ 'encoding' => 'ISO-8859-1'
1274
+ )
1275
+ );
1276
+
1277
+ $result = $client->capturarResultadosGeral2($data);
1278
+
1279
+ return $result->capturarResultadosGeral2Result->WsAnalise2;
1280
+ }
1281
+
1282
+ public function confirmarRetorno($pedido)
1283
+ {
1284
+ $data = array(
1285
+ 'login' => $this->usuario,
1286
+ 'senha' => $this->senha,
1287
+ 'codigoPedido' => $pedido
1288
+ );
1289
+
1290
+ $client = new Zend_Soap_Client($this->_wsdl,
1291
+ array(
1292
+ 'soap_version' => SOAP_1_1,
1293
+ 'encoding' => 'ISO-8859-1'
1294
+ )
1295
+ );
1296
+
1297
+ $result = $client->confirmarRetorno($data);
1298
+
1299
+ return $result;
1300
+ }
1301
+
1302
+ protected function xmlentities($text)
1303
+ {
1304
+ $text = str_replace("&","&#38;#38;",$text);
1305
+ return $text;
1306
+ }
1307
+
1308
+ protected function format($currency)
1309
+ {
1310
+ return (float) $currency*100;
1311
+ }
1312
+
1313
+ public function getUser()
1314
+ {
1315
+ if (!$this->hasData('fcontrol_user')) {
1316
+ $this->setData('fcontrol_user', Mage::getStoreConfig('sales/fcontrol/user', $this->getStoreId()));
1317
+ }
1318
+ return $this->getData('fcontrol_user');
1319
+ }
1320
+
1321
+ public function getPassword()
1322
+ {
1323
+ if (!$this->hasData('fcontrol_password')) {
1324
+ $this->setData('fcontrol_password', Mage::getStoreConfig('sales/fcontrol/password', $this->getStoreId()));
1325
+ }
1326
+ return $this->getData('fcontrol_password');
1327
+ }
1328
+
1329
+ public function getTypeService()
1330
+ {
1331
+ if (!$this->hasData('fcontrol_type_service')) {
1332
+ $this->setData('fcontrol_type_service', Mage::getStoreConfig('sales/fcontrol/type_service', $this->getStoreId()));
1333
+ }
1334
+ return $this->getData('fcontrol_type_service');
1335
+ }
1336
+
1337
+ public function getNow()
1338
+ {
1339
+ return Mage::getSingleton('core/date')->date('Y-m-d H:i:s');
1340
+ }
1341
+
1342
+ public function getCountry($country_name = null)
1343
+ {
1344
+ if(is_null($country_name)) {
1345
+ $countryId = Mage::getStoreConfig('general/country/default');
1346
+
1347
+ $countryList = Mage::getModel('directory/country')->getResourceCollection()->getData();
1348
+
1349
+ foreach($countryList as $item) {
1350
+ if($item['country_id'] == $countryId) {
1351
+ $country_name = $item['iso3_code'];
1352
+ }
1353
+ }
1354
+ }
1355
+
1356
+ return $country_name;
1357
+ }
1358
+ }
app/code/community/Buscape/Fcontrol/Model/Config.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
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 suporte.developer@buscape-inc.com so we can send you a copy immediately.
14
+ *
15
+ * @category Buscape
16
+ * @package Buscape_Fcontrol
17
+ * @copyright Copyright (c) 2010 Buscapé Company (http://www.buscapecompany.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Buscape_Fcontrol_Model_Config extends Varien_Object
22
+ {
23
+ const XML_PATH = 'sales/fcontrol/';
24
+
25
+ const XML_PATH_ACTIVE = 'sales/fcontrol/active';
26
+
27
+ const XML_PATH_ACCOUNT = 'sales/fcontrol/account';
28
+
29
+ protected $_config = array();
30
+
31
+ public function getConfigData($key, $storeId = null)
32
+ {
33
+ if (!isset($this->_config[$key][$storeId])) {
34
+ $value = Mage::getStoreConfig(self::XML_PATH . $key, $storeId);
35
+ $this->_config[$key][$storeId] = $value;
36
+ }
37
+ return $this->_config[$key][$storeId];
38
+ }
39
+
40
+ public function getAccount($store = null)
41
+ {
42
+ if (!$this->hasData('fcontrol_account')) {
43
+ $this->setData('fcontrol_account', $this->getConfigData('account', $storeId));
44
+ }
45
+
46
+ return $this->getData('fcontrol_account');
47
+ }
48
+ }
app/code/community/Buscape/Fcontrol/Model/Observer.php ADDED
@@ -0,0 +1,336 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
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 suporte.developer@buscape-inc.com so we can send you a copy immediately.
14
+ *
15
+ * @category Buscape
16
+ * @package Buscape_Fcontrol
17
+ * @copyright Copyright (c) 2010 Buscapé Company (http://www.buscapecompany.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Buscape_Fcontrol_Model_Observer
22
+ {
23
+
24
+ public function controllerFrontInitBefore($observer)
25
+ {
26
+ if((bool) Mage::helper('fcontrol')->moduleActive()) return;
27
+
28
+ if (version_compare(Mage::getVersion(), '1.3.0', '>'))
29
+ {
30
+ $path = array('customer/address/dob_show', 'customer/address/taxvat_show');
31
+
32
+ $address = Mage::getModel('core/config_data')
33
+ ->getCollection()
34
+ ->addPathFilter('customer/address')
35
+ ->load();
36
+
37
+ /*if(count($address->getData()) <= 1) {
38
+ if(count($address->getData()) == 1) {
39
+
40
+ $result = $address->getData();
41
+
42
+ if(($result[0]['value'] != 'req') && (in_array($result[0]['path'], $path))) {
43
+ $data = Mage::getModel('core/config_data')->load($result[0]['config_id']);
44
+
45
+ $data->setValue('req')->save();
46
+ } else {
47
+ print_r($result);
48
+ }
49
+
50
+ } else {
51
+
52
+ Mage::getModel('core/config_data')->setPath("customer/address/dob_show")
53
+ ->setValue('req')
54
+ ->save();
55
+
56
+ Mage::getModel('core/config_data')->setPath("customer/address/taxvat_show")
57
+ ->setValue('req')
58
+ ->save();
59
+ }
60
+ } else {
61
+
62
+ }*/
63
+ }
64
+
65
+ //exit;
66
+ }
67
+
68
+ /**
69
+ * Get list of datas of orders
70
+ *
71
+ * @return string
72
+ */
73
+ public static function frameOrder($observer)
74
+ {
75
+ $order = Mage::getModel('sales/order')->loadByIncrementId($observer->getOrder()->getIncrementId());
76
+
77
+ $api = Mage::getModel('fcontrol/api');
78
+
79
+ $api->preparaTransacao($order);
80
+
81
+ $api->analisaFrame();
82
+ }
83
+
84
+ /**
85
+ * Get list of datas of orders
86
+ *
87
+ * @return string
88
+ */
89
+ public static function checkStatusFrame()
90
+ {
91
+ if(intval(Mage::helper('fcontrol')->getConfig('type_service')) === Buscape_Fcontrol_Model_Api::FRAME) {
92
+
93
+ try
94
+ {
95
+ $quotes = Mage::getModel('sales/order')->getCollection();
96
+
97
+ $quotes->addAttributeToFilter('state',
98
+ array('in' =>
99
+ array(
100
+ Mage_Sales_Model_Order::STATE_COMPLETE,
101
+ Mage_Sales_Model_Order::STATE_CLOSED,
102
+ Mage_Sales_Model_Order::STATE_CANCELED
103
+ )
104
+ ));
105
+
106
+ $quotes->load();
107
+
108
+ foreach($quotes as $quote)
109
+ {
110
+ $api = Mage::getModel('fcontrol/api');
111
+
112
+ $api->codigoPedido = intval($quote->getIncrementId());
113
+
114
+ switch($api->getState())
115
+ {
116
+ case Mage_Sales_Model_Order::STATE_COMPLETE:
117
+ $api->status = Buscape_Fcontrol_Model_Api::STATUS_ENVIADO;
118
+ $api->comentario = "Status do pedido atualizado para 'completo' na Loja";
119
+ break;
120
+ case Mage_Sales_Model_Order::STATE_CLOSED:
121
+ $api->status = Buscape_Fcontrol_Model_Api::STATUS_CANCELADO;
122
+ $api->comentario = "Status do pedido atualizado para 'fechado' na Loja";
123
+ break;
124
+ case Mage_Sales_Model_Order::STATE_CANCELED:
125
+ $api->status = Buscape_Fcontrol_Model_Api::STATUS_CANCELADO;
126
+ $api->comentario = "Status do pedido atualizado para 'cancelado' na Loja";
127
+ break;
128
+ }
129
+
130
+ $api->alterarStatus();
131
+ }
132
+ } catch(Mage_Core_Exception $e) {
133
+
134
+ }
135
+ }
136
+ }
137
+
138
+ /**
139
+ * Get list of datas of orders
140
+ *
141
+ * @return this
142
+ */
143
+ public static function queueListOrder()
144
+ {
145
+ $quotes = Mage::getModel('sales/order')->getCollection();
146
+
147
+ $quotes->addAttributeToFilter('state', Mage_Sales_Model_Order::STATE_NEW);
148
+ $quotes->load();
149
+
150
+ foreach($quotes as $quote)
151
+ {
152
+
153
+ self::queueOrder($quote);
154
+ }
155
+
156
+ return $this;
157
+ }
158
+
159
+ /**
160
+ * Get queue of datas of orders
161
+ *
162
+ * @return string
163
+ */
164
+ public static function queueOrder($observer, $analyse = false)
165
+ {
166
+ try
167
+ {
168
+ $order = Mage::getModel('sales/order')->loadByIncrementId($observer->getIncrementId());
169
+
170
+ $api = Mage::getModel('fcontrol/api');
171
+
172
+ $api->preparaTransacao($order);
173
+
174
+ if($analyse) {
175
+ return $api->analisarTransacao(); // not used still
176
+ } else {
177
+ return $api->enfileirarTransacao();
178
+ }
179
+ } catch(Mage_Core_Exception $e) {
180
+
181
+ }
182
+ }
183
+
184
+ /**
185
+ * Get list of datas of orders
186
+ *
187
+ * @return string
188
+ */
189
+ public static function captureList($observer)
190
+ {
191
+ try {
192
+ $api = Mage::getModel('fcontrol/api');
193
+
194
+ $data = $api->capturarResultados();
195
+
196
+ return $data;
197
+
198
+ } catch(Mage_Core_Exception $e) {
199
+ return false;
200
+ }
201
+ }
202
+
203
+ /**
204
+ * Get capture of orders
205
+ *
206
+ * @return string
207
+ */
208
+ public static function captureOrder($observer)
209
+ {
210
+ try
211
+ {
212
+ $data = self::captureList();
213
+
214
+ $api = Mage::getModel('fcontrol/api');
215
+
216
+ if(sizeof($data) == 1) {
217
+
218
+ $data = array($data);
219
+ }
220
+
221
+ if (is_array($data) && sizeof($data) > 0)
222
+ {
223
+ $max = count($data);
224
+
225
+ for($i = 0; $i < $max; $i++)
226
+ {
227
+
228
+ if (isset($data[$i]->CodigoCompra) && is_numeric($data[$i]->CodigoCompra)) {
229
+
230
+ $status = $data[$i]->Status;
231
+
232
+ $order_id = $data[$i]->CodigoCompra;
233
+
234
+ $order = Mage::getModel('sales/order');
235
+
236
+ $order->loadByIncrementId($order_id);
237
+
238
+ if($order->getId()) {
239
+
240
+ switch($order->getState()) {
241
+ case Mage_Sales_Model_Order::STATE_NEW:
242
+
243
+ try {
244
+
245
+ if(in_array($status, Buscape_Fcontrol_Model_Api::$acaoAprovar)) {
246
+
247
+ $orderState = Mage_Sales_Model_Order::STATE_PENDING_PAYMENT;
248
+
249
+ $orderStatus = $order->getConfig()->getStateDefaultStatus($orderState);
250
+
251
+ $comment = Mage::helper('fcontrol')->__('Pedido com Pagamento Pendente.');
252
+
253
+ $order->setState($orderState, $orderStatus, $comment, $notified = true);
254
+
255
+ $order->save();
256
+
257
+ $api->confirmarRetorno($order_id);
258
+ }
259
+
260
+ if(in_array($status, Buscape_Fcontrol_Model_Api::$acaoCancelar)) {
261
+ if($order->canCancel()) {
262
+
263
+ $order->cancel()->save();
264
+
265
+ $api->confirmarRetorno($order_id);
266
+ }
267
+ }
268
+
269
+ } catch(Mage_Core_Exception $e) {
270
+ // implement log
271
+ }
272
+ break;
273
+ case Mage_Sales_Model_Order::STATE_PENDING_PAYMENT:
274
+
275
+ $api->codigoPedido = $order_id;
276
+ $api->status = Buscape_Fcontrol_Model_Api::STATUS_ENVIADO;
277
+ $api->comentario = "Status do pedido atualizado para 'pagamento pendente' na Loja";
278
+
279
+ $api->alterarStatus();
280
+ $api->confirmarRetorno($order_id);
281
+ break;
282
+ case Mage_Sales_Model_Order::STATE_PROCESSING:
283
+
284
+ $api->codigoPedido = $order_id;
285
+ $api->status = Buscape_Fcontrol_Model_Api::STATUS_ENVIADO;
286
+ $api->comentario = "Status do pedido atualizado para 'processando' na Loja";
287
+
288
+ $api->alterarStatus();
289
+ $api->confirmarRetorno($order_id);
290
+ break;
291
+ case Mage_Sales_Model_Order::STATE_COMPLETE:
292
+
293
+ $api->codigoPedido = $order_id;
294
+ $api->status = Buscape_Fcontrol_Model_Api::STATUS_ENVIADO;
295
+ $api->comentario = "Status do pedido atualizado para 'completo' na Loja";
296
+
297
+ $api->alterarStatus();
298
+ $api->confirmarRetorno($order_id);
299
+ break;
300
+ case Mage_Sales_Model_Order::STATE_CLOSED:
301
+
302
+ $api->codigoPedido = $order_id;
303
+ $api->status = Buscape_Fcontrol_Model_Api::STATUS_CANCELADO;
304
+ $api->comentario = "Status do pedido atualizado para 'fechado' na Loja";
305
+
306
+ $api->alterarStatus();
307
+ $api->confirmarRetorno($order_id);
308
+ break;
309
+ case Mage_Sales_Model_Order::STATE_CANCELED:
310
+
311
+ $api->codigoPedido = $order_id;
312
+ $api->status = Buscape_Fcontrol_Model_Api::STATUS_CANCELADO;
313
+ $api->comentario = "Pedido atualizado para 'cancelado' na Loja";
314
+
315
+ $api->alterarStatus();
316
+ $api->confirmarRetorno($order_id);
317
+ break;
318
+ case Mage_Sales_Model_Order::STATE_HOLDED:
319
+
320
+ $api->codigoPedido = $order_id;
321
+ $api->status = Buscape_Fcontrol_Model_Api::STATUS_SOLICITADA_SUPERVISAO;
322
+ $api->comentario = "Pedido atualizado para 'segurar' na Loja";
323
+
324
+ $api->alterarStatus();
325
+ $api->confirmarRetorno($order_id);
326
+ break;
327
+ }
328
+ }
329
+ }
330
+ }
331
+ }
332
+ } catch(Mage_Core_Exception $e) {
333
+ // implement log
334
+ }
335
+ }
336
+ }
app/code/community/Buscape/Fcontrol/Model/Source/Service.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
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 suporte.developer@buscape-inc.com so we can send you a copy immediately.
14
+ *
15
+ * @category Buscape
16
+ * @package Buscape_Fcontrol
17
+ * @copyright Copyright (c) 2010 Buscapé Company (http://www.buscapecompany.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Buscape_Fcontrol_Model_Source_Service
22
+ {
23
+ public function toOptionArray()
24
+ {
25
+ return array(
26
+ array('value' => 1, 'label' => '[ Frame ] Padrão'),
27
+ array('value' => 2, 'label' => '[ Modelo de Filas ] Análise lojista único'),
28
+ //array('value' => 3, 'label' => '[ Modelo de Filas ] Análise lojista único para Análise de Risco na venda de Passagens'),
29
+ //array('value' => 4, 'label' => '[ Modelo de Filas ] Análise vários lojistas'),
30
+ //array('value' => 5, 'label' => '[ Modelo Recarda ] WebService')
31
+ );
32
+ }
33
+ }
app/code/community/Buscape/Fcontrol/controllers/Adminhtml/Sales/OrderController.php ADDED
@@ -0,0 +1,190 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
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 suporte.developer@buscape-inc.com so we can send you a copy immediately.
14
+ *
15
+ * @category Buscape
16
+ * @package Buscape_Fcontrol
17
+ * @copyright Copyright (c) 2010 Buscapé Company (http://www.buscapecompany.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ include_once("Mage/Adminhtml/controllers/Sales/OrderController.php");
22
+
23
+ class Buscape_Fcontrol_Adminhtml_Sales_OrderController extends Mage_Adminhtml_Sales_OrderController
24
+ {
25
+
26
+ const BLOCK_SALES_ORDER_FRAME = 'Buscape_Fcontrol_Block_Adminhtml_Sales_Order_View_Info';
27
+
28
+ public function viewAction()
29
+ {
30
+ if(version_compare(Mage::getVersion(), '1.4.0', '>'))
31
+ {
32
+ $this->_title($this->__('Sales'))->_title($this->__('Orders'));
33
+ }
34
+
35
+ if($order = $this->_initOrder()) {
36
+
37
+ $this->_initAction();
38
+
39
+ if(version_compare(Mage::getVersion(), '1.4.0', '>'))
40
+ {
41
+ $this->_title(sprintf("#%s", $order->getRealOrderId()));
42
+ }
43
+
44
+ switch(Mage::helper('fcontrol')->getConfig('type_service')) {
45
+ case Buscape_Fcontrol_Model_Api::FRAME:
46
+ $block = $this->getLayout()->createBlock(
47
+ self::BLOCK_SALES_ORDER_FRAME,
48
+ 'fcontrol.sales.order.view.info',
49
+ array(
50
+ 'template' => 'buscape/fcontrol/sales/order/view/info.phtml',
51
+ 'before' => '-'
52
+ )
53
+ );
54
+
55
+ $this->getLayout()->getBlock('content')->insert($block);
56
+ break;
57
+ case Buscape_Fcontrol_Model_Api::FILA_LOJISTA_UNICO:
58
+ case Buscape_Fcontrol_Model_Api::FILA_LOJISTA_PASSAGENS:
59
+ case Buscape_Fcontrol_Model_Api::FILA_VARIOS_LOJISTAS:
60
+ if($order->getId()) {
61
+ Mage::getModel('fcontrol/observer')->queueOrder($order);
62
+ }
63
+ break;
64
+ }
65
+
66
+ $this->renderLayout();
67
+ }
68
+ }
69
+
70
+ public function sendlistAction()
71
+ {
72
+ if($orderList = $this->getRequest()->getPost('order_ids')) {
73
+
74
+ try
75
+ {
76
+ foreach($orderList as $orderId)
77
+ {
78
+ $order = Mage::getModel('sales/order')->load($orderId);
79
+
80
+ if(Mage_Sales_Model_Order::STATE_NEW === $order->getState()) {
81
+
82
+ Mage::getModel('fcontrol/observer')->queueOrder($order);
83
+
84
+ $this->_getSession()->addSuccess($this->__('Pedido(s) enviado(s) para o FControl.'));
85
+ } else {
86
+ $this->_getSession()->addNotice($this->__('Enviado somente o(s) novo(s) pedidos.'));
87
+ }
88
+ }
89
+ } catch(Mage_Core_Exception $e) {
90
+ $this->_getSession()->addError($this->__('Não foi possível enviar o(s) Pedido(s) para o FControl.'));
91
+ }
92
+ }
93
+
94
+ $this->_redirect('*/*/');
95
+ }
96
+
97
+ public function capturelistAction()
98
+ {
99
+ // return frame;
100
+
101
+ $data = array();
102
+
103
+ $count = (!is_null($this->_getSession()->getCountCaptureList())) ? $this->_getSession()->getCountCaptureList() : 0;
104
+
105
+ $count += 1;
106
+
107
+ $this->_getSession()->setCountCaptureList($count);
108
+
109
+ if($count == 1) {
110
+ $data[$count] = Mage::getSingleton('core/date')->date('Y-m-d H:i:s');
111
+ $this->_getSession()->setCaptureList($data);
112
+
113
+ } elseif($count >= 2) {
114
+
115
+ $anterior = $this->_getSession()->getCaptureList();
116
+
117
+ $diff = abs(strtotime(Mage::getSingleton('core/date')->date('Y-m-d H:i:s')) - strtotime($anterior[1]));
118
+
119
+ $years = floor($diff / (365*60*60*24));
120
+
121
+ $months = floor(($diff - $years * 365*60*60*24) / (30*60*60*24));
122
+
123
+ $days = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24)/ (60*60*24));
124
+
125
+ $hours = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24 - $days*60*60*24)/ (60*60));
126
+
127
+ $minuts = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24 - $days*60*60*24 - $hours*60*60)/ 60);
128
+
129
+ $seconds = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24 - $days*60*60*24 - $hours*60*60 - $minuts*60));
130
+
131
+ if($minuts <= 4) {
132
+ $this->_getSession()->addNotice($this->__('Aguarde alguns instantes para a próxima sincronização com o FControl.'));
133
+ return $this->_redirect('*/*/');
134
+ } else {
135
+ $this->_getSession()->setCountCaptureList(null);
136
+ $this->_getSession()->setCaptureList(null);
137
+ }
138
+ }
139
+
140
+ try
141
+ {
142
+ $list = Mage::getModel('fcontrol/observer')->captureList();
143
+
144
+ if($list) {
145
+
146
+ Mage::getModel('fcontrol/observer')->captureOrder($list);
147
+
148
+ $this->_getSession()->addSuccess($this->__('Sincronização com o FControl foi realizada.'));
149
+
150
+ $this->_getSession()->setCountCaptureList(null);
151
+ $this->_getSession()->setCaptureList(null);
152
+ }
153
+ } catch(Mage_Core_Exception $e) {
154
+ $this->_getSession()->addError($this->__('Não foi possível sincronizar com o FControl.'));
155
+
156
+ $this->_getSession()->setCountCaptureList(null);
157
+ $this->_getSession()->setCaptureList(null);
158
+ }
159
+
160
+ $this->_redirect('*/*/');
161
+ }
162
+
163
+ /**
164
+ * Acl check for admin
165
+ *
166
+ * @return bool
167
+ */
168
+ protected function _isAllowed()
169
+ {
170
+ parent::_isAllowed();
171
+
172
+ $action = strtolower($this->getRequest()->getActionName());
173
+
174
+ switch ($action) {
175
+ case 'sendlist':
176
+ $aclResource = 'sales/order/actions/sendlist';
177
+
178
+ return Mage::getSingleton('admin/session')->isAllowed($aclResource);
179
+ break;
180
+ case 'capturelist':
181
+ $aclResource = 'sales/order/actions/capturelist';
182
+
183
+ return Mage::getSingleton('admin/session')->isAllowed($aclResource);
184
+ break;
185
+ default:
186
+ return Mage::getSingleton('admin/session')->isAllowed('sales/order/');
187
+ break;
188
+ }
189
+ }
190
+ }
app/code/community/Buscape/Fcontrol/etc/config.xml ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * Magento
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 suporte.developer@buscape-inc.com so we can send you a copy immediately.
15
+ *
16
+ * @category Buscape
17
+ * @package Buscape_Fcontrol
18
+ * @copyright Copyright (c) 2010 Buscapé Company (http://www.buscapecompany.com)
19
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
+ */
21
+ -->
22
+ <config>
23
+ <modules>
24
+ <Buscape_Fcontrol>
25
+ <version>0.1.0</version>
26
+ </Buscape_Fcontrol>
27
+ </modules>
28
+ <global>
29
+ <blocks>
30
+ <fcontrol>
31
+ <class>Buscape_Fcontrol_Block</class>
32
+ </fcontrol>
33
+ <adminhtml>
34
+ <rewrite>
35
+ <sales_order>Buscape_Fcontrol_Block_Adminhtml_Sales_Order</sales_order>
36
+ <sales_order_grid>Buscape_Fcontrol_Block_Adminhtml_Sales_Order_Grid</sales_order_grid>
37
+ <sales_order_view_info>Buscape_Fcontrol_Block_Adminhtml_Sales_Order_View_Info</sales_order_view_info>
38
+ </rewrite>
39
+ </adminhtml>
40
+ </blocks>
41
+ <models>
42
+ <fcontrol>
43
+ <class>Buscape_Fcontrol_Model</class>
44
+ </fcontrol>
45
+ </models>
46
+ <helpers>
47
+ <fcontrol>
48
+ <class>Buscape_Fcontrol_Helper</class>
49
+ </fcontrol>
50
+ </helpers>
51
+ <events>
52
+ <controller_front_init_before>
53
+ <observers>
54
+ <fcontrol>
55
+ <type>singleton</type>
56
+ <class>fcontrol/observer</class>
57
+ <method>controllerFrontInitBefore</method>
58
+ </fcontrol>
59
+ </observers>
60
+ </controller_front_init_before>
61
+ </events>
62
+ </global>
63
+ <frontend>
64
+ <routers>
65
+ <fcontrol>
66
+ <use>standard</use>
67
+ <args>
68
+ <module>Buscape_Fcontrol</module>
69
+ <frontName>fcontrol</frontName>
70
+ </args>
71
+ </fcontrol>
72
+ </routers>
73
+ <events>
74
+ <sales_order_save_analyse_transaction>
75
+ <observers>
76
+ <fcontrol_observer>
77
+ <class>fcontrol/observer</class>
78
+ <method>queueOrder</method>
79
+ </fcontrol_observer>
80
+ </observers>
81
+ </sales_order_save_analyse_transaction>
82
+ <sales_order_save_queue_transaction>
83
+ <observers>
84
+ <fcontrol_observer>
85
+ <class>fcontrol/observer</class>
86
+ <method>queueOrder</method>
87
+ </fcontrol_observer>
88
+ </observers>
89
+ </sales_order_save_queue_transaction>
90
+ <sales_order_save_change_status>
91
+ <observers>
92
+ <fcontrol_observer>
93
+ <class>fcontrol/observer</class>
94
+ <method>changeStatusOrder</method>
95
+ </fcontrol_observer>
96
+ </observers>
97
+ </sales_order_save_change_status>
98
+ <sales_order_save_capture_results>
99
+ <observers>
100
+ <fcontrol_observer>
101
+ <class>fcontrol/observer</class>
102
+ <method>captureOrder</method>
103
+ </fcontrol_observer>
104
+ </observers>
105
+ </sales_order_save_capture_results>
106
+ <sales_order_save_confirmed_return>
107
+ <observers>
108
+ <fcontrol_observer>
109
+ <class>fcontrol/observer</class>
110
+ <method>queueOrder</method>
111
+ </fcontrol_observer>
112
+ </observers>
113
+ </sales_order_save_confirmed_return>
114
+ </events>
115
+ </frontend>
116
+ <crontab>
117
+ <jobs>
118
+ <fcontrol_observer_capture_results>
119
+ <schedule><cron_expr>*/15 * * * *</cron_expr></schedule>
120
+ <run><model>fcontrol/observer::captureOrder</model></run>
121
+ </fcontrol_observer_capture_results>
122
+ <fcontrol_observer_queue_transaction>
123
+ <schedule><cron_expr>*/10 * * * *</cron_expr></schedule>
124
+ <run><model>fcontrol/observer::queueListOrder</model></run>
125
+ </fcontrol_observer_queue_transaction>
126
+ <fcontrol_observer_check_status>
127
+ <schedule><cron_expr>0 0 * * *</cron_expr></schedule>
128
+ <run><model>fcontrol/observer::checkStatusFrame</model></run>
129
+ </fcontrol_observer_check_status>
130
+ </jobs>
131
+ </crontab>
132
+ <admin>
133
+ <routers>
134
+ <fcontrol>
135
+ <use>admin</use>
136
+ <args>
137
+ <module>Buscape_Fcontrol_Adminhtml</module>
138
+ <frontName>fcontrol</frontName>
139
+ </args>
140
+ </fcontrol>
141
+ <adminhtml>
142
+ <args>
143
+ <modules>
144
+ <Buscape_Fcontrol before="Mage_Adminhtml">Buscape_Fcontrol_Adminhtml</Buscape_Fcontrol>
145
+ </modules>
146
+ </args>
147
+ </adminhtml>
148
+ </routers>
149
+ </admin>
150
+ </config>
app/code/community/Buscape/Fcontrol/etc/system.xml ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * Magento
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 suporte.developer@buscape-inc.com so we can send you a copy immediately.
15
+ *
16
+ * @category Buscape
17
+ * @package Buscape_Fcontrol
18
+ * @copyright Copyright (c) 2010 Buscapé Company (http://www.buscapecompany.com)
19
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
+ */
21
+ -->
22
+ <config>
23
+ <sections>
24
+ <sales translate="label" module="fcontrol">
25
+ <groups>
26
+ <fcontrol translate="label">
27
+ <label>BuscaPé FControl</label>
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
+ <comment>
33
+ <![CDATA[
34
+ <div style="padding:10px;background-color:#fff;border:1px solid #ddd;margin-bottom:7px;">
35
+ Este módulo foi desenvolvido pelo <a href="http://developer.buscape.com" target="_blank">BuscaPé Developer</a>.
36
+ Por favor reportar bugs para <a href="mailto:suporte.developer@buscape-inc.com">suporte.developer@buscape-inc.com</a>.
37
+ </div>
38
+ ]]>
39
+ </comment>
40
+ <fields>
41
+ <active translate="label">
42
+ <label>Enable</label>
43
+ <frontend_type>select</frontend_type>
44
+ <source_model>adminhtml/system_config_source_yesno</source_model>
45
+ <sort_order>5</sort_order>
46
+ <show_in_default>1</show_in_default>
47
+ <show_in_website>1</show_in_website>
48
+ <show_in_store>1</show_in_store>
49
+ </active>
50
+ <user translate="label">
51
+ <label>Nome do usuário</label>
52
+ <frontend_type>text</frontend_type>
53
+ <sort_order>10</sort_order>
54
+ <show_in_default>1</show_in_default>
55
+ <show_in_website>1</show_in_website>
56
+ <show_in_store>1</show_in_store>
57
+ <comment><![CDATA[Login do usuário cadastrado na FControl.]]></comment>
58
+ </user>
59
+ <password translate="label">
60
+ <label>Senha do usuário</label>
61
+ <frontend_type>password</frontend_type>
62
+ <sort_order>15</sort_order>
63
+ <show_in_default>1</show_in_default>
64
+ <show_in_website>1</show_in_website>
65
+ <show_in_store>1</show_in_store>
66
+ <comment><![CDATA[Senha do usuário cadastrado na FControl.]]></comment>
67
+ </password>
68
+ <type_service translate="label">
69
+ <label>Tipo do Serviço</label>
70
+ <frontend_type>select</frontend_type>
71
+ <source_model>fcontrol/source_service</source_model>
72
+ <sort_order>20</sort_order>
73
+ <show_in_default>1</show_in_default>
74
+ <show_in_website>1</show_in_website>
75
+ <show_in_store>1</show_in_store>
76
+ <comment><![CDATA[Selecione o tipo de serviço contratado no FControl.]]></comment>
77
+ </type_service>
78
+ </fields>
79
+ </fcontrol>
80
+ </groups>
81
+ </sales>
82
+ </sections>
83
+ </config>
app/etc/modules/Buscape_Fcontrol.xml ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * Magento
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 suporte.developer@buscape-inc.com so we can send you a copy immediately.
15
+ *
16
+ * @category Buscape
17
+ * @package Buscape_Fcontrol
18
+ * @copyright Copyright (c) 2010 Buscapé Company (http://www.buscapecompany.com)
19
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
+ */
21
+ -->
22
+ <config>
23
+ <modules>
24
+ <Buscape_Fcontrol>
25
+ <active>true</active>
26
+ <codePool>community</codePool>
27
+ </Buscape_Fcontrol>
28
+ </modules>
29
+ </config>
lib/nusoap/nusoap.php ADDED
@@ -0,0 +1,8018 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
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 suporte.developer@buscape-inc.com so we can send you a copy immediately.
14
+ *
15
+ * @category Buscape
16
+ * @package Buscape_Fcontrol
17
+ * @copyright Copyright (c) 2010 Buscapé Company (http://www.buscapecompany.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ /*
22
+ $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $
23
+
24
+ NuSOAP - Web Services Toolkit for PHP
25
+
26
+ Copyright (c) 2002 NuSphere Corporation
27
+
28
+ This library is free software; you can redistribute it and/or
29
+ modify it under the terms of the GNU Lesser General Public
30
+ License as published by the Free Software Foundation; either
31
+ version 2.1 of the License, or (at your option) any later version.
32
+
33
+ This library is distributed in the hope that it will be useful,
34
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
35
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
36
+ Lesser General Public License for more details.
37
+
38
+ You should have received a copy of the GNU Lesser General Public
39
+ License along with this library; if not, write to the Free Software
40
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
41
+
42
+ The NuSOAP project home is:
43
+ http://sourceforge.net/projects/nusoap/
44
+
45
+ The primary support for NuSOAP is the mailing list:
46
+ nusoap-general@lists.sourceforge.net
47
+
48
+ If you have any questions or comments, please email:
49
+
50
+ Dietrich Ayala
51
+ dietrich@ganx4.com
52
+ http://dietrich.ganx4.com/nusoap
53
+
54
+ NuSphere Corporation
55
+ http://www.nusphere.com
56
+
57
+ */
58
+
59
+ /*
60
+ * Some of the standards implmented in whole or part by NuSOAP:
61
+ *
62
+ * SOAP 1.1 (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/)
63
+ * WSDL 1.1 (http://www.w3.org/TR/2001/NOTE-wsdl-20010315)
64
+ * SOAP Messages With Attachments (http://www.w3.org/TR/SOAP-attachments)
65
+ * XML 1.0 (http://www.w3.org/TR/2006/REC-xml-20060816/)
66
+ * Namespaces in XML 1.0 (http://www.w3.org/TR/2006/REC-xml-names-20060816/)
67
+ * XML Schema 1.0 (http://www.w3.org/TR/xmlschema-0/)
68
+ * RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies
69
+ * RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1
70
+ * RFC 2617 HTTP Authentication: Basic and Digest Access Authentication
71
+ */
72
+
73
+ /* load classes
74
+
75
+ // necessary classes
76
+ require_once('class.soapclient.php');
77
+ require_once('class.soap_val.php');
78
+ require_once('class.soap_parser.php');
79
+ require_once('class.soap_fault.php');
80
+
81
+ // transport classes
82
+ require_once('class.soap_transport_http.php');
83
+
84
+ // optional add-on classes
85
+ require_once('class.xmlschema.php');
86
+ require_once('class.wsdl.php');
87
+
88
+ // server class
89
+ require_once('class.soap_server.php');*/
90
+
91
+ // class variable emulation
92
+ // cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
93
+ // $ GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = 9;
94
+
95
+ /**
96
+ *
97
+ * nusoap_base
98
+ *
99
+ * @author Dietrich Ayala <dietrich@ganx4.com>
100
+ * @author Scott Nichol <snichol@users.sourceforge.net>
101
+ * @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $
102
+ * @access public
103
+ */
104
+ class nusoap_base {
105
+
106
+ // class variable emulation
107
+ // cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
108
+
109
+ public static $globalDebugLevel = 9;
110
+
111
+ /**
112
+ * Identification for HTTP headers.
113
+ *
114
+ * @var string
115
+ * @access private
116
+ */
117
+ var $title = 'NuSOAP';
118
+ /**
119
+ * Version for HTTP headers.
120
+ *
121
+ * @var string
122
+ * @access private
123
+ */
124
+ var $version = '0.7.3';
125
+ /**
126
+ * CVS revision for HTTP headers.
127
+ *
128
+ * @var string
129
+ * @access private
130
+ */
131
+ var $revision = '$Revision: 1.114 $';
132
+ /**
133
+ * Current error string (manipulated by getError/setError)
134
+ *
135
+ * @var string
136
+ * @access private
137
+ */
138
+ var $error_str = '';
139
+ /**
140
+ * Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment)
141
+ *
142
+ * @var string
143
+ * @access private
144
+ */
145
+ var $debug_str = '';
146
+ /**
147
+ * toggles automatic encoding of special characters as entities
148
+ * (should always be true, I think)
149
+ *
150
+ * @var boolean
151
+ * @access private
152
+ */
153
+ var $charencoding = true;
154
+ /**
155
+ * the debug level for this instance
156
+ *
157
+ * @var integer
158
+ * @access private
159
+ */
160
+ var $debugLevel;
161
+
162
+ /**
163
+ * set schema version
164
+ *
165
+ * @var string
166
+ * @access public
167
+ */
168
+ var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
169
+
170
+ /**
171
+ * charset encoding for outgoing messages
172
+ *
173
+ * @var string
174
+ * @access public
175
+ */
176
+ var $soap_defencoding = 'ISO-8859-1';
177
+ //var $soap_defencoding = 'UTF-8';
178
+
179
+ /**
180
+ * namespaces in an array of prefix => uri
181
+ *
182
+ * this is "seeded" by a set of constants, but it may be altered by code
183
+ *
184
+ * @var array
185
+ * @access public
186
+ */
187
+ var $namespaces = array(
188
+ 'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
189
+ 'xsd' => 'http://www.w3.org/2001/XMLSchema',
190
+ 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
191
+ 'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
192
+ );
193
+
194
+ /**
195
+ * namespaces used in the current context, e.g. during serialization
196
+ *
197
+ * @var array
198
+ * @access private
199
+ */
200
+ var $usedNamespaces = array();
201
+
202
+ /**
203
+ * XML Schema types in an array of uri => (array of xml type => php type)
204
+ * is this legacy yet?
205
+ * no, this is used by the nusoap_xmlschema class to verify type => namespace mappings.
206
+ * @var array
207
+ * @access public
208
+ */
209
+ var $typemap = array(
210
+ 'http://www.w3.org/2001/XMLSchema' => array(
211
+ 'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
212
+ 'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
213
+ 'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
214
+ // abstract "any" types
215
+ 'anyType'=>'string','anySimpleType'=>'string',
216
+ // derived datatypes
217
+ 'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
218
+ 'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
219
+ 'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
220
+ 'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
221
+ 'http://www.w3.org/2000/10/XMLSchema' => array(
222
+ 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
223
+ 'float'=>'double','dateTime'=>'string',
224
+ 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
225
+ 'http://www.w3.org/1999/XMLSchema' => array(
226
+ 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
227
+ 'float'=>'double','dateTime'=>'string',
228
+ 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
229
+ 'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
230
+ 'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),
231
+ 'http://xml.apache.org/xml-soap' => array('Map')
232
+ );
233
+
234
+ /**
235
+ * XML entities to convert
236
+ *
237
+ * @var array
238
+ * @access public
239
+ * @deprecated
240
+ * @see expandEntities
241
+ */
242
+ var $xmlEntities = array('quot' => '"','amp' => '&',
243
+ 'lt' => '<','gt' => '>','apos' => "'");
244
+
245
+ /**
246
+ * constructor
247
+ *
248
+ * @access public
249
+ */
250
+ function nusoap_base() {
251
+ $this->debugLevel = self::$globalDebugLevel;
252
+ }
253
+
254
+ /**
255
+ * gets the global debug level, which applies to future instances
256
+ *
257
+ * @return integer Debug level 0-9, where 0 turns off
258
+ * @access public
259
+ */
260
+ function getGlobalDebugLevel() {
261
+ return self::$globalDebugLevel;
262
+ }
263
+
264
+ /**
265
+ * sets the global debug level, which applies to future instances
266
+ *
267
+ * @param int $level Debug level 0-9, where 0 turns off
268
+ * @access public
269
+ */
270
+ function setGlobalDebugLevel($level) {
271
+ self::$globalDebugLevel = $level;
272
+ }
273
+
274
+ /**
275
+ * gets the debug level for this instance
276
+ *
277
+ * @return int Debug level 0-9, where 0 turns off
278
+ * @access public
279
+ */
280
+ function getDebugLevel() {
281
+ return $this->debugLevel;
282
+ }
283
+
284
+ /**
285
+ * sets the debug level for this instance
286
+ *
287
+ * @param int $level Debug level 0-9, where 0 turns off
288
+ * @access public
289
+ */
290
+ function setDebugLevel($level) {
291
+ $this->debugLevel = $level;
292
+ }
293
+
294
+ /**
295
+ * adds debug data to the instance debug string with formatting
296
+ *
297
+ * @param string $string debug data
298
+ * @access private
299
+ */
300
+ function debug($string){
301
+ if ($this->debugLevel > 0) {
302
+ $this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n");
303
+ }
304
+ }
305
+
306
+ /**
307
+ * adds debug data to the instance debug string without formatting
308
+ *
309
+ * @param string $string debug data
310
+ * @access public
311
+ */
312
+ function appendDebug($string){
313
+ if ($this->debugLevel > 0) {
314
+ // it would be nice to use a memory stream here to use
315
+ // memory more efficiently
316
+ $this->debug_str .= $string;
317
+ }
318
+ }
319
+
320
+ /**
321
+ * clears the current debug data for this instance
322
+ *
323
+ * @access public
324
+ */
325
+ function clearDebug() {
326
+ // it would be nice to use a memory stream here to use
327
+ // memory more efficiently
328
+ $this->debug_str = '';
329
+ }
330
+
331
+ /**
332
+ * gets the current debug data for this instance
333
+ *
334
+ * @return debug data
335
+ * @access public
336
+ */
337
+ function &getDebug() {
338
+ // it would be nice to use a memory stream here to use
339
+ // memory more efficiently
340
+ return $this->debug_str;
341
+ }
342
+
343
+ /**
344
+ * gets the current debug data for this instance as an XML comment
345
+ * this may change the contents of the debug data
346
+ *
347
+ * @return debug data as an XML comment
348
+ * @access public
349
+ */
350
+ function &getDebugAsXMLComment() {
351
+ // it would be nice to use a memory stream here to use
352
+ // memory more efficiently
353
+ while (strpos($this->debug_str, '--')) {
354
+ $this->debug_str = str_replace('--', '- -', $this->debug_str);
355
+ }
356
+ $ret = "<!--\n" . $this->debug_str . "\n-->";
357
+ return $ret;
358
+ }
359
+
360
+ /**
361
+ * expands entities, e.g. changes '<' to '&lt;'.
362
+ *
363
+ * @param string $val The string in which to expand entities.
364
+ * @access private
365
+ */
366
+ function expandEntities($val) {
367
+ if ($this->charencoding) {
368
+ $val = str_replace('&', '&amp;', $val);
369
+ $val = str_replace("'", '&apos;', $val);
370
+ $val = str_replace('"', '&quot;', $val);
371
+ $val = str_replace('<', '&lt;', $val);
372
+ $val = str_replace('>', '&gt;', $val);
373
+ }
374
+ return $val;
375
+ }
376
+
377
+ /**
378
+ * returns error string if present
379
+ *
380
+ * @return mixed error string or false
381
+ * @access public
382
+ */
383
+ function getError(){
384
+ if($this->error_str != ''){
385
+ return $this->error_str;
386
+ }
387
+ return false;
388
+ }
389
+
390
+ /**
391
+ * sets error string
392
+ *
393
+ * @return boolean $string error string
394
+ * @access private
395
+ */
396
+ function setError($str){
397
+ $this->error_str = $str;
398
+ }
399
+
400
+ /**
401
+ * detect if array is a simple array or a struct (associative array)
402
+ *
403
+ * @param mixed $val The PHP array
404
+ * @return string (arraySimple|arrayStruct)
405
+ * @access private
406
+ */
407
+ function isArraySimpleOrStruct($val) {
408
+ $keyList = array_keys($val);
409
+ foreach ($keyList as $keyListValue) {
410
+ if (!is_int($keyListValue)) {
411
+ return 'arrayStruct';
412
+ }
413
+ }
414
+ return 'arraySimple';
415
+ }
416
+
417
+ /**
418
+ * serializes PHP values in accordance w/ section 5. Type information is
419
+ * not serialized if $use == 'literal'.
420
+ *
421
+ * @param mixed $val The value to serialize
422
+ * @param string $name The name (local part) of the XML element
423
+ * @param string $type The XML schema type (local part) for the element
424
+ * @param string $name_ns The namespace for the name of the XML element
425
+ * @param string $type_ns The namespace for the type of the element
426
+ * @param array $attributes The attributes to serialize as name=>value pairs
427
+ * @param string $use The WSDL "use" (encoded|literal)
428
+ * @param boolean $soapval Whether this is called from soapval.
429
+ * @return string The serialized element, possibly with child elements
430
+ * @access public
431
+ */
432
+ function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded',$soapval=false) {
433
+ $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval");
434
+ $this->appendDebug('value=' . $this->varDump($val));
435
+ $this->appendDebug('attributes=' . $this->varDump($attributes));
436
+
437
+ if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) {
438
+ $this->debug("serialize_val: serialize soapval");
439
+ $xml = $val->serialize($use);
440
+ $this->appendDebug($val->getDebug());
441
+ $val->clearDebug();
442
+ $this->debug("serialize_val of soapval returning $xml");
443
+ return $xml;
444
+ }
445
+ // force valid name if necessary
446
+ if (is_numeric($name)) {
447
+ $name = '__numeric_' . $name;
448
+ } elseif (! $name) {
449
+ $name = 'noname';
450
+ }
451
+ // if name has ns, add ns prefix to name
452
+ $xmlns = '';
453
+ if($name_ns){
454
+ $prefix = 'nu'.rand(1000,9999);
455
+ $name = $prefix.':'.$name;
456
+ $xmlns .= " xmlns:$prefix=\"$name_ns\"";
457
+ }
458
+ // if type is prefixed, create type prefix
459
+ if($type_ns != '' && $type_ns == $this->namespaces['xsd']){
460
+ // need to fix this. shouldn't default to xsd if no ns specified
461
+ // w/o checking against typemap
462
+ $type_prefix = 'xsd';
463
+ } elseif($type_ns){
464
+ $type_prefix = 'ns'.rand(1000,9999);
465
+ $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
466
+ }
467
+ // serialize attributes if present
468
+ $atts = '';
469
+ if($attributes){
470
+ foreach($attributes as $k => $v){
471
+ $atts .= " $k=\"".$this->expandEntities($v).'"';
472
+ }
473
+ }
474
+ // serialize null value
475
+ if (is_null($val)) {
476
+ $this->debug("serialize_val: serialize null");
477
+ if ($use == 'literal') {
478
+ // TODO: depends on minOccurs
479
+ $xml = "<$name$xmlns$atts/>";
480
+ $this->debug("serialize_val returning $xml");
481
+ return $xml;
482
+ } else {
483
+ if (isset($type) && isset($type_prefix)) {
484
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
485
+ } else {
486
+ $type_str = '';
487
+ }
488
+ $xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>";
489
+ $this->debug("serialize_val returning $xml");
490
+ return $xml;
491
+ }
492
+ }
493
+ // serialize if an xsd built-in primitive type
494
+ if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){
495
+ $this->debug("serialize_val: serialize xsd built-in primitive type");
496
+ if (is_bool($val)) {
497
+ if ($type == 'boolean') {
498
+ $val = $val ? 'true' : 'false';
499
+ } elseif (! $val) {
500
+ $val = 0;
501
+ }
502
+ } else if (is_string($val)) {
503
+ $val = $this->expandEntities($val);
504
+ }
505
+ if ($use == 'literal') {
506
+ $xml = "<$name$xmlns$atts>$val</$name>";
507
+ $this->debug("serialize_val returning $xml");
508
+ return $xml;
509
+ } else {
510
+ $xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>";
511
+ $this->debug("serialize_val returning $xml");
512
+ return $xml;
513
+ }
514
+ }
515
+ // detect type and serialize
516
+ $xml = '';
517
+ switch(true) {
518
+ case (is_bool($val) || $type == 'boolean'):
519
+ $this->debug("serialize_val: serialize boolean");
520
+ if ($type == 'boolean') {
521
+ $val = $val ? 'true' : 'false';
522
+ } elseif (! $val) {
523
+ $val = 0;
524
+ }
525
+ if ($use == 'literal') {
526
+ $xml .= "<$name$xmlns$atts>$val</$name>";
527
+ } else {
528
+ $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
529
+ }
530
+ break;
531
+ case (is_int($val) || is_long($val) || $type == 'int'):
532
+ $this->debug("serialize_val: serialize int");
533
+ if ($use == 'literal') {
534
+ $xml .= "<$name$xmlns$atts>$val</$name>";
535
+ } else {
536
+ $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
537
+ }
538
+ break;
539
+ case (is_float($val)|| is_double($val) || $type == 'float'):
540
+ $this->debug("serialize_val: serialize float");
541
+ if ($use == 'literal') {
542
+ $xml .= "<$name$xmlns$atts>$val</$name>";
543
+ } else {
544
+ $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
545
+ }
546
+ break;
547
+ case (is_string($val) || $type == 'string'):
548
+ $this->debug("serialize_val: serialize string");
549
+ $val = $this->expandEntities($val);
550
+ if ($use == 'literal') {
551
+ $xml .= "<$name$xmlns$atts>$val</$name>";
552
+ } else {
553
+ $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
554
+ }
555
+ break;
556
+ case is_object($val):
557
+ $this->debug("serialize_val: serialize object");
558
+ if (get_class($val) == 'soapval') {
559
+ $this->debug("serialize_val: serialize soapval object");
560
+ $pXml = $val->serialize($use);
561
+ $this->appendDebug($val->getDebug());
562
+ $val->clearDebug();
563
+ } else {
564
+ if (! $name) {
565
+ $name = get_class($val);
566
+ $this->debug("In serialize_val, used class name $name as element name");
567
+ } else {
568
+ $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
569
+ }
570
+ foreach(get_object_vars($val) as $k => $v){
571
+ $pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use);
572
+ }
573
+ }
574
+ if(isset($type) && isset($type_prefix)){
575
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
576
+ } else {
577
+ $type_str = '';
578
+ }
579
+ if ($use == 'literal') {
580
+ $xml .= "<$name$xmlns$atts>$pXml</$name>";
581
+ } else {
582
+ $xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";
583
+ }
584
+ break;
585
+ break;
586
+ case (is_array($val) || $type):
587
+ // detect if struct or array
588
+ $valueType = $this->isArraySimpleOrStruct($val);
589
+ if($valueType=='arraySimple' || ereg('^ArrayOf',$type)){
590
+ $this->debug("serialize_val: serialize array");
591
+ $i = 0;
592
+ if(is_array($val) && count($val)> 0){
593
+ foreach($val as $v){
594
+ if(is_object($v) && get_class($v) == 'soapval'){
595
+ $tt_ns = $v->type_ns;
596
+ $tt = $v->type;
597
+ } elseif (is_array($v)) {
598
+ $tt = $this->isArraySimpleOrStruct($v);
599
+ } else {
600
+ $tt = gettype($v);
601
+ }
602
+ $array_types[$tt] = 1;
603
+ // TODO: for literal, the name should be $name
604
+ $xml .= $this->serialize_val($v,'item',false,false,false,false,$use);
605
+ ++$i;
606
+ }
607
+ if(count($array_types) > 1){
608
+ $array_typename = 'xsd:anyType';
609
+ } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
610
+ if ($tt == 'integer') {
611
+ $tt = 'int';
612
+ }
613
+ $array_typename = 'xsd:'.$tt;
614
+ } elseif(isset($tt) && $tt == 'arraySimple'){
615
+ $array_typename = 'SOAP-ENC:Array';
616
+ } elseif(isset($tt) && $tt == 'arrayStruct'){
617
+ $array_typename = 'unnamed_struct_use_soapval';
618
+ } else {
619
+ // if type is prefixed, create type prefix
620
+ if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){
621
+ $array_typename = 'xsd:' . $tt;
622
+ } elseif ($tt_ns) {
623
+ $tt_prefix = 'ns' . rand(1000, 9999);
624
+ $array_typename = "$tt_prefix:$tt";
625
+ $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
626
+ } else {
627
+ $array_typename = $tt;
628
+ }
629
+ }
630
+ $array_type = $i;
631
+ if ($use == 'literal') {
632
+ $type_str = '';
633
+ } else if (isset($type) && isset($type_prefix)) {
634
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
635
+ } else {
636
+ $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"";
637
+ }
638
+ // empty array
639
+ } else {
640
+ if ($use == 'literal') {
641
+ $type_str = '';
642
+ } else if (isset($type) && isset($type_prefix)) {
643
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
644
+ } else {
645
+ $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
646
+ }
647
+ }
648
+ // TODO: for array in literal, there is no wrapper here
649
+ $xml = "<$name$xmlns$type_str$atts>".$xml."</$name>";
650
+ } else {
651
+ // got a struct
652
+ $this->debug("serialize_val: serialize struct");
653
+ if(isset($type) && isset($type_prefix)){
654
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
655
+ } else {
656
+ $type_str = '';
657
+ }
658
+ if ($use == 'literal') {
659
+ $xml .= "<$name$xmlns$atts>";
660
+ } else {
661
+ $xml .= "<$name$xmlns$type_str$atts>";
662
+ }
663
+ foreach($val as $k => $v){
664
+ // Apache Map
665
+ if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
666
+ $xml .= '<item>';
667
+ $xml .= $this->serialize_val($k,'key',false,false,false,false,$use);
668
+ $xml .= $this->serialize_val($v,'value',false,false,false,false,$use);
669
+ $xml .= '</item>';
670
+ } else {
671
+ $xml .= $this->serialize_val($v,$k,false,false,false,false,$use);
672
+ }
673
+ }
674
+ $xml .= "</$name>";
675
+ }
676
+ break;
677
+ default:
678
+ $this->debug("serialize_val: serialize unknown");
679
+ $xml .= 'not detected, got '.gettype($val).' for '.$val;
680
+ break;
681
+ }
682
+ $this->debug("serialize_val returning $xml");
683
+ return $xml;
684
+ }
685
+
686
+ /**
687
+ * serializes a message
688
+ *
689
+ * @param string $body the XML of the SOAP body
690
+ * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
691
+ * @param array $namespaces optional the namespaces used in generating the body and headers
692
+ * @param string $style optional (rpc|document)
693
+ * @param string $use optional (encoded|literal)
694
+ * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
695
+ * @return string the message
696
+ * @access public
697
+ */
698
+ function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded',$encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'){
699
+ // TODO: add an option to automatically run utf8_encode on $body and $headers
700
+ // if $this->soap_defencoding is UTF-8. Not doing this automatically allows
701
+ // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
702
+
703
+ $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");
704
+ $this->debug("headers:");
705
+ $this->appendDebug($this->varDump($headers));
706
+ $this->debug("namespaces:");
707
+ $this->appendDebug($this->varDump($namespaces));
708
+
709
+ // serialize namespaces
710
+ $ns_string = '';
711
+ foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
712
+ $ns_string .= " xmlns:$k=\"$v\"";
713
+ }
714
+ if($encodingStyle) {
715
+ $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
716
+ }
717
+
718
+ // serialize headers
719
+ if($headers){
720
+ if (is_array($headers)) {
721
+ $xml = '';
722
+ foreach ($headers as $k => $v) {
723
+ if (is_object($v) && get_class($v) == 'soapval') {
724
+ $xml .= $this->serialize_val($v, false, false, false, false, false, $use);
725
+ } else {
726
+ $xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
727
+ }
728
+ }
729
+ $headers = $xml;
730
+ $this->debug("In serializeEnvelope, serialized array of headers to $headers");
731
+ }
732
+ $headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
733
+ }
734
+ // serialize envelope
735
+ return
736
+ '<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
737
+ '<SOAP-ENV:Envelope'.$ns_string.">".
738
+ $headers.
739
+ "<SOAP-ENV:Body>".
740
+ $body.
741
+ "</SOAP-ENV:Body>".
742
+ "</SOAP-ENV:Envelope>";
743
+ }
744
+
745
+ /**
746
+ * formats a string to be inserted into an HTML stream
747
+ *
748
+ * @param string $str The string to format
749
+ * @return string The formatted string
750
+ * @access public
751
+ * @deprecated
752
+ */
753
+ function formatDump($str){
754
+ $str = htmlspecialchars($str);
755
+ return nl2br($str);
756
+ }
757
+
758
+ /**
759
+ * contracts (changes namespace to prefix) a qualified name
760
+ *
761
+ * @param string $qname qname
762
+ * @return string contracted qname
763
+ * @access private
764
+ */
765
+ function contractQname($qname){
766
+ // get element namespace
767
+ //$this->xdebug("Contract $qname");
768
+ if (strrpos($qname, ':')) {
769
+ // get unqualified name
770
+ $name = substr($qname, strrpos($qname, ':') + 1);
771
+ // get ns
772
+ $ns = substr($qname, 0, strrpos($qname, ':'));
773
+ $p = $this->getPrefixFromNamespace($ns);
774
+ if ($p) {
775
+ return $p . ':' . $name;
776
+ }
777
+ return $qname;
778
+ } else {
779
+ return $qname;
780
+ }
781
+ }
782
+
783
+ /**
784
+ * expands (changes prefix to namespace) a qualified name
785
+ *
786
+ * @param string $qname qname
787
+ * @return string expanded qname
788
+ * @access private
789
+ */
790
+ function expandQname($qname){
791
+ // get element prefix
792
+ if(strpos($qname,':') && !ereg('^http://',$qname)){
793
+ // get unqualified name
794
+ $name = substr(strstr($qname,':'),1);
795
+ // get ns prefix
796
+ $prefix = substr($qname,0,strpos($qname,':'));
797
+ if(isset($this->namespaces[$prefix])){
798
+ return $this->namespaces[$prefix].':'.$name;
799
+ } else {
800
+ return $qname;
801
+ }
802
+ } else {
803
+ return $qname;
804
+ }
805
+ }
806
+
807
+ /**
808
+ * returns the local part of a prefixed string
809
+ * returns the original string, if not prefixed
810
+ *
811
+ * @param string $str The prefixed string
812
+ * @return string The local part
813
+ * @access public
814
+ */
815
+ function getLocalPart($str){
816
+ if($sstr = strrchr($str,':')){
817
+ // get unqualified name
818
+ return substr( $sstr, 1 );
819
+ } else {
820
+ return $str;
821
+ }
822
+ }
823
+
824
+ /**
825
+ * returns the prefix part of a prefixed string
826
+ * returns false, if not prefixed
827
+ *
828
+ * @param string $str The prefixed string
829
+ * @return mixed The prefix or false if there is no prefix
830
+ * @access public
831
+ */
832
+ function getPrefix($str){
833
+ if($pos = strrpos($str,':')){
834
+ // get prefix
835
+ return substr($str,0,$pos);
836
+ }
837
+ return false;
838
+ }
839
+
840
+ /**
841
+ * pass it a prefix, it returns a namespace
842
+ *
843
+ * @param string $prefix The prefix
844
+ * @return mixed The namespace, false if no namespace has the specified prefix
845
+ * @access public
846
+ */
847
+ function getNamespaceFromPrefix($prefix){
848
+ if (isset($this->namespaces[$prefix])) {
849
+ return $this->namespaces[$prefix];
850
+ }
851
+ //$this->setError("No namespace registered for prefix '$prefix'");
852
+ return false;
853
+ }
854
+
855
+ /**
856
+ * returns the prefix for a given namespace (or prefix)
857
+ * or false if no prefixes registered for the given namespace
858
+ *
859
+ * @param string $ns The namespace
860
+ * @return mixed The prefix, false if the namespace has no prefixes
861
+ * @access public
862
+ */
863
+ function getPrefixFromNamespace($ns) {
864
+ foreach ($this->namespaces as $p => $n) {
865
+ if ($ns == $n || $ns == $p) {
866
+ $this->usedNamespaces[$p] = $n;
867
+ return $p;
868
+ }
869
+ }
870
+ return false;
871
+ }
872
+
873
+ /**
874
+ * returns the time in ODBC canonical form with microseconds
875
+ *
876
+ * @return string The time in ODBC canonical form with microseconds
877
+ * @access public
878
+ */
879
+ function getmicrotime() {
880
+ if (function_exists('gettimeofday')) {
881
+ $tod = gettimeofday();
882
+ $sec = $tod['sec'];
883
+ $usec = $tod['usec'];
884
+ } else {
885
+ $sec = time();
886
+ $usec = 0;
887
+ }
888
+ return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
889
+ }
890
+
891
+ /**
892
+ * Returns a string with the output of var_dump
893
+ *
894
+ * @param mixed $data The variable to var_dump
895
+ * @return string The output of var_dump
896
+ * @access public
897
+ */
898
+ function varDump($data) {
899
+ ob_start();
900
+ var_dump($data);
901
+ $ret_val = ob_get_contents();
902
+ ob_end_clean();
903
+ return $ret_val;
904
+ }
905
+
906
+ /**
907
+ * represents the object as a string
908
+ *
909
+ * @return string
910
+ * @access public
911
+ */
912
+ function __toString() {
913
+ return $this->varDump($this);
914
+ }
915
+ }
916
+
917
+ // XML Schema Datatype Helper Functions
918
+
919
+ //xsd:dateTime helpers
920
+
921
+ /**
922
+ * convert unix timestamp to ISO 8601 compliant date string
923
+ *
924
+ * @param string $timestamp Unix time stamp
925
+ * @param boolean $utc Whether the time stamp is UTC or local
926
+ * @access public
927
+ */
928
+ function timestamp_to_iso8601($timestamp,$utc=true){
929
+ $datestr = date('Y-m-d\TH:i:sO',$timestamp);
930
+ if($utc){
931
+ $eregStr =
932
+ '([0-9]{4})-'. // centuries & years CCYY-
933
+ '([0-9]{2})-'. // months MM-
934
+ '([0-9]{2})'. // days DD
935
+ 'T'. // separator T
936
+ '([0-9]{2}):'. // hours hh:
937
+ '([0-9]{2}):'. // minutes mm:
938
+ '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
939
+ '(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
940
+
941
+ if(ereg($eregStr,$datestr,$regs)){
942
+ return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
943
+ }
944
+ return false;
945
+ } else {
946
+ return $datestr;
947
+ }
948
+ }
949
+
950
+ /**
951
+ * convert ISO 8601 compliant date string to unix timestamp
952
+ *
953
+ * @param string $datestr ISO 8601 compliant date string
954
+ * @access public
955
+ */
956
+ function iso8601_to_timestamp($datestr){
957
+ $eregStr =
958
+ '([0-9]{4})-'. // centuries & years CCYY-
959
+ '([0-9]{2})-'. // months MM-
960
+ '([0-9]{2})'. // days DD
961
+ 'T'. // separator T
962
+ '([0-9]{2}):'. // hours hh:
963
+ '([0-9]{2}):'. // minutes mm:
964
+ '([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
965
+ '(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
966
+ if(ereg($eregStr,$datestr,$regs)){
967
+ // not utc
968
+ if($regs[8] != 'Z'){
969
+ $op = substr($regs[8],0,1);
970
+ $h = substr($regs[8],1,2);
971
+ $m = substr($regs[8],strlen($regs[8])-2,2);
972
+ if($op == '-'){
973
+ $regs[4] = $regs[4] + $h;
974
+ $regs[5] = $regs[5] + $m;
975
+ } elseif($op == '+'){
976
+ $regs[4] = $regs[4] - $h;
977
+ $regs[5] = $regs[5] - $m;
978
+ }
979
+ }
980
+ return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
981
+ // return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
982
+ } else {
983
+ return false;
984
+ }
985
+ }
986
+
987
+ /**
988
+ * sleeps some number of microseconds
989
+ *
990
+ * @param string $usec the number of microseconds to sleep
991
+ * @access public
992
+ * @deprecated
993
+ */
994
+ function usleepWindows($usec)
995
+ {
996
+ $start = gettimeofday();
997
+
998
+ do
999
+ {
1000
+ $stop = gettimeofday();
1001
+ $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
1002
+ + $stop['usec'] - $start['usec'];
1003
+ }
1004
+ while ($timePassed < $usec);
1005
+ }
1006
+
1007
+ ?><?php
1008
+
1009
+
1010
+
1011
+ /**
1012
+ * Contains information for a SOAP fault.
1013
+ * Mainly used for returning faults from deployed functions
1014
+ * in a server instance.
1015
+ * @author Dietrich Ayala <dietrich@ganx4.com>
1016
+ * @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $
1017
+ * @access public
1018
+ */
1019
+ class nusoap_fault extends nusoap_base {
1020
+ /**
1021
+ * The fault code (client|server)
1022
+ * @var string
1023
+ * @access private
1024
+ */
1025
+ var $faultcode;
1026
+ /**
1027
+ * The fault actor
1028
+ * @var string
1029
+ * @access private
1030
+ */
1031
+ var $faultactor;
1032
+ /**
1033
+ * The fault string, a description of the fault
1034
+ * @var string
1035
+ * @access private
1036
+ */
1037
+ var $faultstring;
1038
+ /**
1039
+ * The fault detail, typically a string or array of string
1040
+ * @var mixed
1041
+ * @access private
1042
+ */
1043
+ var $faultdetail;
1044
+
1045
+ /**
1046
+ * constructor
1047
+ *
1048
+ * @param string $faultcode (SOAP-ENV:Client | SOAP-ENV:Server)
1049
+ * @param string $faultactor only used when msg routed between multiple actors
1050
+ * @param string $faultstring human readable error message
1051
+ * @param mixed $faultdetail detail, typically a string or array of string
1052
+ */
1053
+ function nusoap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){
1054
+ parent::nusoap_base();
1055
+ $this->faultcode = $faultcode;
1056
+ $this->faultactor = $faultactor;
1057
+ $this->faultstring = $faultstring;
1058
+ $this->faultdetail = $faultdetail;
1059
+ }
1060
+
1061
+ /**
1062
+ * serialize a fault
1063
+ *
1064
+ * @return string The serialization of the fault instance.
1065
+ * @access public
1066
+ */
1067
+ function serialize(){
1068
+ $ns_string = '';
1069
+ foreach($this->namespaces as $k => $v){
1070
+ $ns_string .= "\n xmlns:$k=\"$v\"";
1071
+ }
1072
+ $return_msg =
1073
+ '<?xml version="1.0" encoding="'.$this->soap_defencoding.'"?>'.
1074
+ '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.">\n".
1075
+ '<SOAP-ENV:Body>'.
1076
+ '<SOAP-ENV:Fault>'.
1077
+ $this->serialize_val($this->faultcode, 'faultcode').
1078
+ $this->serialize_val($this->faultactor, 'faultactor').
1079
+ $this->serialize_val($this->faultstring, 'faultstring').
1080
+ $this->serialize_val($this->faultdetail, 'detail').
1081
+ '</SOAP-ENV:Fault>'.
1082
+ '</SOAP-ENV:Body>'.
1083
+ '</SOAP-ENV:Envelope>';
1084
+ return $return_msg;
1085
+ }
1086
+ }
1087
+
1088
+ /**
1089
+ * Backward compatibility
1090
+ */
1091
+ class soap_fault extends nusoap_fault {
1092
+ }
1093
+
1094
+ ?><?php
1095
+
1096
+
1097
+
1098
+ /**
1099
+ * parses an XML Schema, allows access to it's data, other utility methods.
1100
+ * imperfect, no validation... yet, but quite functional.
1101
+ *
1102
+ * @author Dietrich Ayala <dietrich@ganx4.com>
1103
+ * @author Scott Nichol <snichol@users.sourceforge.net>
1104
+ * @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $
1105
+ * @access public
1106
+ */
1107
+ class nusoap_xmlschema extends nusoap_base {
1108
+
1109
+ // files
1110
+ var $schema = '';
1111
+ var $xml = '';
1112
+ // namespaces
1113
+ var $enclosingNamespaces;
1114
+ // schema info
1115
+ var $schemaInfo = array();
1116
+ var $schemaTargetNamespace = '';
1117
+ // types, elements, attributes defined by the schema
1118
+ var $attributes = array();
1119
+ var $complexTypes = array();
1120
+ var $complexTypeStack = array();
1121
+ var $currentComplexType = null;
1122
+ var $elements = array();
1123
+ var $elementStack = array();
1124
+ var $currentElement = null;
1125
+ var $simpleTypes = array();
1126
+ var $simpleTypeStack = array();
1127
+ var $currentSimpleType = null;
1128
+ // imports
1129
+ var $imports = array();
1130
+ // parser vars
1131
+ var $parser;
1132
+ var $position = 0;
1133
+ var $depth = 0;
1134
+ var $depth_array = array();
1135
+ var $message = array();
1136
+ var $defaultNamespace = array();
1137
+
1138
+ /**
1139
+ * constructor
1140
+ *
1141
+ * @param string $schema schema document URI
1142
+ * @param string $xml xml document URI
1143
+ * @param string $namespaces namespaces defined in enclosing XML
1144
+ * @access public
1145
+ */
1146
+ function nusoap_xmlschema($schema='',$xml='',$namespaces=array()){
1147
+ parent::nusoap_base();
1148
+ $this->debug('nusoap_xmlschema class instantiated, inside constructor');
1149
+ // files
1150
+ $this->schema = $schema;
1151
+ $this->xml = $xml;
1152
+
1153
+ // namespaces
1154
+ $this->enclosingNamespaces = $namespaces;
1155
+ $this->namespaces = array_merge($this->namespaces, $namespaces);
1156
+
1157
+ // parse schema file
1158
+ if($schema != ''){
1159
+ $this->debug('initial schema file: '.$schema);
1160
+ $this->parseFile($schema, 'schema');
1161
+ }
1162
+
1163
+ // parse xml file
1164
+ if($xml != ''){
1165
+ $this->debug('initial xml file: '.$xml);
1166
+ $this->parseFile($xml, 'xml');
1167
+ }
1168
+
1169
+ }
1170
+
1171
+ /**
1172
+ * parse an XML file
1173
+ *
1174
+ * @param string $xml path/URL to XML file
1175
+ * @param string $type (schema | xml)
1176
+ * @return boolean
1177
+ * @access public
1178
+ */
1179
+ function parseFile($xml,$type){
1180
+ // parse xml file
1181
+ if($xml != ""){
1182
+ $xmlStr = @join("",@file($xml));
1183
+ if($xmlStr == ""){
1184
+ $msg = 'Error reading XML from '.$xml;
1185
+ $this->setError($msg);
1186
+ $this->debug($msg);
1187
+ return false;
1188
+ } else {
1189
+ $this->debug("parsing $xml");
1190
+ $this->parseString($xmlStr,$type);
1191
+ $this->debug("done parsing $xml");
1192
+ return true;
1193
+ }
1194
+ }
1195
+ return false;
1196
+ }
1197
+
1198
+ /**
1199
+ * parse an XML string
1200
+ *
1201
+ * @param string $xml path or URL
1202
+ * @param string $type (schema|xml)
1203
+ * @access private
1204
+ */
1205
+ function parseString($xml,$type){
1206
+ // parse xml string
1207
+ if($xml != ""){
1208
+
1209
+ // Create an XML parser.
1210
+ $this->parser = xml_parser_create();
1211
+ // Set the options for parsing the XML data.
1212
+ xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
1213
+
1214
+ // Set the object for the parser.
1215
+ xml_set_object($this->parser, $this);
1216
+
1217
+ // Set the element handlers for the parser.
1218
+ if($type == "schema"){
1219
+ xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
1220
+ xml_set_character_data_handler($this->parser,'schemaCharacterData');
1221
+ } elseif($type == "xml"){
1222
+ xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');
1223
+ xml_set_character_data_handler($this->parser,'xmlCharacterData');
1224
+ }
1225
+
1226
+ // Parse the XML file.
1227
+ if(!xml_parse($this->parser,$xml,true)){
1228
+ // Display an error message.
1229
+ $errstr = sprintf('XML error parsing XML schema on line %d: %s',
1230
+ xml_get_current_line_number($this->parser),
1231
+ xml_error_string(xml_get_error_code($this->parser))
1232
+ );
1233
+ $this->debug($errstr);
1234
+ $this->debug("XML payload:\n" . $xml);
1235
+ $this->setError($errstr);
1236
+ }
1237
+
1238
+ xml_parser_free($this->parser);
1239
+ } else{
1240
+ $this->debug('no xml passed to parseString()!!');
1241
+ $this->setError('no xml passed to parseString()!!');
1242
+ }
1243
+ }
1244
+
1245
+ /**
1246
+ * gets a type name for an unnamed type
1247
+ *
1248
+ * @param string Element name
1249
+ * @return string A type name for an unnamed type
1250
+ * @access private
1251
+ */
1252
+ function CreateTypeName($ename) {
1253
+ $scope = '';
1254
+ for ($i = 0; $i < count($this->complexTypeStack); $i++) {
1255
+ $scope .= $this->complexTypeStack[$i] . '_';
1256
+ }
1257
+ return $scope . $ename . '_ContainedType';
1258
+ }
1259
+
1260
+ /**
1261
+ * start-element handler
1262
+ *
1263
+ * @param string $parser XML parser object
1264
+ * @param string $name element name
1265
+ * @param string $attrs associative array of attributes
1266
+ * @access private
1267
+ */
1268
+ function schemaStartElement($parser, $name, $attrs) {
1269
+
1270
+ // position in the total number of elements, starting from 0
1271
+ $pos = $this->position++;
1272
+ $depth = $this->depth++;
1273
+ // set self as current value for this depth
1274
+ $this->depth_array[$depth] = $pos;
1275
+ $this->message[$pos] = array('cdata' => '');
1276
+ if ($depth > 0) {
1277
+ $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
1278
+ } else {
1279
+ $this->defaultNamespace[$pos] = false;
1280
+ }
1281
+
1282
+ // get element prefix
1283
+ if($prefix = $this->getPrefix($name)){
1284
+ // get unqualified name
1285
+ $name = $this->getLocalPart($name);
1286
+ } else {
1287
+ $prefix = '';
1288
+ }
1289
+
1290
+ // loop thru attributes, expanding, and registering namespace declarations
1291
+ if(count($attrs) > 0){
1292
+ foreach($attrs as $k => $v){
1293
+ // if ns declarations, add to class level array of valid namespaces
1294
+ if(ereg("^xmlns",$k)){
1295
+ //$this->xdebug("$k: $v");
1296
+ //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
1297
+ if($ns_prefix = substr(strrchr($k,':'),1)){
1298
+ //$this->xdebug("Add namespace[$ns_prefix] = $v");
1299
+ $this->namespaces[$ns_prefix] = $v;
1300
+ } else {
1301
+ $this->defaultNamespace[$pos] = $v;
1302
+ if (! $this->getPrefixFromNamespace($v)) {
1303
+ $this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
1304
+ }
1305
+ }
1306
+ if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){
1307
+ $this->XMLSchemaVersion = $v;
1308
+ $this->namespaces['xsi'] = $v.'-instance';
1309
+ }
1310
+ }
1311
+ }
1312
+ foreach($attrs as $k => $v){
1313
+ // expand each attribute
1314
+ $k = strpos($k,':') ? $this->expandQname($k) : $k;
1315
+ $v = strpos($v,':') ? $this->expandQname($v) : $v;
1316
+ $eAttrs[$k] = $v;
1317
+ }
1318
+ $attrs = $eAttrs;
1319
+ } else {
1320
+ $attrs = array();
1321
+ }
1322
+ // find status, register data
1323
+ switch($name){
1324
+ case 'all': // (optional) compositor content for a complexType
1325
+ case 'choice':
1326
+ case 'group':
1327
+ case 'sequence':
1328
+ //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
1329
+ $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
1330
+ //if($name == 'all' || $name == 'sequence'){
1331
+ // $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1332
+ //}
1333
+ break;
1334
+ case 'attribute': // complexType attribute
1335
+ //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
1336
+ $this->xdebug("parsing attribute:");
1337
+ $this->appendDebug($this->varDump($attrs));
1338
+ if (!isset($attrs['form'])) {
1339
+ $attrs['form'] = $this->schemaInfo['attributeFormDefault'];
1340
+ }
1341
+ if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1342
+ $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1343
+ if (!strpos($v, ':')) {
1344
+ // no namespace in arrayType attribute value...
1345
+ if ($this->defaultNamespace[$pos]) {
1346
+ // ...so use the default
1347
+ $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1348
+ }
1349
+ }
1350
+ }
1351
+ if(isset($attrs['name'])){
1352
+ $this->attributes[$attrs['name']] = $attrs;
1353
+ $aname = $attrs['name'];
1354
+ } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
1355
+ if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1356
+ $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1357
+ } else {
1358
+ $aname = '';
1359
+ }
1360
+ } elseif(isset($attrs['ref'])){
1361
+ $aname = $attrs['ref'];
1362
+ $this->attributes[$attrs['ref']] = $attrs;
1363
+ }
1364
+
1365
+ if($this->currentComplexType){ // This should *always* be
1366
+ $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
1367
+ }
1368
+ // arrayType attribute
1369
+ if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){
1370
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1371
+ $prefix = $this->getPrefix($aname);
1372
+ if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
1373
+ $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1374
+ } else {
1375
+ $v = '';
1376
+ }
1377
+ if(strpos($v,'[,]')){
1378
+ $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
1379
+ }
1380
+ $v = substr($v,0,strpos($v,'[')); // clip the []
1381
+ if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
1382
+ $v = $this->XMLSchemaVersion.':'.$v;
1383
+ }
1384
+ $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
1385
+ }
1386
+ break;
1387
+ case 'complexContent': // (optional) content for a complexType
1388
+ break;
1389
+ case 'complexType':
1390
+ array_push($this->complexTypeStack, $this->currentComplexType);
1391
+ if(isset($attrs['name'])){
1392
+ // TODO: what is the scope of named complexTypes that appear
1393
+ // nested within other c complexTypes?
1394
+ $this->xdebug('processing named complexType '.$attrs['name']);
1395
+ //$this->currentElement = false;
1396
+ $this->currentComplexType = $attrs['name'];
1397
+ $this->complexTypes[$this->currentComplexType] = $attrs;
1398
+ $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1399
+ // This is for constructs like
1400
+ // <complexType name="ListOfString" base="soap:Array">
1401
+ // <sequence>
1402
+ // <element name="string" type="xsd:string"
1403
+ // minOccurs="0" maxOccurs="unbounded" />
1404
+ // </sequence>
1405
+ // </complexType>
1406
+ if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){
1407
+ $this->xdebug('complexType is unusual array');
1408
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1409
+ } else {
1410
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1411
+ }
1412
+ } else {
1413
+ $name = $this->CreateTypeName($this->currentElement);
1414
+ $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
1415
+ $this->currentComplexType = $name;
1416
+ //$this->currentElement = false;
1417
+ $this->complexTypes[$this->currentComplexType] = $attrs;
1418
+ $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1419
+ // This is for constructs like
1420
+ // <complexType name="ListOfString" base="soap:Array">
1421
+ // <sequence>
1422
+ // <element name="string" type="xsd:string"
1423
+ // minOccurs="0" maxOccurs="unbounded" />
1424
+ // </sequence>
1425
+ // </complexType>
1426
+ if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){
1427
+ $this->xdebug('complexType is unusual array');
1428
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1429
+ } else {
1430
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1431
+ }
1432
+ }
1433
+ break;
1434
+ case 'element':
1435
+ array_push($this->elementStack, $this->currentElement);
1436
+ if (!isset($attrs['form'])) {
1437
+ $attrs['form'] = $this->schemaInfo['elementFormDefault'];
1438
+ }
1439
+ if(isset($attrs['type'])){
1440
+ $this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']);
1441
+ if (! $this->getPrefix($attrs['type'])) {
1442
+ if ($this->defaultNamespace[$pos]) {
1443
+ $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
1444
+ $this->xdebug('used default namespace to make type ' . $attrs['type']);
1445
+ }
1446
+ }
1447
+ // This is for constructs like
1448
+ // <complexType name="ListOfString" base="soap:Array">
1449
+ // <sequence>
1450
+ // <element name="string" type="xsd:string"
1451
+ // minOccurs="0" maxOccurs="unbounded" />
1452
+ // </sequence>
1453
+ // </complexType>
1454
+ if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
1455
+ $this->xdebug('arrayType for unusual array is ' . $attrs['type']);
1456
+ $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
1457
+ }
1458
+ $this->currentElement = $attrs['name'];
1459
+ $ename = $attrs['name'];
1460
+ } elseif(isset($attrs['ref'])){
1461
+ $this->xdebug("processing element as ref to ".$attrs['ref']);
1462
+ $this->currentElement = "ref to ".$attrs['ref'];
1463
+ $ename = $this->getLocalPart($attrs['ref']);
1464
+ } else {
1465
+ $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
1466
+ $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
1467
+ $this->currentElement = $attrs['name'];
1468
+ $attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
1469
+ $ename = $attrs['name'];
1470
+ }
1471
+ if (isset($ename) && $this->currentComplexType) {
1472
+ $this->xdebug("add element $ename to complexType $this->currentComplexType");
1473
+ $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
1474
+ } elseif (!isset($attrs['ref'])) {
1475
+ $this->xdebug("add element $ename to elements array");
1476
+ $this->elements[ $attrs['name'] ] = $attrs;
1477
+ $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
1478
+ }
1479
+ break;
1480
+ case 'enumeration': // restriction value list member
1481
+ $this->xdebug('enumeration ' . $attrs['value']);
1482
+ if ($this->currentSimpleType) {
1483
+ $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
1484
+ } elseif ($this->currentComplexType) {
1485
+ $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
1486
+ }
1487
+ break;
1488
+ case 'extension': // simpleContent or complexContent type extension
1489
+ $this->xdebug('extension ' . $attrs['base']);
1490
+ if ($this->currentComplexType) {
1491
+ $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
1492
+ }
1493
+ break;
1494
+ case 'import':
1495
+ if (isset($attrs['schemaLocation'])) {
1496
+ //$this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
1497
+ $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
1498
+ } else {
1499
+ //$this->xdebug('import namespace ' . $attrs['namespace']);
1500
+ $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
1501
+ if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
1502
+ $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
1503
+ }
1504
+ }
1505
+ break;
1506
+ case 'list': // simpleType value list
1507
+ break;
1508
+ case 'restriction': // simpleType, simpleContent or complexContent value restriction
1509
+ $this->xdebug('restriction ' . $attrs['base']);
1510
+ if($this->currentSimpleType){
1511
+ $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
1512
+ } elseif($this->currentComplexType){
1513
+ $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
1514
+ if(strstr($attrs['base'],':') == ':Array'){
1515
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1516
+ }
1517
+ }
1518
+ break;
1519
+ case 'schema':
1520
+ $this->schemaInfo = $attrs;
1521
+ $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
1522
+ if (isset($attrs['targetNamespace'])) {
1523
+ $this->schemaTargetNamespace = $attrs['targetNamespace'];
1524
+ }
1525
+ if (!isset($attrs['elementFormDefault'])) {
1526
+ $this->schemaInfo['elementFormDefault'] = 'unqualified';
1527
+ }
1528
+ if (!isset($attrs['attributeFormDefault'])) {
1529
+ $this->schemaInfo['attributeFormDefault'] = 'unqualified';
1530
+ }
1531
+ break;
1532
+ case 'simpleContent': // (optional) content for a complexType
1533
+ break;
1534
+ case 'simpleType':
1535
+ array_push($this->simpleTypeStack, $this->currentSimpleType);
1536
+ if(isset($attrs['name'])){
1537
+ $this->xdebug("processing simpleType for name " . $attrs['name']);
1538
+ $this->currentSimpleType = $attrs['name'];
1539
+ $this->simpleTypes[ $attrs['name'] ] = $attrs;
1540
+ $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
1541
+ $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
1542
+ } else {
1543
+ $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
1544
+ $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
1545
+ $this->currentSimpleType = $name;
1546
+ //$this->currentElement = false;
1547
+ $this->simpleTypes[$this->currentSimpleType] = $attrs;
1548
+ $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
1549
+ }
1550
+ break;
1551
+ case 'union': // simpleType type list
1552
+ break;
1553
+ default:
1554
+ //$this->xdebug("do not have anything to do for element $name");
1555
+ }
1556
+ }
1557
+
1558
+ /**
1559
+ * end-element handler
1560
+ *
1561
+ * @param string $parser XML parser object
1562
+ * @param string $name element name
1563
+ * @access private
1564
+ */
1565
+ function schemaEndElement($parser, $name) {
1566
+ // bring depth down a notch
1567
+ $this->depth--;
1568
+ // position of current element is equal to the last value left in depth_array for my depth
1569
+ if(isset($this->depth_array[$this->depth])){
1570
+ $pos = $this->depth_array[$this->depth];
1571
+ }
1572
+ // get element prefix
1573
+ if ($prefix = $this->getPrefix($name)){
1574
+ // get unqualified name
1575
+ $name = $this->getLocalPart($name);
1576
+ } else {
1577
+ $prefix = '';
1578
+ }
1579
+ // move on...
1580
+ if($name == 'complexType'){
1581
+ $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
1582
+ $this->currentComplexType = array_pop($this->complexTypeStack);
1583
+ //$this->currentElement = false;
1584
+ }
1585
+ if($name == 'element'){
1586
+ $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
1587
+ $this->currentElement = array_pop($this->elementStack);
1588
+ }
1589
+ if($name == 'simpleType'){
1590
+ $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
1591
+ $this->currentSimpleType = array_pop($this->simpleTypeStack);
1592
+ }
1593
+ }
1594
+
1595
+ /**
1596
+ * element content handler
1597
+ *
1598
+ * @param string $parser XML parser object
1599
+ * @param string $data element content
1600
+ * @access private
1601
+ */
1602
+ function schemaCharacterData($parser, $data){
1603
+ $pos = $this->depth_array[$this->depth - 1];
1604
+ $this->message[$pos]['cdata'] .= $data;
1605
+ }
1606
+
1607
+ /**
1608
+ * serialize the schema
1609
+ *
1610
+ * @access public
1611
+ */
1612
+ function serializeSchema(){
1613
+
1614
+ $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
1615
+ $xml = '';
1616
+ // imports
1617
+ if (sizeof($this->imports) > 0) {
1618
+ foreach($this->imports as $ns => $list) {
1619
+ foreach ($list as $ii) {
1620
+ if ($ii['location'] != '') {
1621
+ $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
1622
+ } else {
1623
+ $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
1624
+ }
1625
+ }
1626
+ }
1627
+ }
1628
+ // complex types
1629
+ foreach($this->complexTypes as $typeName => $attrs){
1630
+ $contentStr = '';
1631
+ // serialize child elements
1632
+ if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){
1633
+ foreach($attrs['elements'] as $element => $eParts){
1634
+ if(isset($eParts['ref'])){
1635
+ $contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n";
1636
+ } else {
1637
+ $contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
1638
+ foreach ($eParts as $aName => $aValue) {
1639
+ // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
1640
+ if ($aName != 'name' && $aName != 'type') {
1641
+ $contentStr .= " $aName=\"$aValue\"";
1642
+ }
1643
+ }
1644
+ $contentStr .= "/>\n";
1645
+ }
1646
+ }
1647
+ // compositor wraps elements
1648
+ if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
1649
+ $contentStr = " <$schemaPrefix:$attrs[compositor]>\n".$contentStr." </$schemaPrefix:$attrs[compositor]>\n";
1650
+ }
1651
+ }
1652
+ // attributes
1653
+ if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){
1654
+ foreach($attrs['attrs'] as $attr => $aParts){
1655
+ $contentStr .= " <$schemaPrefix:attribute";
1656
+ foreach ($aParts as $a => $v) {
1657
+ if ($a == 'ref' || $a == 'type') {
1658
+ $contentStr .= " $a=\"".$this->contractQName($v).'"';
1659
+ } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
1660
+ $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
1661
+ $contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"';
1662
+ } else {
1663
+ $contentStr .= " $a=\"$v\"";
1664
+ }
1665
+ }
1666
+ $contentStr .= "/>\n";
1667
+ }
1668
+ }
1669
+ // if restriction
1670
+ if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){
1671
+ $contentStr = " <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr." </$schemaPrefix:restriction>\n";
1672
+ // complex or simple content
1673
+ if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){
1674
+ $contentStr = " <$schemaPrefix:complexContent>\n".$contentStr." </$schemaPrefix:complexContent>\n";
1675
+ }
1676
+ }
1677
+ // finalize complex type
1678
+ if($contentStr != ''){
1679
+ $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n";
1680
+ } else {
1681
+ $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
1682
+ }
1683
+ $xml .= $contentStr;
1684
+ }
1685
+ // simple types
1686
+ if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){
1687
+ foreach($this->simpleTypes as $typeName => $eParts){
1688
+ $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\">\n";
1689
+ if (isset($eParts['enumeration'])) {
1690
+ foreach ($eParts['enumeration'] as $e) {
1691
+ $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n";
1692
+ }
1693
+ }
1694
+ $xml .= " </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
1695
+ }
1696
+ }
1697
+ // elements
1698
+ if(isset($this->elements) && count($this->elements) > 0){
1699
+ foreach($this->elements as $element => $eParts){
1700
+ $xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n";
1701
+ }
1702
+ }
1703
+ // attributes
1704
+ if(isset($this->attributes) && count($this->attributes) > 0){
1705
+ foreach($this->attributes as $attr => $aParts){
1706
+ $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>";
1707
+ }
1708
+ }
1709
+ // finish 'er up
1710
+ $attr = '';
1711
+ foreach ($this->schemaInfo as $k => $v) {
1712
+ if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {
1713
+ $attr .= " $k=\"$v\"";
1714
+ }
1715
+ }
1716
+ $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
1717
+ foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
1718
+ $el .= " xmlns:$nsp=\"$ns\"";
1719
+ }
1720
+ $xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
1721
+ return $xml;
1722
+ }
1723
+
1724
+ /**
1725
+ * adds debug data to the clas level debug string
1726
+ *
1727
+ * @param string $string debug data
1728
+ * @access private
1729
+ */
1730
+ function xdebug($string){
1731
+ $this->debug('<' . $this->schemaTargetNamespace . '> '.$string);
1732
+ }
1733
+
1734
+ /**
1735
+ * get the PHP type of a user defined type in the schema
1736
+ * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays
1737
+ * returns false if no type exists, or not w/ the given namespace
1738
+ * else returns a string that is either a native php type, or 'struct'
1739
+ *
1740
+ * @param string $type name of defined type
1741
+ * @param string $ns namespace of type
1742
+ * @return mixed
1743
+ * @access public
1744
+ * @deprecated
1745
+ */
1746
+ function getPHPType($type,$ns){
1747
+ if(isset($this->typemap[$ns][$type])){
1748
+ //print "found type '$type' and ns $ns in typemap<br>";
1749
+ return $this->typemap[$ns][$type];
1750
+ } elseif(isset($this->complexTypes[$type])){
1751
+ //print "getting type '$type' and ns $ns from complexTypes array<br>";
1752
+ return $this->complexTypes[$type]['phpType'];
1753
+ }
1754
+ return false;
1755
+ }
1756
+
1757
+ /**
1758
+ * returns an associative array of information about a given type
1759
+ * returns false if no type exists by the given name
1760
+ *
1761
+ * For a complexType typeDef = array(
1762
+ * 'restrictionBase' => '',
1763
+ * 'phpType' => '',
1764
+ * 'compositor' => '(sequence|all)',
1765
+ * 'elements' => array(), // refs to elements array
1766
+ * 'attrs' => array() // refs to attributes array
1767
+ * ... and so on (see addComplexType)
1768
+ * )
1769
+ *
1770
+ * For simpleType or element, the array has different keys.
1771
+ *
1772
+ * @param string $type
1773
+ * @return mixed
1774
+ * @access public
1775
+ * @see addComplexType
1776
+ * @see addSimpleType
1777
+ * @see addElement
1778
+ */
1779
+ function getTypeDef($type){
1780
+ //$this->debug("in getTypeDef for type $type");
1781
+ if (substr($type, -1) == '^') {
1782
+ $is_element = 1;
1783
+ $type = substr($type, 0, -1);
1784
+ } else {
1785
+ $is_element = 0;
1786
+ }
1787
+
1788
+ if((! $is_element) && isset($this->complexTypes[$type])){
1789
+ $this->xdebug("in getTypeDef, found complexType $type");
1790
+ return $this->complexTypes[$type];
1791
+ } elseif((! $is_element) && isset($this->simpleTypes[$type])){
1792
+ $this->xdebug("in getTypeDef, found simpleType $type");
1793
+ if (!isset($this->simpleTypes[$type]['phpType'])) {
1794
+ // get info for type to tack onto the simple type
1795
+ // TODO: can this ever really apply (i.e. what is a simpleType really?)
1796
+ $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
1797
+ $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
1798
+ $etype = $this->getTypeDef($uqType);
1799
+ if ($etype) {
1800
+ $this->xdebug("in getTypeDef, found type for simpleType $type:");
1801
+ $this->xdebug($this->varDump($etype));
1802
+ if (isset($etype['phpType'])) {
1803
+ $this->simpleTypes[$type]['phpType'] = $etype['phpType'];
1804
+ }
1805
+ if (isset($etype['elements'])) {
1806
+ $this->simpleTypes[$type]['elements'] = $etype['elements'];
1807
+ }
1808
+ }
1809
+ }
1810
+ return $this->simpleTypes[$type];
1811
+ } elseif(isset($this->elements[$type])){
1812
+ $this->xdebug("in getTypeDef, found element $type");
1813
+ if (!isset($this->elements[$type]['phpType'])) {
1814
+ // get info for type to tack onto the element
1815
+ $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
1816
+ $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
1817
+ $etype = $this->getTypeDef($uqType);
1818
+ if ($etype) {
1819
+ $this->xdebug("in getTypeDef, found type for element $type:");
1820
+ $this->xdebug($this->varDump($etype));
1821
+ if (isset($etype['phpType'])) {
1822
+ $this->elements[$type]['phpType'] = $etype['phpType'];
1823
+ }
1824
+ if (isset($etype['elements'])) {
1825
+ $this->elements[$type]['elements'] = $etype['elements'];
1826
+ }
1827
+ } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
1828
+ $this->xdebug("in getTypeDef, element $type is an XSD type");
1829
+ $this->elements[$type]['phpType'] = 'scalar';
1830
+ }
1831
+ }
1832
+ return $this->elements[$type];
1833
+ } elseif(isset($this->attributes[$type])){
1834
+ $this->xdebug("in getTypeDef, found attribute $type");
1835
+ return $this->attributes[$type];
1836
+ } elseif (ereg('_ContainedType$', $type)) {
1837
+ $this->xdebug("in getTypeDef, have an untyped element $type");
1838
+ $typeDef['typeClass'] = 'simpleType';
1839
+ $typeDef['phpType'] = 'scalar';
1840
+ $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
1841
+ return $typeDef;
1842
+ }
1843
+ $this->xdebug("in getTypeDef, did not find $type");
1844
+ return false;
1845
+ }
1846
+
1847
+ /**
1848
+ * returns a sample serialization of a given type, or false if no type by the given name
1849
+ *
1850
+ * @param string $type name of type
1851
+ * @return mixed
1852
+ * @access public
1853
+ * @deprecated
1854
+ */
1855
+ function serializeTypeDef($type){
1856
+ //print "in sTD() for type $type<br>";
1857
+ if($typeDef = $this->getTypeDef($type)){
1858
+ $str .= '<'.$type;
1859
+ if(is_array($typeDef['attrs'])){
1860
+ foreach($typeDef['attrs'] as $attName => $data){
1861
+ $str .= " $attName=\"{type = ".$data['type']."}\"";
1862
+ }
1863
+ }
1864
+ $str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
1865
+ if(count($typeDef['elements']) > 0){
1866
+ $str .= ">";
1867
+ foreach($typeDef['elements'] as $element => $eData){
1868
+ $str .= $this->serializeTypeDef($element);
1869
+ }
1870
+ $str .= "</$type>";
1871
+ } elseif($typeDef['typeClass'] == 'element') {
1872
+ $str .= "></$type>";
1873
+ } else {
1874
+ $str .= "/>";
1875
+ }
1876
+ return $str;
1877
+ }
1878
+ return false;
1879
+ }
1880
+
1881
+ /**
1882
+ * returns HTML form elements that allow a user
1883
+ * to enter values for creating an instance of the given type.
1884
+ *
1885
+ * @param string $name name for type instance
1886
+ * @param string $type name of type
1887
+ * @return string
1888
+ * @access public
1889
+ * @deprecated
1890
+ */
1891
+ function typeToForm($name,$type){
1892
+ // get typedef
1893
+ if($typeDef = $this->getTypeDef($type)){
1894
+ // if struct
1895
+ if($typeDef['phpType'] == 'struct'){
1896
+ $buffer .= '<table>';
1897
+ foreach($typeDef['elements'] as $child => $childDef){
1898
+ $buffer .= "
1899
+ <tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>
1900
+ <td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";
1901
+ }
1902
+ $buffer .= '</table>';
1903
+ // if array
1904
+ } elseif($typeDef['phpType'] == 'array'){
1905
+ $buffer .= '<table>';
1906
+ for($i=0;$i < 3; $i++){
1907
+ $buffer .= "
1908
+ <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
1909
+ <td><input type='text' name='parameters[".$name."][]'></td></tr>";
1910
+ }
1911
+ $buffer .= '</table>';
1912
+ // if scalar
1913
+ } else {
1914
+ $buffer .= "<input type='text' name='parameters[$name]'>";
1915
+ }
1916
+ } else {
1917
+ $buffer .= "<input type='text' name='parameters[$name]'>";
1918
+ }
1919
+ return $buffer;
1920
+ }
1921
+
1922
+ /**
1923
+ * adds a complex type to the schema
1924
+ *
1925
+ * example: array
1926
+ *
1927
+ * addType(
1928
+ * 'ArrayOfstring',
1929
+ * 'complexType',
1930
+ * 'array',
1931
+ * '',
1932
+ * 'SOAP-ENC:Array',
1933
+ * array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),
1934
+ * 'xsd:string'
1935
+ * );
1936
+ *
1937
+ * example: PHP associative array ( SOAP Struct )
1938
+ *
1939
+ * addType(
1940
+ * 'SOAPStruct',
1941
+ * 'complexType',
1942
+ * 'struct',
1943
+ * 'all',
1944
+ * array('myVar'=> array('name'=>'myVar','type'=>'string')
1945
+ * );
1946
+ *
1947
+ * @param name
1948
+ * @param typeClass (complexType|simpleType|attribute)
1949
+ * @param phpType: currently supported are array and struct (php assoc array)
1950
+ * @param compositor (all|sequence|choice)
1951
+ * @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
1952
+ * @param elements = array ( name = array(name=>'',type=>'') )
1953
+ * @param attrs = array(
1954
+ * array(
1955
+ * 'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",
1956
+ * "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"
1957
+ * )
1958
+ * )
1959
+ * @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)
1960
+ * @access public
1961
+ * @see getTypeDef
1962
+ */
1963
+ function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){
1964
+ $this->complexTypes[$name] = array(
1965
+ 'name' => $name,
1966
+ 'typeClass' => $typeClass,
1967
+ 'phpType' => $phpType,
1968
+ 'compositor'=> $compositor,
1969
+ 'restrictionBase' => $restrictionBase,
1970
+ 'elements' => $elements,
1971
+ 'attrs' => $attrs,
1972
+ 'arrayType' => $arrayType
1973
+ );
1974
+
1975
+ $this->xdebug("addComplexType $name:");
1976
+ $this->appendDebug($this->varDump($this->complexTypes[$name]));
1977
+ }
1978
+
1979
+ /**
1980
+ * adds a simple type to the schema
1981
+ *
1982
+ * @param string $name
1983
+ * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
1984
+ * @param string $typeClass (should always be simpleType)
1985
+ * @param string $phpType (should always be scalar)
1986
+ * @param array $enumeration array of values
1987
+ * @access public
1988
+ * @see nusoap_xmlschema
1989
+ * @see getTypeDef
1990
+ */
1991
+ function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
1992
+ $this->simpleTypes[$name] = array(
1993
+ 'name' => $name,
1994
+ 'typeClass' => $typeClass,
1995
+ 'phpType' => $phpType,
1996
+ 'type' => $restrictionBase,
1997
+ 'enumeration' => $enumeration
1998
+ );
1999
+
2000
+ $this->xdebug("addSimpleType $name:");
2001
+ $this->appendDebug($this->varDump($this->simpleTypes[$name]));
2002
+ }
2003
+
2004
+ /**
2005
+ * adds an element to the schema
2006
+ *
2007
+ * @param array $attrs attributes that must include name and type
2008
+ * @see nusoap_xmlschema
2009
+ * @access public
2010
+ */
2011
+ function addElement($attrs) {
2012
+ if (! $this->getPrefix($attrs['type'])) {
2013
+ $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
2014
+ }
2015
+ $this->elements[ $attrs['name'] ] = $attrs;
2016
+ $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
2017
+
2018
+ $this->xdebug("addElement " . $attrs['name']);
2019
+ $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
2020
+ }
2021
+ }
2022
+
2023
+ /**
2024
+ * Backward compatibility
2025
+ */
2026
+ class XMLSchema extends nusoap_xmlschema {
2027
+ }
2028
+
2029
+ ?><?php
2030
+
2031
+
2032
+
2033
+ /**
2034
+ * For creating serializable abstractions of native PHP types. This class
2035
+ * allows element name/namespace, XSD type, and XML attributes to be
2036
+ * associated with a value. This is extremely useful when WSDL is not
2037
+ * used, but is also useful when WSDL is used with polymorphic types, including
2038
+ * xsd:anyType and user-defined types.
2039
+ *
2040
+ * @author Dietrich Ayala <dietrich@ganx4.com>
2041
+ * @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $
2042
+ * @access public
2043
+ */
2044
+ class soapval extends nusoap_base {
2045
+ /**
2046
+ * The XML element name
2047
+ *
2048
+ * @var string
2049
+ * @access private
2050
+ */
2051
+ var $name;
2052
+ /**
2053
+ * The XML type name (string or false)
2054
+ *
2055
+ * @var mixed
2056
+ * @access private
2057
+ */
2058
+ var $type;
2059
+ /**
2060
+ * The PHP value
2061
+ *
2062
+ * @var mixed
2063
+ * @access private
2064
+ */
2065
+ var $value;
2066
+ /**
2067
+ * The XML element namespace (string or false)
2068
+ *
2069
+ * @var mixed
2070
+ * @access private
2071
+ */
2072
+ var $element_ns;
2073
+ /**
2074
+ * The XML type namespace (string or false)
2075
+ *
2076
+ * @var mixed
2077
+ * @access private
2078
+ */
2079
+ var $type_ns;
2080
+ /**
2081
+ * The XML element attributes (array or false)
2082
+ *
2083
+ * @var mixed
2084
+ * @access private
2085
+ */
2086
+ var $attributes;
2087
+
2088
+ /**
2089
+ * constructor
2090
+ *
2091
+ * @param string $name optional name
2092
+ * @param mixed $type optional type name
2093
+ * @param mixed $value optional value
2094
+ * @param mixed $element_ns optional namespace of value
2095
+ * @param mixed $type_ns optional namespace of type
2096
+ * @param mixed $attributes associative array of attributes to add to element serialization
2097
+ * @access public
2098
+ */
2099
+ function soapval($name='soapval',$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false) {
2100
+ parent::nusoap_base();
2101
+ $this->name = $name;
2102
+ $this->type = $type;
2103
+ $this->value = $value;
2104
+ $this->element_ns = $element_ns;
2105
+ $this->type_ns = $type_ns;
2106
+ $this->attributes = $attributes;
2107
+ }
2108
+
2109
+ /**
2110
+ * return serialized value
2111
+ *
2112
+ * @param string $use The WSDL use value (encoded|literal)
2113
+ * @return string XML data
2114
+ * @access public
2115
+ */
2116
+ function serialize($use='encoded') {
2117
+ return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true);
2118
+ }
2119
+
2120
+ /**
2121
+ * decodes a soapval object into a PHP native type
2122
+ *
2123
+ * @return mixed
2124
+ * @access public
2125
+ */
2126
+ function decode(){
2127
+ return $this->value;
2128
+ }
2129
+ }
2130
+
2131
+
2132
+
2133
+ ?><?php
2134
+
2135
+
2136
+
2137
+ /**
2138
+ * transport class for sending/receiving data via HTTP and HTTPS
2139
+ * NOTE: PHP must be compiled with the CURL extension for HTTPS support
2140
+ *
2141
+ * @author Dietrich Ayala <dietrich@ganx4.com>
2142
+ * @author Scott Nichol <snichol@users.sourceforge.net>
2143
+ * @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $
2144
+ * @access public
2145
+ */
2146
+ class soap_transport_http extends nusoap_base {
2147
+
2148
+ var $url = '';
2149
+ var $uri = '';
2150
+ var $digest_uri = '';
2151
+ var $scheme = '';
2152
+ var $host = '';
2153
+ var $port = '';
2154
+ var $path = '';
2155
+ var $request_method = 'POST';
2156
+ var $protocol_version = '1.0';
2157
+ var $encoding = '';
2158
+ var $outgoing_headers = array();
2159
+ var $incoming_headers = array();
2160
+ var $incoming_cookies = array();
2161
+ var $outgoing_payload = '';
2162
+ var $incoming_payload = '';
2163
+ var $response_status_line; // HTTP response status line
2164
+ var $useSOAPAction = true;
2165
+ var $persistentConnection = false;
2166
+ var $ch = false; // cURL handle
2167
+ var $ch_options = array(); // cURL custom options
2168
+ var $use_curl = false; // force cURL use
2169
+ var $proxy = null; // proxy information (associative array)
2170
+ var $username = '';
2171
+ var $password = '';
2172
+ var $authtype = '';
2173
+ var $digestRequest = array();
2174
+ var $certRequest = array(); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional)
2175
+ // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'
2176
+ // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
2177
+ // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'
2178
+ // passphrase: SSL key password/passphrase
2179
+ // certpassword: SSL certificate password
2180
+ // verifypeer: default is 1
2181
+ // verifyhost: default is 1
2182
+
2183
+ /**
2184
+ * constructor
2185
+ *
2186
+ * @param string $url The URL to which to connect
2187
+ * @param array $curl_options User-specified cURL options
2188
+ * @param boolean $use_curl Whether to try to force cURL use
2189
+ * @access public
2190
+ */
2191
+ function soap_transport_http($url, $curl_options = NULL, $use_curl = false){
2192
+ parent::nusoap_base();
2193
+ $this->debug("ctor url=$url use_curl=$use_curl curl_options:");
2194
+ $this->appendDebug($this->varDump($curl_options));
2195
+ $this->setURL($url);
2196
+ if (is_array($curl_options)) {
2197
+ $this->ch_options = $curl_options;
2198
+ }
2199
+ $this->use_curl = $use_curl;
2200
+ ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev);
2201
+ $this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')');
2202
+ }
2203
+
2204
+ /**
2205
+ * sets a cURL option
2206
+ *
2207
+ * @param mixed $option The cURL option (always integer?)
2208
+ * @param mixed $value The cURL option value
2209
+ * @access private
2210
+ */
2211
+ function setCurlOption($option, $value) {
2212
+ $this->debug("setCurlOption option=$option, value=");
2213
+ $this->appendDebug($this->varDump($value));
2214
+ curl_setopt($this->ch, $option, $value);
2215
+ }
2216
+
2217
+ /**
2218
+ * sets an HTTP header
2219
+ *
2220
+ * @param string $name The name of the header
2221
+ * @param string $value The value of the header
2222
+ * @access private
2223
+ */
2224
+ function setHeader($name, $value) {
2225
+ $this->outgoing_headers[$name] = $value;
2226
+ $this->debug("set header $name: $value");
2227
+ }
2228
+
2229
+ /**
2230
+ * unsets an HTTP header
2231
+ *
2232
+ * @param string $name The name of the header
2233
+ * @access private
2234
+ */
2235
+ function unsetHeader($name) {
2236
+ if (isset($this->outgoing_headers[$name])) {
2237
+ $this->debug("unset header $name");
2238
+ unset($this->outgoing_headers[$name]);
2239
+ }
2240
+ }
2241
+
2242
+ /**
2243
+ * sets the URL to which to connect
2244
+ *
2245
+ * @param string $url The URL to which to connect
2246
+ * @access private
2247
+ */
2248
+ function setURL($url) {
2249
+ $this->url = $url;
2250
+
2251
+ $u = parse_url($url);
2252
+ foreach($u as $k => $v){
2253
+ $this->debug("parsed URL $k = $v");
2254
+ $this->$k = $v;
2255
+ }
2256
+
2257
+ // add any GET params to path
2258
+ if(isset($u['query']) && $u['query'] != ''){
2259
+ $this->path .= '?' . $u['query'];
2260
+ }
2261
+
2262
+ // set default port
2263
+ if(!isset($u['port'])){
2264
+ if($u['scheme'] == 'https'){
2265
+ $this->port = 443;
2266
+ } else {
2267
+ $this->port = 80;
2268
+ }
2269
+ }
2270
+
2271
+ $this->uri = $this->path;
2272
+ $this->digest_uri = $this->uri;
2273
+
2274
+ // build headers
2275
+ if (!isset($u['port'])) {
2276
+ $this->setHeader('Host', $this->host);
2277
+ } else {
2278
+ $this->setHeader('Host', $this->host.':'.$this->port);
2279
+ }
2280
+
2281
+ if (isset($u['user']) && $u['user'] != '') {
2282
+ $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : '');
2283
+ }
2284
+ }
2285
+
2286
+ /**
2287
+ * gets the I/O method to use
2288
+ *
2289
+ * @return string I/O method to use (socket|curl|unknown)
2290
+ * @access private
2291
+ */
2292
+ function io_method() {
2293
+ if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm'))
2294
+ return 'curl';
2295
+ if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm'))
2296
+ return 'socket';
2297
+ return 'unknown';
2298
+ }
2299
+
2300
+ /**
2301
+ * establish an HTTP connection
2302
+ *
2303
+ * @param integer $timeout set connection timeout in seconds
2304
+ * @param integer $response_timeout set response timeout in seconds
2305
+ * @return boolean true if connected, false if not
2306
+ * @access private
2307
+ */
2308
+ function connect($connection_timeout=0,$response_timeout=30){
2309
+ // For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like
2310
+ // "regular" socket.
2311
+ // TODO: disabled for now because OpenSSL must be *compiled* in (not just
2312
+ // loaded), and until PHP5 stream_get_wrappers is not available.
2313
+ // if ($this->scheme == 'https') {
2314
+ // if (version_compare(phpversion(), '4.3.0') >= 0) {
2315
+ // if (extension_loaded('openssl')) {
2316
+ // $this->scheme = 'ssl';
2317
+ // $this->debug('Using SSL over OpenSSL');
2318
+ // }
2319
+ // }
2320
+ // }
2321
+ $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
2322
+ if ($this->io_method() == 'socket') {
2323
+ if (!is_array($this->proxy)) {
2324
+ $host = $this->host;
2325
+ $port = $this->port;
2326
+ } else {
2327
+ $host = $this->proxy['host'];
2328
+ $port = $this->proxy['port'];
2329
+ }
2330
+
2331
+ // use persistent connection
2332
+ if($this->persistentConnection && isset($this->fp) && is_resource($this->fp)){
2333
+ if (!feof($this->fp)) {
2334
+ $this->debug('Re-use persistent connection');
2335
+ return true;
2336
+ }
2337
+ fclose($this->fp);
2338
+ $this->debug('Closed persistent connection at EOF');
2339
+ }
2340
+
2341
+ // munge host if using OpenSSL
2342
+ if ($this->scheme == 'ssl') {
2343
+ $host = 'ssl://' . $host;
2344
+ }
2345
+ $this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);
2346
+
2347
+ // open socket
2348
+ if($connection_timeout > 0){
2349
+ $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str, $connection_timeout);
2350
+ } else {
2351
+ $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str);
2352
+ }
2353
+
2354
+ // test pointer
2355
+ if(!$this->fp) {
2356
+ $msg = 'Couldn\'t open socket connection to server ' . $this->url;
2357
+ if ($this->errno) {
2358
+ $msg .= ', Error ('.$this->errno.'): '.$this->error_str;
2359
+ } else {
2360
+ $msg .= ' prior to connect(). This is often a problem looking up the host name.';
2361
+ }
2362
+ $this->debug($msg);
2363
+ $this->setError($msg);
2364
+ return false;
2365
+ }
2366
+
2367
+ // set response timeout
2368
+ $this->debug('set response timeout to ' . $response_timeout);
2369
+ socket_set_timeout( $this->fp, $response_timeout);
2370
+
2371
+ $this->debug('socket connected');
2372
+ return true;
2373
+ } else if ($this->io_method() == 'curl') {
2374
+ if (!extension_loaded('curl')) {
2375
+ // $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
2376
+ $this->setError('The PHP cURL Extension is required for HTTPS or NLTM. You will need to re-build or update your PHP to included cURL.');
2377
+ return false;
2378
+ }
2379
+ // Avoid warnings when PHP does not have these options
2380
+ if (defined('CURLOPT_CONNECTIONTIMEOUT'))
2381
+ $CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT;
2382
+ else
2383
+ $CURLOPT_CONNECTIONTIMEOUT = 78;
2384
+ if (defined('CURLOPT_HTTPAUTH'))
2385
+ $CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH;
2386
+ else
2387
+ $CURLOPT_HTTPAUTH = 107;
2388
+ if (defined('CURLOPT_PROXYAUTH'))
2389
+ $CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH;
2390
+ else
2391
+ $CURLOPT_PROXYAUTH = 111;
2392
+ if (defined('CURLAUTH_BASIC'))
2393
+ $CURLAUTH_BASIC = CURLAUTH_BASIC;
2394
+ else
2395
+ $CURLAUTH_BASIC = 1;
2396
+ if (defined('CURLAUTH_DIGEST'))
2397
+ $CURLAUTH_DIGEST = CURLAUTH_DIGEST;
2398
+ else
2399
+ $CURLAUTH_DIGEST = 2;
2400
+ if (defined('CURLAUTH_NTLM'))
2401
+ $CURLAUTH_NTLM = CURLAUTH_NTLM;
2402
+ else
2403
+ $CURLAUTH_NTLM = 8;
2404
+
2405
+ $this->debug('connect using cURL');
2406
+ // init CURL
2407
+ $this->ch = curl_init();
2408
+ // set url
2409
+ $hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host";
2410
+ // add path
2411
+ $hostURL .= $this->path;
2412
+ $this->setCurlOption(CURLOPT_URL, $hostURL);
2413
+ // follow location headers (re-directs)
2414
+ if (ini_get('safe_mode') || ini_get('open_basedir')) {
2415
+ $this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION');
2416
+ $this->debug('safe_mode = ');
2417
+ $this->appendDebug($this->varDump(ini_get('safe_mode')));
2418
+ $this->debug('open_basedir = ');
2419
+ $this->appendDebug($this->varDump(ini_get('open_basedir')));
2420
+ } else {
2421
+ $this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1);
2422
+ }
2423
+ // ask for headers in the response output
2424
+ $this->setCurlOption(CURLOPT_HEADER, 1);
2425
+ // ask for the response output as the return value
2426
+ $this->setCurlOption(CURLOPT_RETURNTRANSFER, 1);
2427
+ // encode
2428
+ // We manage this ourselves through headers and encoding
2429
+ // if(function_exists('gzuncompress')){
2430
+ // $this->setCurlOption(CURLOPT_ENCODING, 'deflate');
2431
+ // }
2432
+ // persistent connection
2433
+ if ($this->persistentConnection) {
2434
+ // I believe the following comment is now bogus, having applied to
2435
+ // the code when it used CURLOPT_CUSTOMREQUEST to send the request.
2436
+ // The way we send data, we cannot use persistent connections, since
2437
+ // there will be some "junk" at the end of our request.
2438
+ //$this->setCurlOption(CURL_HTTP_VERSION_1_1, true);
2439
+ $this->persistentConnection = false;
2440
+ $this->setHeader('Connection', 'close');
2441
+ }
2442
+ // set timeouts
2443
+ if ($connection_timeout != 0) {
2444
+ $this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);
2445
+ }
2446
+ if ($response_timeout != 0) {
2447
+ $this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout);
2448
+ }
2449
+
2450
+ if ($this->scheme == 'https') {
2451
+ $this->debug('set cURL SSL verify options');
2452
+ // recent versions of cURL turn on peer/host checking by default,
2453
+ // while PHP binaries are not compiled with a default location for the
2454
+ // CA cert bundle, so disable peer/host checking.
2455
+ //$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');
2456
+ $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0);
2457
+ $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0);
2458
+
2459
+ // support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)
2460
+ if ($this->authtype == 'certificate') {
2461
+ $this->debug('set cURL certificate options');
2462
+ if (isset($this->certRequest['cainfofile'])) {
2463
+ $this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']);
2464
+ }
2465
+ if (isset($this->certRequest['verifypeer'])) {
2466
+ $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);
2467
+ } else {
2468
+ $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1);
2469
+ }
2470
+ if (isset($this->certRequest['verifyhost'])) {
2471
+ $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);
2472
+ } else {
2473
+ $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1);
2474
+ }
2475
+ if (isset($this->certRequest['sslcertfile'])) {
2476
+ $this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);
2477
+ }
2478
+ if (isset($this->certRequest['sslkeyfile'])) {
2479
+ $this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);
2480
+ }
2481
+ if (isset($this->certRequest['passphrase'])) {
2482
+ $this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']);
2483
+ }
2484
+ if (isset($this->certRequest['certpassword'])) {
2485
+ $this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']);
2486
+ }
2487
+ }
2488
+ }
2489
+ if ($this->authtype && ($this->authtype != 'certificate')) {
2490
+ if ($this->username) {
2491
+ $this->debug('set cURL username/password');
2492
+ $this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password");
2493
+ }
2494
+ if ($this->authtype == 'basic') {
2495
+ $this->debug('set cURL for Basic authentication');
2496
+ $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC);
2497
+ }
2498
+ if ($this->authtype == 'digest') {
2499
+ $this->debug('set cURL for digest authentication');
2500
+ $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST);
2501
+ }
2502
+ if ($this->authtype == 'ntlm') {
2503
+ $this->debug('set cURL for NTLM authentication');
2504
+ $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM);
2505
+ }
2506
+ }
2507
+ if (is_array($this->proxy)) {
2508
+ $this->debug('set cURL proxy options');
2509
+ if ($this->proxy['port'] != '') {
2510
+ $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'].':'.$this->proxy['port']);
2511
+ } else {
2512
+ $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']);
2513
+ }
2514
+ if ($this->proxy['username'] || $this->proxy['password']) {
2515
+ $this->debug('set cURL proxy authentication options');
2516
+ $this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'].':'.$this->proxy['password']);
2517
+ if ($this->proxy['authtype'] == 'basic') {
2518
+ $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC);
2519
+ }
2520
+ if ($this->proxy['authtype'] == 'ntlm') {
2521
+ $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM);
2522
+ }
2523
+ }
2524
+ }
2525
+ $this->debug('cURL connection set up');
2526
+ return true;
2527
+ } else {
2528
+ $this->setError('Unknown scheme ' . $this->scheme);
2529
+ $this->debug('Unknown scheme ' . $this->scheme);
2530
+ return false;
2531
+ }
2532
+ }
2533
+
2534
+ /**
2535
+ * sends the SOAP request and gets the SOAP response via HTTP[S]
2536
+ *
2537
+ * @param string $data message data
2538
+ * @param integer $timeout set connection timeout in seconds
2539
+ * @param integer $response_timeout set response timeout in seconds
2540
+ * @param array $cookies cookies to send
2541
+ * @return string data
2542
+ * @access public
2543
+ */
2544
+ function send($data, $timeout=0, $response_timeout=30, $cookies=NULL) {
2545
+
2546
+ $this->debug('entered send() with data of length: '.strlen($data));
2547
+
2548
+ $this->tryagain = true;
2549
+ $tries = 0;
2550
+ while ($this->tryagain) {
2551
+ $this->tryagain = false;
2552
+ if ($tries++ < 2) {
2553
+ // make connnection
2554
+ if (!$this->connect($timeout, $response_timeout)){
2555
+ return false;
2556
+ }
2557
+
2558
+ // send request
2559
+ if (!$this->sendRequest($data, $cookies)){
2560
+ return false;
2561
+ }
2562
+
2563
+ // get response
2564
+ $respdata = $this->getResponse();
2565
+ } else {
2566
+ $this->setError("Too many tries to get an OK response ($this->response_status_line)");
2567
+ }
2568
+ }
2569
+ $this->debug('end of send()');
2570
+ return $respdata;
2571
+ }
2572
+
2573
+
2574
+ /**
2575
+ * sends the SOAP request and gets the SOAP response via HTTPS using CURL
2576
+ *
2577
+ * @param string $data message data
2578
+ * @param integer $timeout set connection timeout in seconds
2579
+ * @param integer $response_timeout set response timeout in seconds
2580
+ * @param array $cookies cookies to send
2581
+ * @return string data
2582
+ * @access public
2583
+ * @deprecated
2584
+ */
2585
+ function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies) {
2586
+ return $this->send($data, $timeout, $response_timeout, $cookies);
2587
+ }
2588
+
2589
+ /**
2590
+ * if authenticating, set user credentials here
2591
+ *
2592
+ * @param string $username
2593
+ * @param string $password
2594
+ * @param string $authtype (basic|digest|certificate|ntlm)
2595
+ * @param array $digestRequest (keys must be nonce, nc, realm, qop)
2596
+ * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
2597
+ * @access public
2598
+ */
2599
+ function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array()) {
2600
+ $this->debug("setCredentials username=$username authtype=$authtype digestRequest=");
2601
+ $this->appendDebug($this->varDump($digestRequest));
2602
+ $this->debug("certRequest=");
2603
+ $this->appendDebug($this->varDump($certRequest));
2604
+ // cf. RFC 2617
2605
+ if ($authtype == 'basic') {
2606
+ $this->setHeader('Authorization', 'Basic '.base64_encode(str_replace(':','',$username).':'.$password));
2607
+ } elseif ($authtype == 'digest') {
2608
+ if (isset($digestRequest['nonce'])) {
2609
+ $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
2610
+
2611
+ // calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)
2612
+
2613
+ // A1 = unq(username-value) ":" unq(realm-value) ":" passwd
2614
+ $A1 = $username. ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password;
2615
+
2616
+ // H(A1) = MD5(A1)
2617
+ $HA1 = md5($A1);
2618
+
2619
+ // A2 = Method ":" digest-uri-value
2620
+ $A2 = $this->request_method . ':' . $this->digest_uri;
2621
+
2622
+ // H(A2)
2623
+ $HA2 = md5($A2);
2624
+
2625
+ // KD(secret, data) = H(concat(secret, ":", data))
2626
+ // if qop == auth:
2627
+ // request-digest = <"> < KD ( H(A1), unq(nonce-value)
2628
+ // ":" nc-value
2629
+ // ":" unq(cnonce-value)
2630
+ // ":" unq(qop-value)
2631
+ // ":" H(A2)
2632
+ // ) <">
2633
+ // if qop is missing,
2634
+ // request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
2635
+
2636
+ $unhashedDigest = '';
2637
+ $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';
2638
+ $cnonce = $nonce;
2639
+ if ($digestRequest['qop'] != '') {
2640
+ $unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
2641
+ } else {
2642
+ $unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
2643
+ }
2644
+
2645
+ $hashedDigest = md5($unhashedDigest);
2646
+
2647
+ $opaque = '';
2648
+ if (isset($digestRequest['opaque'])) {
2649
+ $opaque = ', opaque="' . $digestRequest['opaque'] . '"';
2650
+ }
2651
+
2652
+ $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 . '"');
2653
+ }
2654
+ } elseif ($authtype == 'certificate') {
2655
+ $this->certRequest = $certRequest;
2656
+ $this->debug('Authorization header not set for certificate');
2657
+ } elseif ($authtype == 'ntlm') {
2658
+ // do nothing
2659
+ $this->debug('Authorization header not set for ntlm');
2660
+ }
2661
+ $this->username = $username;
2662
+ $this->password = $password;
2663
+ $this->authtype = $authtype;
2664
+ $this->digestRequest = $digestRequest;
2665
+ }
2666
+
2667
+ /**
2668
+ * set the soapaction value
2669
+ *
2670
+ * @param string $soapaction
2671
+ * @access public
2672
+ */
2673
+ function setSOAPAction($soapaction) {
2674
+ $this->setHeader('SOAPAction', '"' . $soapaction . '"');
2675
+ }
2676
+
2677
+ /**
2678
+ * use http encoding
2679
+ *
2680
+ * @param string $enc encoding style. supported values: gzip, deflate, or both
2681
+ * @access public
2682
+ */
2683
+ function setEncoding($enc='gzip, deflate') {
2684
+ if (function_exists('gzdeflate')) {
2685
+ $this->protocol_version = '1.1';
2686
+ $this->setHeader('Accept-Encoding', $enc);
2687
+ if (!isset($this->outgoing_headers['Connection'])) {
2688
+ $this->setHeader('Connection', 'close');
2689
+ $this->persistentConnection = false;
2690
+ }
2691
+ set_magic_quotes_runtime(0);
2692
+ // deprecated
2693
+ $this->encoding = $enc;
2694
+ }
2695
+ }
2696
+
2697
+ /**
2698
+ * set proxy info here
2699
+ *
2700
+ * @param string $proxyhost use an empty string to remove proxy
2701
+ * @param string $proxyport
2702
+ * @param string $proxyusername
2703
+ * @param string $proxypassword
2704
+ * @param string $proxyauthtype (basic|ntlm)
2705
+ * @access public
2706
+ */
2707
+ function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic') {
2708
+ if ($proxyhost) {
2709
+ $this->proxy = array(
2710
+ 'host' => $proxyhost,
2711
+ 'port' => $proxyport,
2712
+ 'username' => $proxyusername,
2713
+ 'password' => $proxypassword,
2714
+ 'authtype' => $proxyauthtype
2715
+ );
2716
+ if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') {
2717
+ $this->setHeader('Proxy-Authorization', ' Basic '.base64_encode($proxyusername.':'.$proxypassword));
2718
+ }
2719
+ } else {
2720
+ $this->debug('remove proxy');
2721
+ $proxy = null;
2722
+ unsetHeader('Proxy-Authorization');
2723
+ }
2724
+ }
2725
+
2726
+
2727
+ /**
2728
+ * Test if the given string starts with a header that is to be skipped.
2729
+ * Skippable headers result from chunked transfer and proxy requests.
2730
+ *
2731
+ * @param string $data The string to check.
2732
+ * @returns boolean Whether a skippable header was found.
2733
+ * @access private
2734
+ */
2735
+ function isSkippableCurlHeader(&$data) {
2736
+ $skipHeaders = array( 'HTTP/1.1 100',
2737
+ 'HTTP/1.0 301',
2738
+ 'HTTP/1.1 301',
2739
+ 'HTTP/1.0 302',
2740
+ 'HTTP/1.1 302',
2741
+ 'HTTP/1.0 401',
2742
+ 'HTTP/1.1 401',
2743
+ 'HTTP/1.0 200 Connection established');
2744
+ foreach ($skipHeaders as $hd) {
2745
+ $prefix = substr($data, 0, strlen($hd));
2746
+ if ($prefix == $hd) return true;
2747
+ }
2748
+
2749
+ return false;
2750
+ }
2751
+
2752
+ /**
2753
+ * decode a string that is encoded w/ "chunked' transfer encoding
2754
+ * as defined in RFC2068 19.4.6
2755
+ *
2756
+ * @param string $buffer
2757
+ * @param string $lb
2758
+ * @returns string
2759
+ * @access public
2760
+ * @deprecated
2761
+ */
2762
+ function decodeChunked($buffer, $lb){
2763
+ // length := 0
2764
+ $length = 0;
2765
+ $new = '';
2766
+
2767
+ // read chunk-size, chunk-extension (if any) and CRLF
2768
+ // get the position of the linebreak
2769
+ $chunkend = strpos($buffer, $lb);
2770
+ if ($chunkend == FALSE) {
2771
+ $this->debug('no linebreak found in decodeChunked');
2772
+ return $new;
2773
+ }
2774
+ $temp = substr($buffer,0,$chunkend);
2775
+ $chunk_size = hexdec( trim($temp) );
2776
+ $chunkstart = $chunkend + strlen($lb);
2777
+ // while (chunk-size > 0) {
2778
+ while ($chunk_size > 0) {
2779
+ $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
2780
+ $chunkend = strpos( $buffer, $lb, $chunkstart + $chunk_size);
2781
+
2782
+ // Just in case we got a broken connection
2783
+ if ($chunkend == FALSE) {
2784
+ $chunk = substr($buffer,$chunkstart);
2785
+ // append chunk-data to entity-body
2786
+ $new .= $chunk;
2787
+ $length += strlen($chunk);
2788
+ break;
2789
+ }
2790
+
2791
+ // read chunk-data and CRLF
2792
+ $chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart);
2793
+ // append chunk-data to entity-body
2794
+ $new .= $chunk;
2795
+ // length := length + chunk-size
2796
+ $length += strlen($chunk);
2797
+ // read chunk-size and CRLF
2798
+ $chunkstart = $chunkend + strlen($lb);
2799
+
2800
+ $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
2801
+ if ($chunkend == FALSE) {
2802
+ break; //Just in case we got a broken connection
2803
+ }
2804
+ $temp = substr($buffer,$chunkstart,$chunkend-$chunkstart);
2805
+ $chunk_size = hexdec( trim($temp) );
2806
+ $chunkstart = $chunkend;
2807
+ }
2808
+ return $new;
2809
+ }
2810
+
2811
+ /**
2812
+ * Writes the payload, including HTTP headers, to $this->outgoing_payload.
2813
+ *
2814
+ * @param string $data HTTP body
2815
+ * @param string $cookie_str data for HTTP Cookie header
2816
+ * @return void
2817
+ * @access private
2818
+ */
2819
+ function buildPayload($data, $cookie_str = '') {
2820
+ // Note: for cURL connections, $this->outgoing_payload is ignored,
2821
+ // as is the Content-Length header, but these are still created as
2822
+ // debugging guides.
2823
+
2824
+ // add content-length header
2825
+ $this->setHeader('Content-Length', strlen($data));
2826
+
2827
+ // start building outgoing payload:
2828
+ if ($this->proxy) {
2829
+ $uri = $this->url;
2830
+ } else {
2831
+ $uri = $this->uri;
2832
+ }
2833
+ $req = "$this->request_method $uri HTTP/$this->protocol_version";
2834
+ $this->debug("HTTP request: $req");
2835
+ $this->outgoing_payload = "$req\r\n";
2836
+
2837
+ // loop thru headers, serializing
2838
+ foreach($this->outgoing_headers as $k => $v){
2839
+ $hdr = $k.': '.$v;
2840
+ $this->debug("HTTP header: $hdr");
2841
+ $this->outgoing_payload .= "$hdr\r\n";
2842
+ }
2843
+
2844
+ // add any cookies
2845
+ if ($cookie_str != '') {
2846
+ $hdr = 'Cookie: '.$cookie_str;
2847
+ $this->debug("HTTP header: $hdr");
2848
+ $this->outgoing_payload .= "$hdr\r\n";
2849
+ }
2850
+
2851
+ // header/body separator
2852
+ $this->outgoing_payload .= "\r\n";
2853
+
2854
+ // add data
2855
+ $this->outgoing_payload .= $data;
2856
+ }
2857
+
2858
+ /**
2859
+ * sends the SOAP request via HTTP[S]
2860
+ *
2861
+ * @param string $data message data
2862
+ * @param array $cookies cookies to send
2863
+ * @return boolean true if OK, false if problem
2864
+ * @access private
2865
+ */
2866
+ function sendRequest($data, $cookies = NULL) {
2867
+ // build cookie string
2868
+ $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));
2869
+
2870
+ // build payload
2871
+ $this->buildPayload($data, $cookie_str);
2872
+
2873
+ if ($this->io_method() == 'socket') {
2874
+ // send payload
2875
+ if(!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
2876
+ $this->setError('couldn\'t write message data to socket');
2877
+ $this->debug('couldn\'t write message data to socket');
2878
+ return false;
2879
+ }
2880
+ $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
2881
+ return true;
2882
+ } else if ($this->io_method() == 'curl') {
2883
+ // set payload
2884
+ // cURL does say this should only be the verb, and in fact it
2885
+ // turns out that the URI and HTTP version are appended to this, which
2886
+ // some servers refuse to work with (so we no longer use this method!)
2887
+ //$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
2888
+ $curl_headers = array();
2889
+ foreach($this->outgoing_headers as $k => $v){
2890
+ if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') {
2891
+ $this->debug("Skip cURL header $k: $v");
2892
+ } else {
2893
+ $curl_headers[] = "$k: $v";
2894
+ }
2895
+ }
2896
+ if ($cookie_str != '') {
2897
+ $curl_headers[] = 'Cookie: ' . $cookie_str;
2898
+ }
2899
+ $this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers);
2900
+ $this->debug('set cURL HTTP headers');
2901
+ if ($this->request_method == "POST") {
2902
+ $this->setCurlOption(CURLOPT_POST, 1);
2903
+ $this->setCurlOption(CURLOPT_POSTFIELDS, $data);
2904
+ $this->debug('set cURL POST data');
2905
+ } else {
2906
+ }
2907
+ // insert custom user-set cURL options
2908
+ foreach ($this->ch_options as $key => $val) {
2909
+ $this->setCurlOption($key, $val);
2910
+ }
2911
+
2912
+ $this->debug('set cURL payload');
2913
+ return true;
2914
+ }
2915
+ }
2916
+
2917
+ /**
2918
+ * gets the SOAP response via HTTP[S]
2919
+ *
2920
+ * @return string the response (also sets member variables like incoming_payload)
2921
+ * @access private
2922
+ */
2923
+ function getResponse(){
2924
+ $this->incoming_payload = '';
2925
+
2926
+ if ($this->io_method() == 'socket') {
2927
+ // loop until headers have been retrieved
2928
+ $data = '';
2929
+ while (!isset($lb)){
2930
+
2931
+ // We might EOF during header read.
2932
+ if(feof($this->fp)) {
2933
+ $this->incoming_payload = $data;
2934
+ $this->debug('found no headers before EOF after length ' . strlen($data));
2935
+ $this->debug("received before EOF:\n" . $data);
2936
+ $this->setError('server failed to send headers');
2937
+ return false;
2938
+ }
2939
+
2940
+ $tmp = fgets($this->fp, 256);
2941
+ $tmplen = strlen($tmp);
2942
+ $this->debug("read line of $tmplen bytes: " . trim($tmp));
2943
+
2944
+ if ($tmplen == 0) {
2945
+ $this->incoming_payload = $data;
2946
+ $this->debug('socket read of headers timed out after length ' . strlen($data));
2947
+ $this->debug("read before timeout: " . $data);
2948
+ $this->setError('socket read of headers timed out');
2949
+ return false;
2950
+ }
2951
+
2952
+ $data .= $tmp;
2953
+ $pos = strpos($data,"\r\n\r\n");
2954
+ if($pos > 1){
2955
+ $lb = "\r\n";
2956
+ } else {
2957
+ $pos = strpos($data,"\n\n");
2958
+ if($pos > 1){
2959
+ $lb = "\n";
2960
+ }
2961
+ }
2962
+ // remove 100 headers
2963
+ if (isset($lb) && ereg('^HTTP/1.1 100',$data)) {
2964
+ unset($lb);
2965
+ $data = '';
2966
+ }//
2967
+ }
2968
+ // store header data
2969
+ $this->incoming_payload .= $data;
2970
+ $this->debug('found end of headers after length ' . strlen($data));
2971
+ // process headers
2972
+ $header_data = trim(substr($data,0,$pos));
2973
+ $header_array = explode($lb,$header_data);
2974
+ $this->incoming_headers = array();
2975
+ $this->incoming_cookies = array();
2976
+ foreach($header_array as $header_line){
2977
+ $arr = explode(':',$header_line, 2);
2978
+ if(count($arr) > 1){
2979
+ $header_name = strtolower(trim($arr[0]));
2980
+ $this->incoming_headers[$header_name] = trim($arr[1]);
2981
+ if ($header_name == 'set-cookie') {
2982
+ // TODO: allow multiple cookies from parseCookie
2983
+ $cookie = $this->parseCookie(trim($arr[1]));
2984
+ if ($cookie) {
2985
+ $this->incoming_cookies[] = $cookie;
2986
+ $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
2987
+ } else {
2988
+ $this->debug('did not find cookie in ' . trim($arr[1]));
2989
+ }
2990
+ }
2991
+ } else if (isset($header_name)) {
2992
+ // append continuation line to previous header
2993
+ $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
2994
+ }
2995
+ }
2996
+
2997
+ // loop until msg has been received
2998
+ if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') {
2999
+ $content_length = 2147483647; // ignore any content-length header
3000
+ $chunked = true;
3001
+ $this->debug("want to read chunked content");
3002
+ } elseif (isset($this->incoming_headers['content-length'])) {
3003
+ $content_length = $this->incoming_headers['content-length'];
3004
+ $chunked = false;
3005
+ $this->debug("want to read content of length $content_length");
3006
+ } else {
3007
+ $content_length = 2147483647;
3008
+ $chunked = false;
3009
+ $this->debug("want to read content to EOF");
3010
+ }
3011
+ $data = '';
3012
+ do {
3013
+ if ($chunked) {
3014
+ $tmp = fgets($this->fp, 256);
3015
+ $tmplen = strlen($tmp);
3016
+ $this->debug("read chunk line of $tmplen bytes");
3017
+ if ($tmplen == 0) {
3018
+ $this->incoming_payload = $data;
3019
+ $this->debug('socket read of chunk length timed out after length ' . strlen($data));
3020
+ $this->debug("read before timeout:\n" . $data);
3021
+ $this->setError('socket read of chunk length timed out');
3022
+ return false;
3023
+ }
3024
+ $content_length = hexdec(trim($tmp));
3025
+ $this->debug("chunk length $content_length");
3026
+ }
3027
+ $strlen = 0;
3028
+ while (($strlen < $content_length) && (!feof($this->fp))) {
3029
+ $readlen = min(8192, $content_length - $strlen);
3030
+ $tmp = fread($this->fp, $readlen);
3031
+ $tmplen = strlen($tmp);
3032
+ $this->debug("read buffer of $tmplen bytes");
3033
+ if (($tmplen == 0) && (!feof($this->fp))) {
3034
+ $this->incoming_payload = $data;
3035
+ $this->debug('socket read of body timed out after length ' . strlen($data));
3036
+ $this->debug("read before timeout:\n" . $data);
3037
+ $this->setError('socket read of body timed out');
3038
+ return false;
3039
+ }
3040
+ $strlen += $tmplen;
3041
+ $data .= $tmp;
3042
+ }
3043
+ if ($chunked && ($content_length > 0)) {
3044
+ $tmp = fgets($this->fp, 256);
3045
+ $tmplen = strlen($tmp);
3046
+ $this->debug("read chunk terminator of $tmplen bytes");
3047
+ if ($tmplen == 0) {
3048
+ $this->incoming_payload = $data;
3049
+ $this->debug('socket read of chunk terminator timed out after length ' . strlen($data));
3050
+ $this->debug("read before timeout:\n" . $data);
3051
+ $this->setError('socket read of chunk terminator timed out');
3052
+ return false;
3053
+ }
3054
+ }
3055
+ } while ($chunked && ($content_length > 0) && (!feof($this->fp)));
3056
+ if (feof($this->fp)) {
3057
+ $this->debug('read to EOF');
3058
+ }
3059
+ $this->debug('read body of length ' . strlen($data));
3060
+ $this->incoming_payload .= $data;
3061
+ $this->debug('received a total of '.strlen($this->incoming_payload).' bytes of data from server');
3062
+
3063
+ // close filepointer
3064
+ if(
3065
+ (isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') ||
3066
+ (! $this->persistentConnection) || feof($this->fp)){
3067
+ fclose($this->fp);
3068
+ $this->fp = false;
3069
+ $this->debug('closed socket');
3070
+ }
3071
+
3072
+ // connection was closed unexpectedly
3073
+ if($this->incoming_payload == ''){
3074
+ $this->setError('no response from server');
3075
+ return false;
3076
+ }
3077
+
3078
+ // decode transfer-encoding
3079
+ // if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){
3080
+ // if(!$data = $this->decodeChunked($data, $lb)){
3081
+ // $this->setError('Decoding of chunked data failed');
3082
+ // return false;
3083
+ // }
3084
+ //print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";
3085
+ // set decoded payload
3086
+ // $this->incoming_payload = $header_data.$lb.$lb.$data;
3087
+ // }
3088
+
3089
+ } else if ($this->io_method() == 'curl') {
3090
+ // send and receive
3091
+ $this->debug('send and receive with cURL');
3092
+ $this->incoming_payload = curl_exec($this->ch);
3093
+ $data = $this->incoming_payload;
3094
+
3095
+ $cErr = curl_error($this->ch);
3096
+ if ($cErr != '') {
3097
+ $err = 'cURL ERROR: '.curl_errno($this->ch).': '.$cErr.'<br>';
3098
+ // TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE
3099
+ foreach(curl_getinfo($this->ch) as $k => $v){
3100
+ $err .= "$k: $v<br>";
3101
+ }
3102
+ $this->debug($err);
3103
+ $this->setError($err);
3104
+ curl_close($this->ch);
3105
+ return false;
3106
+ } else {
3107
+ //echo '<pre>';
3108
+ //var_dump(curl_getinfo($this->ch));
3109
+ //echo '</pre>';
3110
+ }
3111
+ // close curl
3112
+ $this->debug('No cURL error, closing cURL');
3113
+ curl_close($this->ch);
3114
+
3115
+ // try removing skippable headers
3116
+ $savedata = $data;
3117
+ while ($this->isSkippableCurlHeader($data)) {
3118
+ $this->debug("Found HTTP header to skip");
3119
+ if ($pos = strpos($data,"\r\n\r\n")) {
3120
+ $data = ltrim(substr($data,$pos));
3121
+ } elseif($pos = strpos($data,"\n\n") ) {
3122
+ $data = ltrim(substr($data,$pos));
3123
+ }
3124
+ }
3125
+
3126
+ if ($data == '') {
3127
+ // have nothing left; just remove 100 header(s)
3128
+ $data = $savedata;
3129
+ while (ereg('^HTTP/1.1 100',$data)) {
3130
+ if ($pos = strpos($data,"\r\n\r\n")) {
3131
+ $data = ltrim(substr($data,$pos));
3132
+ } elseif($pos = strpos($data,"\n\n") ) {
3133
+ $data = ltrim(substr($data,$pos));
3134
+ }
3135
+ }
3136
+ }
3137
+
3138
+ // separate content from HTTP headers
3139
+ if ($pos = strpos($data,"\r\n\r\n")) {
3140
+ $lb = "\r\n";
3141
+ } elseif( $pos = strpos($data,"\n\n")) {
3142
+ $lb = "\n";
3143
+ } else {
3144
+ $this->debug('no proper separation of headers and document');
3145
+ $this->setError('no proper separation of headers and document');
3146
+ return false;
3147
+ }
3148
+ $header_data = trim(substr($data,0,$pos));
3149
+ $header_array = explode($lb,$header_data);
3150
+ $data = ltrim(substr($data,$pos));
3151
+ $this->debug('found proper separation of headers and document');
3152
+ $this->debug('cleaned data, stringlen: '.strlen($data));
3153
+ // clean headers
3154
+ foreach ($header_array as $header_line) {
3155
+ $arr = explode(':',$header_line,2);
3156
+ if(count($arr) > 1){
3157
+ $header_name = strtolower(trim($arr[0]));
3158
+ $this->incoming_headers[$header_name] = trim($arr[1]);
3159
+ if ($header_name == 'set-cookie') {
3160
+ // TODO: allow multiple cookies from parseCookie
3161
+ $cookie = $this->parseCookie(trim($arr[1]));
3162
+ if ($cookie) {
3163
+ $this->incoming_cookies[] = $cookie;
3164
+ $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
3165
+ } else {
3166
+ $this->debug('did not find cookie in ' . trim($arr[1]));
3167
+ }
3168
+ }
3169
+ } else if (isset($header_name)) {
3170
+ // append continuation line to previous header
3171
+ $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
3172
+ }
3173
+ }
3174
+ }
3175
+
3176
+ $this->response_status_line = $header_array[0];
3177
+ $arr = explode(' ', $this->response_status_line, 3);
3178
+ $http_version = $arr[0];
3179
+ $http_status = intval($arr[1]);
3180
+ $http_reason = count($arr) > 2 ? $arr[2] : '';
3181
+
3182
+ // see if we need to resend the request with http digest authentication
3183
+ if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) {
3184
+ $this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']);
3185
+ $this->setURL($this->incoming_headers['location']);
3186
+ $this->tryagain = true;
3187
+ return false;
3188
+ }
3189
+
3190
+ // see if we need to resend the request with http digest authentication
3191
+ if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) {
3192
+ $this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']);
3193
+ if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) {
3194
+ $this->debug('Server wants digest authentication');
3195
+ // remove "Digest " from our elements
3196
+ $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);
3197
+
3198
+ // parse elements into array
3199
+ $digestElements = explode(',', $digestString);
3200
+ foreach ($digestElements as $val) {
3201
+ $tempElement = explode('=', trim($val), 2);
3202
+ $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);
3203
+ }
3204
+
3205
+ // should have (at least) qop, realm, nonce
3206
+ if (isset($digestRequest['nonce'])) {
3207
+ $this->setCredentials($this->username, $this->password, 'digest', $digestRequest);
3208
+ $this->tryagain = true;
3209
+ return false;
3210
+ }
3211
+ }
3212
+ $this->debug('HTTP authentication failed');
3213
+ $this->setError('HTTP authentication failed');
3214
+ return false;
3215
+ }
3216
+
3217
+ if (
3218
+ ($http_status >= 300 && $http_status <= 307) ||
3219
+ ($http_status >= 400 && $http_status <= 417) ||
3220
+ ($http_status >= 501 && $http_status <= 505)
3221
+ ) {
3222
+ $this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");
3223
+ return false;
3224
+ }
3225
+
3226
+ // decode content-encoding
3227
+ if(isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != ''){
3228
+ if(strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip'){
3229
+ // if decoding works, use it. else assume data wasn't gzencoded
3230
+ if(function_exists('gzinflate')){
3231
+ //$timer->setMarker('starting decoding of gzip/deflated content');
3232
+ // IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress)
3233
+ // this means there are no Zlib headers, although there should be
3234
+ $this->debug('The gzinflate function exists');
3235
+ $datalen = strlen($data);
3236
+ if ($this->incoming_headers['content-encoding'] == 'deflate') {
3237
+ if ($degzdata = @gzinflate($data)) {
3238
+ $data = $degzdata;
3239
+ $this->debug('The payload has been inflated to ' . strlen($data) . ' bytes');
3240
+ if (strlen($data) < $datalen) {
3241
+ // test for the case that the payload has been compressed twice
3242
+ $this->debug('The inflated payload is smaller than the gzipped one; try again');
3243
+ if ($degzdata = @gzinflate($data)) {
3244
+ $data = $degzdata;
3245
+ $this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes');
3246
+ }
3247
+ }
3248
+ } else {
3249
+ $this->debug('Error using gzinflate to inflate the payload');
3250
+ $this->setError('Error using gzinflate to inflate the payload');
3251
+ }
3252
+ } elseif ($this->incoming_headers['content-encoding'] == 'gzip') {
3253
+ if ($degzdata = @gzinflate(substr($data, 10))) { // do our best
3254
+ $data = $degzdata;
3255
+ $this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes');
3256
+ if (strlen($data) < $datalen) {
3257
+ // test for the case that the payload has been compressed twice
3258
+ $this->debug('The un-gzipped payload is smaller than the gzipped one; try again');
3259
+ if ($degzdata = @gzinflate(substr($data, 10))) {
3260
+ $data = $degzdata;
3261
+ $this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes');
3262
+ }
3263
+ }
3264
+ } else {
3265
+ $this->debug('Error using gzinflate to un-gzip the payload');
3266
+ $this->setError('Error using gzinflate to un-gzip the payload');
3267
+ }
3268
+ }
3269
+ //$timer->setMarker('finished decoding of gzip/deflated content');
3270
+ //print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";
3271
+ // set decoded payload
3272
+ $this->incoming_payload = $header_data.$lb.$lb.$data;
3273
+ } else {
3274
+ $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
3275
+ $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
3276
+ }
3277
+ } else {
3278
+ $this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
3279
+ $this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
3280
+ }
3281
+ } else {
3282
+ $this->debug('No Content-Encoding header');
3283
+ }
3284
+
3285
+ if(strlen($data) == 0){
3286
+ $this->debug('no data after headers!');
3287
+ $this->setError('no data present after HTTP headers');
3288
+ return false;
3289
+ }
3290
+
3291
+ return $data;
3292
+ }
3293
+
3294
+ /**
3295
+ * sets the content-type for the SOAP message to be sent
3296
+ *
3297
+ * @param string $type the content type, MIME style
3298
+ * @param mixed $charset character set used for encoding (or false)
3299
+ * @access public
3300
+ */
3301
+ function setContentType($type, $charset = false) {
3302
+ $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
3303
+ }
3304
+
3305
+ /**
3306
+ * specifies that an HTTP persistent connection should be used
3307
+ *
3308
+ * @return boolean whether the request was honored by this method.
3309
+ * @access public
3310
+ */
3311
+ function usePersistentConnection(){
3312
+ if (isset($this->outgoing_headers['Accept-Encoding'])) {
3313
+ return false;
3314
+ }
3315
+ $this->protocol_version = '1.1';
3316
+ $this->persistentConnection = true;
3317
+ $this->setHeader('Connection', 'Keep-Alive');
3318
+ return true;
3319
+ }
3320
+
3321
+ /**
3322
+ * parse an incoming Cookie into it's parts
3323
+ *
3324
+ * @param string $cookie_str content of cookie
3325
+ * @return array with data of that cookie
3326
+ * @access private
3327
+ */
3328
+ /*
3329
+ * TODO: allow a Set-Cookie string to be parsed into multiple cookies
3330
+ */
3331
+ function parseCookie($cookie_str) {
3332
+ $cookie_str = str_replace('; ', ';', $cookie_str) . ';';
3333
+ $data = split(';', $cookie_str);
3334
+ $value_str = $data[0];
3335
+
3336
+ $cookie_param = 'domain=';
3337
+ $start = strpos($cookie_str, $cookie_param);
3338
+ if ($start > 0) {
3339
+ $domain = substr($cookie_str, $start + strlen($cookie_param));
3340
+ $domain = substr($domain, 0, strpos($domain, ';'));
3341
+ } else {
3342
+ $domain = '';
3343
+ }
3344
+
3345
+ $cookie_param = 'expires=';
3346
+ $start = strpos($cookie_str, $cookie_param);
3347
+ if ($start > 0) {
3348
+ $expires = substr($cookie_str, $start + strlen($cookie_param));
3349
+ $expires = substr($expires, 0, strpos($expires, ';'));
3350
+ } else {
3351
+ $expires = '';
3352
+ }
3353
+
3354
+ $cookie_param = 'path=';
3355
+ $start = strpos($cookie_str, $cookie_param);
3356
+ if ( $start > 0 ) {
3357
+ $path = substr($cookie_str, $start + strlen($cookie_param));
3358
+ $path = substr($path, 0, strpos($path, ';'));
3359
+ } else {
3360
+ $path = '/';
3361
+ }
3362
+
3363
+ $cookie_param = ';secure;';
3364
+ if (strpos($cookie_str, $cookie_param) !== FALSE) {
3365
+ $secure = true;
3366
+ } else {
3367
+ $secure = false;
3368
+ }
3369
+
3370
+ $sep_pos = strpos($value_str, '=');
3371
+
3372
+ if ($sep_pos) {
3373
+ $name = substr($value_str, 0, $sep_pos);
3374
+ $value = substr($value_str, $sep_pos + 1);
3375
+ $cookie= array( 'name' => $name,
3376
+ 'value' => $value,
3377
+ 'domain' => $domain,
3378
+ 'path' => $path,
3379
+ 'expires' => $expires,
3380
+ 'secure' => $secure
3381
+ );
3382
+ return $cookie;
3383
+ }
3384
+ return false;
3385
+ }
3386
+
3387
+ /**
3388
+ * sort out cookies for the current request
3389
+ *
3390
+ * @param array $cookies array with all cookies
3391
+ * @param boolean $secure is the send-content secure or not?
3392
+ * @return string for Cookie-HTTP-Header
3393
+ * @access private
3394
+ */
3395
+ function getCookiesForRequest($cookies, $secure=false) {
3396
+ $cookie_str = '';
3397
+ if ((! is_null($cookies)) && (is_array($cookies))) {
3398
+ foreach ($cookies as $cookie) {
3399
+ if (! is_array($cookie)) {
3400
+ continue;
3401
+ }
3402
+ $this->debug("check cookie for validity: ".$cookie['name'].'='.$cookie['value']);
3403
+ if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
3404
+ if (strtotime($cookie['expires']) <= time()) {
3405
+ $this->debug('cookie has expired');
3406
+ continue;
3407
+ }
3408
+ }
3409
+ if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) {
3410
+ $domain = preg_quote($cookie['domain']);
3411
+ if (! preg_match("'.*$domain$'i", $this->host)) {
3412
+ $this->debug('cookie has different domain');
3413
+ continue;
3414
+ }
3415
+ }
3416
+ if ((isset($cookie['path'])) && (! empty($cookie['path']))) {
3417
+ $path = preg_quote($cookie['path']);
3418
+ if (! preg_match("'^$path.*'i", $this->path)) {
3419
+ $this->debug('cookie is for a different path');
3420
+ continue;
3421
+ }
3422
+ }
3423
+ if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) {
3424
+ $this->debug('cookie is secure, transport is not');
3425
+ continue;
3426
+ }
3427
+ $cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';
3428
+ $this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']);
3429
+ }
3430
+ }
3431
+ return $cookie_str;
3432
+ }
3433
+ }
3434
+
3435
+ ?><?php
3436
+
3437
+
3438
+
3439
+ /**
3440
+ *
3441
+ * nusoap_server allows the user to create a SOAP server
3442
+ * that is capable of receiving messages and returning responses
3443
+ *
3444
+ * @author Dietrich Ayala <dietrich@ganx4.com>
3445
+ * @author Scott Nichol <snichol@users.sourceforge.net>
3446
+ * @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $
3447
+ * @access public
3448
+ */
3449
+ class nusoap_server extends nusoap_base {
3450
+ /**
3451
+ * HTTP headers of request
3452
+ * @var array
3453
+ * @access private
3454
+ */
3455
+ var $headers = array();
3456
+ /**
3457
+ * HTTP request
3458
+ * @var string
3459
+ * @access private
3460
+ */
3461
+ var $request = '';
3462
+ /**
3463
+ * SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text)
3464
+ * @var string
3465
+ * @access public
3466
+ */
3467
+ var $requestHeaders = '';
3468
+ /**
3469
+ * SOAP Headers from request (parsed)
3470
+ * @var mixed
3471
+ * @access public
3472
+ */
3473
+ var $requestHeader = NULL;
3474
+ /**
3475
+ * SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text)
3476
+ * @var string
3477
+ * @access public
3478
+ */
3479
+ var $document = '';
3480
+ /**
3481
+ * SOAP payload for request (text)
3482
+ * @var string
3483
+ * @access public
3484
+ */
3485
+ var $requestSOAP = '';
3486
+ /**
3487
+ * requested method namespace URI
3488
+ * @var string
3489
+ * @access private
3490
+ */
3491
+ var $methodURI = '';
3492
+ /**
3493
+ * name of method requested
3494
+ * @var string
3495
+ * @access private
3496
+ */
3497
+ var $methodname = '';
3498
+ /**
3499
+ * method parameters from request
3500
+ * @var array
3501
+ * @access private
3502
+ */
3503
+ var $methodparams = array();
3504
+ /**
3505
+ * SOAP Action from request
3506
+ * @var string
3507
+ * @access private
3508
+ */
3509
+ var $SOAPAction = '';
3510
+ /**
3511
+ * character set encoding of incoming (request) messages
3512
+ * @var string
3513
+ * @access public
3514
+ */
3515
+ var $xml_encoding = '';
3516
+ /**
3517
+ * toggles whether the parser decodes element content w/ utf8_decode()
3518
+ * @var boolean
3519
+ * @access public
3520
+ */
3521
+ var $decode_utf8 = true;
3522
+
3523
+ /**
3524
+ * HTTP headers of response
3525
+ * @var array
3526
+ * @access public
3527
+ */
3528
+ var $outgoing_headers = array();
3529
+ /**
3530
+ * HTTP response
3531
+ * @var string
3532
+ * @access private
3533
+ */
3534
+ var $response = '';
3535
+ /**
3536
+ * SOAP headers for response (text or array of soapval or associative array)
3537
+ * @var mixed
3538
+ * @access public
3539
+ */
3540
+ var $responseHeaders = '';
3541
+ /**
3542
+ * SOAP payload for response (text)
3543
+ * @var string
3544
+ * @access private
3545
+ */
3546
+ var $responseSOAP = '';
3547
+ /**
3548
+ * method return value to place in response
3549
+ * @var mixed
3550
+ * @access private
3551
+ */
3552
+ var $methodreturn = false;
3553
+ /**
3554
+ * whether $methodreturn is a string of literal XML
3555
+ * @var boolean
3556
+ * @access public
3557
+ */
3558
+ var $methodreturnisliteralxml = false;
3559
+ /**
3560
+ * SOAP fault for response (or false)
3561
+ * @var mixed
3562
+ * @access private
3563
+ */
3564
+ var $fault = false;
3565
+ /**
3566
+ * text indication of result (for debugging)
3567
+ * @var string
3568
+ * @access private
3569
+ */
3570
+ var $result = 'successful';
3571
+
3572
+ /**
3573
+ * assoc array of operations => opData; operations are added by the register()
3574
+ * method or by parsing an external WSDL definition
3575
+ * @var array
3576
+ * @access private
3577
+ */
3578
+ var $operations = array();
3579
+ /**
3580
+ * wsdl instance (if one)
3581
+ * @var mixed
3582
+ * @access private
3583
+ */
3584
+ var $wsdl = false;
3585
+ /**
3586
+ * URL for WSDL (if one)
3587
+ * @var mixed
3588
+ * @access private
3589
+ */
3590
+ var $externalWSDLURL = false;
3591
+ /**
3592
+ * whether to append debug to response as XML comment
3593
+ * @var boolean
3594
+ * @access public
3595
+ */
3596
+ var $debug_flag = false;
3597
+
3598
+
3599
+ /**
3600
+ * constructor
3601
+ * the optional parameter is a path to a WSDL file that you'd like to bind the server instance to.
3602
+ *
3603
+ * @param mixed $wsdl file path or URL (string), or wsdl instance (object)
3604
+ * @access public
3605
+ */
3606
+ function nusoap_server($wsdl=false){
3607
+ parent::nusoap_base();
3608
+ // turn on debugging?
3609
+ global $debug;
3610
+ global $HTTP_SERVER_VARS;
3611
+
3612
+ if (isset($_SERVER)) {
3613
+ $this->debug("_SERVER is defined:");
3614
+ $this->appendDebug($this->varDump($_SERVER));
3615
+ } elseif (isset($HTTP_SERVER_VARS)) {
3616
+ $this->debug("HTTP_SERVER_VARS is defined:");
3617
+ $this->appendDebug($this->varDump($HTTP_SERVER_VARS));
3618
+ } else {
3619
+ $this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
3620
+ }
3621
+
3622
+ if (isset($debug)) {
3623
+ $this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
3624
+ $this->debug_flag = $debug;
3625
+ } elseif (isset($_SERVER['QUERY_STRING'])) {
3626
+ $qs = explode('&', $_SERVER['QUERY_STRING']);
3627
+ foreach ($qs as $v) {
3628
+ if (substr($v, 0, 6) == 'debug=') {
3629
+ $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
3630
+ $this->debug_flag = substr($v, 6);
3631
+ }
3632
+ }
3633
+ } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
3634
+ $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
3635
+ foreach ($qs as $v) {
3636
+ if (substr($v, 0, 6) == 'debug=') {
3637
+ $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
3638
+ $this->debug_flag = substr($v, 6);
3639
+ }
3640
+ }
3641
+ }
3642
+
3643
+ // wsdl
3644
+ if($wsdl){
3645
+ $this->debug("In nusoap_server, WSDL is specified");
3646
+ if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
3647
+ $this->wsdl = $wsdl;
3648
+ $this->externalWSDLURL = $this->wsdl->wsdl;
3649
+ $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
3650
+ } else {
3651
+ $this->debug('Create wsdl from ' . $wsdl);
3652
+ $this->wsdl = new wsdl($wsdl);
3653
+ $this->externalWSDLURL = $wsdl;
3654
+ }
3655
+ $this->appendDebug($this->wsdl->getDebug());
3656
+ $this->wsdl->clearDebug();
3657
+ if($err = $this->wsdl->getError()){
3658
+ die('WSDL ERROR: '.$err);
3659
+ }
3660
+ }
3661
+ }
3662
+
3663
+ /**
3664
+ * processes request and returns response
3665
+ *
3666
+ * @param string $data usually is the value of $HTTP_RAW_POST_DATA
3667
+ * @access public
3668
+ */
3669
+ function service($data){
3670
+ global $HTTP_SERVER_VARS;
3671
+
3672
+ if (isset($_SERVER['QUERY_STRING'])) {
3673
+ $qs = $_SERVER['QUERY_STRING'];
3674
+ } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
3675
+ $qs = $HTTP_SERVER_VARS['QUERY_STRING'];
3676
+ } else {
3677
+ $qs = '';
3678
+ }
3679
+ $this->debug("In service, query string=$qs");
3680
+
3681
+ if (ereg('wsdl', $qs) ){
3682
+ $this->debug("In service, this is a request for WSDL");
3683
+ if($this->externalWSDLURL){
3684
+ if (strpos($this->externalWSDLURL,"://")!==false) { // assume URL
3685
+ header('Location: '.$this->externalWSDLURL);
3686
+ } else { // assume file
3687
+ header("Content-Type: text/xml\r\n");
3688
+ $fp = fopen($this->externalWSDLURL, 'r');
3689
+ fpassthru($fp);
3690
+ }
3691
+ } elseif ($this->wsdl) {
3692
+ header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
3693
+ print $this->wsdl->serialize($this->debug_flag);
3694
+ if ($this->debug_flag) {
3695
+ $this->debug('wsdl:');
3696
+ $this->appendDebug($this->varDump($this->wsdl));
3697
+ print $this->getDebugAsXMLComment();
3698
+ }
3699
+ } else {
3700
+ header("Content-Type: text/html; charset=ISO-8859-1\r\n");
3701
+ print "This service does not provide WSDL";
3702
+ }
3703
+ } elseif ($data == '' && $this->wsdl) {
3704
+ $this->debug("In service, there is no data, so return Web description");
3705
+ print $this->wsdl->webDescription();
3706
+ } else {
3707
+ $this->debug("In service, invoke the request");
3708
+ $this->parse_request($data);
3709
+ if (! $this->fault) {
3710
+ $this->invoke_method();
3711
+ }
3712
+ if (! $this->fault) {
3713
+ $this->serialize_return();
3714
+ }
3715
+ $this->send_response();
3716
+ }
3717
+ }
3718
+
3719
+ /**
3720
+ * parses HTTP request headers.
3721
+ *
3722
+ * The following fields are set by this function (when successful)
3723
+ *
3724
+ * headers
3725
+ * request
3726
+ * xml_encoding
3727
+ * SOAPAction
3728
+ *
3729
+ * @access private
3730
+ */
3731
+ function parse_http_headers() {
3732
+ global $HTTP_SERVER_VARS;
3733
+
3734
+ $this->request = '';
3735
+ $this->SOAPAction = '';
3736
+ if(function_exists('getallheaders')){
3737
+ $this->debug("In parse_http_headers, use getallheaders");
3738
+ $headers = getallheaders();
3739
+ foreach($headers as $k=>$v){
3740
+ $k = strtolower($k);
3741
+ $this->headers[$k] = $v;
3742
+ $this->request .= "$k: $v\r\n";
3743
+ $this->debug("$k: $v");
3744
+ }
3745
+ // get SOAPAction header
3746
+ if(isset($this->headers['soapaction'])){
3747
+ $this->SOAPAction = str_replace('"','',$this->headers['soapaction']);
3748
+ }
3749
+ // get the character encoding of the incoming request
3750
+ if(isset($this->headers['content-type']) && strpos($this->headers['content-type'],'=')){
3751
+ $enc = str_replace('"','',substr(strstr($this->headers["content-type"],'='),1));
3752
+ if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){
3753
+ $this->xml_encoding = strtoupper($enc);
3754
+ } else {
3755
+ $this->xml_encoding = 'US-ASCII';
3756
+ }
3757
+ } else {
3758
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3759
+ $this->xml_encoding = 'ISO-8859-1';
3760
+ }
3761
+ } elseif(isset($_SERVER) && is_array($_SERVER)){
3762
+ $this->debug("In parse_http_headers, use _SERVER");
3763
+ foreach ($_SERVER as $k => $v) {
3764
+ if (substr($k, 0, 5) == 'HTTP_') {
3765
+ $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
3766
+ } else {
3767
+ $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
3768
+ }
3769
+ if ($k == 'soapaction') {
3770
+ // get SOAPAction header
3771
+ $k = 'SOAPAction';
3772
+ $v = str_replace('"', '', $v);
3773
+ $v = str_replace('\\', '', $v);
3774
+ $this->SOAPAction = $v;
3775
+ } else if ($k == 'content-type') {
3776
+ // get the character encoding of the incoming request
3777
+ if (strpos($v, '=')) {
3778
+ $enc = substr(strstr($v, '='), 1);
3779
+ $enc = str_replace('"', '', $enc);
3780
+ $enc = str_replace('\\', '', $enc);
3781
+ if (eregi('^(ISO-8859-1|US-ASCII|UTF-8)$', $enc)) {
3782
+ $this->xml_encoding = strtoupper($enc);
3783
+ } else {
3784
+ $this->xml_encoding = 'US-ASCII';
3785
+ }
3786
+ } else {
3787
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3788
+ $this->xml_encoding = 'ISO-8859-1';
3789
+ }
3790
+ }
3791
+ $this->headers[$k] = $v;
3792
+ $this->request .= "$k: $v\r\n";
3793
+ $this->debug("$k: $v");
3794
+ }
3795
+ } elseif (is_array($HTTP_SERVER_VARS)) {
3796
+ $this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
3797
+ foreach ($HTTP_SERVER_VARS as $k => $v) {
3798
+ if (substr($k, 0, 5) == 'HTTP_') {
3799
+ $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); $k = strtolower(substr($k, 5));
3800
+ } else {
3801
+ $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); $k = strtolower($k);
3802
+ }
3803
+ if ($k == 'soapaction') {
3804
+ // get SOAPAction header
3805
+ $k = 'SOAPAction';
3806
+ $v = str_replace('"', '', $v);
3807
+ $v = str_replace('\\', '', $v);
3808
+ $this->SOAPAction = $v;
3809
+ } else if ($k == 'content-type') {
3810
+ // get the character encoding of the incoming request
3811
+ if (strpos($v, '=')) {
3812
+ $enc = substr(strstr($v, '='), 1);
3813
+ $enc = str_replace('"', '', $enc);
3814
+ $enc = str_replace('\\', '', $enc);
3815
+ if (eregi('^(ISO-8859-1|US-ASCII|UTF-8)$', $enc)) {
3816
+ $this->xml_encoding = strtoupper($enc);
3817
+ } else {
3818
+ $this->xml_encoding = 'US-ASCII';
3819
+ }
3820
+ } else {
3821
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3822
+ $this->xml_encoding = 'ISO-8859-1';
3823
+ }
3824
+ }
3825
+ $this->headers[$k] = $v;
3826
+ $this->request .= "$k: $v\r\n";
3827
+ $this->debug("$k: $v");
3828
+ }
3829
+ } else {
3830
+ $this->debug("In parse_http_headers, HTTP headers not accessible");
3831
+ $this->setError("HTTP headers not accessible");
3832
+ }
3833
+ }
3834
+
3835
+ /**
3836
+ * parses a request
3837
+ *
3838
+ * The following fields are set by this function (when successful)
3839
+ *
3840
+ * headers
3841
+ * request
3842
+ * xml_encoding
3843
+ * SOAPAction
3844
+ * request
3845
+ * requestSOAP
3846
+ * methodURI
3847
+ * methodname
3848
+ * methodparams
3849
+ * requestHeaders
3850
+ * document
3851
+ *
3852
+ * This sets the fault field on error
3853
+ *
3854
+ * @param string $data XML string
3855
+ * @access private
3856
+ */
3857
+ function parse_request($data='') {
3858
+ $this->debug('entering parse_request()');
3859
+ $this->parse_http_headers();
3860
+ $this->debug('got character encoding: '.$this->xml_encoding);
3861
+ // uncompress if necessary
3862
+ if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
3863
+ $this->debug('got content encoding: ' . $this->headers['content-encoding']);
3864
+ if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
3865
+ // if decoding works, use it. else assume data wasn't gzencoded
3866
+ if (function_exists('gzuncompress')) {
3867
+ if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
3868
+ $data = $degzdata;
3869
+ } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
3870
+ $data = $degzdata;
3871
+ } else {
3872
+ $this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
3873
+ return;
3874
+ }
3875
+ } else {
3876
+ $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
3877
+ return;
3878
+ }
3879
+ }
3880
+ }
3881
+ $this->request .= "\r\n".$data;
3882
+ $data = $this->parseRequest($this->headers, $data);
3883
+ $this->requestSOAP = $data;
3884
+ $this->debug('leaving parse_request');
3885
+ }
3886
+
3887
+ /**
3888
+ * invokes a PHP function for the requested SOAP method
3889
+ *
3890
+ * The following fields are set by this function (when successful)
3891
+ *
3892
+ * methodreturn
3893
+ *
3894
+ * Note that the PHP function that is called may also set the following
3895
+ * fields to affect the response sent to the client
3896
+ *
3897
+ * responseHeaders
3898
+ * outgoing_headers
3899
+ *
3900
+ * This sets the fault field on error
3901
+ *
3902
+ * @access private
3903
+ */
3904
+ function invoke_method() {
3905
+ $this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
3906
+
3907
+ if ($this->wsdl) {
3908
+ if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
3909
+ $this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
3910
+ $this->appendDebug('opData=' . $this->varDump($this->opData));
3911
+ } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
3912
+ // Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
3913
+ $this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
3914
+ $this->appendDebug('opData=' . $this->varDump($this->opData));
3915
+ $this->methodname = $this->opData['name'];
3916
+ } else {
3917
+ $this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
3918
+ $this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
3919
+ return;
3920
+ }
3921
+ } else {
3922
+ $this->debug('in invoke_method, no WSDL to validate method');
3923
+ }
3924
+
3925
+ // if a . is present in $this->methodname, we see if there is a class in scope,
3926
+ // which could be referred to. We will also distinguish between two deliminators,
3927
+ // to allow methods to be called a the class or an instance
3928
+ $class = '';
3929
+ $method = '';
3930
+ if (strpos($this->methodname, '..') > 0) {
3931
+ $delim = '..';
3932
+ } else if (strpos($this->methodname, '.') > 0) {
3933
+ $delim = '.';
3934
+ } else {
3935
+ $delim = '';
3936
+ }
3937
+
3938
+ if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1 &&
3939
+ class_exists(substr($this->methodname, 0, strpos($this->methodname, $delim)))) {
3940
+ // get the class and method name
3941
+ $class = substr($this->methodname, 0, strpos($this->methodname, $delim));
3942
+ $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
3943
+ $this->debug("in invoke_method, class=$class method=$method delim=$delim");
3944
+ }
3945
+
3946
+ // does method exist?
3947
+ if ($class == '') {
3948
+ if (!function_exists($this->methodname)) {
3949
+ $this->debug("in invoke_method, function '$this->methodname' not found!");
3950
+ $this->result = 'fault: method not found';
3951
+ $this->fault('SOAP-ENV:Client',"method '$this->methodname' not defined in service");
3952
+ return;
3953
+ }
3954
+ } else {
3955
+ $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
3956
+ if (!in_array($method_to_compare, get_class_methods($class))) {
3957
+ $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
3958
+ $this->result = 'fault: method not found';
3959
+ $this->fault('SOAP-ENV:Client',"method '$this->methodname' not defined in service");
3960
+ return;
3961
+ }
3962
+ }
3963
+
3964
+ // evaluate message, getting back parameters
3965
+ // verify that request parameters match the method's signature
3966
+ if(! $this->verify_method($this->methodname,$this->methodparams)){
3967
+ // debug
3968
+ $this->debug('ERROR: request not verified against method signature');
3969
+ $this->result = 'fault: request failed validation against method signature';
3970
+ // return fault
3971
+ $this->fault('SOAP-ENV:Client',"Operation '$this->methodname' not defined in service.");
3972
+ return;
3973
+ }
3974
+
3975
+ // if there are parameters to pass
3976
+ $this->debug('in invoke_method, params:');
3977
+ $this->appendDebug($this->varDump($this->methodparams));
3978
+ $this->debug("in invoke_method, calling '$this->methodname'");
3979
+ if (!function_exists('call_user_func_array')) {
3980
+ if ($class == '') {
3981
+ $this->debug('in invoke_method, calling function using eval()');
3982
+ $funcCall = "\$this->methodreturn = $this->methodname(";
3983
+ } else {
3984
+ if ($delim == '..') {
3985
+ $this->debug('in invoke_method, calling class method using eval()');
3986
+ $funcCall = "\$this->methodreturn = ".$class."::".$method."(";
3987
+ } else {
3988
+ $this->debug('in invoke_method, calling instance method using eval()');
3989
+ // generate unique instance name
3990
+ $instname = "\$inst_".time();
3991
+ $funcCall = $instname." = new ".$class."(); ";
3992
+ $funcCall .= "\$this->methodreturn = ".$instname."->".$method."(";
3993
+ }
3994
+ }
3995
+ if ($this->methodparams) {
3996
+ foreach ($this->methodparams as $param) {
3997
+ if (is_array($param) || is_object($param)) {
3998
+ $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
3999
+ return;
4000
+ }
4001
+ $funcCall .= "\"$param\",";
4002
+ }
4003
+ $funcCall = substr($funcCall, 0, -1);
4004
+ }
4005
+ $funcCall .= ');';
4006
+ $this->debug('in invoke_method, function call: '.$funcCall);
4007
+ @eval($funcCall);
4008
+ } else {
4009
+ if ($class == '') {
4010
+ $this->debug('in invoke_method, calling function using call_user_func_array()');
4011
+ $call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array()
4012
+ } elseif ($delim == '..') {
4013
+ $this->debug('in invoke_method, calling class method using call_user_func_array()');
4014
+ $call_arg = array ($class, $method);
4015
+ } else {
4016
+ $this->debug('in invoke_method, calling instance method using call_user_func_array()');
4017
+ $instance = new $class ();
4018
+ $call_arg = array(&$instance, $method);
4019
+ }
4020
+ if (is_array($this->methodparams)) {
4021
+ $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
4022
+ } else {
4023
+ $this->methodreturn = call_user_func_array($call_arg, array());
4024
+ }
4025
+ }
4026
+ $this->debug('in invoke_method, methodreturn:');
4027
+ $this->appendDebug($this->varDump($this->methodreturn));
4028
+ $this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn));
4029
+ }
4030
+
4031
+ /**
4032
+ * serializes the return value from a PHP function into a full SOAP Envelope
4033
+ *
4034
+ * The following fields are set by this function (when successful)
4035
+ *
4036
+ * responseSOAP
4037
+ *
4038
+ * This sets the fault field on error
4039
+ *
4040
+ * @access private
4041
+ */
4042
+ function serialize_return() {
4043
+ $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
4044
+ // if fault
4045
+ if (isset($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) {
4046
+ $this->debug('got a fault object from method');
4047
+ $this->fault = $this->methodreturn;
4048
+ return;
4049
+ } elseif ($this->methodreturnisliteralxml) {
4050
+ $return_val = $this->methodreturn;
4051
+ // returned value(s)
4052
+ } else {
4053
+ $this->debug('got a(n) '.gettype($this->methodreturn).' from method');
4054
+ $this->debug('serializing return value');
4055
+ if($this->wsdl){
4056
+ if (sizeof($this->opData['output']['parts']) > 1) {
4057
+ $this->debug('more than one output part, so use the method return unchanged');
4058
+ $opParams = $this->methodreturn;
4059
+ } elseif (sizeof($this->opData['output']['parts']) == 1) {
4060
+ $this->debug('exactly one output part, so wrap the method return in a simple array');
4061
+ // TODO: verify that it is not already wrapped!
4062
+ //foreach ($this->opData['output']['parts'] as $name => $type) {
4063
+ // $this->debug('wrap in element named ' . $name);
4064
+ //}
4065
+ $opParams = array($this->methodreturn);
4066
+ }
4067
+ $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams);
4068
+ $this->appendDebug($this->wsdl->getDebug());
4069
+ $this->wsdl->clearDebug();
4070
+ if($errstr = $this->wsdl->getError()){
4071
+ $this->debug('got wsdl error: '.$errstr);
4072
+ $this->fault('SOAP-ENV:Server', 'unable to serialize result');
4073
+ return;
4074
+ }
4075
+ } else {
4076
+ if (isset($this->methodreturn)) {
4077
+ $return_val = $this->serialize_val($this->methodreturn, 'return');
4078
+ } else {
4079
+ $return_val = '';
4080
+ $this->debug('in absence of WSDL, assume void return for backward compatibility');
4081
+ }
4082
+ }
4083
+ }
4084
+ $this->debug('return value:');
4085
+ $this->appendDebug($this->varDump($return_val));
4086
+
4087
+ $this->debug('serializing response');
4088
+ if ($this->wsdl) {
4089
+ $this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
4090
+ if ($this->opData['style'] == 'rpc') {
4091
+ $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
4092
+ if ($this->opData['output']['use'] == 'literal') {
4093
+ // 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
4094
+ $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
4095
+ } else {
4096
+ $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
4097
+ }
4098
+ } else {
4099
+ $this->debug('style is not rpc for serialization: assume document');
4100
+ $payload = $return_val;
4101
+ }
4102
+ } else {
4103
+ $this->debug('do not have WSDL for serialization: assume rpc/encoded');
4104
+ $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
4105
+ }
4106
+ $this->result = 'successful';
4107
+ if($this->wsdl){
4108
+ //if($this->debug_flag){
4109
+ $this->appendDebug($this->wsdl->getDebug());
4110
+ // }
4111
+ if (isset($opData['output']['encodingStyle'])) {
4112
+ $encodingStyle = $opData['output']['encodingStyle'];
4113
+ } else {
4114
+ $encodingStyle = '';
4115
+ }
4116
+ // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
4117
+ $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$this->opData['output']['use'],$encodingStyle);
4118
+ } else {
4119
+ $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders);
4120
+ }
4121
+ $this->debug("Leaving serialize_return");
4122
+ }
4123
+
4124
+ /**
4125
+ * sends an HTTP response
4126
+ *
4127
+ * The following fields are set by this function (when successful)
4128
+ *
4129
+ * outgoing_headers
4130
+ * response
4131
+ *
4132
+ * @access private
4133
+ */
4134
+ function send_response() {
4135
+ $this->debug('Enter send_response');
4136
+ if ($this->fault) {
4137
+ $payload = $this->fault->serialize();
4138
+ $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
4139
+ $this->outgoing_headers[] = "Status: 500 Internal Server Error";
4140
+ } else {
4141
+ $payload = $this->responseSOAP;
4142
+ // Some combinations of PHP+Web server allow the Status
4143
+ // to come through as a header. Since OK is the default
4144
+ // just do nothing.
4145
+ // $this->outgoing_headers[] = "HTTP/1.0 200 OK";
4146
+ // $this->outgoing_headers[] = "Status: 200 OK";
4147
+ }
4148
+ // add debug data if in debug mode
4149
+ if(isset($this->debug_flag) && $this->debug_flag){
4150
+ $payload .= $this->getDebugAsXMLComment();
4151
+ }
4152
+ $this->outgoing_headers[] = "Server: $this->title Server v$this->version";
4153
+ ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev);
4154
+ $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")";
4155
+ // Let the Web server decide about this
4156
+ //$this->outgoing_headers[] = "Connection: Close\r\n";
4157
+ $payload = $this->getHTTPBody($payload);
4158
+ $type = $this->getHTTPContentType();
4159
+ $charset = $this->getHTTPContentTypeCharset();
4160
+ $this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
4161
+ //begin code to compress payload - by John
4162
+ // NOTE: there is no way to know whether the Web server will also compress
4163
+ // this data.
4164
+ if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {
4165
+ if (strstr($this->headers['accept-encoding'], 'gzip')) {
4166
+ if (function_exists('gzencode')) {
4167
+ if (isset($this->debug_flag) && $this->debug_flag) {
4168
+ $payload .= "<!-- Content being gzipped -->";
4169
+ }
4170
+ $this->outgoing_headers[] = "Content-Encoding: gzip";
4171
+ $payload = gzencode($payload);
4172
+ } else {
4173
+ if (isset($this->debug_flag) && $this->debug_flag) {
4174
+ $payload .= "<!-- Content will not be gzipped: no gzencode -->";
4175
+ }
4176
+ }
4177
+ } elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
4178
+ // Note: MSIE requires gzdeflate output (no Zlib header and checksum),
4179
+ // instead of gzcompress output,
4180
+ // which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
4181
+ if (function_exists('gzdeflate')) {
4182
+ if (isset($this->debug_flag) && $this->debug_flag) {
4183
+ $payload .= "<!-- Content being deflated -->";
4184
+ }
4185
+ $this->outgoing_headers[] = "Content-Encoding: deflate";
4186
+ $payload = gzdeflate($payload);
4187
+ } else {
4188
+ if (isset($this->debug_flag) && $this->debug_flag) {
4189
+ $payload .= "<!-- Content will not be deflated: no gzcompress -->";
4190
+ }
4191
+ }
4192
+ }
4193
+ }
4194
+ //end code
4195
+ $this->outgoing_headers[] = "Content-Length: ".strlen($payload);
4196
+ reset($this->outgoing_headers);
4197
+ foreach($this->outgoing_headers as $hdr){
4198
+ header($hdr, false);
4199
+ }
4200
+ print $payload;
4201
+ $this->response = join("\r\n",$this->outgoing_headers)."\r\n\r\n".$payload;
4202
+ }
4203
+
4204
+ /**
4205
+ * takes the value that was created by parsing the request
4206
+ * and compares to the method's signature, if available.
4207
+ *
4208
+ * @param string $operation The operation to be invoked
4209
+ * @param array $request The array of parameter values
4210
+ * @return boolean Whether the operation was found
4211
+ * @access private
4212
+ */
4213
+ function verify_method($operation,$request){
4214
+ if(isset($this->wsdl) && is_object($this->wsdl)){
4215
+ if($this->wsdl->getOperationData($operation)){
4216
+ return true;
4217
+ }
4218
+ } elseif(isset($this->operations[$operation])){
4219
+ return true;
4220
+ }
4221
+ return false;
4222
+ }
4223
+
4224
+ /**
4225
+ * processes SOAP message received from client
4226
+ *
4227
+ * @param array $headers The HTTP headers
4228
+ * @param string $data unprocessed request data from client
4229
+ * @return mixed value of the message, decoded into a PHP type
4230
+ * @access private
4231
+ */
4232
+ function parseRequest($headers, $data) {
4233
+ $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' and type ' . $headers['content-type']);
4234
+ if (!strstr($headers['content-type'], 'text/xml')) {
4235
+ $this->setError('Request not of type text/xml');
4236
+ return false;
4237
+ }
4238
+ if (strpos($headers['content-type'], '=')) {
4239
+ $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
4240
+ $this->debug('Got response encoding: ' . $enc);
4241
+ if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){
4242
+ $this->xml_encoding = strtoupper($enc);
4243
+ } else {
4244
+ $this->xml_encoding = 'US-ASCII';
4245
+ }
4246
+ } else {
4247
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
4248
+ $this->xml_encoding = 'ISO-8859-1';
4249
+ }
4250
+ $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
4251
+ // parse response, get soap parser obj
4252
+ $parser = new nusoap_parser($data,$this->xml_encoding,'',$this->decode_utf8);
4253
+ // parser debug
4254
+ $this->debug("parser debug: \n".$parser->getDebug());
4255
+ // if fault occurred during message parsing
4256
+ if($err = $parser->getError()){
4257
+ $this->result = 'fault: error in msg parsing: '.$err;
4258
+ $this->fault('SOAP-ENV:Client',"error in msg parsing:\n".$err);
4259
+ // else successfully parsed request into soapval object
4260
+ } else {
4261
+ // get/set methodname
4262
+ $this->methodURI = $parser->root_struct_namespace;
4263
+ $this->methodname = $parser->root_struct_name;
4264
+ $this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI);
4265
+ $this->debug('calling parser->get_soapbody()');
4266
+ $this->methodparams = $parser->get_soapbody();
4267
+ // get SOAP headers
4268
+ $this->requestHeaders = $parser->getHeaders();
4269
+ // get SOAP Header
4270
+ $this->requestHeader = $parser->get_soapheader();
4271
+ // add document for doclit support
4272
+ $this->document = $parser->document;
4273
+ }
4274
+ }
4275
+
4276
+ /**
4277
+ * gets the HTTP body for the current response.
4278
+ *
4279
+ * @param string $soapmsg The SOAP payload
4280
+ * @return string The HTTP body, which includes the SOAP payload
4281
+ * @access private
4282
+ */
4283
+ function getHTTPBody($soapmsg) {
4284
+ return $soapmsg;
4285
+ }
4286
+
4287
+ /**
4288
+ * gets the HTTP content type for the current response.
4289
+ *
4290
+ * Note: getHTTPBody must be called before this.
4291
+ *
4292
+ * @return string the HTTP content type for the current response.
4293
+ * @access private
4294
+ */
4295
+ function getHTTPContentType() {
4296
+ return 'text/xml';
4297
+ }
4298
+
4299
+ /**
4300
+ * gets the HTTP content type charset for the current response.
4301
+ * returns false for non-text content types.
4302
+ *
4303
+ * Note: getHTTPBody must be called before this.
4304
+ *
4305
+ * @return string the HTTP content type charset for the current response.
4306
+ * @access private
4307
+ */
4308
+ function getHTTPContentTypeCharset() {
4309
+ return $this->soap_defencoding;
4310
+ }
4311
+
4312
+ /**
4313
+ * add a method to the dispatch map (this has been replaced by the register method)
4314
+ *
4315
+ * @param string $methodname
4316
+ * @param string $in array of input values
4317
+ * @param string $out array of output values
4318
+ * @access public
4319
+ * @deprecated
4320
+ */
4321
+ function add_to_map($methodname,$in,$out){
4322
+ $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
4323
+ }
4324
+
4325
+ /**
4326
+ * register a service function with the server
4327
+ *
4328
+ * @param string $name the name of the PHP function, class.method or class..method
4329
+ * @param array $in assoc array of input values: key = param name, value = param type
4330
+ * @param array $out assoc array of output values: key = param name, value = param type
4331
+ * @param mixed $namespace the element namespace for the method or false
4332
+ * @param mixed $soapaction the soapaction for the method or false
4333
+ * @param mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically
4334
+ * @param mixed $use optional (encoded|literal) or false
4335
+ * @param string $documentation optional Description to include in WSDL
4336
+ * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
4337
+ * @access public
4338
+ */
4339
+ function register($name,$in=array(),$out=array(),$namespace=false,$soapaction=false,$style=false,$use=false,$documentation='',$encodingStyle=''){
4340
+ global $HTTP_SERVER_VARS;
4341
+
4342
+ if($this->externalWSDLURL){
4343
+ die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
4344
+ }
4345
+ if (! $name) {
4346
+ die('You must specify a name when you register an operation');
4347
+ }
4348
+ if (!is_array($in)) {
4349
+ die('You must provide an array for operation inputs');
4350
+ }
4351
+ if (!is_array($out)) {
4352
+ die('You must provide an array for operation outputs');
4353
+ }
4354
+ if(false == $namespace) {
4355
+ }
4356
+ if(false == $soapaction) {
4357
+ if (isset($_SERVER)) {
4358
+ $SERVER_NAME = $_SERVER['SERVER_NAME'];
4359
+ $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
4360
+ $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
4361
+ } elseif (isset($HTTP_SERVER_VARS)) {
4362
+ $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
4363
+ $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
4364
+ $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
4365
+ } else {
4366
+ $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
4367
+ }
4368
+ if ($HTTPS == '1' || $HTTPS == 'on') {
4369
+ $SCHEME = 'https';
4370
+ } else {
4371
+ $SCHEME = 'http';
4372
+ }
4373
+ $soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
4374
+ }
4375
+ if(false == $style) {
4376
+ $style = "rpc";
4377
+ }
4378
+ if(false == $use) {
4379
+ $use = "encoded";
4380
+ }
4381
+ if ($use == 'encoded' && $encodingStyle = '') {
4382
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
4383
+ }
4384
+
4385
+ $this->operations[$name] = array(
4386
+ 'name' => $name,
4387
+ 'in' => $in,
4388
+ 'out' => $out,
4389
+ 'namespace' => $namespace,
4390
+ 'soapaction' => $soapaction,
4391
+ 'style' => $style);
4392
+ if($this->wsdl){
4393
+ $this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use,$documentation,$encodingStyle);
4394
+ }
4395
+ return true;
4396
+ }
4397
+
4398
+ /**
4399
+ * Specify a fault to be returned to the client.
4400
+ * This also acts as a flag to the server that a fault has occured.
4401
+ *
4402
+ * @param string $faultcode
4403
+ * @param string $faultstring
4404
+ * @param string $faultactor
4405
+ * @param string $faultdetail
4406
+ * @access public
4407
+ */
4408
+ function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){
4409
+ if ($faultdetail == '' && $this->debug_flag) {
4410
+ $faultdetail = $this->getDebug();
4411
+ }
4412
+ $this->fault = new nusoap_fault($faultcode,$faultactor,$faultstring,$faultdetail);
4413
+ $this->fault->soap_defencoding = $this->soap_defencoding;
4414
+ }
4415
+
4416
+ /**
4417
+ * Sets up wsdl object.
4418
+ * Acts as a flag to enable internal WSDL generation
4419
+ *
4420
+ * @param string $serviceName, name of the service
4421
+ * @param mixed $namespace optional 'tns' service namespace or false
4422
+ * @param mixed $endpoint optional URL of service endpoint or false
4423
+ * @param string $style optional (rpc|document) WSDL style (also specified by operation)
4424
+ * @param string $transport optional SOAP transport
4425
+ * @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false
4426
+ */
4427
+ function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
4428
+ {
4429
+ global $HTTP_SERVER_VARS;
4430
+
4431
+ if (isset($_SERVER)) {
4432
+ $SERVER_NAME = $_SERVER['SERVER_NAME'];
4433
+ $SERVER_PORT = $_SERVER['SERVER_PORT'];
4434
+ $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
4435
+ $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
4436
+ } elseif (isset($HTTP_SERVER_VARS)) {
4437
+ $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
4438
+ $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
4439
+ $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
4440
+ $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
4441
+ } else {
4442
+ $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
4443
+ }
4444
+ // If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)
4445
+ $colon = strpos($SERVER_NAME,":");
4446
+ if ($colon) {
4447
+ $SERVER_NAME = substr($SERVER_NAME, 0, $colon);
4448
+ }
4449
+ if ($SERVER_PORT == 80) {
4450
+ $SERVER_PORT = '';
4451
+ } else {
4452
+ $SERVER_PORT = ':' . $SERVER_PORT;
4453
+ }
4454
+ if(false == $namespace) {
4455
+ $namespace = "http://$SERVER_NAME/soap/$serviceName";
4456
+ }
4457
+
4458
+ if(false == $endpoint) {
4459
+ if ($HTTPS == '1' || $HTTPS == 'on') {
4460
+ $SCHEME = 'https';
4461
+ } else {
4462
+ $SCHEME = 'http';
4463
+ }
4464
+ $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
4465
+ }
4466
+
4467
+ if(false == $schemaTargetNamespace) {
4468
+ $schemaTargetNamespace = $namespace;
4469
+ }
4470
+
4471
+ $this->wsdl = new wsdl;
4472
+ $this->wsdl->serviceName = $serviceName;
4473
+ $this->wsdl->endpoint = $endpoint;
4474
+ $this->wsdl->namespaces['tns'] = $namespace;
4475
+ $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
4476
+ $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
4477
+ if ($schemaTargetNamespace != $namespace) {
4478
+ $this->wsdl->namespaces['types'] = $schemaTargetNamespace;
4479
+ }
4480
+ $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces);
4481
+ if ($style == 'document') {
4482
+ $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified';
4483
+ }
4484
+ $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
4485
+ $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
4486
+ $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
4487
+ $this->wsdl->bindings[$serviceName.'Binding'] = array(
4488
+ 'name'=>$serviceName.'Binding',
4489
+ 'style'=>$style,
4490
+ 'transport'=>$transport,
4491
+ 'portType'=>$serviceName.'PortType');
4492
+ $this->wsdl->ports[$serviceName.'Port'] = array(
4493
+ 'binding'=>$serviceName.'Binding',
4494
+ 'location'=>$endpoint,
4495
+ 'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/');
4496
+ }
4497
+ }
4498
+
4499
+ /**
4500
+ * Backward compatibility
4501
+ */
4502
+ class soap_server extends nusoap_server {
4503
+ }
4504
+
4505
+ ?><?php
4506
+
4507
+
4508
+
4509
+ /**
4510
+ * parses a WSDL file, allows access to it's data, other utility methods.
4511
+ * also builds WSDL structures programmatically.
4512
+ *
4513
+ * @author Dietrich Ayala <dietrich@ganx4.com>
4514
+ * @author Scott Nichol <snichol@users.sourceforge.net>
4515
+ * @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $
4516
+ * @access public
4517
+ */
4518
+ class wsdl extends nusoap_base {
4519
+ // URL or filename of the root of this WSDL
4520
+ var $wsdl;
4521
+ // define internal arrays of bindings, ports, operations, messages, etc.
4522
+ var $schemas = array();
4523
+ var $currentSchema;
4524
+ var $message = array();
4525
+ var $complexTypes = array();
4526
+ var $messages = array();
4527
+ var $currentMessage;
4528
+ var $currentOperation;
4529
+ var $portTypes = array();
4530
+ var $currentPortType;
4531
+ var $bindings = array();
4532
+ var $currentBinding;
4533
+ var $ports = array();
4534
+ var $currentPort;
4535
+ var $opData = array();
4536
+ var $status = '';
4537
+ var $documentation = false;
4538
+ var $endpoint = '';
4539
+ // array of wsdl docs to import
4540
+ var $import = array();
4541
+ // parser vars
4542
+ var $parser;
4543
+ var $position = 0;
4544
+ var $depth = 0;
4545
+ var $depth_array = array();
4546
+ // for getting wsdl
4547
+ var $proxyhost = '';
4548
+ var $proxyport = '';
4549
+ var $proxyusername = '';
4550
+ var $proxypassword = '';
4551
+ var $timeout = 0;
4552
+ var $response_timeout = 30;
4553
+ var $curl_options = array(); // User-specified cURL options
4554
+ var $use_curl = false; // whether to always try to use cURL
4555
+ // for HTTP authentication
4556
+ var $username = ''; // Username for HTTP authentication
4557
+ var $password = ''; // Password for HTTP authentication
4558
+ var $authtype = ''; // Type of HTTP authentication
4559
+ var $certRequest = array(); // Certificate for HTTP SSL authentication
4560
+
4561
+ /**
4562
+ * constructor
4563
+ *
4564
+ * @param string $wsdl WSDL document URL
4565
+ * @param string $proxyhost
4566
+ * @param string $proxyport
4567
+ * @param string $proxyusername
4568
+ * @param string $proxypassword
4569
+ * @param integer $timeout set the connection timeout
4570
+ * @param integer $response_timeout set the response timeout
4571
+ * @param array $curl_options user-specified cURL options
4572
+ * @param boolean $use_curl try to use cURL
4573
+ * @access public
4574
+ */
4575
+ function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30,$curl_options=null,$use_curl=false){
4576
+ parent::nusoap_base();
4577
+ $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
4578
+ $this->proxyhost = $proxyhost;
4579
+ $this->proxyport = $proxyport;
4580
+ $this->proxyusername = $proxyusername;
4581
+ $this->proxypassword = $proxypassword;
4582
+ $this->timeout = $timeout;
4583
+ $this->response_timeout = $response_timeout;
4584
+ if (is_array($curl_options))
4585
+ $this->curl_options = $curl_options;
4586
+ $this->use_curl = $use_curl;
4587
+ $this->fetchWSDL($wsdl);
4588
+ }
4589
+
4590
+ /**
4591
+ * fetches the WSDL document and parses it
4592
+ *
4593
+ * @access public
4594
+ */
4595
+ function fetchWSDL($wsdl) {
4596
+ $this->debug("parse and process WSDL path=$wsdl");
4597
+ $this->wsdl = $wsdl;
4598
+ // parse wsdl file
4599
+ if ($this->wsdl != "") {
4600
+ $this->parseWSDL($this->wsdl);
4601
+ }
4602
+ // imports
4603
+ // TODO: handle imports more properly, grabbing them in-line and nesting them
4604
+ $imported_urls = array();
4605
+ $imported = 1;
4606
+ while ($imported > 0) {
4607
+ $imported = 0;
4608
+ // Schema imports
4609
+ foreach ($this->schemas as $ns => $list) {
4610
+ foreach ($list as $xs) {
4611
+ $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
4612
+ foreach ($xs->imports as $ns2 => $list2) {
4613
+ for ($ii = 0; $ii < count($list2); $ii++) {
4614
+ if (! $list2[$ii]['loaded']) {
4615
+ $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
4616
+ $url = $list2[$ii]['location'];
4617
+ if ($url != '') {
4618
+ $urlparts = parse_url($url);
4619
+ if (!isset($urlparts['host'])) {
4620
+ $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') .
4621
+ substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
4622
+ }
4623
+ if (! in_array($url, $imported_urls)) {
4624
+ $this->parseWSDL($url);
4625
+ $imported++;
4626
+ $imported_urls[] = $url;
4627
+ }
4628
+ } else {
4629
+ $this->debug("Unexpected scenario: empty URL for unloaded import");
4630
+ }
4631
+ }
4632
+ }
4633
+ }
4634
+ }
4635
+ }
4636
+ // WSDL imports
4637
+ $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
4638
+ foreach ($this->import as $ns => $list) {
4639
+ for ($ii = 0; $ii < count($list); $ii++) {
4640
+ if (! $list[$ii]['loaded']) {
4641
+ $this->import[$ns][$ii]['loaded'] = true;
4642
+ $url = $list[$ii]['location'];
4643
+ if ($url != '') {
4644
+ $urlparts = parse_url($url);
4645
+ if (!isset($urlparts['host'])) {
4646
+ $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
4647
+ substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
4648
+ }
4649
+ if (! in_array($url, $imported_urls)) {
4650
+ $this->parseWSDL($url);
4651
+ $imported++;
4652
+ $imported_urls[] = $url;
4653
+ }
4654
+ } else {
4655
+ $this->debug("Unexpected scenario: empty URL for unloaded import");
4656
+ }
4657
+ }
4658
+ }
4659
+ }
4660
+ }
4661
+ // add new data to operation data
4662
+ foreach($this->bindings as $binding => $bindingData) {
4663
+ if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
4664
+ foreach($bindingData['operations'] as $operation => $data) {
4665
+ $this->debug('post-parse data gathering for ' . $operation);
4666
+ $this->bindings[$binding]['operations'][$operation]['input'] =
4667
+ isset($this->bindings[$binding]['operations'][$operation]['input']) ?
4668
+ array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
4669
+ $this->portTypes[ $bindingData['portType'] ][$operation]['input'];
4670
+ $this->bindings[$binding]['operations'][$operation]['output'] =
4671
+ isset($this->bindings[$binding]['operations'][$operation]['output']) ?
4672
+ array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
4673
+ $this->portTypes[ $bindingData['portType'] ][$operation]['output'];
4674
+ if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])){
4675
+ $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
4676
+ }
4677
+ if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])){
4678
+ $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
4679
+ }
4680
+ // Set operation style if necessary, but do not override one already provided
4681
+ if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) {
4682
+ $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
4683
+ }
4684
+ $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
4685
+ $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
4686
+ $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
4687
+ }
4688
+ }
4689
+ }
4690
+ }
4691
+
4692
+ /**
4693
+ * parses the wsdl document
4694
+ *
4695
+ * @param string $wsdl path or URL
4696
+ * @access private
4697
+ */
4698
+ function parseWSDL($wsdl = '') {
4699
+ $this->debug("parse WSDL at path=$wsdl");
4700
+
4701
+ if ($wsdl == '') {
4702
+ $this->debug('no wsdl passed to parseWSDL()!!');
4703
+ $this->setError('no wsdl passed to parseWSDL()!!');
4704
+ return false;
4705
+ }
4706
+
4707
+ // parse $wsdl for url format
4708
+ $wsdl_props = parse_url($wsdl);
4709
+
4710
+ if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
4711
+ $this->debug('getting WSDL http(s) URL ' . $wsdl);
4712
+ // get wsdl
4713
+ $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl);
4714
+ $tr->request_method = 'GET';
4715
+ $tr->useSOAPAction = false;
4716
+ if($this->proxyhost && $this->proxyport){
4717
+ $tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
4718
+ }
4719
+ if ($this->authtype != '') {
4720
+ $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
4721
+ }
4722
+ $tr->setEncoding('gzip, deflate');
4723
+ $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
4724
+ //$this->debug("WSDL request\n" . $tr->outgoing_payload);
4725
+ //$this->debug("WSDL response\n" . $tr->incoming_payload);
4726
+ $this->appendDebug($tr->getDebug());
4727
+ // catch errors
4728
+ if($err = $tr->getError() ){
4729
+ $errstr = 'HTTP ERROR: '.$err;
4730
+ $this->debug($errstr);
4731
+ $this->setError($errstr);
4732
+ unset($tr);
4733
+ return false;
4734
+ }
4735
+ unset($tr);
4736
+ $this->debug("got WSDL URL");
4737
+ } else {
4738
+ // $wsdl is not http(s), so treat it as a file URL or plain file path
4739
+ if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
4740
+ $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
4741
+ } else {
4742
+ $path = $wsdl;
4743
+ }
4744
+ $this->debug('getting WSDL file ' . $path);
4745
+ if ($fp = @fopen($path, 'r')) {
4746
+ $wsdl_string = '';
4747
+ while ($data = fread($fp, 32768)) {
4748
+ $wsdl_string .= $data;
4749
+ }
4750
+ fclose($fp);
4751
+ } else {
4752
+ $errstr = "Bad path to WSDL file $path";
4753
+ $this->debug($errstr);
4754
+ $this->setError($errstr);
4755
+ return false;
4756
+ }
4757
+ }
4758
+ $this->debug('Parse WSDL');
4759
+ // end new code added
4760
+ // Create an XML parser.
4761
+ $this->parser = xml_parser_create();
4762
+ // Set the options for parsing the XML data.
4763
+ // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
4764
+ xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
4765
+ // Set the object for the parser.
4766
+ xml_set_object($this->parser, $this);
4767
+ // Set the element handlers for the parser.
4768
+ xml_set_element_handler($this->parser, 'start_element', 'end_element');
4769
+ xml_set_character_data_handler($this->parser, 'character_data');
4770
+ // Parse the XML file.
4771
+ if (!xml_parse($this->parser, $wsdl_string, true)) {
4772
+ // Display an error message.
4773
+ $errstr = sprintf(
4774
+ 'XML error parsing WSDL from %s on line %d: %s',
4775
+ $wsdl,
4776
+ xml_get_current_line_number($this->parser),
4777
+ xml_error_string(xml_get_error_code($this->parser))
4778
+ );
4779
+ $this->debug($errstr);
4780
+ $this->debug("XML payload:\n" . $wsdl_string);
4781
+ $this->setError($errstr);
4782
+ return false;
4783
+ }
4784
+ // free the parser
4785
+ xml_parser_free($this->parser);
4786
+ $this->debug('Parsing WSDL done');
4787
+ // catch wsdl parse errors
4788
+ if($this->getError()){
4789
+ return false;
4790
+ }
4791
+ return true;
4792
+ }
4793
+
4794
+ /**
4795
+ * start-element handler
4796
+ *
4797
+ * @param string $parser XML parser object
4798
+ * @param string $name element name
4799
+ * @param string $attrs associative array of attributes
4800
+ * @access private
4801
+ */
4802
+ function start_element($parser, $name, $attrs)
4803
+ {
4804
+ if ($this->status == 'schema') {
4805
+ $this->currentSchema->schemaStartElement($parser, $name, $attrs);
4806
+ $this->appendDebug($this->currentSchema->getDebug());
4807
+ $this->currentSchema->clearDebug();
4808
+ } elseif (ereg('schema$', $name)) {
4809
+ $this->debug('Parsing WSDL schema');
4810
+ // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
4811
+ $this->status = 'schema';
4812
+ $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
4813
+ $this->currentSchema->schemaStartElement($parser, $name, $attrs);
4814
+ $this->appendDebug($this->currentSchema->getDebug());
4815
+ $this->currentSchema->clearDebug();
4816
+ } else {
4817
+ // position in the total number of elements, starting from 0
4818
+ $pos = $this->position++;
4819
+ $depth = $this->depth++;
4820
+ // set self as current value for this depth
4821
+ $this->depth_array[$depth] = $pos;
4822
+ $this->message[$pos] = array('cdata' => '');
4823
+ // process attributes
4824
+ if (count($attrs) > 0) {
4825
+ // register namespace declarations
4826
+ foreach($attrs as $k => $v) {
4827
+ if (ereg("^xmlns", $k)) {
4828
+ if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
4829
+ $this->namespaces[$ns_prefix] = $v;
4830
+ } else {
4831
+ $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
4832
+ }
4833
+ if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
4834
+ $this->XMLSchemaVersion = $v;
4835
+ $this->namespaces['xsi'] = $v . '-instance';
4836
+ }
4837
+ }
4838
+ }
4839
+ // expand each attribute prefix to its namespace
4840
+ foreach($attrs as $k => $v) {
4841
+ $k = strpos($k, ':') ? $this->expandQname($k) : $k;
4842
+ if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
4843
+ $v = strpos($v, ':') ? $this->expandQname($v) : $v;
4844
+ }
4845
+ $eAttrs[$k] = $v;
4846
+ }
4847
+ $attrs = $eAttrs;
4848
+ } else {
4849
+ $attrs = array();
4850
+ }
4851
+ // get element prefix, namespace and name
4852
+ if (ereg(':', $name)) {
4853
+ // get ns prefix
4854
+ $prefix = substr($name, 0, strpos($name, ':'));
4855
+ // get ns
4856
+ $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : '';
4857
+ // get unqualified name
4858
+ $name = substr(strstr($name, ':'), 1);
4859
+ }
4860
+ // process attributes, expanding any prefixes to namespaces
4861
+ // find status, register data
4862
+ switch ($this->status) {
4863
+ case 'message':
4864
+ if ($name == 'part') {
4865
+ if (isset($attrs['type'])) {
4866
+ $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs));
4867
+ $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
4868
+ }
4869
+ if (isset($attrs['element'])) {
4870
+ $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));
4871
+ $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';
4872
+ }
4873
+ }
4874
+ break;
4875
+ case 'portType':
4876
+ switch ($name) {
4877
+ case 'operation':
4878
+ $this->currentPortOperation = $attrs['name'];
4879
+ $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
4880
+ if (isset($attrs['parameterOrder'])) {
4881
+ $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
4882
+ }
4883
+ break;
4884
+ case 'documentation':
4885
+ $this->documentation = true;
4886
+ break;
4887
+ // merge input/output data
4888
+ default:
4889
+ $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
4890
+ $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
4891
+ break;
4892
+ }
4893
+ break;
4894
+ case 'binding':
4895
+ switch ($name) {
4896
+ case 'binding':
4897
+ // get ns prefix
4898
+ if (isset($attrs['style'])) {
4899
+ $this->bindings[$this->currentBinding]['prefix'] = $prefix;
4900
+ }
4901
+ $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
4902
+ break;
4903
+ case 'header':
4904
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
4905
+ break;
4906
+ case 'operation':
4907
+ if (isset($attrs['soapAction'])) {
4908
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
4909
+ }
4910
+ if (isset($attrs['style'])) {
4911
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
4912
+ }
4913
+ if (isset($attrs['name'])) {
4914
+ $this->currentOperation = $attrs['name'];
4915
+ $this->debug("current binding operation: $this->currentOperation");
4916
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
4917
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
4918
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
4919
+ }
4920
+ break;
4921
+ case 'input':
4922
+ $this->opStatus = 'input';
4923
+ break;
4924
+ case 'output':
4925
+ $this->opStatus = 'output';
4926
+ break;
4927
+ case 'body':
4928
+ if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
4929
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
4930
+ } else {
4931
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
4932
+ }
4933
+ break;
4934
+ }
4935
+ break;
4936
+ case 'service':
4937
+ switch ($name) {
4938
+ case 'port':
4939
+ $this->currentPort = $attrs['name'];
4940
+ $this->debug('current port: ' . $this->currentPort);
4941
+ $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
4942
+
4943
+ break;
4944
+ case 'address':
4945
+ $this->ports[$this->currentPort]['location'] = $attrs['location'];
4946
+ $this->ports[$this->currentPort]['bindingType'] = $namespace;
4947
+ $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;
4948
+ $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
4949
+ break;
4950
+ }
4951
+ break;
4952
+ }
4953
+ // set status
4954
+ switch ($name) {
4955
+ case 'import':
4956
+ if (isset($attrs['location'])) {
4957
+ $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
4958
+ $this->debug('parsing import ' . $attrs['namespace']. ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]).')');
4959
+ } else {
4960
+ $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
4961
+ if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
4962
+ $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
4963
+ }
4964
+ $this->debug('parsing import ' . $attrs['namespace']. ' - [no location] (' . count($this->import[$attrs['namespace']]).')');
4965
+ }
4966
+ break;
4967
+ //wait for schema
4968
+ //case 'types':
4969
+ // $this->status = 'schema';
4970
+ // break;
4971
+ case 'message':
4972
+ $this->status = 'message';
4973
+ $this->messages[$attrs['name']] = array();
4974
+ $this->currentMessage = $attrs['name'];
4975
+ break;
4976
+ case 'portType':
4977
+ $this->status = 'portType';
4978
+ $this->portTypes[$attrs['name']] = array();
4979
+ $this->currentPortType = $attrs['name'];
4980
+ break;
4981
+ case "binding":
4982
+ if (isset($attrs['name'])) {
4983
+ // get binding name
4984
+ if (strpos($attrs['name'], ':')) {
4985
+ $this->currentBinding = $this->getLocalPart($attrs['name']);
4986
+ } else {
4987
+ $this->currentBinding = $attrs['name'];
4988
+ }
4989
+ $this->status = 'binding';
4990
+ $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
4991
+ $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
4992
+ }
4993
+ break;
4994
+ case 'service':
4995
+ $this->serviceName = $attrs['name'];
4996
+ $this->status = 'service';
4997
+ $this->debug('current service: ' . $this->serviceName);
4998
+ break;
4999
+ case 'definitions':
5000
+ foreach ($attrs as $name => $value) {
5001
+ $this->wsdl_info[$name] = $value;
5002
+ }
5003
+ break;
5004
+ }
5005
+ }
5006
+ }
5007
+
5008
+ /**
5009
+ * end-element handler
5010
+ *
5011
+ * @param string $parser XML parser object
5012
+ * @param string $name element name
5013
+ * @access private
5014
+ */
5015
+ function end_element($parser, $name){
5016
+ // unset schema status
5017
+ if (/*ereg('types$', $name) ||*/ ereg('schema$', $name)) {
5018
+ $this->status = "";
5019
+ $this->appendDebug($this->currentSchema->getDebug());
5020
+ $this->currentSchema->clearDebug();
5021
+ $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
5022
+ $this->debug('Parsing WSDL schema done');
5023
+ }
5024
+ if ($this->status == 'schema') {
5025
+ $this->currentSchema->schemaEndElement($parser, $name);
5026
+ } else {
5027
+ // bring depth down a notch
5028
+ $this->depth--;
5029
+ }
5030
+ // end documentation
5031
+ if ($this->documentation) {
5032
+ //TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
5033
+ //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
5034
+ $this->documentation = false;
5035
+ }
5036
+ }
5037
+
5038
+ /**
5039
+ * element content handler
5040
+ *
5041
+ * @param string $parser XML parser object
5042
+ * @param string $data element content
5043
+ * @access private
5044
+ */
5045
+ function character_data($parser, $data)
5046
+ {
5047
+ $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
5048
+ if (isset($this->message[$pos]['cdata'])) {
5049
+ $this->message[$pos]['cdata'] .= $data;
5050
+ }
5051
+ if ($this->documentation) {
5052
+ $this->documentation .= $data;
5053
+ }
5054
+ }
5055
+
5056
+ /**
5057
+ * if authenticating, set user credentials here
5058
+ *
5059
+ * @param string $username
5060
+ * @param string $password
5061
+ * @param string $authtype (basic|digest|certificate|ntlm)
5062
+ * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
5063
+ * @access public
5064
+ */
5065
+ function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
5066
+ $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
5067
+ $this->appendDebug($this->varDump($certRequest));
5068
+ $this->username = $username;
5069
+ $this->password = $password;
5070
+ $this->authtype = $authtype;
5071
+ $this->certRequest = $certRequest;
5072
+ }
5073
+
5074
+ function getBindingData($binding)
5075
+ {
5076
+ if (is_array($this->bindings[$binding])) {
5077
+ return $this->bindings[$binding];
5078
+ }
5079
+ }
5080
+
5081
+ /**
5082
+ * returns an assoc array of operation names => operation data
5083
+ *
5084
+ * @param string $bindingType eg: soap, smtp, dime (only soap and soap12 are currently supported)
5085
+ * @return array
5086
+ * @access public
5087
+ */
5088
+ function getOperations($bindingType = 'soap') {
5089
+ $ops = array();
5090
+ if ($bindingType == 'soap') {
5091
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5092
+ } elseif ($bindingType == 'soap12') {
5093
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5094
+ }
5095
+ // loop thru ports
5096
+ foreach($this->ports as $port => $portData) {
5097
+ // binding type of port matches parameter
5098
+ if ($portData['bindingType'] == $bindingType) {
5099
+ //$this->debug("getOperations for port $port");
5100
+ //$this->debug("port data: " . $this->varDump($portData));
5101
+ //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
5102
+ // merge bindings
5103
+ if (isset($this->bindings[ $portData['binding'] ]['operations'])) {
5104
+ $ops = array_merge ($ops, $this->bindings[ $portData['binding'] ]['operations']);
5105
+ }
5106
+ }
5107
+ }
5108
+ return $ops;
5109
+ }
5110
+
5111
+ /**
5112
+ * returns an associative array of data necessary for calling an operation
5113
+ *
5114
+ * @param string $operation name of operation
5115
+ * @param string $bindingType type of binding eg: soap, soap12
5116
+ * @return array
5117
+ * @access public
5118
+ */
5119
+ function getOperationData($operation, $bindingType = 'soap')
5120
+ {
5121
+ if ($bindingType == 'soap') {
5122
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5123
+ } elseif ($bindingType == 'soap12') {
5124
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5125
+ }
5126
+ // loop thru ports
5127
+ foreach($this->ports as $port => $portData) {
5128
+ // binding type of port matches parameter
5129
+ if ($portData['bindingType'] == $bindingType) {
5130
+ // get binding
5131
+ //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
5132
+ foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {
5133
+ // note that we could/should also check the namespace here
5134
+ if ($operation == $bOperation) {
5135
+ $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];
5136
+ return $opData;
5137
+ }
5138
+ }
5139
+ }
5140
+ }
5141
+ }
5142
+
5143
+ /**
5144
+ * returns an associative array of data necessary for calling an operation
5145
+ *
5146
+ * @param string $soapAction soapAction for operation
5147
+ * @param string $bindingType type of binding eg: soap, soap12
5148
+ * @return array
5149
+ * @access public
5150
+ */
5151
+ function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') {
5152
+ if ($bindingType == 'soap') {
5153
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5154
+ } elseif ($bindingType == 'soap12') {
5155
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5156
+ }
5157
+ // loop thru ports
5158
+ foreach($this->ports as $port => $portData) {
5159
+ // binding type of port matches parameter
5160
+ if ($portData['bindingType'] == $bindingType) {
5161
+ // loop through operations for the binding
5162
+ foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
5163
+ if ($opData['soapAction'] == $soapAction) {
5164
+ return $opData;
5165
+ }
5166
+ }
5167
+ }
5168
+ }
5169
+ }
5170
+
5171
+ /**
5172
+ * returns an array of information about a given type
5173
+ * returns false if no type exists by the given name
5174
+ *
5175
+ * typeDef = array(
5176
+ * 'elements' => array(), // refs to elements array
5177
+ * 'restrictionBase' => '',
5178
+ * 'phpType' => '',
5179
+ * 'order' => '(sequence|all)',
5180
+ * 'attrs' => array() // refs to attributes array
5181
+ * )
5182
+ *
5183
+ * @param string $type the type
5184
+ * @param string $ns namespace (not prefix) of the type
5185
+ * @return mixed
5186
+ * @access public
5187
+ * @see nusoap_xmlschema
5188
+ */
5189
+ function getTypeDef($type, $ns) {
5190
+ $this->debug("in getTypeDef: type=$type, ns=$ns");
5191
+ if ((! $ns) && isset($this->namespaces['tns'])) {
5192
+ $ns = $this->namespaces['tns'];
5193
+ $this->debug("in getTypeDef: type namespace forced to $ns");
5194
+ }
5195
+ if (!isset($this->schemas[$ns])) {
5196
+ foreach ($this->schemas as $ns0 => $schema0) {
5197
+ if (strcasecmp($ns, $ns0) == 0) {
5198
+ $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0");
5199
+ $ns = $ns0;
5200
+ break;
5201
+ }
5202
+ }
5203
+ }
5204
+ if (isset($this->schemas[$ns])) {
5205
+ $this->debug("in getTypeDef: have schema for namespace $ns");
5206
+ for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
5207
+ $xs = &$this->schemas[$ns][$i];
5208
+ $t = $xs->getTypeDef($type);
5209
+ //$this->appendDebug($xs->getDebug());
5210
+ //$xs->clearDebug();
5211
+ if ($t) {
5212
+ if (!isset($t['phpType'])) {
5213
+ // get info for type to tack onto the element
5214
+ $uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
5215
+ $ns = substr($t['type'], 0, strrpos($t['type'], ':'));
5216
+ $etype = $this->getTypeDef($uqType, $ns);
5217
+ if ($etype) {
5218
+ $this->debug("found type for [element] $type:");
5219
+ $this->debug($this->varDump($etype));
5220
+ if (isset($etype['phpType'])) {
5221
+ $t['phpType'] = $etype['phpType'];
5222
+ }
5223
+ if (isset($etype['elements'])) {
5224
+ $t['elements'] = $etype['elements'];
5225
+ }
5226
+ if (isset($etype['attrs'])) {
5227
+ $t['attrs'] = $etype['attrs'];
5228
+ }
5229
+ }
5230
+ }
5231
+ return $t;
5232
+ }
5233
+ }
5234
+ } else {
5235
+ $this->debug("in getTypeDef: do not have schema for namespace $ns");
5236
+ }
5237
+ return false;
5238
+ }
5239
+
5240
+ /**
5241
+ * prints html description of services
5242
+ *
5243
+ * @access private
5244
+ */
5245
+ function webDescription(){
5246
+ global $HTTP_SERVER_VARS;
5247
+
5248
+ if (isset($_SERVER)) {
5249
+ $PHP_SELF = $_SERVER['PHP_SELF'];
5250
+ } elseif (isset($HTTP_SERVER_VARS)) {
5251
+ $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
5252
+ } else {
5253
+ $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
5254
+ }
5255
+
5256
+ $b = '
5257
+ <html><head><title>NuSOAP: '.$this->serviceName.'</title>
5258
+ <style type="text/css">
5259
+ body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
5260
+ p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
5261
+ pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
5262
+ ul { margin-top: 10px; margin-left: 20px; }
5263
+ li { list-style-type: none; margin-top: 10px; color: #000000; }
5264
+ .content{
5265
+ margin-left: 0px; padding-bottom: 2em; }
5266
+ .nav {
5267
+ padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
5268
+ margin-top: 10px; margin-left: 0px; color: #000000;
5269
+ background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
5270
+ .title {
5271
+ font-family: arial; font-size: 26px; color: #ffffff;
5272
+ background-color: #999999; width: 105%; margin-left: 0px;
5273
+ padding-top: 10px; padding-bottom: 10px; padding-left: 15px;}
5274
+ .hidden {
5275
+ position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
5276
+ font-family: arial; overflow: hidden; width: 600;
5277
+ padding: 20px; font-size: 10px; background-color: #999999;
5278
+ layer-background-color:#FFFFFF; }
5279
+ a,a:active { color: charcoal; font-weight: bold; }
5280
+ a:visited { color: #666666; font-weight: bold; }
5281
+ a:hover { color: cc3300; font-weight: bold; }
5282
+ </style>
5283
+ <script language="JavaScript" type="text/javascript">
5284
+ <!--
5285
+ // POP-UP CAPTIONS...
5286
+ function lib_bwcheck(){ //Browsercheck (needed)
5287
+ this.ver=navigator.appVersion
5288
+ this.agent=navigator.userAgent
5289
+ this.dom=document.getElementById?1:0
5290
+ this.opera5=this.agent.indexOf("Opera 5")>-1
5291
+ this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
5292
+ this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
5293
+ this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
5294
+ this.ie=this.ie4||this.ie5||this.ie6
5295
+ this.mac=this.agent.indexOf("Mac")>-1
5296
+ this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
5297
+ this.ns4=(document.layers && !this.dom)?1:0;
5298
+ this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
5299
+ return this
5300
+ }
5301
+ var bw = new lib_bwcheck()
5302
+ //Makes crossbrowser object.
5303
+ function makeObj(obj){
5304
+ this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
5305
+ if(!this.evnt) return false
5306
+ this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
5307
+ this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
5308
+ this.writeIt=b_writeIt;
5309
+ return this
5310
+ }
5311
+ // A unit of measure that will be added when setting the position of a layer.
5312
+ //var px = bw.ns4||window.opera?"":"px";
5313
+ function b_writeIt(text){
5314
+ if (bw.ns4){this.wref.write(text);this.wref.close()}
5315
+ else this.wref.innerHTML = text
5316
+ }
5317
+ //Shows the messages
5318
+ var oDesc;
5319
+ function popup(divid){
5320
+ if(oDesc = new makeObj(divid)){
5321
+ oDesc.css.visibility = "visible"
5322
+ }
5323
+ }
5324
+ function popout(){ // Hides message
5325
+ if(oDesc) oDesc.css.visibility = "hidden"
5326
+ }
5327
+ //-->
5328
+ </script>
5329
+ </head>
5330
+ <body>
5331
+ <div class=content>
5332
+ <br><br>
5333
+ <div class=title>'.$this->serviceName.'</div>
5334
+ <div class=nav>
5335
+ <p>View the <a href="'.$PHP_SELF.'?wsdl">WSDL</a> for the service.
5336
+ Click on an operation name to view it&apos;s details.</p>
5337
+ <ul>';
5338
+ foreach($this->getOperations() as $op => $data){
5339
+ $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
5340
+ // create hidden div
5341
+ $b .= "<div id='$op' class='hidden'>
5342
+ <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
5343
+ foreach($data as $donnie => $marie){ // loop through opdata
5344
+ if($donnie == 'input' || $donnie == 'output'){ // show input/output data
5345
+ $b .= "<font color='white'>".ucfirst($donnie).':</font><br>';
5346
+ foreach($marie as $captain => $tenille){ // loop through data
5347
+ if($captain == 'parts'){ // loop thru parts
5348
+ $b .= "&nbsp;&nbsp;$captain:<br>";
5349
+ //if(is_array($tenille)){
5350
+ foreach($tenille as $joanie => $chachi){
5351
+ $b .= "&nbsp;&nbsp;&nbsp;&nbsp;$joanie: $chachi<br>";
5352
+ }
5353
+ //}
5354
+ } else {
5355
+ $b .= "&nbsp;&nbsp;$captain: $tenille<br>";
5356
+ }
5357
+ }
5358
+ } else {
5359
+ $b .= "<font color='white'>".ucfirst($donnie).":</font> $marie<br>";
5360
+ }
5361
+ }
5362
+ $b .= '</div>';
5363
+ }
5364
+ $b .= '
5365
+ <ul>
5366
+ </div>
5367
+ </div></body></html>';
5368
+ return $b;
5369
+ }
5370
+
5371
+ /**
5372
+ * serialize the parsed wsdl
5373
+ *
5374
+ * @param mixed $debug whether to put debug=1 in endpoint URL
5375
+ * @return string serialization of WSDL
5376
+ * @access public
5377
+ */
5378
+ function serialize($debug = 0)
5379
+ {
5380
+ $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
5381
+ $xml .= "\n<definitions";
5382
+ foreach($this->namespaces as $k => $v) {
5383
+ $xml .= " xmlns:$k=\"$v\"";
5384
+ }
5385
+ // 10.9.02 - add poulter fix for wsdl and tns declarations
5386
+ if (isset($this->namespaces['wsdl'])) {
5387
+ $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
5388
+ }
5389
+ if (isset($this->namespaces['tns'])) {
5390
+ $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
5391
+ }
5392
+ $xml .= '>';
5393
+ // imports
5394
+ if (sizeof($this->import) > 0) {
5395
+ foreach($this->import as $ns => $list) {
5396
+ foreach ($list as $ii) {
5397
+ if ($ii['location'] != '') {
5398
+ $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
5399
+ } else {
5400
+ $xml .= '<import namespace="' . $ns . '" />';
5401
+ }
5402
+ }
5403
+ }
5404
+ }
5405
+ // types
5406
+ if (count($this->schemas)>=1) {
5407
+ $xml .= "\n<types>\n";
5408
+ foreach ($this->schemas as $ns => $list) {
5409
+ foreach ($list as $xs) {
5410
+ $xml .= $xs->serializeSchema();
5411
+ }
5412
+ }
5413
+ $xml .= '</types>';
5414
+ }
5415
+ // messages
5416
+ if (count($this->messages) >= 1) {
5417
+ foreach($this->messages as $msgName => $msgParts) {
5418
+ $xml .= "\n<message name=\"" . $msgName . '">';
5419
+ if(is_array($msgParts)){
5420
+ foreach($msgParts as $partName => $partType) {
5421
+ // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
5422
+ if (strpos($partType, ':')) {
5423
+ $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
5424
+ } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
5425
+ // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
5426
+ $typePrefix = 'xsd';
5427
+ } else {
5428
+ foreach($this->typemap as $ns => $types) {
5429
+ if (isset($types[$partType])) {
5430
+ $typePrefix = $this->getPrefixFromNamespace($ns);
5431
+ }
5432
+ }
5433
+ if (!isset($typePrefix)) {
5434
+ die("$partType has no namespace!");
5435
+ }
5436
+ }
5437
+ $ns = $this->getNamespaceFromPrefix($typePrefix);
5438
+ $localPart = $this->getLocalPart($partType);
5439
+ $typeDef = $this->getTypeDef($localPart, $ns);
5440
+ if ($typeDef['typeClass'] == 'element') {
5441
+ $elementortype = 'element';
5442
+ if (substr($localPart, -1) == '^') {
5443
+ $localPart = substr($localPart, 0, -1);
5444
+ }
5445
+ } else {
5446
+ $elementortype = 'type';
5447
+ }
5448
+ $xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
5449
+ }
5450
+ }
5451
+ $xml .= '</message>';
5452
+ }
5453
+ }
5454
+ // bindings & porttypes
5455
+ if (count($this->bindings) >= 1) {
5456
+ $binding_xml = '';
5457
+ $portType_xml = '';
5458
+ foreach($this->bindings as $bindingName => $attrs) {
5459
+ $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
5460
+ $binding_xml .= "\n" . ' <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
5461
+ $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
5462
+ foreach($attrs['operations'] as $opName => $opParts) {
5463
+ $binding_xml .= "\n" . ' <operation name="' . $opName . '">';
5464
+ $binding_xml .= "\n" . ' <soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $opParts['style'] . '"/>';
5465
+ if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
5466
+ $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
5467
+ } else {
5468
+ $enc_style = '';
5469
+ }
5470
+ $binding_xml .= "\n" . ' <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
5471
+ if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
5472
+ $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
5473
+ } else {
5474
+ $enc_style = '';
5475
+ }
5476
+ $binding_xml .= "\n" . ' <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
5477
+ $binding_xml .= "\n" . ' </operation>';
5478
+ $portType_xml .= "\n" . ' <operation name="' . $opParts['name'] . '"';
5479
+ if (isset($opParts['parameterOrder'])) {
5480
+ $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
5481
+ }
5482
+ $portType_xml .= '>';
5483
+ if(isset($opParts['documentation']) && $opParts['documentation'] != '') {
5484
+ $portType_xml .= "\n" . ' <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
5485
+ }
5486
+ $portType_xml .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>';
5487
+ $portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>';
5488
+ $portType_xml .= "\n" . ' </operation>';
5489
+ }
5490
+ $portType_xml .= "\n" . '</portType>';
5491
+ $binding_xml .= "\n" . '</binding>';
5492
+ }
5493
+ $xml .= $portType_xml . $binding_xml;
5494
+ }
5495
+ // services
5496
+ $xml .= "\n<service name=\"" . $this->serviceName . '">';
5497
+ if (count($this->ports) >= 1) {
5498
+ foreach($this->ports as $pName => $attrs) {
5499
+ $xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
5500
+ $xml .= "\n" . ' <soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>';
5501
+ $xml .= "\n" . ' </port>';
5502
+ }
5503
+ }
5504
+ $xml .= "\n" . '</service>';
5505
+ return $xml . "\n</definitions>";
5506
+ }
5507
+
5508
+ /**
5509
+ * determine whether a set of parameters are unwrapped
5510
+ * when they are expect to be wrapped, Microsoft-style.
5511
+ *
5512
+ * @param string $type the type (element name) of the wrapper
5513
+ * @param array $parameters the parameter values for the SOAP call
5514
+ * @return boolean whether they parameters are unwrapped (and should be wrapped)
5515
+ * @access private
5516
+ */
5517
+ function parametersMatchWrapped($type, &$parameters) {
5518
+ $this->debug("in parametersMatchWrapped type=$type, parameters=");
5519
+ $this->appendDebug($this->varDump($parameters));
5520
+
5521
+ // split type into namespace:unqualified-type
5522
+ if (strpos($type, ':')) {
5523
+ $uqType = substr($type, strrpos($type, ':') + 1);
5524
+ $ns = substr($type, 0, strrpos($type, ':'));
5525
+ $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns");
5526
+ if ($this->getNamespaceFromPrefix($ns)) {
5527
+ $ns = $this->getNamespaceFromPrefix($ns);
5528
+ $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns");
5529
+ }
5530
+ } else {
5531
+ // TODO: should the type be compared to types in XSD, and the namespace
5532
+ // set to XSD if the type matches?
5533
+ $this->debug("in parametersMatchWrapped: No namespace for type $type");
5534
+ $ns = '';
5535
+ $uqType = $type;
5536
+ }
5537
+
5538
+ // get the type information
5539
+ if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
5540
+ $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type.");
5541
+ return false;
5542
+ }
5543
+ $this->debug("in parametersMatchWrapped: found typeDef=");
5544
+ $this->appendDebug($this->varDump($typeDef));
5545
+ if (substr($uqType, -1) == '^') {
5546
+ $uqType = substr($uqType, 0, -1);
5547
+ }
5548
+ $phpType = $typeDef['phpType'];
5549
+ $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '');
5550
+ $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType");
5551
+
5552
+ // we expect a complexType or element of complexType
5553
+ if ($phpType != 'struct') {
5554
+ $this->debug("in parametersMatchWrapped: not a struct");
5555
+ return false;
5556
+ }
5557
+
5558
+ // see whether the parameter names match the elements
5559
+ if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
5560
+ $elements = 0;
5561
+ $matches = 0;
5562
+ $change = false;
5563
+ if ($this->isArraySimpleOrStruct($parameters) == 'arraySimple' && count($parameters) == count($typeDef['elements'])) {
5564
+ $this->debug("in parametersMatchWrapped: (wrapped return value kludge) correct number of elements in simple array, so change array and wrap");
5565
+ $change = true;
5566
+ }
5567
+ foreach ($typeDef['elements'] as $name => $attrs) {
5568
+ if ($change) {
5569
+ $this->debug("in parametersMatchWrapped: change parameter $element to name $name");
5570
+ $parameters[$name] = $parameters[$elements];
5571
+ unset($parameters[$elements]);
5572
+ $matches++;
5573
+ } elseif (isset($parameters[$name])) {
5574
+ $this->debug("in parametersMatchWrapped: have parameter named $name");
5575
+ $matches++;
5576
+ } else {
5577
+ $this->debug("in parametersMatchWrapped: do not have parameter named $name");
5578
+ }
5579
+ $elements++;
5580
+ }
5581
+
5582
+ $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names");
5583
+ if ($matches == 0) {
5584
+ return false;
5585
+ }
5586
+ return true;
5587
+ }
5588
+
5589
+ // since there are no elements for the type, if the user passed no
5590
+ // parameters, the parameters match wrapped.
5591
+ $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType");
5592
+ return count($parameters) == 0;
5593
+ }
5594
+
5595
+ /**
5596
+ * serialize PHP values according to a WSDL message definition
5597
+ * contrary to the method name, this is not limited to RPC
5598
+ *
5599
+ * TODO
5600
+ * - multi-ref serialization
5601
+ * - validate PHP values against type definitions, return errors if invalid
5602
+ *
5603
+ * @param string $operation operation name
5604
+ * @param string $direction (input|output)
5605
+ * @param mixed $parameters parameter value(s)
5606
+ * @param string $bindingType (soap|soap12)
5607
+ * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
5608
+ * @access public
5609
+ */
5610
+ function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap') {
5611
+ $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");
5612
+ $this->appendDebug('parameters=' . $this->varDump($parameters));
5613
+
5614
+ if ($direction != 'input' && $direction != 'output') {
5615
+ $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
5616
+ $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
5617
+ return false;
5618
+ }
5619
+ if (!$opData = $this->getOperationData($operation, $bindingType)) {
5620
+ $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
5621
+ $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
5622
+ return false;
5623
+ }
5624
+ $this->debug('in serializeRPCParameters: opData:');
5625
+ $this->appendDebug($this->varDump($opData));
5626
+
5627
+ // Get encoding style for output and set to current
5628
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5629
+ if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
5630
+ $encodingStyle = $opData['output']['encodingStyle'];
5631
+ $enc_style = $encodingStyle;
5632
+ }
5633
+
5634
+ // set input params
5635
+ $xml = '';
5636
+ if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
5637
+ $parts = &$opData[$direction]['parts'];
5638
+ $part_count = sizeof($parts);
5639
+ $style = $opData['style'];
5640
+ $use = $opData[$direction]['use'];
5641
+ $this->debug("have $part_count part(s) to serialize using $style/$use");
5642
+ if (is_array($parameters)) {
5643
+ $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
5644
+ $parameter_count = count($parameters);
5645
+ $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize");
5646
+ // check for Microsoft-style wrapped parameters
5647
+ if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) {
5648
+ $this->debug('check whether the caller has wrapped the parameters');
5649
+ if ((($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) || ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1)) {
5650
+ $this->debug('check whether caller\'s parameters match the wrapped ones');
5651
+ if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) {
5652
+ $this->debug('wrap the parameters for the caller');
5653
+ $parameters = array('parameters' => $parameters);
5654
+ $parameter_count = 1;
5655
+ }
5656
+ }
5657
+ }
5658
+ foreach ($parts as $name => $type) {
5659
+ $this->debug("serializing part $name of type $type");
5660
+ // Track encoding style
5661
+ if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
5662
+ $encodingStyle = $opData[$direction]['encodingStyle'];
5663
+ $enc_style = $encodingStyle;
5664
+ } else {
5665
+ $enc_style = false;
5666
+ }
5667
+ // NOTE: add error handling here
5668
+ // if serializeType returns false, then catch global error and fault
5669
+ if ($parametersArrayType == 'arraySimple') {
5670
+ $p = array_shift($parameters);
5671
+ $this->debug('calling serializeType w/indexed param');
5672
+ $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
5673
+ } elseif (isset($parameters[$name])) {
5674
+ $this->debug('calling serializeType w/named param');
5675
+ $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
5676
+ } else {
5677
+ // TODO: only send nillable
5678
+ $this->debug('calling serializeType w/null param');
5679
+ $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
5680
+ }
5681
+ }
5682
+ } else {
5683
+ $this->debug('no parameters passed.');
5684
+ }
5685
+ }
5686
+ $this->debug("serializeRPCParameters returning: $xml");
5687
+ return $xml;
5688
+ }
5689
+
5690
+ /**
5691
+ * serialize a PHP value according to a WSDL message definition
5692
+ *
5693
+ * TODO
5694
+ * - multi-ref serialization
5695
+ * - validate PHP values against type definitions, return errors if invalid
5696
+ *
5697
+ * @param string $operation operation name
5698
+ * @param string $direction (input|output)
5699
+ * @param mixed $parameters parameter value(s)
5700
+ * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
5701
+ * @access public
5702
+ * @deprecated
5703
+ */
5704
+ function serializeParameters($operation, $direction, $parameters)
5705
+ {
5706
+ $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
5707
+ $this->appendDebug('parameters=' . $this->varDump($parameters));
5708
+
5709
+ if ($direction != 'input' && $direction != 'output') {
5710
+ $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
5711
+ $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
5712
+ return false;
5713
+ }
5714
+ if (!$opData = $this->getOperationData($operation)) {
5715
+ $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
5716
+ $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
5717
+ return false;
5718
+ }
5719
+ $this->debug('opData:');
5720
+ $this->appendDebug($this->varDump($opData));
5721
+
5722
+ // Get encoding style for output and set to current
5723
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5724
+ if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
5725
+ $encodingStyle = $opData['output']['encodingStyle'];
5726
+ $enc_style = $encodingStyle;
5727
+ }
5728
+
5729
+ // set input params
5730
+ $xml = '';
5731
+ if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
5732
+
5733
+ $use = $opData[$direction]['use'];
5734
+ $this->debug("use=$use");
5735
+ $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
5736
+ if (is_array($parameters)) {
5737
+ $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
5738
+ $this->debug('have ' . $parametersArrayType . ' parameters');
5739
+ foreach($opData[$direction]['parts'] as $name => $type) {
5740
+ $this->debug('serializing part "'.$name.'" of type "'.$type.'"');
5741
+ // Track encoding style
5742
+ if(isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
5743
+ $encodingStyle = $opData[$direction]['encodingStyle'];
5744
+ $enc_style = $encodingStyle;
5745
+ } else {
5746
+ $enc_style = false;
5747
+ }
5748
+ // NOTE: add error handling here
5749
+ // if serializeType returns false, then catch global error and fault
5750
+ if ($parametersArrayType == 'arraySimple') {
5751
+ $p = array_shift($parameters);
5752
+ $this->debug('calling serializeType w/indexed param');
5753
+ $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
5754
+ } elseif (isset($parameters[$name])) {
5755
+ $this->debug('calling serializeType w/named param');
5756
+ $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
5757
+ } else {
5758
+ // TODO: only send nillable
5759
+ $this->debug('calling serializeType w/null param');
5760
+ $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
5761
+ }
5762
+ }
5763
+ } else {
5764
+ $this->debug('no parameters passed.');
5765
+ }
5766
+ }
5767
+ $this->debug("serializeParameters returning: $xml");
5768
+ return $xml;
5769
+ }
5770
+
5771
+ /**
5772
+ * serializes a PHP value according a given type definition
5773
+ *
5774
+ * @param string $name name of value (part or element)
5775
+ * @param string $type XML schema type of value (type or element)
5776
+ * @param mixed $value a native PHP value (parameter value)
5777
+ * @param string $use use for part (encoded|literal)
5778
+ * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
5779
+ * @param boolean $unqualified a kludge for what should be XML namespace form handling
5780
+ * @return string value serialized as an XML string
5781
+ * @access private
5782
+ */
5783
+ function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
5784
+ {
5785
+ $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));
5786
+ $this->appendDebug("value=" . $this->varDump($value));
5787
+ if($use == 'encoded' && $encodingStyle) {
5788
+ $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
5789
+ }
5790
+
5791
+ // if a soapval has been supplied, let its type override the WSDL
5792
+ if (is_object($value) && get_class($value) == 'soapval') {
5793
+ if ($value->type_ns) {
5794
+ $type = $value->type_ns . ':' . $value->type;
5795
+ $forceType = true;
5796
+ $this->debug("in serializeType: soapval overrides type to $type");
5797
+ } elseif ($value->type) {
5798
+ $type = $value->type;
5799
+ $forceType = true;
5800
+ $this->debug("in serializeType: soapval overrides type to $type");
5801
+ } else {
5802
+ $forceType = false;
5803
+ $this->debug("in serializeType: soapval does not override type");
5804
+ }
5805
+ $attrs = $value->attributes;
5806
+ $value = $value->value;
5807
+ $this->debug("in serializeType: soapval overrides value to $value");
5808
+ if ($attrs) {
5809
+ if (!is_array($value)) {
5810
+ $value['!'] = $value;
5811
+ }
5812
+ foreach ($attrs as $n => $v) {
5813
+ $value['!' . $n] = $v;
5814
+ }
5815
+ $this->debug("in serializeType: soapval provides attributes");
5816
+ }
5817
+ } else {
5818
+ $forceType = false;
5819
+ }
5820
+
5821
+ $xml = '';
5822
+ if (strpos($type, ':')) {
5823
+ $uqType = substr($type, strrpos($type, ':') + 1);
5824
+ $ns = substr($type, 0, strrpos($type, ':'));
5825
+ $this->debug("in serializeType: got a prefixed type: $uqType, $ns");
5826
+ if ($this->getNamespaceFromPrefix($ns)) {
5827
+ $ns = $this->getNamespaceFromPrefix($ns);
5828
+ $this->debug("in serializeType: expanded prefixed type: $uqType, $ns");
5829
+ }
5830
+
5831
+ if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/'){
5832
+ $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
5833
+ if ($unqualified && $use == 'literal') {
5834
+ $elementNS = " xmlns=\"\"";
5835
+ } else {
5836
+ $elementNS = '';
5837
+ }
5838
+ if (is_null($value)) {
5839
+ if ($use == 'literal') {
5840
+ // TODO: depends on minOccurs
5841
+ $xml = "<$name$elementNS/>";
5842
+ } else {
5843
+ // TODO: depends on nillable, which should be checked before calling this method
5844
+ $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
5845
+ }
5846
+ $this->debug("in serializeType: returning: $xml");
5847
+ return $xml;
5848
+ }
5849
+ if ($uqType == 'Array') {
5850
+ // JBoss/Axis does this sometimes
5851
+ return $this->serialize_val($value, $name, false, false, false, false, $use);
5852
+ }
5853
+ if ($uqType == 'boolean') {
5854
+ if ((is_string($value) && $value == 'false') || (! $value)) {
5855
+ $value = 'false';
5856
+ } else {
5857
+ $value = 'true';
5858
+ }
5859
+ }
5860
+ if ($uqType == 'string' && gettype($value) == 'string') {
5861
+ $value = $this->expandEntities($value);
5862
+ }
5863
+ if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {
5864
+ $value = sprintf("%.0lf", $value);
5865
+ }
5866
+ // it's a scalar
5867
+ // TODO: what about null/nil values?
5868
+ // check type isn't a custom type extending xmlschema namespace
5869
+ if (!$this->getTypeDef($uqType, $ns)) {
5870
+ if ($use == 'literal') {
5871
+ if ($forceType) {
5872
+ $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
5873
+ } else {
5874
+ $xml = "<$name$elementNS>$value</$name>";
5875
+ }
5876
+ } else {
5877
+ $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
5878
+ }
5879
+ $this->debug("in serializeType: returning: $xml");
5880
+ return $xml;
5881
+ }
5882
+ $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');
5883
+ } else if ($ns == 'http://xml.apache.org/xml-soap') {
5884
+ $this->debug('in serializeType: appears to be Apache SOAP type');
5885
+ if ($uqType == 'Map') {
5886
+ $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
5887
+ if (! $tt_prefix) {
5888
+ $this->debug('in serializeType: Add namespace for Apache SOAP type');
5889
+ $tt_prefix = 'ns' . rand(1000, 9999);
5890
+ $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap';
5891
+ // force this to be added to usedNamespaces
5892
+ $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
5893
+ }
5894
+ $contents = '';
5895
+ foreach($value as $k => $v) {
5896
+ $this->debug("serializing map element: key $k, value $v");
5897
+ $contents .= '<item>';
5898
+ $contents .= $this->serialize_val($k,'key',false,false,false,false,$use);
5899
+ $contents .= $this->serialize_val($v,'value',false,false,false,false,$use);
5900
+ $contents .= '</item>';
5901
+ }
5902
+ if ($use == 'literal') {
5903
+ if ($forceType) {
5904
+ $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
5905
+ } else {
5906
+ $xml = "<$name>$contents</$name>";
5907
+ }
5908
+ } else {
5909
+ $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
5910
+ }
5911
+ $this->debug("in serializeType: returning: $xml");
5912
+ return $xml;
5913
+ }
5914
+ $this->debug('in serializeType: Apache SOAP type, but only support Map');
5915
+ }
5916
+ } else {
5917
+ // TODO: should the type be compared to types in XSD, and the namespace
5918
+ // set to XSD if the type matches?
5919
+ $this->debug("in serializeType: No namespace for type $type");
5920
+ $ns = '';
5921
+ $uqType = $type;
5922
+ }
5923
+ if(!$typeDef = $this->getTypeDef($uqType, $ns)){
5924
+ $this->setError("$type ($uqType) is not a supported type.");
5925
+ $this->debug("in serializeType: $type ($uqType) is not a supported type.");
5926
+ return false;
5927
+ } else {
5928
+ $this->debug("in serializeType: found typeDef");
5929
+ $this->appendDebug('typeDef=' . $this->varDump($typeDef));
5930
+ if (substr($uqType, -1) == '^') {
5931
+ $uqType = substr($uqType, 0, -1);
5932
+ }
5933
+ }
5934
+ $phpType = $typeDef['phpType'];
5935
+ $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') );
5936
+ // if php type == struct, map value to the <all> element names
5937
+ if ($phpType == 'struct') {
5938
+ if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
5939
+ $elementName = $uqType;
5940
+ if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
5941
+ $elementNS = " xmlns=\"$ns\"";
5942
+ } else {
5943
+ $elementNS = " xmlns=\"\"";
5944
+ }
5945
+ } else {
5946
+ $elementName = $name;
5947
+ if ($unqualified) {
5948
+ $elementNS = " xmlns=\"\"";
5949
+ } else {
5950
+ $elementNS = '';
5951
+ }
5952
+ }
5953
+ if (is_null($value)) {
5954
+ if ($use == 'literal') {
5955
+ // TODO: depends on minOccurs
5956
+ $xml = "<$elementName$elementNS/>";
5957
+ } else {
5958
+ $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
5959
+ }
5960
+ $this->debug("in serializeType: returning: $xml");
5961
+ return $xml;
5962
+ }
5963
+ if (is_object($value)) {
5964
+ $value = get_object_vars($value);
5965
+ }
5966
+ if (is_array($value)) {
5967
+ $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
5968
+ if ($use == 'literal') {
5969
+ if ($forceType) {
5970
+ $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
5971
+ } else {
5972
+ $xml = "<$elementName$elementNS$elementAttrs>";
5973
+ }
5974
+ } else {
5975
+ $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
5976
+ }
5977
+
5978
+ $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
5979
+ $xml .= "</$elementName>";
5980
+ } else {
5981
+ $this->debug("in serializeType: phpType is struct, but value is not an array");
5982
+ $this->setError("phpType is struct, but value is not an array: see debug output for details");
5983
+ $xml = '';
5984
+ }
5985
+ } elseif ($phpType == 'array') {
5986
+ if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
5987
+ $elementNS = " xmlns=\"$ns\"";
5988
+ } else {
5989
+ if ($unqualified) {
5990
+ $elementNS = " xmlns=\"\"";
5991
+ } else {
5992
+ $elementNS = '';
5993
+ }
5994
+ }
5995
+ if (is_null($value)) {
5996
+ if ($use == 'literal') {
5997
+ // TODO: depends on minOccurs
5998
+ $xml = "<$name$elementNS/>";
5999
+ } else {
6000
+ $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
6001
+ $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
6002
+ ":Array\" " .
6003
+ $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
6004
+ ':arrayType="' .
6005
+ $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .
6006
+ ':' .
6007
+ $this->getLocalPart($typeDef['arrayType'])."[0]\"/>";
6008
+ }
6009
+ $this->debug("in serializeType: returning: $xml");
6010
+ return $xml;
6011
+ }
6012
+ if (isset($typeDef['multidimensional'])) {
6013
+ $nv = array();
6014
+ foreach($value as $v) {
6015
+ $cols = ',' . sizeof($v);
6016
+ $nv = array_merge($nv, $v);
6017
+ }
6018
+ $value = $nv;
6019
+ } else {
6020
+ $cols = '';
6021
+ }
6022
+ if (is_array($value) && sizeof($value) >= 1) {
6023
+ $rows = sizeof($value);
6024
+ $contents = '';
6025
+ foreach($value as $k => $v) {
6026
+ $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");
6027
+ //if (strpos($typeDef['arrayType'], ':') ) {
6028
+ if (!in_array($typeDef['arrayType'],$this->typemap['http://www.w3.org/2001/XMLSchema'])) {
6029
+ $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
6030
+ } else {
6031
+ $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
6032
+ }
6033
+ }
6034
+ } else {
6035
+ $rows = 0;
6036
+ $contents = null;
6037
+ }
6038
+ // TODO: for now, an empty value will be serialized as a zero element
6039
+ // array. Revisit this when coding the handling of null/nil values.
6040
+ if ($use == 'literal') {
6041
+ $xml = "<$name$elementNS>"
6042
+ .$contents
6043
+ ."</$name>";
6044
+ } else {
6045
+ $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '.
6046
+ $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
6047
+ .':arrayType="'
6048
+ .$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
6049
+ .":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">"
6050
+ .$contents
6051
+ ."</$name>";
6052
+ }
6053
+ } elseif ($phpType == 'scalar') {
6054
+ if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
6055
+ $elementNS = " xmlns=\"$ns\"";
6056
+ } else {
6057
+ if ($unqualified) {
6058
+ $elementNS = " xmlns=\"\"";
6059
+ } else {
6060
+ $elementNS = '';
6061
+ }
6062
+ }
6063
+ if ($use == 'literal') {
6064
+ if ($forceType) {
6065
+ $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
6066
+ } else {
6067
+ $xml = "<$name$elementNS>$value</$name>";
6068
+ }
6069
+ } else {
6070
+ $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
6071
+ }
6072
+ }
6073
+ $this->debug("in serializeType: returning: $xml");
6074
+ return $xml;
6075
+ }
6076
+
6077
+ /**
6078
+ * serializes the attributes for a complexType
6079
+ *
6080
+ * @param array $typeDef our internal representation of an XML schema type (or element)
6081
+ * @param mixed $value a native PHP value (parameter value)
6082
+ * @param string $ns the namespace of the type
6083
+ * @param string $uqType the local part of the type
6084
+ * @return string value serialized as an XML string
6085
+ * @access private
6086
+ */
6087
+ function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) {
6088
+ $xml = '';
6089
+ if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
6090
+ $this->debug("serialize attributes for XML Schema type $ns:$uqType");
6091
+ if (is_array($value)) {
6092
+ $xvalue = $value;
6093
+ } elseif (is_object($value)) {
6094
+ $xvalue = get_object_vars($value);
6095
+ } else {
6096
+ $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
6097
+ $xvalue = array();
6098
+ }
6099
+ foreach ($typeDef['attrs'] as $aName => $attrs) {
6100
+ if (isset($xvalue['!' . $aName])) {
6101
+ $xname = '!' . $aName;
6102
+ $this->debug("value provided for attribute $aName with key $xname");
6103
+ } elseif (isset($xvalue[$aName])) {
6104
+ $xname = $aName;
6105
+ $this->debug("value provided for attribute $aName with key $xname");
6106
+ } elseif (isset($attrs['default'])) {
6107
+ $xname = '!' . $aName;
6108
+ $xvalue[$xname] = $attrs['default'];
6109
+ $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);
6110
+ } else {
6111
+ $xname = '';
6112
+ $this->debug("no value provided for attribute $aName");
6113
+ }
6114
+ if ($xname) {
6115
+ $xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";
6116
+ }
6117
+ }
6118
+ } else {
6119
+ $this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
6120
+ }
6121
+ if (isset($typeDef['extensionBase'])) {
6122
+ $ns = $this->getPrefix($typeDef['extensionBase']);
6123
+ $uqType = $this->getLocalPart($typeDef['extensionBase']);
6124
+ if ($this->getNamespaceFromPrefix($ns)) {
6125
+ $ns = $this->getNamespaceFromPrefix($ns);
6126
+ }
6127
+ if ($typeDef = $this->getTypeDef($uqType, $ns)) {
6128
+ $this->debug("serialize attributes for extension base $ns:$uqType");
6129
+ $xml .= $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
6130
+ } else {
6131
+ $this->debug("extension base $ns:$uqType is not a supported type");
6132
+ }
6133
+ }
6134
+ return $xml;
6135
+ }
6136
+
6137
+ /**
6138
+ * serializes the elements for a complexType
6139
+ *
6140
+ * @param array $typeDef our internal representation of an XML schema type (or element)
6141
+ * @param mixed $value a native PHP value (parameter value)
6142
+ * @param string $ns the namespace of the type
6143
+ * @param string $uqType the local part of the type
6144
+ * @param string $use use for part (encoded|literal)
6145
+ * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
6146
+ * @return string value serialized as an XML string
6147
+ * @access private
6148
+ */
6149
+ function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) {
6150
+ $xml = '';
6151
+ if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
6152
+ $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
6153
+ if (is_array($value)) {
6154
+ $xvalue = $value;
6155
+ } elseif (is_object($value)) {
6156
+ $xvalue = get_object_vars($value);
6157
+ } else {
6158
+ $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
6159
+ $xvalue = array();
6160
+ }
6161
+ // toggle whether all elements are present - ideally should validate against schema
6162
+ if (count($typeDef['elements']) != count($xvalue)){
6163
+ $optionals = true;
6164
+ }
6165
+ foreach ($typeDef['elements'] as $eName => $attrs) {
6166
+ if (!isset($xvalue[$eName])) {
6167
+ if (isset($attrs['default'])) {
6168
+ $xvalue[$eName] = $attrs['default'];
6169
+ $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);
6170
+ }
6171
+ }
6172
+ // if user took advantage of a minOccurs=0, then only serialize named parameters
6173
+ if (isset($optionals)
6174
+ && (!isset($xvalue[$eName]))
6175
+ && ( (!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')
6176
+ ){
6177
+ if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {
6178
+ $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
6179
+ }
6180
+ // do nothing
6181
+ $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");
6182
+ } else {
6183
+ // get value
6184
+ if (isset($xvalue[$eName])) {
6185
+ $v = $xvalue[$eName];
6186
+ } else {
6187
+ $v = null;
6188
+ }
6189
+ if (isset($attrs['form'])) {
6190
+ $unqualified = ($attrs['form'] == 'unqualified');
6191
+ } else {
6192
+ $unqualified = false;
6193
+ }
6194
+ if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
6195
+ $vv = $v;
6196
+ foreach ($vv as $k => $v) {
6197
+ if (isset($attrs['type']) || isset($attrs['ref'])) {
6198
+ // serialize schema-defined type
6199
+ $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
6200
+ } else {
6201
+ // serialize generic type (can this ever really happen?)
6202
+ $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
6203
+ $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
6204
+ }
6205
+ }
6206
+ } else {
6207
+ if (isset($attrs['type']) || isset($attrs['ref'])) {
6208
+ // serialize schema-defined type
6209
+ $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
6210
+ } else {
6211
+ // serialize generic type (can this ever really happen?)
6212
+ $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
6213
+ $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
6214
+ }
6215
+ }
6216
+ }
6217
+ }
6218
+ } else {
6219
+ $this->debug("no elements to serialize for XML Schema type $ns:$uqType");
6220
+ }
6221
+ if (isset($typeDef['extensionBase'])) {
6222
+ $ns = $this->getPrefix($typeDef['extensionBase']);
6223
+ $uqType = $this->getLocalPart($typeDef['extensionBase']);
6224
+ if ($this->getNamespaceFromPrefix($ns)) {
6225
+ $ns = $this->getNamespaceFromPrefix($ns);
6226
+ }
6227
+ if ($typeDef = $this->getTypeDef($uqType, $ns)) {
6228
+ $this->debug("serialize elements for extension base $ns:$uqType");
6229
+ $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
6230
+ } else {
6231
+ $this->debug("extension base $ns:$uqType is not a supported type");
6232
+ }
6233
+ }
6234
+ return $xml;
6235
+ }
6236
+
6237
+ /**
6238
+ * adds an XML Schema complex type to the WSDL types
6239
+ *
6240
+ * @param string $name
6241
+ * @param string $typeClass (complexType|simpleType|attribute)
6242
+ * @param string $phpType currently supported are array and struct (php assoc array)
6243
+ * @param string $compositor (all|sequence|choice)
6244
+ * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
6245
+ * @param array $elements e.g. array ( name => array(name=>'',type=>'') )
6246
+ * @param array $attrs e.g. array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]'))
6247
+ * @param string $arrayType as namespace:name (xsd:string)
6248
+ * @see nusoap_xmlschema
6249
+ * @access public
6250
+ */
6251
+ function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') {
6252
+ if (count($elements) > 0) {
6253
+ $eElements = array();
6254
+ foreach($elements as $n => $e){
6255
+ // expand each element
6256
+ $ee = array();
6257
+ foreach ($e as $k => $v) {
6258
+ $k = strpos($k,':') ? $this->expandQname($k) : $k;
6259
+ $v = strpos($v,':') ? $this->expandQname($v) : $v;
6260
+ $ee[$k] = $v;
6261
+ }
6262
+ $eElements[$n] = $ee;
6263
+ }
6264
+ $elements = $eElements;
6265
+ }
6266
+
6267
+ if (count($attrs) > 0) {
6268
+ foreach($attrs as $n => $a){
6269
+ // expand each attribute
6270
+ foreach ($a as $k => $v) {
6271
+ $k = strpos($k,':') ? $this->expandQname($k) : $k;
6272
+ $v = strpos($v,':') ? $this->expandQname($v) : $v;
6273
+ $aa[$k] = $v;
6274
+ }
6275
+ $eAttrs[$n] = $aa;
6276
+ }
6277
+ $attrs = $eAttrs;
6278
+ }
6279
+
6280
+ $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
6281
+ $arrayType = strpos($arrayType,':') ? $this->expandQname($arrayType) : $arrayType;
6282
+
6283
+ $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6284
+ $this->schemas[$typens][0]->addComplexType($name,$typeClass,$phpType,$compositor,$restrictionBase,$elements,$attrs,$arrayType);
6285
+ }
6286
+
6287
+ /**
6288
+ * adds an XML Schema simple type to the WSDL types
6289
+ *
6290
+ * @param string $name
6291
+ * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
6292
+ * @param string $typeClass (should always be simpleType)
6293
+ * @param string $phpType (should always be scalar)
6294
+ * @param array $enumeration array of values
6295
+ * @see nusoap_xmlschema
6296
+ * @access public
6297
+ */
6298
+ function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
6299
+ $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
6300
+
6301
+ $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6302
+ $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
6303
+ }
6304
+
6305
+ /**
6306
+ * adds an element to the WSDL types
6307
+ *
6308
+ * @param array $attrs attributes that must include name and type
6309
+ * @see nusoap_xmlschema
6310
+ * @access public
6311
+ */
6312
+ function addElement($attrs) {
6313
+ $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6314
+ $this->schemas[$typens][0]->addElement($attrs);
6315
+ }
6316
+
6317
+ /**
6318
+ * register an operation with the server
6319
+ *
6320
+ * @param string $name operation (method) name
6321
+ * @param array $in assoc array of input values: key = param name, value = param type
6322
+ * @param array $out assoc array of output values: key = param name, value = param type
6323
+ * @param string $namespace optional The namespace for the operation
6324
+ * @param string $soapaction optional The soapaction for the operation
6325
+ * @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
6326
+ * @param string $use (encoded|literal) optional The use for the parameters (cannot mix right now)
6327
+ * @param string $documentation optional The description to include in the WSDL
6328
+ * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
6329
+ * @access public
6330
+ */
6331
+ function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = ''){
6332
+ if ($use == 'encoded' && $encodingStyle == '') {
6333
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
6334
+ }
6335
+
6336
+ if ($style == 'document') {
6337
+ $elements = array();
6338
+ foreach ($in as $n => $t) {
6339
+ $elements[$n] = array('name' => $n, 'type' => $t);
6340
+ }
6341
+ $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
6342
+ $this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
6343
+ $in = array('parameters' => 'tns:' . $name . '^');
6344
+
6345
+ $elements = array();
6346
+ foreach ($out as $n => $t) {
6347
+ $elements[$n] = array('name' => $n, 'type' => $t);
6348
+ }
6349
+ $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
6350
+ $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
6351
+ $out = array('parameters' => 'tns:' . $name . 'Response' . '^');
6352
+ }
6353
+
6354
+ // get binding
6355
+ $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =
6356
+ array(
6357
+ 'name' => $name,
6358
+ 'binding' => $this->serviceName . 'Binding',
6359
+ 'endpoint' => $this->endpoint,
6360
+ 'soapAction' => $soapaction,
6361
+ 'style' => $style,
6362
+ 'input' => array(
6363
+ 'use' => $use,
6364
+ 'namespace' => $namespace,
6365
+ 'encodingStyle' => $encodingStyle,
6366
+ 'message' => $name . 'Request',
6367
+ 'parts' => $in),
6368
+ 'output' => array(
6369
+ 'use' => $use,
6370
+ 'namespace' => $namespace,
6371
+ 'encodingStyle' => $encodingStyle,
6372
+ 'message' => $name . 'Response',
6373
+ 'parts' => $out),
6374
+ 'namespace' => $namespace,
6375
+ 'transport' => 'http://schemas.xmlsoap.org/soap/http',
6376
+ 'documentation' => $documentation);
6377
+ // add portTypes
6378
+ // add messages
6379
+ if($in)
6380
+ {
6381
+ foreach($in as $pName => $pType)
6382
+ {
6383
+ if(strpos($pType,':')) {
6384
+ $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
6385
+ }
6386
+ $this->messages[$name.'Request'][$pName] = $pType;
6387
+ }
6388
+ } else {
6389
+ $this->messages[$name.'Request']= '0';
6390
+ }
6391
+ if($out)
6392
+ {
6393
+ foreach($out as $pName => $pType)
6394
+ {
6395
+ if(strpos($pType,':')) {
6396
+ $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
6397
+ }
6398
+ $this->messages[$name.'Response'][$pName] = $pType;
6399
+ }
6400
+ } else {
6401
+ $this->messages[$name.'Response']= '0';
6402
+ }
6403
+ return true;
6404
+ }
6405
+ }
6406
+ ?><?php
6407
+
6408
+
6409
+
6410
+ /**
6411
+ *
6412
+ * nusoap_parser class parses SOAP XML messages into native PHP values
6413
+ *
6414
+ * @author Dietrich Ayala <dietrich@ganx4.com>
6415
+ * @author Scott Nichol <snichol@users.sourceforge.net>
6416
+ * @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $
6417
+ * @access public
6418
+ */
6419
+ class nusoap_parser extends nusoap_base {
6420
+
6421
+ var $xml = '';
6422
+ var $xml_encoding = '';
6423
+ var $method = '';
6424
+ var $root_struct = '';
6425
+ var $root_struct_name = '';
6426
+ var $root_struct_namespace = '';
6427
+ var $root_header = '';
6428
+ var $document = ''; // incoming SOAP body (text)
6429
+ // determines where in the message we are (envelope,header,body,method)
6430
+ var $status = '';
6431
+ var $position = 0;
6432
+ var $depth = 0;
6433
+ var $default_namespace = '';
6434
+ var $namespaces = array();
6435
+ var $message = array();
6436
+ var $parent = '';
6437
+ var $fault = false;
6438
+ var $fault_code = '';
6439
+ var $fault_str = '';
6440
+ var $fault_detail = '';
6441
+ var $depth_array = array();
6442
+ var $debug_flag = true;
6443
+ var $soapresponse = NULL; // parsed SOAP Body
6444
+ var $soapheader = NULL; // parsed SOAP Header
6445
+ var $responseHeaders = ''; // incoming SOAP headers (text)
6446
+ var $body_position = 0;
6447
+ // for multiref parsing:
6448
+ // array of id => pos
6449
+ var $ids = array();
6450
+ // array of id => hrefs => pos
6451
+ var $multirefs = array();
6452
+ // toggle for auto-decoding element content
6453
+ var $decode_utf8 = true;
6454
+
6455
+ /**
6456
+ * constructor that actually does the parsing
6457
+ *
6458
+ * @param string $xml SOAP message
6459
+ * @param string $encoding character encoding scheme of message
6460
+ * @param string $method method for which XML is parsed (unused?)
6461
+ * @param string $decode_utf8 whether to decode UTF-8 to ISO-8859-1
6462
+ * @access public
6463
+ */
6464
+ function nusoap_parser($xml,$encoding='UTF-8',$method='',$decode_utf8=true){
6465
+ parent::nusoap_base();
6466
+ $this->xml = $xml;
6467
+ $this->xml_encoding = $encoding;
6468
+ $this->method = $method;
6469
+ $this->decode_utf8 = $decode_utf8;
6470
+
6471
+ // Check whether content has been read.
6472
+ if(!empty($xml)){
6473
+ // Check XML encoding
6474
+ $pos_xml = strpos($xml, '<?xml');
6475
+ if ($pos_xml !== FALSE) {
6476
+ $xml_decl = substr($xml, $pos_xml, strpos($xml, '?>', $pos_xml + 2) - $pos_xml + 1);
6477
+ if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
6478
+ $xml_encoding = $res[1];
6479
+ if (strtoupper($xml_encoding) != $encoding) {
6480
+ $err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";
6481
+ $this->debug($err);
6482
+ if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') {
6483
+ $this->setError($err);
6484
+ return;
6485
+ }
6486
+ // when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed
6487
+ } else {
6488
+ $this->debug('Charset from HTTP Content-Type matches encoding from XML declaration');
6489
+ }
6490
+ } else {
6491
+ $this->debug('No encoding specified in XML declaration');
6492
+ }
6493
+ } else {
6494
+ $this->debug('No XML declaration');
6495
+ }
6496
+ $this->debug('Entering nusoap_parser(), length='.strlen($xml).', encoding='.$encoding);
6497
+ // Create an XML parser - why not xml_parser_create_ns?
6498
+ $this->parser = xml_parser_create($this->xml_encoding);
6499
+ // Set the options for parsing the XML data.
6500
+ //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
6501
+ xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
6502
+ xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
6503
+ // Set the object for the parser.
6504
+ xml_set_object($this->parser, $this);
6505
+ // Set the element handlers for the parser.
6506
+ xml_set_element_handler($this->parser, 'start_element','end_element');
6507
+ xml_set_character_data_handler($this->parser,'character_data');
6508
+
6509
+ // Parse the XML file.
6510
+ if(!xml_parse($this->parser,$xml,true)){
6511
+ // Display an error message.
6512
+ $err = sprintf('XML error parsing SOAP payload on line %d: %s',
6513
+ xml_get_current_line_number($this->parser),
6514
+ xml_error_string(xml_get_error_code($this->parser)));
6515
+ $this->debug($err);
6516
+ $this->debug("XML payload:\n" . $xml);
6517
+ $this->setError($err);
6518
+ } else {
6519
+ $this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name);
6520
+ // get final value
6521
+ $this->soapresponse = $this->message[$this->root_struct]['result'];
6522
+ // get header value
6523
+ if($this->root_header != '' && isset($this->message[$this->root_header]['result'])){
6524
+ $this->soapheader = $this->message[$this->root_header]['result'];
6525
+ }
6526
+ // resolve hrefs/ids
6527
+ if(sizeof($this->multirefs) > 0){
6528
+ foreach($this->multirefs as $id => $hrefs){
6529
+ $this->debug('resolving multirefs for id: '.$id);
6530
+ $idVal = $this->buildVal($this->ids[$id]);
6531
+ if (is_array($idVal) && isset($idVal['!id'])) {
6532
+ unset($idVal['!id']);
6533
+ }
6534
+ foreach($hrefs as $refPos => $ref){
6535
+ $this->debug('resolving href at pos '.$refPos);
6536
+ $this->multirefs[$id][$refPos] = $idVal;
6537
+ }
6538
+ }
6539
+ }
6540
+ }
6541
+ xml_parser_free($this->parser);
6542
+ } else {
6543
+ $this->debug('xml was empty, didn\'t parse!');
6544
+ $this->setError('xml was empty, didn\'t parse!');
6545
+ }
6546
+ }
6547
+
6548
+ /**
6549
+ * start-element handler
6550
+ *
6551
+ * @param resource $parser XML parser object
6552
+ * @param string $name element name
6553
+ * @param array $attrs associative array of attributes
6554
+ * @access private
6555
+ */
6556
+ function start_element($parser, $name, $attrs) {
6557
+ // position in a total number of elements, starting from 0
6558
+ // update class level pos
6559
+ $pos = $this->position++;
6560
+ // and set mine
6561
+ $this->message[$pos] = array('pos' => $pos,'children'=>'','cdata'=>'');
6562
+ // depth = how many levels removed from root?
6563
+ // set mine as current global depth and increment global depth value
6564
+ $this->message[$pos]['depth'] = $this->depth++;
6565
+
6566
+ // else add self as child to whoever the current parent is
6567
+ if($pos != 0){
6568
+ $this->message[$this->parent]['children'] .= '|'.$pos;
6569
+ }
6570
+ // set my parent
6571
+ $this->message[$pos]['parent'] = $this->parent;
6572
+ // set self as current parent
6573
+ $this->parent = $pos;
6574
+ // set self as current value for this depth
6575
+ $this->depth_array[$this->depth] = $pos;
6576
+ // get element prefix
6577
+ if(strpos($name,':')){
6578
+ // get ns prefix
6579
+ $prefix = substr($name,0,strpos($name,':'));
6580
+ // get unqualified name
6581
+ $name = substr(strstr($name,':'),1);
6582
+ }
6583
+ // set status
6584
+ if($name == 'Envelope'){
6585
+ $this->status = 'envelope';
6586
+ } elseif($name == 'Header' && $this->status = 'envelope'){
6587
+ $this->root_header = $pos;
6588
+ $this->status = 'header';
6589
+ } elseif($name == 'Body' && $this->status = 'envelope'){
6590
+ $this->status = 'body';
6591
+ $this->body_position = $pos;
6592
+ // set method
6593
+ } elseif($this->status == 'body' && $pos == ($this->body_position+1)){
6594
+ $this->status = 'method';
6595
+ $this->root_struct_name = $name;
6596
+ $this->root_struct = $pos;
6597
+ $this->message[$pos]['type'] = 'struct';
6598
+ $this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
6599
+ }
6600
+ // set my status
6601
+ $this->message[$pos]['status'] = $this->status;
6602
+ // set name
6603
+ $this->message[$pos]['name'] = htmlspecialchars($name);
6604
+ // set attrs
6605
+ $this->message[$pos]['attrs'] = $attrs;
6606
+
6607
+ // loop through atts, logging ns and type declarations
6608
+ $attstr = '';
6609
+ foreach($attrs as $key => $value){
6610
+ $key_prefix = $this->getPrefix($key);
6611
+ $key_localpart = $this->getLocalPart($key);
6612
+ // if ns declarations, add to class level array of valid namespaces
6613
+ if($key_prefix == 'xmlns'){
6614
+ if(ereg('^http://www.w3.org/[0-9]{4}/XMLSchema$',$value)){
6615
+ $this->XMLSchemaVersion = $value;
6616
+ $this->namespaces['xsd'] = $this->XMLSchemaVersion;
6617
+ $this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance';
6618
+ }
6619
+ $this->namespaces[$key_localpart] = $value;
6620
+ // set method namespace
6621
+ if($name == $this->root_struct_name){
6622
+ $this->methodNamespace = $value;
6623
+ }
6624
+ // if it's a type declaration, set type
6625
+ } elseif($key_localpart == 'type'){
6626
+ if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') {
6627
+ // do nothing: already processed arrayType
6628
+ } else {
6629
+ $value_prefix = $this->getPrefix($value);
6630
+ $value_localpart = $this->getLocalPart($value);
6631
+ $this->message[$pos]['type'] = $value_localpart;
6632
+ $this->message[$pos]['typePrefix'] = $value_prefix;
6633
+ if(isset($this->namespaces[$value_prefix])){
6634
+ $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
6635
+ } else if(isset($attrs['xmlns:'.$value_prefix])) {
6636
+ $this->message[$pos]['type_namespace'] = $attrs['xmlns:'.$value_prefix];
6637
+ }
6638
+ // should do something here with the namespace of specified type?
6639
+ }
6640
+ } elseif($key_localpart == 'arrayType'){
6641
+ $this->message[$pos]['type'] = 'array';
6642
+ /* do arrayType ereg here
6643
+ [1] arrayTypeValue ::= atype asize
6644
+ [2] atype ::= QName rank*
6645
+ [3] rank ::= '[' (',')* ']'
6646
+ [4] asize ::= '[' length~ ']'
6647
+ [5] length ::= nextDimension* Digit+
6648
+ [6] nextDimension ::= Digit+ ','
6649
+ */
6650
+ $expr = '([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]';
6651
+ if(ereg($expr,$value,$regs)){
6652
+ $this->message[$pos]['typePrefix'] = $regs[1];
6653
+ $this->message[$pos]['arrayTypePrefix'] = $regs[1];
6654
+ if (isset($this->namespaces[$regs[1]])) {
6655
+ $this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];
6656
+ } else if (isset($attrs['xmlns:'.$regs[1]])) {
6657
+ $this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:'.$regs[1]];
6658
+ }
6659
+ $this->message[$pos]['arrayType'] = $regs[2];
6660
+ $this->message[$pos]['arraySize'] = $regs[3];
6661
+ $this->message[$pos]['arrayCols'] = $regs[4];
6662
+ }
6663
+ // specifies nil value (or not)
6664
+ } elseif ($key_localpart == 'nil'){
6665
+ $this->message[$pos]['nil'] = ($value == 'true' || $value == '1');
6666
+ // some other attribute
6667
+ } elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') {
6668
+ $this->message[$pos]['xattrs']['!' . $key] = $value;
6669
+ }
6670
+
6671
+ if ($key == 'xmlns') {
6672
+ $this->default_namespace = $value;
6673
+ }
6674
+ // log id
6675
+ if($key == 'id'){
6676
+ $this->ids[$value] = $pos;
6677
+ }
6678
+ // root
6679
+ if($key_localpart == 'root' && $value == 1){
6680
+ $this->status = 'method';
6681
+ $this->root_struct_name = $name;
6682
+ $this->root_struct = $pos;
6683
+ $this->debug("found root struct $this->root_struct_name, pos $pos");
6684
+ }
6685
+ // for doclit
6686
+ $attstr .= " $key=\"$value\"";
6687
+ }
6688
+ // get namespace - must be done after namespace atts are processed
6689
+ if(isset($prefix)){
6690
+ $this->message[$pos]['namespace'] = $this->namespaces[$prefix];
6691
+ $this->default_namespace = $this->namespaces[$prefix];
6692
+ } else {
6693
+ $this->message[$pos]['namespace'] = $this->default_namespace;
6694
+ }
6695
+ if($this->status == 'header'){
6696
+ if ($this->root_header != $pos) {
6697
+ $this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
6698
+ }
6699
+ } elseif($this->root_struct_name != ''){
6700
+ $this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
6701
+ }
6702
+ }
6703
+
6704
+ /**
6705
+ * end-element handler
6706
+ *
6707
+ * @param resource $parser XML parser object
6708
+ * @param string $name element name
6709
+ * @access private
6710
+ */
6711
+ function end_element($parser, $name) {
6712
+ // position of current element is equal to the last value left in depth_array for my depth
6713
+ $pos = $this->depth_array[$this->depth--];
6714
+
6715
+ // get element prefix
6716
+ if(strpos($name,':')){
6717
+ // get ns prefix
6718
+ $prefix = substr($name,0,strpos($name,':'));
6719
+ // get unqualified name
6720
+ $name = substr(strstr($name,':'),1);
6721
+ }
6722
+
6723
+ // build to native type
6724
+ if(isset($this->body_position) && $pos > $this->body_position){
6725
+ // deal w/ multirefs
6726
+ if(isset($this->message[$pos]['attrs']['href'])){
6727
+ // get id
6728
+ $id = substr($this->message[$pos]['attrs']['href'],1);
6729
+ // add placeholder to href array
6730
+ $this->multirefs[$id][$pos] = 'placeholder';
6731
+ // add set a reference to it as the result value
6732
+ $this->message[$pos]['result'] =& $this->multirefs[$id][$pos];
6733
+ // build complexType values
6734
+ } elseif($this->message[$pos]['children'] != ''){
6735
+ // if result has already been generated (struct/array)
6736
+ if(!isset($this->message[$pos]['result'])){
6737
+ $this->message[$pos]['result'] = $this->buildVal($pos);
6738
+ }
6739
+ // build complexType values of attributes and possibly simpleContent
6740
+ } elseif (isset($this->message[$pos]['xattrs'])) {
6741
+ if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
6742
+ $this->message[$pos]['xattrs']['!'] = null;
6743
+ } elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
6744
+ if (isset($this->message[$pos]['type'])) {
6745
+ $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'] : '');
6746
+ } else {
6747
+ $parent = $this->message[$pos]['parent'];
6748
+ if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
6749
+ $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
6750
+ } else {
6751
+ $this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];
6752
+ }
6753
+ }
6754
+ }
6755
+ $this->message[$pos]['result'] = $this->message[$pos]['xattrs'];
6756
+ // set value of simpleType (or nil complexType)
6757
+ } else {
6758
+ //$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
6759
+ if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
6760
+ $this->message[$pos]['xattrs']['!'] = null;
6761
+ } elseif (isset($this->message[$pos]['type'])) {
6762
+ $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'] : '');
6763
+ } else {
6764
+ $parent = $this->message[$pos]['parent'];
6765
+ if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
6766
+ $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
6767
+ } else {
6768
+ $this->message[$pos]['result'] = $this->message[$pos]['cdata'];
6769
+ }
6770
+ }
6771
+
6772
+ /* add value to parent's result, if parent is struct/array
6773
+ $parent = $this->message[$pos]['parent'];
6774
+ if($this->message[$parent]['type'] != 'map'){
6775
+ if(strtolower($this->message[$parent]['type']) == 'array'){
6776
+ $this->message[$parent]['result'][] = $this->message[$pos]['result'];
6777
+ } else {
6778
+ $this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];
6779
+ }
6780
+ }
6781
+ */
6782
+ }
6783
+ }
6784
+
6785
+ // for doclit
6786
+ if($this->status == 'header'){
6787
+ if ($this->root_header != $pos) {
6788
+ $this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
6789
+ }
6790
+ } elseif($pos >= $this->root_struct){
6791
+ $this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
6792
+ }
6793
+ // switch status
6794
+ if($pos == $this->root_struct){
6795
+ $this->status = 'body';
6796
+ $this->root_struct_namespace = $this->message[$pos]['namespace'];
6797
+ } elseif($name == 'Body'){
6798
+ $this->status = 'envelope';
6799
+ } elseif($name == 'Header'){
6800
+ $this->status = 'envelope';
6801
+ } elseif($name == 'Envelope'){
6802
+ //
6803
+ }
6804
+ // set parent back to my parent
6805
+ $this->parent = $this->message[$pos]['parent'];
6806
+ }
6807
+
6808
+ /**
6809
+ * element content handler
6810
+ *
6811
+ * @param resource $parser XML parser object
6812
+ * @param string $data element content
6813
+ * @access private
6814
+ */
6815
+ function character_data($parser, $data){
6816
+ $pos = $this->depth_array[$this->depth];
6817
+ if ($this->xml_encoding=='UTF-8'){
6818
+ // TODO: add an option to disable this for folks who want
6819
+ // raw UTF-8 that, e.g., might not map to iso-8859-1
6820
+ // TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
6821
+ if($this->decode_utf8){
6822
+ $data = utf8_decode($data);
6823
+ }
6824
+ }
6825
+ $this->message[$pos]['cdata'] .= $data;
6826
+ // for doclit
6827
+ if($this->status == 'header'){
6828
+ $this->responseHeaders .= $data;
6829
+ } else {
6830
+ $this->document .= $data;
6831
+ }
6832
+ }
6833
+
6834
+ /**
6835
+ * get the parsed message (SOAP Body)
6836
+ *
6837
+ * @return mixed
6838
+ * @access public
6839
+ * @deprecated use get_soapbody instead
6840
+ */
6841
+ function get_response(){
6842
+ return $this->soapresponse;
6843
+ }
6844
+
6845
+ /**
6846
+ * get the parsed SOAP Body (NULL if there was none)
6847
+ *
6848
+ * @return mixed
6849
+ * @access public
6850
+ */
6851
+ function get_soapbody(){
6852
+ return $this->soapresponse;
6853
+ }
6854
+
6855
+ /**
6856
+ * get the parsed SOAP Header (NULL if there was none)
6857
+ *
6858
+ * @return mixed
6859
+ * @access public
6860
+ */
6861
+ function get_soapheader(){
6862
+ return $this->soapheader;
6863
+ }
6864
+
6865
+ /**
6866
+ * get the unparsed SOAP Header
6867
+ *
6868
+ * @return string XML or empty if no Header
6869
+ * @access public
6870
+ */
6871
+ function getHeaders(){
6872
+ return $this->responseHeaders;
6873
+ }
6874
+
6875
+ /**
6876
+ * decodes simple types into PHP variables
6877
+ *
6878
+ * @param string $value value to decode
6879
+ * @param string $type XML type to decode
6880
+ * @param string $typens XML type namespace to decode
6881
+ * @return mixed PHP value
6882
+ * @access private
6883
+ */
6884
+ function decodeSimple($value, $type, $typens) {
6885
+ // TODO: use the namespace!
6886
+ if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {
6887
+ return (string) $value;
6888
+ }
6889
+ if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {
6890
+ return (int) $value;
6891
+ }
6892
+ if ($type == 'float' || $type == 'double' || $type == 'decimal') {
6893
+ return (double) $value;
6894
+ }
6895
+ if ($type == 'boolean') {
6896
+ if (strtolower($value) == 'false' || strtolower($value) == 'f') {
6897
+ return false;
6898
+ }
6899
+ return (boolean) $value;
6900
+ }
6901
+ if ($type == 'base64' || $type == 'base64Binary') {
6902
+ $this->debug('Decode base64 value');
6903
+ return base64_decode($value);
6904
+ }
6905
+ // obscure numeric types
6906
+ if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
6907
+ || $type == 'nonNegativeInteger' || $type == 'positiveInteger'
6908
+ || $type == 'unsignedInt'
6909
+ || $type == 'unsignedShort' || $type == 'unsignedByte') {
6910
+ return (int) $value;
6911
+ }
6912
+ // bogus: parser treats array with no elements as a simple type
6913
+ if ($type == 'array') {
6914
+ return array();
6915
+ }
6916
+ // everything else
6917
+ return (string) $value;
6918
+ }
6919
+
6920
+ /**
6921
+ * builds response structures for compound values (arrays/structs)
6922
+ * and scalars
6923
+ *
6924
+ * @param integer $pos position in node tree
6925
+ * @return mixed PHP value
6926
+ * @access private
6927
+ */
6928
+ function buildVal($pos){
6929
+ if(!isset($this->message[$pos]['type'])){
6930
+ $this->message[$pos]['type'] = '';
6931
+ }
6932
+ $this->debug('in buildVal() for '.$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]['type']);
6933
+ // if there are children...
6934
+ if($this->message[$pos]['children'] != ''){
6935
+ $this->debug('in buildVal, there are children');
6936
+ $children = explode('|',$this->message[$pos]['children']);
6937
+ array_shift($children); // knock off empty
6938
+ // md array
6939
+ if(isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != ''){
6940
+ $r=0; // rowcount
6941
+ $c=0; // colcount
6942
+ foreach($children as $child_pos){
6943
+ $this->debug("in buildVal, got an MD array element: $r, $c");
6944
+ $params[$r][] = $this->message[$child_pos]['result'];
6945
+ $c++;
6946
+ if($c == $this->message[$pos]['arrayCols']){
6947
+ $c = 0;
6948
+ $r++;
6949
+ }
6950
+ }
6951
+ // array
6952
+ } elseif($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array'){
6953
+ $this->debug('in buildVal, adding array '.$this->message[$pos]['name']);
6954
+ foreach($children as $child_pos){
6955
+ $params[] = &$this->message[$child_pos]['result'];
6956
+ }
6957
+ // apache Map type: java hashtable
6958
+ } elseif($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap'){
6959
+ $this->debug('in buildVal, Java Map '.$this->message[$pos]['name']);
6960
+ foreach($children as $child_pos){
6961
+ $kv = explode("|",$this->message[$child_pos]['children']);
6962
+ $params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];
6963
+ }
6964
+ // generic compound type
6965
+ //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
6966
+ } else {
6967
+ // Apache Vector type: treat as an array
6968
+ $this->debug('in buildVal, adding Java Vector or generic compound type '.$this->message[$pos]['name']);
6969
+ if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
6970
+ $notstruct = 1;
6971
+ } else {
6972
+ $notstruct = 0;
6973
+ }
6974
+ //
6975
+ foreach($children as $child_pos){
6976
+ if($notstruct){
6977
+ $params[] = &$this->message[$child_pos]['result'];
6978
+ } else {
6979
+ if (isset($params[$this->message[$child_pos]['name']])) {
6980
+ // de-serialize repeated element name into an array
6981
+ if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) {
6982
+ $params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]);
6983
+ }
6984
+ $params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result'];
6985
+ } else {
6986
+ $params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];
6987
+ }
6988
+ }
6989
+ }
6990
+ }
6991
+ if (isset($this->message[$pos]['xattrs'])) {
6992
+ $this->debug('in buildVal, handling attributes');
6993
+ foreach ($this->message[$pos]['xattrs'] as $n => $v) {
6994
+ $params[$n] = $v;
6995
+ }
6996
+ }
6997
+ // handle simpleContent
6998
+ if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
6999
+ $this->debug('in buildVal, handling simpleContent');
7000
+ if (isset($this->message[$pos]['type'])) {
7001
+ $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
7002
+ } else {
7003
+ $parent = $this->message[$pos]['parent'];
7004
+ if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
7005
+ $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
7006
+ } else {
7007
+ $params['!'] = $this->message[$pos]['cdata'];
7008
+ }
7009
+ }
7010
+ }
7011
+ $ret = is_array($params) ? $params : array();
7012
+ $this->debug('in buildVal, return:');
7013
+ $this->appendDebug($this->varDump($ret));
7014
+ return $ret;
7015
+ } else {
7016
+ $this->debug('in buildVal, no children, building scalar');
7017
+ $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : '';
7018
+ if (isset($this->message[$pos]['type'])) {
7019
+ $ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
7020
+ $this->debug("in buildVal, return: $ret");
7021
+ return $ret;
7022
+ }
7023
+ $parent = $this->message[$pos]['parent'];
7024
+ if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
7025
+ $ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
7026
+ $this->debug("in buildVal, return: $ret");
7027
+ return $ret;
7028
+ }
7029
+ $ret = $this->message[$pos]['cdata'];
7030
+ $this->debug("in buildVal, return: $ret");
7031
+ return $ret;
7032
+ }
7033
+ }
7034
+ }
7035
+
7036
+ /**
7037
+ * Backward compatibility
7038
+ */
7039
+ class soap_parser extends nusoap_parser {
7040
+ }
7041
+
7042
+ ?><?php
7043
+
7044
+
7045
+
7046
+ /**
7047
+ *
7048
+ * [nu]soapclient higher level class for easy usage.
7049
+ *
7050
+ * usage:
7051
+ *
7052
+ * // instantiate client with server info
7053
+ * $soapclient = new nusoap_client( string path [ ,mixed wsdl] );
7054
+ *
7055
+ * // call method, get results
7056
+ * echo $soapclient->call( string methodname [ ,array parameters] );
7057
+ *
7058
+ * // bye bye client
7059
+ * unset($soapclient);
7060
+ *
7061
+ * @author Dietrich Ayala <dietrich@ganx4.com>
7062
+ * @author Scott Nichol <snichol@users.sourceforge.net>
7063
+ * @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $
7064
+ * @access public
7065
+ */
7066
+ class nusoap_client extends nusoap_base {
7067
+
7068
+ var $username = ''; // Username for HTTP authentication
7069
+ var $password = ''; // Password for HTTP authentication
7070
+ var $authtype = ''; // Type of HTTP authentication
7071
+ var $certRequest = array(); // Certificate for HTTP SSL authentication
7072
+ var $requestHeaders = false; // SOAP headers in request (text)
7073
+ var $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (text)
7074
+ var $responseHeader = NULL; // SOAP Header from response (parsed)
7075
+ var $document = ''; // SOAP body response portion (incomplete namespace resolution) (text)
7076
+ var $endpoint;
7077
+ var $forceEndpoint = ''; // overrides WSDL endpoint
7078
+ var $proxyhost = '';
7079
+ var $proxyport = '';
7080
+ var $proxyusername = '';
7081
+ var $proxypassword = '';
7082
+ var $xml_encoding = ''; // character set encoding of incoming (response) messages
7083
+ var $http_encoding = false;
7084
+ var $timeout = 0; // HTTP connection timeout
7085
+ var $response_timeout = 30; // HTTP response timeout
7086
+ var $endpointType = ''; // soap|wsdl, empty for WSDL initialization error
7087
+ var $persistentConnection = false;
7088
+ var $defaultRpcParams = false; // This is no longer used
7089
+ var $request = ''; // HTTP request
7090
+ var $response = ''; // HTTP response
7091
+ var $responseData = ''; // SOAP payload of response
7092
+ var $cookies = array(); // Cookies from response or for request
7093
+ var $decode_utf8 = true; // toggles whether the parser decodes element content w/ utf8_decode()
7094
+ var $operations = array(); // WSDL operations, empty for WSDL initialization error
7095
+ var $curl_options = array(); // User-specified cURL options
7096
+ var $bindingType = ''; // WSDL operation binding type
7097
+ var $use_curl = false; // whether to always try to use cURL
7098
+
7099
+ /*
7100
+ * fault related variables
7101
+ */
7102
+ /**
7103
+ * @var fault
7104
+ * @access public
7105
+ */
7106
+ var $fault;
7107
+ /**
7108
+ * @var faultcode
7109
+ * @access public
7110
+ */
7111
+ var $faultcode;
7112
+ /**
7113
+ * @var faultstring
7114
+ * @access public
7115
+ */
7116
+ var $faultstring;
7117
+ /**
7118
+ * @var faultdetail
7119
+ * @access public
7120
+ */
7121
+ var $faultdetail;
7122
+
7123
+ /**
7124
+ * constructor
7125
+ *
7126
+ * @param mixed $endpoint SOAP server or WSDL URL (string), or wsdl instance (object)
7127
+ * @param bool $wsdl optional, set to true if using WSDL
7128
+ * @param int $portName optional portName in WSDL document
7129
+ * @param string $proxyhost
7130
+ * @param string $proxyport
7131
+ * @param string $proxyusername
7132
+ * @param string $proxypassword
7133
+ * @param integer $timeout set the connection timeout
7134
+ * @param integer $response_timeout set the response timeout
7135
+ * @access public
7136
+ */
7137
+ function nusoap_client($endpoint,$wsdl = false,$proxyhost = false,$proxyport = false,$proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30){
7138
+ parent::nusoap_base();
7139
+ $this->endpoint = $endpoint;
7140
+ $this->proxyhost = $proxyhost;
7141
+ $this->proxyport = $proxyport;
7142
+ $this->proxyusername = $proxyusername;
7143
+ $this->proxypassword = $proxypassword;
7144
+ $this->timeout = $timeout;
7145
+ $this->response_timeout = $response_timeout;
7146
+
7147
+ $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
7148
+ $this->appendDebug('endpoint=' . $this->varDump($endpoint));
7149
+
7150
+ // make values
7151
+ if($wsdl){
7152
+ if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) {
7153
+ $this->wsdl = $endpoint;
7154
+ $this->endpoint = $this->wsdl->wsdl;
7155
+ $this->wsdlFile = $this->endpoint;
7156
+ $this->debug('existing wsdl instance created from ' . $this->endpoint);
7157
+ $this->checkWSDL();
7158
+ } else {
7159
+ $this->wsdlFile = $this->endpoint;
7160
+ $this->wsdl = null;
7161
+ $this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint);
7162
+ }
7163
+ $this->endpointType = 'wsdl';
7164
+ } else {
7165
+ $this->debug("instantiate SOAP with endpoint at $endpoint");
7166
+ $this->endpointType = 'soap';
7167
+ }
7168
+ }
7169
+
7170
+ /**
7171
+ * calls method, returns PHP native type
7172
+ *
7173
+ * @param string $operation SOAP server URL or path
7174
+ * @param mixed $params An array, associative or simple, of the parameters
7175
+ * for the method call, or a string that is the XML
7176
+ * for the call. For rpc style, this call will
7177
+ * wrap the XML in a tag named after the method, as
7178
+ * well as the SOAP Envelope and Body. For document
7179
+ * style, this will only wrap with the Envelope and Body.
7180
+ * IMPORTANT: when using an array with document style,
7181
+ * in which case there
7182
+ * is really one parameter, the root of the fragment
7183
+ * used in the call, which encloses what programmers
7184
+ * normally think of parameters. A parameter array
7185
+ * *must* include the wrapper.
7186
+ * @param string $namespace optional method namespace (WSDL can override)
7187
+ * @param string $soapAction optional SOAPAction value (WSDL can override)
7188
+ * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
7189
+ * @param boolean $rpcParams optional (no longer used)
7190
+ * @param string $style optional (rpc|document) the style to use when serializing parameters (WSDL can override)
7191
+ * @param string $use optional (encoded|literal) the use when serializing parameters (WSDL can override)
7192
+ * @return mixed response from SOAP call
7193
+ * @access public
7194
+ */
7195
+ function call($operation,$params=array(),$namespace='http://tempuri.org',$soapAction='',$headers=false,$rpcParams=null,$style='rpc',$use='encoded'){
7196
+ $this->operation = $operation;
7197
+ $this->fault = false;
7198
+ $this->setError('');
7199
+ $this->request = '';
7200
+ $this->response = '';
7201
+ $this->responseData = '';
7202
+ $this->faultstring = '';
7203
+ $this->faultcode = '';
7204
+ $this->opData = array();
7205
+
7206
+ $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType");
7207
+ $this->appendDebug('params=' . $this->varDump($params));
7208
+ $this->appendDebug('headers=' . $this->varDump($headers));
7209
+ if ($headers) {
7210
+ $this->requestHeaders = $headers;
7211
+ }
7212
+ if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7213
+ $this->loadWSDL();
7214
+ if ($this->getError())
7215
+ return false;
7216
+ }
7217
+ // serialize parameters
7218
+ if($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)){
7219
+ // use WSDL for operation
7220
+ $this->opData = $opData;
7221
+ $this->debug("found operation");
7222
+ $this->appendDebug('opData=' . $this->varDump($opData));
7223
+ if (isset($opData['soapAction'])) {
7224
+ $soapAction = $opData['soapAction'];
7225
+ }
7226
+ if (! $this->forceEndpoint) {
7227
+ $this->endpoint = $opData['endpoint'];
7228
+ } else {
7229
+ $this->endpoint = $this->forceEndpoint;
7230
+ }
7231
+ $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] : $namespace;
7232
+ $style = $opData['style'];
7233
+ $use = $opData['input']['use'];
7234
+ // add ns to ns array
7235
+ if($namespace != '' && !isset($this->wsdl->namespaces[$namespace])){
7236
+ $nsPrefix = 'ns' . rand(1000, 9999);
7237
+ $this->wsdl->namespaces[$nsPrefix] = $namespace;
7238
+ }
7239
+ $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);
7240
+ // serialize payload
7241
+ if (is_string($params)) {
7242
+ $this->debug("serializing param string for WSDL operation $operation");
7243
+ $payload = $params;
7244
+ } elseif (is_array($params)) {
7245
+ $this->debug("serializing param array for WSDL operation $operation");
7246
+ $payload = $this->wsdl->serializeRPCParameters($operation,'input',$params,$this->bindingType);
7247
+ } else {
7248
+ $this->debug('params must be array or string');
7249
+ $this->setError('params must be array or string');
7250
+ return false;
7251
+ }
7252
+ $usedNamespaces = $this->wsdl->usedNamespaces;
7253
+ if (isset($opData['input']['encodingStyle'])) {
7254
+ $encodingStyle = $opData['input']['encodingStyle'];
7255
+ } else {
7256
+ $encodingStyle = '';
7257
+ }
7258
+ $this->appendDebug($this->wsdl->getDebug());
7259
+ $this->wsdl->clearDebug();
7260
+ if ($errstr = $this->wsdl->getError()) {
7261
+ $this->debug('got wsdl error: '.$errstr);
7262
+ $this->setError('wsdl error: '.$errstr);
7263
+ return false;
7264
+ }
7265
+ } elseif($this->endpointType == 'wsdl') {
7266
+ // operation not in WSDL
7267
+ $this->appendDebug($this->wsdl->getDebug());
7268
+ $this->wsdl->clearDebug();
7269
+ $this->setError( 'operation '.$operation.' not present.');
7270
+ $this->debug("operation '$operation' not present.");
7271
+ return false;
7272
+ } else {
7273
+ // no WSDL
7274
+ //$this->namespaces['ns1'] = $namespace;
7275
+ $nsPrefix = 'ns' . rand(1000, 9999);
7276
+ // serialize
7277
+ $payload = '';
7278
+ if (is_string($params)) {
7279
+ $this->debug("serializing param string for operation $operation");
7280
+ $payload = $params;
7281
+ } elseif (is_array($params)) {
7282
+ $this->debug("serializing param array for operation $operation");
7283
+ foreach($params as $k => $v){
7284
+ $payload .= $this->serialize_val($v,$k,false,false,false,false,$use);
7285
+ }
7286
+ } else {
7287
+ $this->debug('params must be array or string');
7288
+ $this->setError('params must be array or string');
7289
+ return false;
7290
+ }
7291
+ $usedNamespaces = array();
7292
+ if ($use == 'encoded') {
7293
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
7294
+ } else {
7295
+ $encodingStyle = '';
7296
+ }
7297
+ }
7298
+ // wrap RPC calls with method element
7299
+ if ($style == 'rpc') {
7300
+ if ($use == 'literal') {
7301
+ $this->debug("wrapping RPC request with literal method element");
7302
+ if ($namespace) {
7303
+ // 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
7304
+ $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
7305
+ $payload .
7306
+ "</$nsPrefix:$operation>";
7307
+ } else {
7308
+ $payload = "<$operation>" . $payload . "</$operation>";
7309
+ }
7310
+ } else {
7311
+ $this->debug("wrapping RPC request with encoded method element");
7312
+ if ($namespace) {
7313
+ $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
7314
+ $payload .
7315
+ "</$nsPrefix:$operation>";
7316
+ } else {
7317
+ $payload = "<$operation>" .
7318
+ $payload .
7319
+ "</$operation>";
7320
+ }
7321
+ }
7322
+ }
7323
+ // serialize envelope
7324
+ $soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders,$usedNamespaces,$style,$use,$encodingStyle);
7325
+ $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
7326
+ $this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
7327
+ // send
7328
+ $return = $this->send($this->getHTTPBody($soapmsg),$soapAction,$this->timeout,$this->response_timeout);
7329
+ if($errstr = $this->getError()){
7330
+ $this->debug('Error: '.$errstr);
7331
+ return false;
7332
+ } else {
7333
+ $this->return = $return;
7334
+ $this->debug('sent message successfully and got a(n) '.gettype($return));
7335
+ $this->appendDebug('return=' . $this->varDump($return));
7336
+
7337
+ // fault?
7338
+ if(is_array($return) && isset($return['faultcode'])){
7339
+ $this->debug('got fault');
7340
+ $this->setError($return['faultcode'].': '.$return['faultstring']);
7341
+ $this->fault = true;
7342
+ foreach($return as $k => $v){
7343
+ $this->$k = $v;
7344
+ $this->debug("$k = $v<br>");
7345
+ }
7346
+ return $return;
7347
+ } elseif ($style == 'document') {
7348
+ // NOTE: if the response is defined to have multiple parts (i.e. unwrapped),
7349
+ // we are only going to return the first part here...sorry about that
7350
+ return $return;
7351
+ } else {
7352
+ // array of return values
7353
+ if(is_array($return)){
7354
+ // multiple 'out' parameters, which we return wrapped up
7355
+ // in the array
7356
+ if(sizeof($return) > 1){
7357
+ return $return;
7358
+ }
7359
+ // single 'out' parameter (normally the return value)
7360
+ $return = array_shift($return);
7361
+ $this->debug('return shifted value: ');
7362
+ $this->appendDebug($this->varDump($return));
7363
+ return $return;
7364
+ // nothing returned (ie, echoVoid)
7365
+ } else {
7366
+ return "";
7367
+ }
7368
+ }
7369
+ }
7370
+ }
7371
+
7372
+ /**
7373
+ * check WSDL passed as an instance or pulled from an endpoint
7374
+ *
7375
+ * @access private
7376
+ */
7377
+ function checkWSDL() {
7378
+ $this->appendDebug($this->wsdl->getDebug());
7379
+ $this->wsdl->clearDebug();
7380
+ $this->debug('checkWSDL');
7381
+ // catch errors
7382
+ if ($errstr = $this->wsdl->getError()) {
7383
+ $this->debug('got wsdl error: '.$errstr);
7384
+ $this->setError('wsdl error: '.$errstr);
7385
+ } elseif ($this->operations = $this->wsdl->getOperations('soap')) {
7386
+ $this->bindingType = 'soap';
7387
+ $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
7388
+ } elseif ($this->operations = $this->wsdl->getOperations('soap12')) {
7389
+ $this->bindingType = 'soap12';
7390
+ $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
7391
+ $this->debug('**************** WARNING: SOAP 1.2 BINDING *****************');
7392
+ } else {
7393
+ $this->debug('getOperations returned false');
7394
+ $this->setError('no operations defined in the WSDL document!');
7395
+ }
7396
+ }
7397
+
7398
+ /**
7399
+ * instantiate wsdl object and parse wsdl file
7400
+ *
7401
+ * @access public
7402
+ */
7403
+ function loadWSDL() {
7404
+ $this->debug('instantiating wsdl class with doc: '.$this->wsdlFile);
7405
+ //$this->wsdl =& new wsdl('',$this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeout,$this->response_timeout,$this->curl_options,$this->use_curl);
7406
+ $this->wsdl = new wsdl('',$this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeout,$this->response_timeout,$this->curl_options,$this->use_curl);
7407
+ $this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest);
7408
+ $this->wsdl->fetchWSDL($this->wsdlFile);
7409
+ $this->checkWSDL();
7410
+ }
7411
+
7412
+ /**
7413
+ * get available data pertaining to an operation
7414
+ *
7415
+ * @param string $operation operation name
7416
+ * @return array array of data pertaining to the operation
7417
+ * @access public
7418
+ */
7419
+ function getOperationData($operation){
7420
+ if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7421
+ $this->loadWSDL();
7422
+ if ($this->getError())
7423
+ return false;
7424
+ }
7425
+ if(isset($this->operations[$operation])){
7426
+ return $this->operations[$operation];
7427
+ }
7428
+ $this->debug("No data for operation: $operation");
7429
+ }
7430
+
7431
+ /**
7432
+ * send the SOAP message
7433
+ *
7434
+ * Note: if the operation has multiple return values
7435
+ * the return value of this method will be an array
7436
+ * of those values.
7437
+ *
7438
+ * @param string $msg a SOAPx4 soapmsg object
7439
+ * @param string $soapaction SOAPAction value
7440
+ * @param integer $timeout set connection timeout in seconds
7441
+ * @param integer $response_timeout set response timeout in seconds
7442
+ * @return mixed native PHP types.
7443
+ * @access private
7444
+ */
7445
+ function send($msg, $soapaction = '', $timeout=0, $response_timeout=30) {
7446
+ $this->checkCookies();
7447
+ // detect transport
7448
+ switch(true){
7449
+ // http(s)
7450
+ case ereg('^http',$this->endpoint):
7451
+ $this->debug('transporting via HTTP');
7452
+ if($this->persistentConnection == true && is_object($this->persistentConnection)){
7453
+ $http =& $this->persistentConnection;
7454
+ } else {
7455
+ $http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl);
7456
+ if ($this->persistentConnection) {
7457
+ $http->usePersistentConnection();
7458
+ }
7459
+ }
7460
+ $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset());
7461
+ $http->setSOAPAction($soapaction);
7462
+ if($this->proxyhost && $this->proxyport){
7463
+ $http->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
7464
+ }
7465
+ if($this->authtype != '') {
7466
+ $http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
7467
+ }
7468
+ if($this->http_encoding != ''){
7469
+ $http->setEncoding($this->http_encoding);
7470
+ }
7471
+ $this->debug('sending message, length='.strlen($msg));
7472
+ if(ereg('^http:',$this->endpoint)){
7473
+ //if(strpos($this->endpoint,'http:')){
7474
+ $this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies);
7475
+ } elseif(ereg('^https',$this->endpoint)){
7476
+ //} elseif(strpos($this->endpoint,'https:')){
7477
+ //if(phpversion() == '4.3.0-dev'){
7478
+ //$response = $http->send($msg,$timeout,$response_timeout);
7479
+ //$this->request = $http->outgoing_payload;
7480
+ //$this->response = $http->incoming_payload;
7481
+ //} else
7482
+ $this->responseData = $http->sendHTTPS($msg,$timeout,$response_timeout,$this->cookies);
7483
+ } else {
7484
+ $this->setError('no http/s in endpoint url');
7485
+ }
7486
+ $this->request = $http->outgoing_payload;
7487
+ $this->response = $http->incoming_payload;
7488
+ $this->appendDebug($http->getDebug());
7489
+ $this->UpdateCookies($http->incoming_cookies);
7490
+
7491
+ // save transport object if using persistent connections
7492
+ if ($this->persistentConnection) {
7493
+ $http->clearDebug();
7494
+ if (!is_object($this->persistentConnection)) {
7495
+ $this->persistentConnection = $http;
7496
+ }
7497
+ }
7498
+
7499
+ if($err = $http->getError()){
7500
+ $this->setError('HTTP Error: '.$err);
7501
+ return false;
7502
+ } elseif($this->getError()){
7503
+ return false;
7504
+ } else {
7505
+ $this->debug('got response, length='. strlen($this->responseData).' type='.$http->incoming_headers['content-type']);
7506
+ return $this->parseResponse($http->incoming_headers, $this->responseData);
7507
+ }
7508
+ break;
7509
+ default:
7510
+ $this->setError('no transport found, or selected transport is not yet supported!');
7511
+ return false;
7512
+ break;
7513
+ }
7514
+ }
7515
+
7516
+ /**
7517
+ * processes SOAP message returned from server
7518
+ *
7519
+ * @param array $headers The HTTP headers
7520
+ * @param string $data unprocessed response data from server
7521
+ * @return mixed value of the message, decoded into a PHP type
7522
+ * @access private
7523
+ */
7524
+ function parseResponse($headers, $data) {
7525
+ $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:');
7526
+ $this->appendDebug($this->varDump($headers));
7527
+ if (!strstr($headers['content-type'], 'text/xml')) {
7528
+ $this->setError('Response not of type text/xml: ' . $headers['content-type']);
7529
+ return false;
7530
+ }
7531
+ if (strpos($headers['content-type'], '=')) {
7532
+ $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
7533
+ $this->debug('Got response encoding: ' . $enc);
7534
+ if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){
7535
+ $this->xml_encoding = strtoupper($enc);
7536
+ } else {
7537
+ $this->xml_encoding = 'US-ASCII';
7538
+ }
7539
+ } else {
7540
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
7541
+ $this->xml_encoding = 'ISO-8859-1';
7542
+ }
7543
+ $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
7544
+ $parser = new nusoap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8);
7545
+ // add parser debug data to our debug
7546
+ $this->appendDebug($parser->getDebug());
7547
+ // if parse errors
7548
+ if($errstr = $parser->getError()){
7549
+ $this->setError( $errstr);
7550
+ // destroy the parser object
7551
+ unset($parser);
7552
+ return false;
7553
+ } else {
7554
+ // get SOAP headers
7555
+ $this->responseHeaders = $parser->getHeaders();
7556
+ // get SOAP headers
7557
+ $this->responseHeader = $parser->get_soapheader();
7558
+ // get decoded message
7559
+ $return = $parser->get_soapbody();
7560
+ // add document for doclit support
7561
+ $this->document = $parser->document;
7562
+ // destroy the parser object
7563
+ unset($parser);
7564
+ // return decode message
7565
+ return $return;
7566
+ }
7567
+ }
7568
+
7569
+ /**
7570
+ * sets user-specified cURL options
7571
+ *
7572
+ * @param mixed $option The cURL option (always integer?)
7573
+ * @param mixed $value The cURL option value
7574
+ * @access public
7575
+ */
7576
+ function setCurlOption($option, $value) {
7577
+ $this->debug("setCurlOption option=$option, value=");
7578
+ $this->appendDebug($this->varDump($value));
7579
+ $this->curl_options[$option] = $value;
7580
+ }
7581
+
7582
+ /**
7583
+ * sets the SOAP endpoint, which can override WSDL
7584
+ *
7585
+ * @param string $endpoint The endpoint URL to use, or empty string or false to prevent override
7586
+ * @access public
7587
+ */
7588
+ function setEndpoint($endpoint) {
7589
+ $this->debug("setEndpoint(\"$endpoint\")");
7590
+ $this->forceEndpoint = $endpoint;
7591
+ }
7592
+
7593
+ /**
7594
+ * set the SOAP headers
7595
+ *
7596
+ * @param mixed $headers String of XML with SOAP header content, or array of soapval objects for SOAP headers
7597
+ * @access public
7598
+ */
7599
+ function setHeaders($headers){
7600
+ $this->debug("setHeaders headers=");
7601
+ $this->appendDebug($this->varDump($headers));
7602
+ $this->requestHeaders = $headers;
7603
+ }
7604
+
7605
+ /**
7606
+ * get the SOAP response headers (namespace resolution incomplete)
7607
+ *
7608
+ * @return string
7609
+ * @access public
7610
+ */
7611
+ function getHeaders(){
7612
+ return $this->responseHeaders;
7613
+ }
7614
+
7615
+ /**
7616
+ * get the SOAP response Header (parsed)
7617
+ *
7618
+ * @return mixed
7619
+ * @access public
7620
+ */
7621
+ function getHeader(){
7622
+ return $this->responseHeader;
7623
+ }
7624
+
7625
+ /**
7626
+ * set proxy info here
7627
+ *
7628
+ * @param string $proxyhost
7629
+ * @param string $proxyport
7630
+ * @param string $proxyusername
7631
+ * @param string $proxypassword
7632
+ * @access public
7633
+ */
7634
+ function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') {
7635
+ $this->proxyhost = $proxyhost;
7636
+ $this->proxyport = $proxyport;
7637
+ $this->proxyusername = $proxyusername;
7638
+ $this->proxypassword = $proxypassword;
7639
+ }
7640
+
7641
+ /**
7642
+ * if authenticating, set user credentials here
7643
+ *
7644
+ * @param string $username
7645
+ * @param string $password
7646
+ * @param string $authtype (basic|digest|certificate|ntlm)
7647
+ * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
7648
+ * @access public
7649
+ */
7650
+ function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
7651
+ $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
7652
+ $this->appendDebug($this->varDump($certRequest));
7653
+ $this->username = $username;
7654
+ $this->password = $password;
7655
+ $this->authtype = $authtype;
7656
+ $this->certRequest = $certRequest;
7657
+ }
7658
+
7659
+ /**
7660
+ * use HTTP encoding
7661
+ *
7662
+ * @param string $enc HTTP encoding
7663
+ * @access public
7664
+ */
7665
+ function setHTTPEncoding($enc='gzip, deflate'){
7666
+ $this->debug("setHTTPEncoding(\"$enc\")");
7667
+ $this->http_encoding = $enc;
7668
+ }
7669
+
7670
+ /**
7671
+ * Set whether to try to use cURL connections if possible
7672
+ *
7673
+ * @param boolean $use Whether to try to use cURL
7674
+ * @access public
7675
+ */
7676
+ function setUseCURL($use) {
7677
+ $this->debug("setUseCURL($use)");
7678
+ $this->use_curl = $use;
7679
+ }
7680
+
7681
+ /**
7682
+ * use HTTP persistent connections if possible
7683
+ *
7684
+ * @access public
7685
+ */
7686
+ function useHTTPPersistentConnection(){
7687
+ $this->debug("useHTTPPersistentConnection");
7688
+ $this->persistentConnection = true;
7689
+ }
7690
+
7691
+ /**
7692
+ * gets the default RPC parameter setting.
7693
+ * If true, default is that call params are like RPC even for document style.
7694
+ * Each call() can override this value.
7695
+ *
7696
+ * This is no longer used.
7697
+ *
7698
+ * @return boolean
7699
+ * @access public
7700
+ * @deprecated
7701
+ */
7702
+ function getDefaultRpcParams() {
7703
+ return $this->defaultRpcParams;
7704
+ }
7705
+
7706
+ /**
7707
+ * sets the default RPC parameter setting.
7708
+ * If true, default is that call params are like RPC even for document style
7709
+ * Each call() can override this value.
7710
+ *
7711
+ * This is no longer used.
7712
+ *
7713
+ * @param boolean $rpcParams
7714
+ * @access public
7715
+ * @deprecated
7716
+ */
7717
+ function setDefaultRpcParams($rpcParams) {
7718
+ $this->defaultRpcParams = $rpcParams;
7719
+ }
7720
+
7721
+ /**
7722
+ * dynamically creates an instance of a proxy class,
7723
+ * allowing user to directly call methods from wsdl
7724
+ *
7725
+ * @return object soap_proxy object
7726
+ * @access public
7727
+ */
7728
+ function getProxy() {
7729
+ $r = rand();
7730
+ $evalStr = $this->_getProxyClassCode($r);
7731
+ //$this->debug("proxy class: $evalStr");
7732
+ if ($this->getError()) {
7733
+ $this->debug("Error from _getProxyClassCode, so return NULL");
7734
+ return null;
7735
+ }
7736
+ // eval the class
7737
+ eval($evalStr);
7738
+ // instantiate proxy object
7739
+ eval("\$proxy = new nusoap_proxy_$r('');");
7740
+ // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
7741
+ $proxy->endpointType = 'wsdl';
7742
+ $proxy->wsdlFile = $this->wsdlFile;
7743
+ $proxy->wsdl = $this->wsdl;
7744
+ $proxy->operations = $this->operations;
7745
+ $proxy->defaultRpcParams = $this->defaultRpcParams;
7746
+ // transfer other state
7747
+ $proxy->soap_defencoding = $this->soap_defencoding;
7748
+ $proxy->username = $this->username;
7749
+ $proxy->password = $this->password;
7750
+ $proxy->authtype = $this->authtype;
7751
+ $proxy->certRequest = $this->certRequest;
7752
+ $proxy->requestHeaders = $this->requestHeaders;
7753
+ $proxy->endpoint = $this->endpoint;
7754
+ $proxy->forceEndpoint = $this->forceEndpoint;
7755
+ $proxy->proxyhost = $this->proxyhost;
7756
+ $proxy->proxyport = $this->proxyport;
7757
+ $proxy->proxyusername = $this->proxyusername;
7758
+ $proxy->proxypassword = $this->proxypassword;
7759
+ $proxy->http_encoding = $this->http_encoding;
7760
+ $proxy->timeout = $this->timeout;
7761
+ $proxy->response_timeout = $this->response_timeout;
7762
+ $proxy->persistentConnection = &$this->persistentConnection;
7763
+ $proxy->decode_utf8 = $this->decode_utf8;
7764
+ $proxy->curl_options = $this->curl_options;
7765
+ $proxy->bindingType = $this->bindingType;
7766
+ $proxy->use_curl = $this->use_curl;
7767
+ return $proxy;
7768
+ }
7769
+
7770
+ /**
7771
+ * dynamically creates proxy class code
7772
+ *
7773
+ * @return string PHP/NuSOAP code for the proxy class
7774
+ * @access private
7775
+ */
7776
+ function _getProxyClassCode($r) {
7777
+ $this->debug("in getProxy endpointType=$this->endpointType");
7778
+ $this->appendDebug("wsdl=" . $this->varDump($this->wsdl));
7779
+ if ($this->endpointType != 'wsdl') {
7780
+ $evalStr = 'A proxy can only be created for a WSDL client';
7781
+ $this->setError($evalStr);
7782
+ $evalStr = "echo \"$evalStr\";";
7783
+ return $evalStr;
7784
+ }
7785
+ if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7786
+ $this->loadWSDL();
7787
+ if ($this->getError()) {
7788
+ return "echo \"" . $this->getError() . "\";";
7789
+ }
7790
+ }
7791
+ $evalStr = '';
7792
+ foreach ($this->operations as $operation => $opData) {
7793
+ if ($operation != '') {
7794
+ // create param string and param comment string
7795
+ if (sizeof($opData['input']['parts']) > 0) {
7796
+ $paramStr = '';
7797
+ $paramArrayStr = '';
7798
+ $paramCommentStr = '';
7799
+ foreach ($opData['input']['parts'] as $name => $type) {
7800
+ $paramStr .= "\$$name, ";
7801
+ $paramArrayStr .= "'$name' => \$$name, ";
7802
+ $paramCommentStr .= "$type \$$name, ";
7803
+ }
7804
+ $paramStr = substr($paramStr, 0, strlen($paramStr)-2);
7805
+ $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr)-2);
7806
+ $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2);
7807
+ } else {
7808
+ $paramStr = '';
7809
+ $paramArrayStr = '';
7810
+ $paramCommentStr = 'void';
7811
+ }
7812
+ $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
7813
+ $evalStr .= "// $paramCommentStr
7814
+ function " . str_replace('.', '__', $operation) . "($paramStr) {
7815
+ \$params = array($paramArrayStr);
7816
+ return \$this->call('$operation', \$params, '".$opData['namespace']."', '".(isset($opData['soapAction']) ? $opData['soapAction'] : '')."');
7817
+ }
7818
+ ";
7819
+ unset($paramStr);
7820
+ unset($paramCommentStr);
7821
+ }
7822
+ }
7823
+ $evalStr = 'class nusoap_proxy_'.$r.' extends nusoap_client {
7824
+ '.$evalStr.'
7825
+ }';
7826
+ return $evalStr;
7827
+ }
7828
+
7829
+ /**
7830
+ * dynamically creates proxy class code
7831
+ *
7832
+ * @return string PHP/NuSOAP code for the proxy class
7833
+ * @access public
7834
+ */
7835
+ function getProxyClassCode() {
7836
+ $r = rand();
7837
+ return $this->_getProxyClassCode($r);
7838
+ }
7839
+
7840
+ /**
7841
+ * gets the HTTP body for the current request.
7842
+ *
7843
+ * @param string $soapmsg The SOAP payload
7844
+ * @return string The HTTP body, which includes the SOAP payload
7845
+ * @access private
7846
+ */
7847
+ function getHTTPBody($soapmsg) {
7848
+ return $soapmsg;
7849
+ }
7850
+
7851
+ /**
7852
+ * gets the HTTP content type for the current request.
7853
+ *
7854
+ * Note: getHTTPBody must be called before this.
7855
+ *
7856
+ * @return string the HTTP content type for the current request.
7857
+ * @access private
7858
+ */
7859
+ function getHTTPContentType() {
7860
+ return 'text/xml';
7861
+ }
7862
+
7863
+ /**
7864
+ * gets the HTTP content type charset for the current request.
7865
+ * returns false for non-text content types.
7866
+ *
7867
+ * Note: getHTTPBody must be called before this.
7868
+ *
7869
+ * @return string the HTTP content type charset for the current request.
7870
+ * @access private
7871
+ */
7872
+ function getHTTPContentTypeCharset() {
7873
+ return $this->soap_defencoding;
7874
+ }
7875
+
7876
+ /*
7877
+ * whether or not parser should decode utf8 element content
7878
+ *
7879
+ * @return always returns true
7880
+ * @access public
7881
+ */
7882
+ function decodeUTF8($bool){
7883
+ $this->decode_utf8 = $bool;
7884
+ return true;
7885
+ }
7886
+
7887
+ /**
7888
+ * adds a new Cookie into $this->cookies array
7889
+ *
7890
+ * @param string $name Cookie Name
7891
+ * @param string $value Cookie Value
7892
+ * @return boolean if cookie-set was successful returns true, else false
7893
+ * @access public
7894
+ */
7895
+ function setCookie($name, $value) {
7896
+ if (strlen($name) == 0) {
7897
+ return false;
7898
+ }
7899
+ $this->cookies[] = array('name' => $name, 'value' => $value);
7900
+ return true;
7901
+ }
7902
+
7903
+ /**
7904
+ * gets all Cookies
7905
+ *
7906
+ * @return array with all internal cookies
7907
+ * @access public
7908
+ */
7909
+ function getCookies() {
7910
+ return $this->cookies;
7911
+ }
7912
+
7913
+ /**
7914
+ * checks all Cookies and delete those which are expired
7915
+ *
7916
+ * @return boolean always return true
7917
+ * @access private
7918
+ */
7919
+ function checkCookies() {
7920
+ if (sizeof($this->cookies) == 0) {
7921
+ return true;
7922
+ }
7923
+ $this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies');
7924
+ $curr_cookies = $this->cookies;
7925
+ $this->cookies = array();
7926
+ foreach ($curr_cookies as $cookie) {
7927
+ if (! is_array($cookie)) {
7928
+ $this->debug('Remove cookie that is not an array');
7929
+ continue;
7930
+ }
7931
+ if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
7932
+ if (strtotime($cookie['expires']) > time()) {
7933
+ $this->cookies[] = $cookie;
7934
+ } else {
7935
+ $this->debug('Remove expired cookie ' . $cookie['name']);
7936
+ }
7937
+ } else {
7938
+ $this->cookies[] = $cookie;
7939
+ }
7940
+ }
7941
+ $this->debug('checkCookie: '.sizeof($this->cookies).' cookies left in array');
7942
+ return true;
7943
+ }
7944
+
7945
+ /**
7946
+ * updates the current cookies with a new set
7947
+ *
7948
+ * @param array $cookies new cookies with which to update current ones
7949
+ * @return boolean always return true
7950
+ * @access private
7951
+ */
7952
+ function UpdateCookies($cookies) {
7953
+ if (sizeof($this->cookies) == 0) {
7954
+ // no existing cookies: take whatever is new
7955
+ if (sizeof($cookies) > 0) {
7956
+ $this->debug('Setting new cookie(s)');
7957
+ $this->cookies = $cookies;
7958
+ }
7959
+ return true;
7960
+ }
7961
+ if (sizeof($cookies) == 0) {
7962
+ // no new cookies: keep what we've got
7963
+ return true;
7964
+ }
7965
+ // merge
7966
+ foreach ($cookies as $newCookie) {
7967
+ if (!is_array($newCookie)) {
7968
+ continue;
7969
+ }
7970
+ if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) {
7971
+ continue;
7972
+ }
7973
+ $newName = $newCookie['name'];
7974
+
7975
+ $found = false;
7976
+ for ($i = 0; $i < count($this->cookies); $i++) {
7977
+ $cookie = $this->cookies[$i];
7978
+ if (!is_array($cookie)) {
7979
+ continue;
7980
+ }
7981
+ if (!isset($cookie['name'])) {
7982
+ continue;
7983
+ }
7984
+ if ($newName != $cookie['name']) {
7985
+ continue;
7986
+ }
7987
+ $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN';
7988
+ $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN';
7989
+ if ($newDomain != $domain) {
7990
+ continue;
7991
+ }
7992
+ $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH';
7993
+ $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH';
7994
+ if ($newPath != $path) {
7995
+ continue;
7996
+ }
7997
+ $this->cookies[$i] = $newCookie;
7998
+ $found = true;
7999
+ $this->debug('Update cookie ' . $newName . '=' . $newCookie['value']);
8000
+ break;
8001
+ }
8002
+ if (! $found) {
8003
+ $this->debug('Add cookie ' . $newName . '=' . $newCookie['value']);
8004
+ $this->cookies[] = $newCookie;
8005
+ }
8006
+ }
8007
+ return true;
8008
+ }
8009
+ }
8010
+
8011
+ if (!extension_loaded('soap')) {
8012
+ /**
8013
+ * For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded.
8014
+ */
8015
+ class soapclient extends nusoap_client {
8016
+ }
8017
+ }
8018
+ ?>
lib/nusoap/nusoap_base.php ADDED
@@ -0,0 +1,984 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
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 suporte.developer@buscape-inc.com so we can send you a copy immediately.
14
+ *
15
+ * @category Buscape
16
+ * @package Buscape_Fcontrol
17
+ * @copyright Copyright (c) 2010 Buscapé Company (http://www.buscapecompany.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ /*
22
+ $Id: class.nusoap_base.php,v 1.51 2007/11/06 15:17:46 snichol Exp $
23
+
24
+ NuSOAP - Web Services Toolkit for PHP
25
+
26
+ Copyright (c) 2002 NuSphere Corporation
27
+
28
+ This library is free software; you can redistribute it and/or
29
+ modify it under the terms of the GNU Lesser General Public
30
+ License as published by the Free Software Foundation; either
31
+ version 2.1 of the License, or (at your option) any later version.
32
+
33
+ This library is distributed in the hope that it will be useful,
34
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
35
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
36
+ Lesser General Public License for more details.
37
+
38
+ You should have received a copy of the GNU Lesser General Public
39
+ License along with this library; if not, write to the Free Software
40
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
41
+
42
+ The NuSOAP project home is:
43
+ http://sourceforge.net/projects/nusoap/
44
+
45
+ The primary support for NuSOAP is the mailing list:
46
+ nusoap-general@lists.sourceforge.net
47
+
48
+ If you have any questions or comments, please email:
49
+
50
+ Dietrich Ayala
51
+ dietrich@ganx4.com
52
+ http://dietrich.ganx4.com/nusoap
53
+
54
+ NuSphere Corporation
55
+ http://www.nusphere.com
56
+
57
+ */
58
+
59
+ /*
60
+ * Some of the standards implmented in whole or part by NuSOAP:
61
+ *
62
+ * SOAP 1.1 (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/)
63
+ * WSDL 1.1 (http://www.w3.org/TR/2001/NOTE-wsdl-20010315)
64
+ * SOAP Messages With Attachments (http://www.w3.org/TR/SOAP-attachments)
65
+ * XML 1.0 (http://www.w3.org/TR/2006/REC-xml-20060816/)
66
+ * Namespaces in XML 1.0 (http://www.w3.org/TR/2006/REC-xml-names-20060816/)
67
+ * XML Schema 1.0 (http://www.w3.org/TR/xmlschema-0/)
68
+ * RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies
69
+ * RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1
70
+ * RFC 2617 HTTP Authentication: Basic and Digest Access Authentication
71
+ */
72
+
73
+ // class variable emulation
74
+ // cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
75
+ $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = 9;
76
+
77
+ /**
78
+ *
79
+ * nusoap_base
80
+ *
81
+ * @author Dietrich Ayala <dietrich@ganx4.com>
82
+ * @author Scott Nichol <snichol@users.sourceforge.net>
83
+ * @version $Id: class.nusoap_base.php,v 1.51 2007/11/06 15:17:46 snichol Exp $
84
+ * @access public
85
+ */
86
+ class nusoap_base {
87
+ /**
88
+ * Identification for HTTP headers.
89
+ *
90
+ * @var string
91
+ * @access private
92
+ */
93
+ var $title = 'NuSOAP';
94
+ /**
95
+ * Version for HTTP headers.
96
+ *
97
+ * @var string
98
+ * @access private
99
+ */
100
+ var $version = '0.7.3';
101
+ /**
102
+ * CVS revision for HTTP headers.
103
+ *
104
+ * @var string
105
+ * @access private
106
+ */
107
+ var $revision = '$Revision: 1.51 $';
108
+ /**
109
+ * Current error string (manipulated by getError/setError)
110
+ *
111
+ * @var string
112
+ * @access private
113
+ */
114
+ var $error_str = '';
115
+ /**
116
+ * Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment)
117
+ *
118
+ * @var string
119
+ * @access private
120
+ */
121
+ var $debug_str = '';
122
+ /**
123
+ * toggles automatic encoding of special characters as entities
124
+ * (should always be true, I think)
125
+ *
126
+ * @var boolean
127
+ * @access private
128
+ */
129
+ var $charencoding = true;
130
+ /**
131
+ * the debug level for this instance
132
+ *
133
+ * @var integer
134
+ * @access private
135
+ */
136
+ var $debugLevel;
137
+
138
+ /**
139
+ * set schema version
140
+ *
141
+ * @var string
142
+ * @access public
143
+ */
144
+ var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
145
+
146
+ /**
147
+ * charset encoding for outgoing messages
148
+ *
149
+ * @var string
150
+ * @access public
151
+ */
152
+ var $soap_defencoding = 'ISO-8859-1';
153
+ //var $soap_defencoding = 'UTF-8';
154
+
155
+ /**
156
+ * namespaces in an array of prefix => uri
157
+ *
158
+ * this is "seeded" by a set of constants, but it may be altered by code
159
+ *
160
+ * @var array
161
+ * @access public
162
+ */
163
+ var $namespaces = array(
164
+ 'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
165
+ 'xsd' => 'http://www.w3.org/2001/XMLSchema',
166
+ 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
167
+ 'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
168
+ );
169
+
170
+ /**
171
+ * namespaces used in the current context, e.g. during serialization
172
+ *
173
+ * @var array
174
+ * @access private
175
+ */
176
+ var $usedNamespaces = array();
177
+
178
+ /**
179
+ * XML Schema types in an array of uri => (array of xml type => php type)
180
+ * is this legacy yet?
181
+ * no, this is used by the nusoap_xmlschema class to verify type => namespace mappings.
182
+ * @var array
183
+ * @access public
184
+ */
185
+ var $typemap = array(
186
+ 'http://www.w3.org/2001/XMLSchema' => array(
187
+ 'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
188
+ 'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
189
+ 'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
190
+ // abstract "any" types
191
+ 'anyType'=>'string','anySimpleType'=>'string',
192
+ // derived datatypes
193
+ 'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
194
+ 'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
195
+ 'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
196
+ 'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
197
+ 'http://www.w3.org/2000/10/XMLSchema' => array(
198
+ 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
199
+ 'float'=>'double','dateTime'=>'string',
200
+ 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
201
+ 'http://www.w3.org/1999/XMLSchema' => array(
202
+ 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
203
+ 'float'=>'double','dateTime'=>'string',
204
+ 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
205
+ 'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
206
+ 'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),
207
+ 'http://xml.apache.org/xml-soap' => array('Map')
208
+ );
209
+
210
+ /**
211
+ * XML entities to convert
212
+ *
213
+ * @var array
214
+ * @access public
215
+ * @deprecated
216
+ * @see expandEntities
217
+ */
218
+ var $xmlEntities = array('quot' => '"','amp' => '&',
219
+ 'lt' => '<','gt' => '>','apos' => "'");
220
+
221
+ /**
222
+ * constructor
223
+ *
224
+ * @access public
225
+ */
226
+ function nusoap_base() {
227
+ $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel;
228
+ }
229
+
230
+ /**
231
+ * gets the global debug level, which applies to future instances
232
+ *
233
+ * @return integer Debug level 0-9, where 0 turns off
234
+ * @access public
235
+ */
236
+ function getGlobalDebugLevel() {
237
+ return $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel;
238
+ }
239
+
240
+ /**
241
+ * sets the global debug level, which applies to future instances
242
+ *
243
+ * @param int $level Debug level 0-9, where 0 turns off
244
+ * @access public
245
+ */
246
+ function setGlobalDebugLevel($level) {
247
+ $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = $level;
248
+ }
249
+
250
+ /**
251
+ * gets the debug level for this instance
252
+ *
253
+ * @return int Debug level 0-9, where 0 turns off
254
+ * @access public
255
+ */
256
+ function getDebugLevel() {
257
+ return $this->debugLevel;
258
+ }
259
+
260
+ /**
261
+ * sets the debug level for this instance
262
+ *
263
+ * @param int $level Debug level 0-9, where 0 turns off
264
+ * @access public
265
+ */
266
+ function setDebugLevel($level) {
267
+ $this->debugLevel = $level;
268
+ }
269
+
270
+ /**
271
+ * adds debug data to the instance debug string with formatting
272
+ *
273
+ * @param string $string debug data
274
+ * @access private
275
+ */
276
+ function debug($string){
277
+ if ($this->debugLevel > 0) {
278
+ $this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n");
279
+ }
280
+ }
281
+
282
+ /**
283
+ * adds debug data to the instance debug string without formatting
284
+ *
285
+ * @param string $string debug data
286
+ * @access public
287
+ */
288
+ function appendDebug($string){
289
+ if ($this->debugLevel > 0) {
290
+ // it would be nice to use a memory stream here to use
291
+ // memory more efficiently
292
+ $this->debug_str .= $string;
293
+ }
294
+ }
295
+
296
+ /**
297
+ * clears the current debug data for this instance
298
+ *
299
+ * @access public
300
+ */
301
+ function clearDebug() {
302
+ // it would be nice to use a memory stream here to use
303
+ // memory more efficiently
304
+ $this->debug_str = '';
305
+ }
306
+
307
+ /**
308
+ * gets the current debug data for this instance
309
+ *
310
+ * @return debug data
311
+ * @access public
312
+ */
313
+ function &getDebug() {
314
+ // it would be nice to use a memory stream here to use
315
+ // memory more efficiently
316
+ return $this->debug_str;
317
+ }
318
+
319
+ /**
320
+ * gets the current debug data for this instance as an XML comment
321
+ * this may change the contents of the debug data
322
+ *
323
+ * @return debug data as an XML comment
324
+ * @access public
325
+ */
326
+ function &getDebugAsXMLComment() {
327
+ // it would be nice to use a memory stream here to use
328
+ // memory more efficiently
329
+ while (strpos($this->debug_str, '--')) {
330
+ $this->debug_str = str_replace('--', '- -', $this->debug_str);
331
+ }
332
+ $ret = "<!--\n" . $this->debug_str . "\n-->";
333
+ return $ret;
334
+ }
335
+
336
+ /**
337
+ * expands entities, e.g. changes '<' to '&lt;'.
338
+ *
339
+ * @param string $val The string in which to expand entities.
340
+ * @access private
341
+ */
342
+ function expandEntities($val) {
343
+ if ($this->charencoding) {
344
+ $val = str_replace('&', '&amp;', $val);
345
+ $val = str_replace("'", '&apos;', $val);
346
+ $val = str_replace('"', '&quot;', $val);
347
+ $val = str_replace('<', '&lt;', $val);
348
+ $val = str_replace('>', '&gt;', $val);
349
+ }
350
+ return $val;
351
+ }
352
+
353
+ /**
354
+ * returns error string if present
355
+ *
356
+ * @return mixed error string or false
357
+ * @access public
358
+ */
359
+ function getError(){
360
+ if($this->error_str != ''){
361
+ return $this->error_str;
362
+ }
363
+ return false;
364
+ }
365
+
366
+ /**
367
+ * sets error string
368
+ *
369
+ * @return boolean $string error string
370
+ * @access private
371
+ */
372
+ function setError($str){
373
+ $this->error_str = $str;
374
+ }
375
+
376
+ /**
377
+ * detect if array is a simple array or a struct (associative array)
378
+ *
379
+ * @param mixed $val The PHP array
380
+ * @return string (arraySimple|arrayStruct)
381
+ * @access private
382
+ */
383
+ function isArraySimpleOrStruct($val) {
384
+ $keyList = array_keys($val);
385
+ foreach ($keyList as $keyListValue) {
386
+ if (!is_int($keyListValue)) {
387
+ return 'arrayStruct';
388
+ }
389
+ }
390
+ return 'arraySimple';
391
+ }
392
+
393
+ /**
394
+ * serializes PHP values in accordance w/ section 5. Type information is
395
+ * not serialized if $use == 'literal'.
396
+ *
397
+ * @param mixed $val The value to serialize
398
+ * @param string $name The name (local part) of the XML element
399
+ * @param string $type The XML schema type (local part) for the element
400
+ * @param string $name_ns The namespace for the name of the XML element
401
+ * @param string $type_ns The namespace for the type of the element
402
+ * @param array $attributes The attributes to serialize as name=>value pairs
403
+ * @param string $use The WSDL "use" (encoded|literal)
404
+ * @param boolean $soapval Whether this is called from soapval.
405
+ * @return string The serialized element, possibly with child elements
406
+ * @access public
407
+ */
408
+ function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded',$soapval=false) {
409
+ $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval");
410
+ $this->appendDebug('value=' . $this->varDump($val));
411
+ $this->appendDebug('attributes=' . $this->varDump($attributes));
412
+
413
+ if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) {
414
+ $this->debug("serialize_val: serialize soapval");
415
+ $xml = $val->serialize($use);
416
+ $this->appendDebug($val->getDebug());
417
+ $val->clearDebug();
418
+ $this->debug("serialize_val of soapval returning $xml");
419
+ return $xml;
420
+ }
421
+ // force valid name if necessary
422
+ if (is_numeric($name)) {
423
+ $name = '__numeric_' . $name;
424
+ } elseif (! $name) {
425
+ $name = 'noname';
426
+ }
427
+ // if name has ns, add ns prefix to name
428
+ $xmlns = '';
429
+ if($name_ns){
430
+ $prefix = 'nu'.rand(1000,9999);
431
+ $name = $prefix.':'.$name;
432
+ $xmlns .= " xmlns:$prefix=\"$name_ns\"";
433
+ }
434
+ // if type is prefixed, create type prefix
435
+ if($type_ns != '' && $type_ns == $this->namespaces['xsd']){
436
+ // need to fix this. shouldn't default to xsd if no ns specified
437
+ // w/o checking against typemap
438
+ $type_prefix = 'xsd';
439
+ } elseif($type_ns){
440
+ $type_prefix = 'ns'.rand(1000,9999);
441
+ $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
442
+ }
443
+ // serialize attributes if present
444
+ $atts = '';
445
+ if($attributes){
446
+ foreach($attributes as $k => $v){
447
+ $atts .= " $k=\"".$this->expandEntities($v).'"';
448
+ }
449
+ }
450
+ // serialize null value
451
+ if (is_null($val)) {
452
+ $this->debug("serialize_val: serialize null");
453
+ if ($use == 'literal') {
454
+ // TODO: depends on minOccurs
455
+ $xml = "<$name$xmlns$atts/>";
456
+ $this->debug("serialize_val returning $xml");
457
+ return $xml;
458
+ } else {
459
+ if (isset($type) && isset($type_prefix)) {
460
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
461
+ } else {
462
+ $type_str = '';
463
+ }
464
+ $xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>";
465
+ $this->debug("serialize_val returning $xml");
466
+ return $xml;
467
+ }
468
+ }
469
+ // serialize if an xsd built-in primitive type
470
+ if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){
471
+ $this->debug("serialize_val: serialize xsd built-in primitive type");
472
+ if (is_bool($val)) {
473
+ if ($type == 'boolean') {
474
+ $val = $val ? 'true' : 'false';
475
+ } elseif (! $val) {
476
+ $val = 0;
477
+ }
478
+ } else if (is_string($val)) {
479
+ $val = $this->expandEntities($val);
480
+ }
481
+ if ($use == 'literal') {
482
+ $xml = "<$name$xmlns$atts>$val</$name>";
483
+ $this->debug("serialize_val returning $xml");
484
+ return $xml;
485
+ } else {
486
+ $xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>";
487
+ $this->debug("serialize_val returning $xml");
488
+ return $xml;
489
+ }
490
+ }
491
+ // detect type and serialize
492
+ $xml = '';
493
+ switch(true) {
494
+ case (is_bool($val) || $type == 'boolean'):
495
+ $this->debug("serialize_val: serialize boolean");
496
+ if ($type == 'boolean') {
497
+ $val = $val ? 'true' : 'false';
498
+ } elseif (! $val) {
499
+ $val = 0;
500
+ }
501
+ if ($use == 'literal') {
502
+ $xml .= "<$name$xmlns$atts>$val</$name>";
503
+ } else {
504
+ $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
505
+ }
506
+ break;
507
+ case (is_int($val) || is_long($val) || $type == 'int'):
508
+ $this->debug("serialize_val: serialize int");
509
+ if ($use == 'literal') {
510
+ $xml .= "<$name$xmlns$atts>$val</$name>";
511
+ } else {
512
+ $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
513
+ }
514
+ break;
515
+ case (is_float($val)|| is_double($val) || $type == 'float'):
516
+ $this->debug("serialize_val: serialize float");
517
+ if ($use == 'literal') {
518
+ $xml .= "<$name$xmlns$atts>$val</$name>";
519
+ } else {
520
+ $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
521
+ }
522
+ break;
523
+ case (is_string($val) || $type == 'string'):
524
+ $this->debug("serialize_val: serialize string");
525
+ $val = $this->expandEntities($val);
526
+ if ($use == 'literal') {
527
+ $xml .= "<$name$xmlns$atts>$val</$name>";
528
+ } else {
529
+ $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
530
+ }
531
+ break;
532
+ case is_object($val):
533
+ $this->debug("serialize_val: serialize object");
534
+ if (get_class($val) == 'soapval') {
535
+ $this->debug("serialize_val: serialize soapval object");
536
+ $pXml = $val->serialize($use);
537
+ $this->appendDebug($val->getDebug());
538
+ $val->clearDebug();
539
+ } else {
540
+ if (! $name) {
541
+ $name = get_class($val);
542
+ $this->debug("In serialize_val, used class name $name as element name");
543
+ } else {
544
+ $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
545
+ }
546
+ foreach(get_object_vars($val) as $k => $v){
547
+ $pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use);
548
+ }
549
+ }
550
+ if(isset($type) && isset($type_prefix)){
551
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
552
+ } else {
553
+ $type_str = '';
554
+ }
555
+ if ($use == 'literal') {
556
+ $xml .= "<$name$xmlns$atts>$pXml</$name>";
557
+ } else {
558
+ $xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";
559
+ }
560
+ break;
561
+ break;
562
+ case (is_array($val) || $type):
563
+ // detect if struct or array
564
+ $valueType = $this->isArraySimpleOrStruct($val);
565
+ if($valueType=='arraySimple' || ereg('^ArrayOf',$type)){
566
+ $this->debug("serialize_val: serialize array");
567
+ $i = 0;
568
+ if(is_array($val) && count($val)> 0){
569
+ foreach($val as $v){
570
+ if(is_object($v) && get_class($v) == 'soapval'){
571
+ $tt_ns = $v->type_ns;
572
+ $tt = $v->type;
573
+ } elseif (is_array($v)) {
574
+ $tt = $this->isArraySimpleOrStruct($v);
575
+ } else {
576
+ $tt = gettype($v);
577
+ }
578
+ $array_types[$tt] = 1;
579
+ // TODO: for literal, the name should be $name
580
+ $xml .= $this->serialize_val($v,'item',false,false,false,false,$use);
581
+ ++$i;
582
+ }
583
+ if(count($array_types) > 1){
584
+ $array_typename = 'xsd:anyType';
585
+ } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
586
+ if ($tt == 'integer') {
587
+ $tt = 'int';
588
+ }
589
+ $array_typename = 'xsd:'.$tt;
590
+ } elseif(isset($tt) && $tt == 'arraySimple'){
591
+ $array_typename = 'SOAP-ENC:Array';
592
+ } elseif(isset($tt) && $tt == 'arrayStruct'){
593
+ $array_typename = 'unnamed_struct_use_soapval';
594
+ } else {
595
+ // if type is prefixed, create type prefix
596
+ if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){
597
+ $array_typename = 'xsd:' . $tt;
598
+ } elseif ($tt_ns) {
599
+ $tt_prefix = 'ns' . rand(1000, 9999);
600
+ $array_typename = "$tt_prefix:$tt";
601
+ $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
602
+ } else {
603
+ $array_typename = $tt;
604
+ }
605
+ }
606
+ $array_type = $i;
607
+ if ($use == 'literal') {
608
+ $type_str = '';
609
+ } else if (isset($type) && isset($type_prefix)) {
610
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
611
+ } else {
612
+ $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"";
613
+ }
614
+ // empty array
615
+ } else {
616
+ if ($use == 'literal') {
617
+ $type_str = '';
618
+ } else if (isset($type) && isset($type_prefix)) {
619
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
620
+ } else {
621
+ $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
622
+ }
623
+ }
624
+ // TODO: for array in literal, there is no wrapper here
625
+ $xml = "<$name$xmlns$type_str$atts>".$xml."</$name>";
626
+ } else {
627
+ // got a struct
628
+ $this->debug("serialize_val: serialize struct");
629
+ if(isset($type) && isset($type_prefix)){
630
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
631
+ } else {
632
+ $type_str = '';
633
+ }
634
+ if ($use == 'literal') {
635
+ $xml .= "<$name$xmlns$atts>";
636
+ } else {
637
+ $xml .= "<$name$xmlns$type_str$atts>";
638
+ }
639
+ foreach($val as $k => $v){
640
+ // Apache Map
641
+ if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
642
+ $xml .= '<item>';
643
+ $xml .= $this->serialize_val($k,'key',false,false,false,false,$use);
644
+ $xml .= $this->serialize_val($v,'value',false,false,false,false,$use);
645
+ $xml .= '</item>';
646
+ } else {
647
+ $xml .= $this->serialize_val($v,$k,false,false,false,false,$use);
648
+ }
649
+ }
650
+ $xml .= "</$name>";
651
+ }
652
+ break;
653
+ default:
654
+ $this->debug("serialize_val: serialize unknown");
655
+ $xml .= 'not detected, got '.gettype($val).' for '.$val;
656
+ break;
657
+ }
658
+ $this->debug("serialize_val returning $xml");
659
+ return $xml;
660
+ }
661
+
662
+ /**
663
+ * serializes a message
664
+ *
665
+ * @param string $body the XML of the SOAP body
666
+ * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
667
+ * @param array $namespaces optional the namespaces used in generating the body and headers
668
+ * @param string $style optional (rpc|document)
669
+ * @param string $use optional (encoded|literal)
670
+ * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
671
+ * @return string the message
672
+ * @access public
673
+ */
674
+ function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded',$encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'){
675
+ // TODO: add an option to automatically run utf8_encode on $body and $headers
676
+ // if $this->soap_defencoding is UTF-8. Not doing this automatically allows
677
+ // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
678
+
679
+ $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");
680
+ $this->debug("headers:");
681
+ $this->appendDebug($this->varDump($headers));
682
+ $this->debug("namespaces:");
683
+ $this->appendDebug($this->varDump($namespaces));
684
+
685
+ // serialize namespaces
686
+ $ns_string = '';
687
+ foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
688
+ $ns_string .= " xmlns:$k=\"$v\"";
689
+ }
690
+ if($encodingStyle) {
691
+ $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
692
+ }
693
+
694
+ // serialize headers
695
+ if($headers){
696
+ if (is_array($headers)) {
697
+ $xml = '';
698
+ foreach ($headers as $k => $v) {
699
+ if (is_object($v) && get_class($v) == 'soapval') {
700
+ $xml .= $this->serialize_val($v, false, false, false, false, false, $use);
701
+ } else {
702
+ $xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
703
+ }
704
+ }
705
+ $headers = $xml;
706
+ $this->debug("In serializeEnvelope, serialized array of headers to $headers");
707
+ }
708
+ $headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
709
+ }
710
+ // serialize envelope
711
+ return
712
+ '<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
713
+ '<SOAP-ENV:Envelope'.$ns_string.">".
714
+ $headers.
715
+ "<SOAP-ENV:Body>".
716
+ $body.
717
+ "</SOAP-ENV:Body>".
718
+ "</SOAP-ENV:Envelope>";
719
+ }
720
+
721
+ /**
722
+ * formats a string to be inserted into an HTML stream
723
+ *
724
+ * @param string $str The string to format
725
+ * @return string The formatted string
726
+ * @access public
727
+ * @deprecated
728
+ */
729
+ function formatDump($str){
730
+ $str = htmlspecialchars($str);
731
+ return nl2br($str);
732
+ }
733
+
734
+ /**
735
+ * contracts (changes namespace to prefix) a qualified name
736
+ *
737
+ * @param string $qname qname
738
+ * @return string contracted qname
739
+ * @access private
740
+ */
741
+ function contractQname($qname){
742
+ // get element namespace
743
+ //$this->xdebug("Contract $qname");
744
+ if (strrpos($qname, ':')) {
745
+ // get unqualified name
746
+ $name = substr($qname, strrpos($qname, ':') + 1);
747
+ // get ns
748
+ $ns = substr($qname, 0, strrpos($qname, ':'));
749
+ $p = $this->getPrefixFromNamespace($ns);
750
+ if ($p) {
751
+ return $p . ':' . $name;
752
+ }
753
+ return $qname;
754
+ } else {
755
+ return $qname;
756
+ }
757
+ }
758
+
759
+ /**
760
+ * expands (changes prefix to namespace) a qualified name
761
+ *
762
+ * @param string $qname qname
763
+ * @return string expanded qname
764
+ * @access private
765
+ */
766
+ function expandQname($qname){
767
+ // get element prefix
768
+ if(strpos($qname,':') && !ereg('^http://',$qname)){
769
+ // get unqualified name
770
+ $name = substr(strstr($qname,':'),1);
771
+ // get ns prefix
772
+ $prefix = substr($qname,0,strpos($qname,':'));
773
+ if(isset($this->namespaces[$prefix])){
774
+ return $this->namespaces[$prefix].':'.$name;
775
+ } else {
776
+ return $qname;
777
+ }
778
+ } else {
779
+ return $qname;
780
+ }
781
+ }
782
+
783
+ /**
784
+ * returns the local part of a prefixed string
785
+ * returns the original string, if not prefixed
786
+ *
787
+ * @param string $str The prefixed string
788
+ * @return string The local part
789
+ * @access public
790
+ */
791
+ function getLocalPart($str){
792
+ if($sstr = strrchr($str,':')){
793
+ // get unqualified name
794
+ return substr( $sstr, 1 );
795
+ } else {
796
+ return $str;
797
+ }
798
+ }
799
+
800
+ /**
801
+ * returns the prefix part of a prefixed string
802
+ * returns false, if not prefixed
803
+ *
804
+ * @param string $str The prefixed string
805
+ * @return mixed The prefix or false if there is no prefix
806
+ * @access public
807
+ */
808
+ function getPrefix($str){
809
+ if($pos = strrpos($str,':')){
810
+ // get prefix
811
+ return substr($str,0,$pos);
812
+ }
813
+ return false;
814
+ }
815
+
816
+ /**
817
+ * pass it a prefix, it returns a namespace
818
+ *
819
+ * @param string $prefix The prefix
820
+ * @return mixed The namespace, false if no namespace has the specified prefix
821
+ * @access public
822
+ */
823
+ function getNamespaceFromPrefix($prefix){
824
+ if (isset($this->namespaces[$prefix])) {
825
+ return $this->namespaces[$prefix];
826
+ }
827
+ //$this->setError("No namespace registered for prefix '$prefix'");
828
+ return false;
829
+ }
830
+
831
+ /**
832
+ * returns the prefix for a given namespace (or prefix)
833
+ * or false if no prefixes registered for the given namespace
834
+ *
835
+ * @param string $ns The namespace
836
+ * @return mixed The prefix, false if the namespace has no prefixes
837
+ * @access public
838
+ */
839
+ function getPrefixFromNamespace($ns) {
840
+ foreach ($this->namespaces as $p => $n) {
841
+ if ($ns == $n || $ns == $p) {
842
+ $this->usedNamespaces[$p] = $n;
843
+ return $p;
844
+ }
845
+ }
846
+ return false;
847
+ }
848
+
849
+ /**
850
+ * returns the time in ODBC canonical form with microseconds
851
+ *
852
+ * @return string The time in ODBC canonical form with microseconds
853
+ * @access public
854
+ */
855
+ function getmicrotime() {
856
+ if (function_exists('gettimeofday')) {
857
+ $tod = gettimeofday();
858
+ $sec = $tod['sec'];
859
+ $usec = $tod['usec'];
860
+ } else {
861
+ $sec = time();
862
+ $usec = 0;
863
+ }
864
+ return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
865
+ }
866
+
867
+ /**
868
+ * Returns a string with the output of var_dump
869
+ *
870
+ * @param mixed $data The variable to var_dump
871
+ * @return string The output of var_dump
872
+ * @access public
873
+ */
874
+ function varDump($data) {
875
+ ob_start();
876
+ var_dump($data);
877
+ $ret_val = ob_get_contents();
878
+ ob_end_clean();
879
+ return $ret_val;
880
+ }
881
+
882
+ /**
883
+ * represents the object as a string
884
+ *
885
+ * @return string
886
+ * @access public
887
+ */
888
+ function __toString() {
889
+ return $this->varDump($this);
890
+ }
891
+ }
892
+
893
+ // XML Schema Datatype Helper Functions
894
+
895
+ //xsd:dateTime helpers
896
+
897
+ /**
898
+ * convert unix timestamp to ISO 8601 compliant date string
899
+ *
900
+ * @param string $timestamp Unix time stamp
901
+ * @param boolean $utc Whether the time stamp is UTC or local
902
+ * @access public
903
+ */
904
+ function timestamp_to_iso8601($timestamp,$utc=true){
905
+ $datestr = date('Y-m-d\TH:i:sO',$timestamp);
906
+ if($utc){
907
+ $eregStr =
908
+ '([0-9]{4})-'. // centuries & years CCYY-
909
+ '([0-9]{2})-'. // months MM-
910
+ '([0-9]{2})'. // days DD
911
+ 'T'. // separator T
912
+ '([0-9]{2}):'. // hours hh:
913
+ '([0-9]{2}):'. // minutes mm:
914
+ '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
915
+ '(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
916
+
917
+ if(ereg($eregStr,$datestr,$regs)){
918
+ return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
919
+ }
920
+ return false;
921
+ } else {
922
+ return $datestr;
923
+ }
924
+ }
925
+
926
+ /**
927
+ * convert ISO 8601 compliant date string to unix timestamp
928
+ *
929
+ * @param string $datestr ISO 8601 compliant date string
930
+ * @access public
931
+ */
932
+ function iso8601_to_timestamp($datestr){
933
+ $eregStr =
934
+ '([0-9]{4})-'. // centuries & years CCYY-
935
+ '([0-9]{2})-'. // months MM-
936
+ '([0-9]{2})'. // days DD
937
+ 'T'. // separator T
938
+ '([0-9]{2}):'. // hours hh:
939
+ '([0-9]{2}):'. // minutes mm:
940
+ '([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
941
+ '(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
942
+ if(ereg($eregStr,$datestr,$regs)){
943
+ // not utc
944
+ if($regs[8] != 'Z'){
945
+ $op = substr($regs[8],0,1);
946
+ $h = substr($regs[8],1,2);
947
+ $m = substr($regs[8],strlen($regs[8])-2,2);
948
+ if($op == '-'){
949
+ $regs[4] = $regs[4] + $h;
950
+ $regs[5] = $regs[5] + $m;
951
+ } elseif($op == '+'){
952
+ $regs[4] = $regs[4] - $h;
953
+ $regs[5] = $regs[5] - $m;
954
+ }
955
+ }
956
+ return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
957
+ // return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
958
+ } else {
959
+ return false;
960
+ }
961
+ }
962
+
963
+ /**
964
+ * sleeps some number of microseconds
965
+ *
966
+ * @param string $usec the number of microseconds to sleep
967
+ * @access public
968
+ * @deprecated
969
+ */
970
+ function usleepWindows($usec)
971
+ {
972
+ $start = gettimeofday();
973
+
974
+ do
975
+ {
976
+ $stop = gettimeofday();
977
+ $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
978
+ + $stop['usec'] - $start['usec'];
979
+ }
980
+ while ($timePassed < $usec);
981
+ }
982
+
983
+
984
+ ?>
lib/nusoap/nusoap_fault.php ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
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 suporte.developer@buscape-inc.com so we can send you a copy immediately.
14
+ *
15
+ * @category Buscape
16
+ * @package Buscape_Fcontrol
17
+ * @copyright Copyright (c) 2010 Buscapé Company (http://www.buscapecompany.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ /**
22
+ * Contains information for a SOAP fault.
23
+ * Mainly used for returning faults from deployed functions
24
+ * in a server instance.
25
+ * @author Dietrich Ayala <dietrich@ganx4.com>
26
+ * @version $Id: class.soap_fault.php,v 1.14 2007/04/11 15:49:47 snichol Exp $
27
+ * @access public
28
+ */
29
+ class nusoap_fault extends nusoap_base {
30
+ /**
31
+ * The fault code (client|server)
32
+ * @var string
33
+ * @access private
34
+ */
35
+ var $faultcode;
36
+ /**
37
+ * The fault actor
38
+ * @var string
39
+ * @access private
40
+ */
41
+ var $faultactor;
42
+ /**
43
+ * The fault string, a description of the fault
44
+ * @var string
45
+ * @access private
46
+ */
47
+ var $faultstring;
48
+ /**
49
+ * The fault detail, typically a string or array of string
50
+ * @var mixed
51
+ * @access private
52
+ */
53
+ var $faultdetail;
54
+
55
+ /**
56
+ * constructor
57
+ *
58
+ * @param string $faultcode (SOAP-ENV:Client | SOAP-ENV:Server)
59
+ * @param string $faultactor only used when msg routed between multiple actors
60
+ * @param string $faultstring human readable error message
61
+ * @param mixed $faultdetail detail, typically a string or array of string
62
+ */
63
+ function nusoap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){
64
+ parent::nusoap_base();
65
+ $this->faultcode = $faultcode;
66
+ $this->faultactor = $faultactor;
67
+ $this->faultstring = $faultstring;
68
+ $this->faultdetail = $faultdetail;
69
+ }
70
+
71
+ /**
72
+ * serialize a fault
73
+ *
74
+ * @return string The serialization of the fault instance.
75
+ * @access public
76
+ */
77
+ function serialize(){
78
+ $ns_string = '';
79
+ foreach($this->namespaces as $k => $v){
80
+ $ns_string .= "\n xmlns:$k=\"$v\"";
81
+ }
82
+ $return_msg =
83
+ '<?xml version="1.0" encoding="'.$this->soap_defencoding.'"?>'.
84
+ '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.">\n".
85
+ '<SOAP-ENV:Body>'.
86
+ '<SOAP-ENV:Fault>'.
87
+ $this->serialize_val($this->faultcode, 'faultcode').
88
+ $this->serialize_val($this->faultactor, 'faultactor').
89
+ $this->serialize_val($this->faultstring, 'faultstring').
90
+ $this->serialize_val($this->faultdetail, 'detail').
91
+ '</SOAP-ENV:Fault>'.
92
+ '</SOAP-ENV:Body>'.
93
+ '</SOAP-ENV:Envelope>';
94
+ return $return_msg;
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Backward compatibility
100
+ */
101
+ class soap_fault extends nusoap_fault {
102
+ }
103
+
104
+
105
+ ?>
lib/nusoap/nusoapmime.php ADDED
@@ -0,0 +1,520 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
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 suporte.developer@buscape-inc.com so we can send you a copy immediately.
14
+ *
15
+ * @category Buscape
16
+ * @package Buscape_Fcontrol
17
+ * @copyright Copyright (c) 2010 Buscapé Company (http://www.buscapecompany.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ /*
22
+ $Id: nusoapmime.php,v 1.12 2007/04/17 16:34:03 snichol Exp $
23
+
24
+ NuSOAP - Web Services Toolkit for PHP
25
+
26
+ Copyright (c) 2002 NuSphere Corporation
27
+
28
+ This library is free software; you can redistribute it and/or
29
+ modify it under the terms of the GNU Lesser General Public
30
+ License as published by the Free Software Foundation; either
31
+ version 2.1 of the License, or (at your option) any later version.
32
+
33
+ This library is distributed in the hope that it will be useful,
34
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
35
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
36
+ Lesser General Public License for more details.
37
+
38
+ You should have received a copy of the GNU Lesser General Public
39
+ License along with this library; if not, write to the Free Software
40
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
41
+
42
+ The NuSOAP project home is:
43
+ http://sourceforge.net/projects/nusoap/
44
+
45
+ The primary support for NuSOAP is the mailing list:
46
+ nusoap-general@lists.sourceforge.net
47
+
48
+ If you have any questions or comments, please email:
49
+
50
+ Dietrich Ayala
51
+ dietrich@ganx4.com
52
+ http://dietrich.ganx4.com/nusoap
53
+
54
+ NuSphere Corporation
55
+ http://www.nusphere.com
56
+
57
+ */
58
+
59
+ /*require_once('nusoap.php');*/
60
+ /* PEAR Mail_MIME library */
61
+ require_once('Mail/mimeDecode.php');
62
+ require_once('Mail/mimePart.php');
63
+
64
+ /**
65
+ * nusoap_client_mime client supporting MIME attachments defined at
66
+ * http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library.
67
+ *
68
+ * @author Scott Nichol <snichol@users.sourceforge.net>
69
+ * @author Thanks to Guillaume and Henning Reich for posting great attachment code to the mail list
70
+ * @version $Id: nusoapmime.php,v 1.12 2007/04/17 16:34:03 snichol Exp $
71
+ * @access public
72
+ */
73
+ class nusoap_client_mime extends nusoap_client {
74
+ /**
75
+ * @var array Each array element in the return is an associative array with keys
76
+ * data, filename, contenttype, cid
77
+ * @access private
78
+ */
79
+ var $requestAttachments = array();
80
+ /**
81
+ * @var array Each array element in the return is an associative array with keys
82
+ * data, filename, contenttype, cid
83
+ * @access private
84
+ */
85
+ var $responseAttachments;
86
+ /**
87
+ * @var string
88
+ * @access private
89
+ */
90
+ var $mimeContentType;
91
+
92
+ /**
93
+ * adds a MIME attachment to the current request.
94
+ *
95
+ * If the $data parameter contains an empty string, this method will read
96
+ * the contents of the file named by the $filename parameter.
97
+ *
98
+ * If the $cid parameter is false, this method will generate the cid.
99
+ *
100
+ * @param string $data The data of the attachment
101
+ * @param string $filename The filename of the attachment (default is empty string)
102
+ * @param string $contenttype The MIME Content-Type of the attachment (default is application/octet-stream)
103
+ * @param string $cid The content-id (cid) of the attachment (default is false)
104
+ * @return string The content-id (cid) of the attachment
105
+ * @access public
106
+ */
107
+ function addAttachment($data, $filename = '', $contenttype = 'application/octet-stream', $cid = false) {
108
+ if (! $cid) {
109
+ $cid = md5(uniqid(time()));
110
+ }
111
+
112
+ $info['data'] = $data;
113
+ $info['filename'] = $filename;
114
+ $info['contenttype'] = $contenttype;
115
+ $info['cid'] = $cid;
116
+
117
+ $this->requestAttachments[] = $info;
118
+
119
+ return $cid;
120
+ }
121
+
122
+ /**
123
+ * clears the MIME attachments for the current request.
124
+ *
125
+ * @access public
126
+ */
127
+ function clearAttachments() {
128
+ $this->requestAttachments = array();
129
+ }
130
+
131
+ /**
132
+ * gets the MIME attachments from the current response.
133
+ *
134
+ * Each array element in the return is an associative array with keys
135
+ * data, filename, contenttype, cid. These keys correspond to the parameters
136
+ * for addAttachment.
137
+ *
138
+ * @return array The attachments.
139
+ * @access public
140
+ */
141
+ function getAttachments() {
142
+ return $this->responseAttachments;
143
+ }
144
+
145
+ /**
146
+ * gets the HTTP body for the current request.
147
+ *
148
+ * @param string $soapmsg The SOAP payload
149
+ * @return string The HTTP body, which includes the SOAP payload
150
+ * @access private
151
+ */
152
+ function getHTTPBody($soapmsg) {
153
+ if (count($this->requestAttachments) > 0) {
154
+ $params['content_type'] = 'multipart/related; type="text/xml"';
155
+ $mimeMessage =& new Mail_mimePart('', $params);
156
+ unset($params);
157
+
158
+ $params['content_type'] = 'text/xml';
159
+ $params['encoding'] = '8bit';
160
+ $params['charset'] = $this->soap_defencoding;
161
+ $mimeMessage->addSubpart($soapmsg, $params);
162
+
163
+ foreach ($this->requestAttachments as $att) {
164
+ unset($params);
165
+
166
+ $params['content_type'] = $att['contenttype'];
167
+ $params['encoding'] = 'base64';
168
+ $params['disposition'] = 'attachment';
169
+ $params['dfilename'] = $att['filename'];
170
+ $params['cid'] = $att['cid'];
171
+
172
+ if ($att['data'] == '' && $att['filename'] <> '') {
173
+ if ($fd = fopen($att['filename'], 'rb')) {
174
+ $data = fread($fd, filesize($att['filename']));
175
+ fclose($fd);
176
+ } else {
177
+ $data = '';
178
+ }
179
+ $mimeMessage->addSubpart($data, $params);
180
+ } else {
181
+ $mimeMessage->addSubpart($att['data'], $params);
182
+ }
183
+ }
184
+
185
+ $output = $mimeMessage->encode();
186
+ $mimeHeaders = $output['headers'];
187
+
188
+ foreach ($mimeHeaders as $k => $v) {
189
+ $this->debug("MIME header $k: $v");
190
+ if (strtolower($k) == 'content-type') {
191
+ // PHP header() seems to strip leading whitespace starting
192
+ // the second line, so force everything to one line
193
+ $this->mimeContentType = str_replace("\r\n", " ", $v);
194
+ }
195
+ }
196
+
197
+ return $output['body'];
198
+ }
199
+
200
+ return parent::getHTTPBody($soapmsg);
201
+ }
202
+
203
+ /**
204
+ * gets the HTTP content type for the current request.
205
+ *
206
+ * Note: getHTTPBody must be called before this.
207
+ *
208
+ * @return string the HTTP content type for the current request.
209
+ * @access private
210
+ */
211
+ function getHTTPContentType() {
212
+ if (count($this->requestAttachments) > 0) {
213
+ return $this->mimeContentType;
214
+ }
215
+ return parent::getHTTPContentType();
216
+ }
217
+
218
+ /**
219
+ * gets the HTTP content type charset for the current request.
220
+ * returns false for non-text content types.
221
+ *
222
+ * Note: getHTTPBody must be called before this.
223
+ *
224
+ * @return string the HTTP content type charset for the current request.
225
+ * @access private
226
+ */
227
+ function getHTTPContentTypeCharset() {
228
+ if (count($this->requestAttachments) > 0) {
229
+ return false;
230
+ }
231
+ return parent::getHTTPContentTypeCharset();
232
+ }
233
+
234
+ /**
235
+ * processes SOAP message returned from server
236
+ *
237
+ * @param array $headers The HTTP headers
238
+ * @param string $data unprocessed response data from server
239
+ * @return mixed value of the message, decoded into a PHP type
240
+ * @access private
241
+ */
242
+ function parseResponse($headers, $data) {
243
+ $this->debug('Entering parseResponse() for payload of length ' . strlen($data) . ' and type of ' . $headers['content-type']);
244
+ $this->responseAttachments = array();
245
+ if (strstr($headers['content-type'], 'multipart/related')) {
246
+ $this->debug('Decode multipart/related');
247
+ $input = '';
248
+ foreach ($headers as $k => $v) {
249
+ $input .= "$k: $v\r\n";
250
+ }
251
+ $params['input'] = $input . "\r\n" . $data;
252
+ $params['include_bodies'] = true;
253
+ $params['decode_bodies'] = true;
254
+ $params['decode_headers'] = true;
255
+
256
+ $structure = Mail_mimeDecode::decode($params);
257
+
258
+ foreach ($structure->parts as $part) {
259
+ if (!isset($part->disposition) && (strstr($part->headers['content-type'], 'text/xml'))) {
260
+ $this->debug('Have root part of type ' . $part->headers['content-type']);
261
+ $root = $part->body;
262
+ $return = parent::parseResponse($part->headers, $part->body);
263
+ } else {
264
+ $this->debug('Have an attachment of type ' . $part->headers['content-type']);
265
+ $info['data'] = $part->body;
266
+ $info['filename'] = isset($part->d_parameters['filename']) ? $part->d_parameters['filename'] : '';
267
+ $info['contenttype'] = $part->headers['content-type'];
268
+ $info['cid'] = $part->headers['content-id'];
269
+ $this->responseAttachments[] = $info;
270
+ }
271
+ }
272
+
273
+ if (isset($return)) {
274
+ $this->responseData = $root;
275
+ return $return;
276
+ }
277
+
278
+ $this->setError('No root part found in multipart/related content');
279
+ return '';
280
+ }
281
+ $this->debug('Not multipart/related');
282
+ return parent::parseResponse($headers, $data);
283
+ }
284
+ }
285
+
286
+ /*
287
+ * For backwards compatiblity, define soapclientmime unless the PHP SOAP extension is loaded.
288
+ */
289
+ if (!extension_loaded('soap')) {
290
+ class soapclientmime extends nusoap_client_mime {
291
+ }
292
+ }
293
+
294
+ /**
295
+ * nusoap_server_mime server supporting MIME attachments defined at
296
+ * http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library.
297
+ *
298
+ * @author Scott Nichol <snichol@users.sourceforge.net>
299
+ * @author Thanks to Guillaume and Henning Reich for posting great attachment code to the mail list
300
+ * @version $Id: nusoapmime.php,v 1.12 2007/04/17 16:34:03 snichol Exp $
301
+ * @access public
302
+ */
303
+ class nusoap_server_mime extends nusoap_server {
304
+ /**
305
+ * @var array Each array element in the return is an associative array with keys
306
+ * data, filename, contenttype, cid
307
+ * @access private
308
+ */
309
+ var $requestAttachments = array();
310
+ /**
311
+ * @var array Each array element in the return is an associative array with keys
312
+ * data, filename, contenttype, cid
313
+ * @access private
314
+ */
315
+ var $responseAttachments;
316
+ /**
317
+ * @var string
318
+ * @access private
319
+ */
320
+ var $mimeContentType;
321
+
322
+ /**
323
+ * adds a MIME attachment to the current response.
324
+ *
325
+ * If the $data parameter contains an empty string, this method will read
326
+ * the contents of the file named by the $filename parameter.
327
+ *
328
+ * If the $cid parameter is false, this method will generate the cid.
329
+ *
330
+ * @param string $data The data of the attachment
331
+ * @param string $filename The filename of the attachment (default is empty string)
332
+ * @param string $contenttype The MIME Content-Type of the attachment (default is application/octet-stream)
333
+ * @param string $cid The content-id (cid) of the attachment (default is false)
334
+ * @return string The content-id (cid) of the attachment
335
+ * @access public
336
+ */
337
+ function addAttachment($data, $filename = '', $contenttype = 'application/octet-stream', $cid = false) {
338
+ if (! $cid) {
339
+ $cid = md5(uniqid(time()));
340
+ }
341
+
342
+ $info['data'] = $data;
343
+ $info['filename'] = $filename;
344
+ $info['contenttype'] = $contenttype;
345
+ $info['cid'] = $cid;
346
+
347
+ $this->responseAttachments[] = $info;
348
+
349
+ return $cid;
350
+ }
351
+
352
+ /**
353
+ * clears the MIME attachments for the current response.
354
+ *
355
+ * @access public
356
+ */
357
+ function clearAttachments() {
358
+ $this->responseAttachments = array();
359
+ }
360
+
361
+ /**
362
+ * gets the MIME attachments from the current request.
363
+ *
364
+ * Each array element in the return is an associative array with keys
365
+ * data, filename, contenttype, cid. These keys correspond to the parameters
366
+ * for addAttachment.
367
+ *
368
+ * @return array The attachments.
369
+ * @access public
370
+ */
371
+ function getAttachments() {
372
+ return $this->requestAttachments;
373
+ }
374
+
375
+ /**
376
+ * gets the HTTP body for the current response.
377
+ *
378
+ * @param string $soapmsg The SOAP payload
379
+ * @return string The HTTP body, which includes the SOAP payload
380
+ * @access private
381
+ */
382
+ function getHTTPBody($soapmsg) {
383
+ if (count($this->responseAttachments) > 0) {
384
+ $params['content_type'] = 'multipart/related; type="text/xml"';
385
+ $mimeMessage =& new Mail_mimePart('', $params);
386
+ unset($params);
387
+
388
+ $params['content_type'] = 'text/xml';
389
+ $params['encoding'] = '8bit';
390
+ $params['charset'] = $this->soap_defencoding;
391
+ $mimeMessage->addSubpart($soapmsg, $params);
392
+
393
+ foreach ($this->responseAttachments as $att) {
394
+ unset($params);
395
+
396
+ $params['content_type'] = $att['contenttype'];
397
+ $params['encoding'] = 'base64';
398
+ $params['disposition'] = 'attachment';
399
+ $params['dfilename'] = $att['filename'];
400
+ $params['cid'] = $att['cid'];
401
+
402
+ if ($att['data'] == '' && $att['filename'] <> '') {
403
+ if ($fd = fopen($att['filename'], 'rb')) {
404
+ $data = fread($fd, filesize($att['filename']));
405
+ fclose($fd);
406
+ } else {
407
+ $data = '';
408
+ }
409
+ $mimeMessage->addSubpart($data, $params);
410
+ } else {
411
+ $mimeMessage->addSubpart($att['data'], $params);
412
+ }
413
+ }
414
+
415
+ $output = $mimeMessage->encode();
416
+ $mimeHeaders = $output['headers'];
417
+
418
+ foreach ($mimeHeaders as $k => $v) {
419
+ $this->debug("MIME header $k: $v");
420
+ if (strtolower($k) == 'content-type') {
421
+ // PHP header() seems to strip leading whitespace starting
422
+ // the second line, so force everything to one line
423
+ $this->mimeContentType = str_replace("\r\n", " ", $v);
424
+ }
425
+ }
426
+
427
+ return $output['body'];
428
+ }
429
+
430
+ return parent::getHTTPBody($soapmsg);
431
+ }
432
+
433
+ /**
434
+ * gets the HTTP content type for the current response.
435
+ *
436
+ * Note: getHTTPBody must be called before this.
437
+ *
438
+ * @return string the HTTP content type for the current response.
439
+ * @access private
440
+ */
441
+ function getHTTPContentType() {
442
+ if (count($this->responseAttachments) > 0) {
443
+ return $this->mimeContentType;
444
+ }
445
+ return parent::getHTTPContentType();
446
+ }
447
+
448
+ /**
449
+ * gets the HTTP content type charset for the current response.
450
+ * returns false for non-text content types.
451
+ *
452
+ * Note: getHTTPBody must be called before this.
453
+ *
454
+ * @return string the HTTP content type charset for the current response.
455
+ * @access private
456
+ */
457
+ function getHTTPContentTypeCharset() {
458
+ if (count($this->responseAttachments) > 0) {
459
+ return false;
460
+ }
461
+ return parent::getHTTPContentTypeCharset();
462
+ }
463
+
464
+ /**
465
+ * processes SOAP message received from client
466
+ *
467
+ * @param array $headers The HTTP headers
468
+ * @param string $data unprocessed request data from client
469
+ * @return mixed value of the message, decoded into a PHP type
470
+ * @access private
471
+ */
472
+ function parseRequest($headers, $data) {
473
+ $this->debug('Entering parseRequest() for payload of length ' . strlen($data) . ' and type of ' . $headers['content-type']);
474
+ $this->requestAttachments = array();
475
+ if (strstr($headers['content-type'], 'multipart/related')) {
476
+ $this->debug('Decode multipart/related');
477
+ $input = '';
478
+ foreach ($headers as $k => $v) {
479
+ $input .= "$k: $v\r\n";
480
+ }
481
+ $params['input'] = $input . "\r\n" . $data;
482
+ $params['include_bodies'] = true;
483
+ $params['decode_bodies'] = true;
484
+ $params['decode_headers'] = true;
485
+
486
+ $structure = Mail_mimeDecode::decode($params);
487
+
488
+ foreach ($structure->parts as $part) {
489
+ if (!isset($part->disposition) && (strstr($part->headers['content-type'], 'text/xml'))) {
490
+ $this->debug('Have root part of type ' . $part->headers['content-type']);
491
+ $return = parent::parseRequest($part->headers, $part->body);
492
+ } else {
493
+ $this->debug('Have an attachment of type ' . $part->headers['content-type']);
494
+ $info['data'] = $part->body;
495
+ $info['filename'] = isset($part->d_parameters['filename']) ? $part->d_parameters['filename'] : '';
496
+ $info['contenttype'] = $part->headers['content-type'];
497
+ $info['cid'] = $part->headers['content-id'];
498
+ $this->requestAttachments[] = $info;
499
+ }
500
+ }
501
+
502
+ if (isset($return)) {
503
+ return $return;
504
+ }
505
+
506
+ $this->setError('No root part found in multipart/related content');
507
+ return;
508
+ }
509
+ $this->debug('Not multipart/related');
510
+ return parent::parseRequest($headers, $data);
511
+ }
512
+ }
513
+
514
+ /*
515
+ * For backwards compatiblity
516
+ */
517
+ class nusoapservermime extends nusoap_server_mime {
518
+ }
519
+
520
+ ?>
lib/nusoap/soap_parser.php ADDED
@@ -0,0 +1,654 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
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 suporte.developer@buscape-inc.com so we can send you a copy immediately.
14
+ *
15
+ * @category Buscape
16
+ * @package Buscape_Fcontrol
17
+ * @copyright Copyright (c) 2010 Buscapé Company (http://www.buscapecompany.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ /**
22
+ *
23
+ * nusoap_parser class parses SOAP XML messages into native PHP values
24
+ *
25
+ * @author Dietrich Ayala <dietrich@ganx4.com>
26
+ * @author Scott Nichol <snichol@users.sourceforge.net>
27
+ * @version $Id: class.soap_parser.php,v 1.40 2007/04/17 16:34:03 snichol Exp $
28
+ * @access public
29
+ */
30
+ class nusoap_parser extends nusoap_base {
31
+
32
+ var $xml = '';
33
+ var $xml_encoding = '';
34
+ var $method = '';
35
+ var $root_struct = '';
36
+ var $root_struct_name = '';
37
+ var $root_struct_namespace = '';
38
+ var $root_header = '';
39
+ var $document = ''; // incoming SOAP body (text)
40
+ // determines where in the message we are (envelope,header,body,method)
41
+ var $status = '';
42
+ var $position = 0;
43
+ var $depth = 0;
44
+ var $default_namespace = '';
45
+ var $namespaces = array();
46
+ var $message = array();
47
+ var $parent = '';
48
+ var $fault = false;
49
+ var $fault_code = '';
50
+ var $fault_str = '';
51
+ var $fault_detail = '';
52
+ var $depth_array = array();
53
+ var $debug_flag = true;
54
+ var $soapresponse = NULL; // parsed SOAP Body
55
+ var $soapheader = NULL; // parsed SOAP Header
56
+ var $responseHeaders = ''; // incoming SOAP headers (text)
57
+ var $body_position = 0;
58
+ // for multiref parsing:
59
+ // array of id => pos
60
+ var $ids = array();
61
+ // array of id => hrefs => pos
62
+ var $multirefs = array();
63
+ // toggle for auto-decoding element content
64
+ var $decode_utf8 = true;
65
+
66
+ /**
67
+ * constructor that actually does the parsing
68
+ *
69
+ * @param string $xml SOAP message
70
+ * @param string $encoding character encoding scheme of message
71
+ * @param string $method method for which XML is parsed (unused?)
72
+ * @param string $decode_utf8 whether to decode UTF-8 to ISO-8859-1
73
+ * @access public
74
+ */
75
+ function nusoap_parser($xml,$encoding='UTF-8',$method='',$decode_utf8=true){
76
+ parent::nusoap_base();
77
+ $this->xml = $xml;
78
+ $this->xml_encoding = $encoding;
79
+ $this->method = $method;
80
+ $this->decode_utf8 = $decode_utf8;
81
+
82
+ // Check whether content has been read.
83
+ if(!empty($xml)){
84
+ // Check XML encoding
85
+ $pos_xml = strpos($xml, '<?xml');
86
+ if ($pos_xml !== FALSE) {
87
+ $xml_decl = substr($xml, $pos_xml, strpos($xml, '?>', $pos_xml + 2) - $pos_xml + 1);
88
+ if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
89
+ $xml_encoding = $res[1];
90
+ if (strtoupper($xml_encoding) != $encoding) {
91
+ $err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";
92
+ $this->debug($err);
93
+ if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') {
94
+ $this->setError($err);
95
+ return;
96
+ }
97
+ // when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed
98
+ } else {
99
+ $this->debug('Charset from HTTP Content-Type matches encoding from XML declaration');
100
+ }
101
+ } else {
102
+ $this->debug('No encoding specified in XML declaration');
103
+ }
104
+ } else {
105
+ $this->debug('No XML declaration');
106
+ }
107
+ $this->debug('Entering nusoap_parser(), length='.strlen($xml).', encoding='.$encoding);
108
+ // Create an XML parser - why not xml_parser_create_ns?
109
+ $this->parser = xml_parser_create($this->xml_encoding);
110
+ // Set the options for parsing the XML data.
111
+ //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
112
+ xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
113
+ xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
114
+ // Set the object for the parser.
115
+ xml_set_object($this->parser, $this);
116
+ // Set the element handlers for the parser.
117
+ xml_set_element_handler($this->parser, 'start_element','end_element');
118
+ xml_set_character_data_handler($this->parser,'character_data');
119
+
120
+ // Parse the XML file.
121
+ if(!xml_parse($this->parser,$xml,true)){
122
+ // Display an error message.
123
+ $err = sprintf('XML error parsing SOAP payload on line %d: %s',
124
+ xml_get_current_line_number($this->parser),
125
+ xml_error_string(xml_get_error_code($this->parser)));
126
+ $this->debug($err);
127
+ $this->debug("XML payload:\n" . $xml);
128
+ $this->setError($err);
129
+ } else {
130
+ $this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name);
131
+ // get final value
132
+ $this->soapresponse = $this->message[$this->root_struct]['result'];
133
+ // get header value
134
+ if($this->root_header != '' && isset($this->message[$this->root_header]['result'])){
135
+ $this->soapheader = $this->message[$this->root_header]['result'];
136
+ }
137
+ // resolve hrefs/ids
138
+ if(sizeof($this->multirefs) > 0){
139
+ foreach($this->multirefs as $id => $hrefs){
140
+ $this->debug('resolving multirefs for id: '.$id);
141
+ $idVal = $this->buildVal($this->ids[$id]);
142
+ if (is_array($idVal) && isset($idVal['!id'])) {
143
+ unset($idVal['!id']);
144
+ }
145
+ foreach($hrefs as $refPos => $ref){
146
+ $this->debug('resolving href at pos '.$refPos);
147
+ $this->multirefs[$id][$refPos] = $idVal;
148
+ }
149
+ }
150
+ }
151
+ }
152
+ xml_parser_free($this->parser);
153
+ } else {
154
+ $this->debug('xml was empty, didn\'t parse!');
155
+ $this->setError('xml was empty, didn\'t parse!');
156
+ }
157
+ }
158
+
159
+ /**
160
+ * start-element handler
161
+ *
162
+ * @param resource $parser XML parser object
163
+ * @param string $name element name
164
+ * @param array $attrs associative array of attributes
165
+ * @access private
166
+ */
167
+ function start_element($parser, $name, $attrs) {
168
+ // position in a total number of elements, starting from 0
169
+ // update class level pos
170
+ $pos = $this->position++;
171
+ // and set mine
172
+ $this->message[$pos] = array('pos' => $pos,'children'=>'','cdata'=>'');
173
+ // depth = how many levels removed from root?
174
+ // set mine as current global depth and increment global depth value
175
+ $this->message[$pos]['depth'] = $this->depth++;
176
+
177
+ // else add self as child to whoever the current parent is
178
+ if($pos != 0){
179
+ $this->message[$this->parent]['children'] .= '|'.$pos;
180
+ }
181
+ // set my parent
182
+ $this->message[$pos]['parent'] = $this->parent;
183
+ // set self as current parent
184
+ $this->parent = $pos;
185
+ // set self as current value for this depth
186
+ $this->depth_array[$this->depth] = $pos;
187
+ // get element prefix
188
+ if(strpos($name,':')){
189
+ // get ns prefix
190
+ $prefix = substr($name,0,strpos($name,':'));
191
+ // get unqualified name
192
+ $name = substr(strstr($name,':'),1);
193
+ }
194
+ // set status
195
+ if($name == 'Envelope'){
196
+ $this->status = 'envelope';
197
+ } elseif($name == 'Header' && $this->status = 'envelope'){
198
+ $this->root_header = $pos;
199
+ $this->status = 'header';
200
+ } elseif($name == 'Body' && $this->status = 'envelope'){
201
+ $this->status = 'body';
202
+ $this->body_position = $pos;
203
+ // set method
204
+ } elseif($this->status == 'body' && $pos == ($this->body_position+1)){
205
+ $this->status = 'method';
206
+ $this->root_struct_name = $name;
207
+ $this->root_struct = $pos;
208
+ $this->message[$pos]['type'] = 'struct';
209
+ $this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
210
+ }
211
+ // set my status
212
+ $this->message[$pos]['status'] = $this->status;
213
+ // set name
214
+ $this->message[$pos]['name'] = htmlspecialchars($name);
215
+ // set attrs
216
+ $this->message[$pos]['attrs'] = $attrs;
217
+
218
+ // loop through atts, logging ns and type declarations
219
+ $attstr = '';
220
+ foreach($attrs as $key => $value){
221
+ $key_prefix = $this->getPrefix($key);
222
+ $key_localpart = $this->getLocalPart($key);
223
+ // if ns declarations, add to class level array of valid namespaces
224
+ if($key_prefix == 'xmlns'){
225
+ if(ereg('^http://www.w3.org/[0-9]{4}/XMLSchema$',$value)){
226
+ $this->XMLSchemaVersion = $value;
227
+ $this->namespaces['xsd'] = $this->XMLSchemaVersion;
228
+ $this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance';
229
+ }
230
+ $this->namespaces[$key_localpart] = $value;
231
+ // set method namespace
232
+ if($name == $this->root_struct_name){
233
+ $this->methodNamespace = $value;
234
+ }
235
+ // if it's a type declaration, set type
236
+ } elseif($key_localpart == 'type'){
237
+ if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') {
238
+ // do nothing: already processed arrayType
239
+ } else {
240
+ $value_prefix = $this->getPrefix($value);
241
+ $value_localpart = $this->getLocalPart($value);
242
+ $this->message[$pos]['type'] = $value_localpart;
243
+ $this->message[$pos]['typePrefix'] = $value_prefix;
244
+ if(isset($this->namespaces[$value_prefix])){
245
+ $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
246
+ } else if(isset($attrs['xmlns:'.$value_prefix])) {
247
+ $this->message[$pos]['type_namespace'] = $attrs['xmlns:'.$value_prefix];
248
+ }
249
+ // should do something here with the namespace of specified type?
250
+ }
251
+ } elseif($key_localpart == 'arrayType'){
252
+ $this->message[$pos]['type'] = 'array';
253
+ /* do arrayType ereg here
254
+ [1] arrayTypeValue ::= atype asize
255
+ [2] atype ::= QName rank*
256
+ [3] rank ::= '[' (',')* ']'
257
+ [4] asize ::= '[' length~ ']'
258
+ [5] length ::= nextDimension* Digit+
259
+ [6] nextDimension ::= Digit+ ','
260
+ */
261
+ $expr = '([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]';
262
+ if(ereg($expr,$value,$regs)){
263
+ $this->message[$pos]['typePrefix'] = $regs[1];
264
+ $this->message[$pos]['arrayTypePrefix'] = $regs[1];
265
+ if (isset($this->namespaces[$regs[1]])) {
266
+ $this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];
267
+ } else if (isset($attrs['xmlns:'.$regs[1]])) {
268
+ $this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:'.$regs[1]];
269
+ }
270
+ $this->message[$pos]['arrayType'] = $regs[2];
271
+ $this->message[$pos]['arraySize'] = $regs[3];
272
+ $this->message[$pos]['arrayCols'] = $regs[4];
273
+ }
274
+ // specifies nil value (or not)
275
+ } elseif ($key_localpart == 'nil'){
276
+ $this->message[$pos]['nil'] = ($value == 'true' || $value == '1');
277
+ // some other attribute
278
+ } elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') {
279
+ $this->message[$pos]['xattrs']['!' . $key] = $value;
280
+ }
281
+
282
+ if ($key == 'xmlns') {
283
+ $this->default_namespace = $value;
284
+ }
285
+ // log id
286
+ if($key == 'id'){
287
+ $this->ids[$value] = $pos;
288
+ }
289
+ // root
290
+ if($key_localpart == 'root' && $value == 1){
291
+ $this->status = 'method';
292
+ $this->root_struct_name = $name;
293
+ $this->root_struct = $pos;
294
+ $this->debug("found root struct $this->root_struct_name, pos $pos");
295
+ }
296
+ // for doclit
297
+ $attstr .= " $key=\"$value\"";
298
+ }
299
+ // get namespace - must be done after namespace atts are processed
300
+ if(isset($prefix)){
301
+ $this->message[$pos]['namespace'] = $this->namespaces[$prefix];
302
+ $this->default_namespace = $this->namespaces[$prefix];
303
+ } else {
304
+ $this->message[$pos]['namespace'] = $this->default_namespace;
305
+ }
306
+ if($this->status == 'header'){
307
+ if ($this->root_header != $pos) {
308
+ $this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
309
+ }
310
+ } elseif($this->root_struct_name != ''){
311
+ $this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
312
+ }
313
+ }
314
+
315
+ /**
316
+ * end-element handler
317
+ *
318
+ * @param resource $parser XML parser object
319
+ * @param string $name element name
320
+ * @access private
321
+ */
322
+ function end_element($parser, $name) {
323
+ // position of current element is equal to the last value left in depth_array for my depth
324
+ $pos = $this->depth_array[$this->depth--];
325
+
326
+ // get element prefix
327
+ if(strpos($name,':')){
328
+ // get ns prefix
329
+ $prefix = substr($name,0,strpos($name,':'));
330
+ // get unqualified name
331
+ $name = substr(strstr($name,':'),1);
332
+ }
333
+
334
+ // build to native type
335
+ if(isset($this->body_position) && $pos > $this->body_position){
336
+ // deal w/ multirefs
337
+ if(isset($this->message[$pos]['attrs']['href'])){
338
+ // get id
339
+ $id = substr($this->message[$pos]['attrs']['href'],1);
340
+ // add placeholder to href array
341
+ $this->multirefs[$id][$pos] = 'placeholder';
342
+ // add set a reference to it as the result value
343
+ $this->message[$pos]['result'] =& $this->multirefs[$id][$pos];
344
+ // build complexType values
345
+ } elseif($this->message[$pos]['children'] != ''){
346
+ // if result has already been generated (struct/array)
347
+ if(!isset($this->message[$pos]['result'])){
348
+ $this->message[$pos]['result'] = $this->buildVal($pos);
349
+ }
350
+ // build complexType values of attributes and possibly simpleContent
351
+ } elseif (isset($this->message[$pos]['xattrs'])) {
352
+ if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
353
+ $this->message[$pos]['xattrs']['!'] = null;
354
+ } elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
355
+ if (isset($this->message[$pos]['type'])) {
356
+ $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'] : '');
357
+ } else {
358
+ $parent = $this->message[$pos]['parent'];
359
+ if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
360
+ $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
361
+ } else {
362
+ $this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];
363
+ }
364
+ }
365
+ }
366
+ $this->message[$pos]['result'] = $this->message[$pos]['xattrs'];
367
+ // set value of simpleType (or nil complexType)
368
+ } else {
369
+ //$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
370
+ if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
371
+ $this->message[$pos]['xattrs']['!'] = null;
372
+ } elseif (isset($this->message[$pos]['type'])) {
373
+ $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'] : '');
374
+ } else {
375
+ $parent = $this->message[$pos]['parent'];
376
+ if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
377
+ $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
378
+ } else {
379
+ $this->message[$pos]['result'] = $this->message[$pos]['cdata'];
380
+ }
381
+ }
382
+
383
+ /* add value to parent's result, if parent is struct/array
384
+ $parent = $this->message[$pos]['parent'];
385
+ if($this->message[$parent]['type'] != 'map'){
386
+ if(strtolower($this->message[$parent]['type']) == 'array'){
387
+ $this->message[$parent]['result'][] = $this->message[$pos]['result'];
388
+ } else {
389
+ $this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];
390
+ }
391
+ }
392
+ */
393
+ }
394
+ }
395
+
396
+ // for doclit
397
+ if($this->status == 'header'){
398
+ if ($this->root_header != $pos) {
399
+ $this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
400
+ }
401
+ } elseif($pos >= $this->root_struct){
402
+ $this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
403
+ }
404
+ // switch status
405
+ if($pos == $this->root_struct){
406
+ $this->status = 'body';
407
+ $this->root_struct_namespace = $this->message[$pos]['namespace'];
408
+ } elseif($name == 'Body'){
409
+ $this->status = 'envelope';
410
+ } elseif($name == 'Header'){
411
+ $this->status = 'envelope';
412
+ } elseif($name == 'Envelope'){
413
+ //
414
+ }
415
+ // set parent back to my parent
416
+ $this->parent = $this->message[$pos]['parent'];
417
+ }
418
+
419
+ /**
420
+ * element content handler
421
+ *
422
+ * @param resource $parser XML parser object
423
+ * @param string $data element content
424
+ * @access private
425
+ */
426
+ function character_data($parser, $data){
427
+ $pos = $this->depth_array[$this->depth];
428
+ if ($this->xml_encoding=='UTF-8'){
429
+ // TODO: add an option to disable this for folks who want
430
+ // raw UTF-8 that, e.g., might not map to iso-8859-1
431
+ // TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
432
+ if($this->decode_utf8){
433
+ $data = utf8_decode($data);
434
+ }
435
+ }
436
+ $this->message[$pos]['cdata'] .= $data;
437
+ // for doclit
438
+ if($this->status == 'header'){
439
+ $this->responseHeaders .= $data;
440
+ } else {
441
+ $this->document .= $data;
442
+ }
443
+ }
444
+
445
+ /**
446
+ * get the parsed message (SOAP Body)
447
+ *
448
+ * @return mixed
449
+ * @access public
450
+ * @deprecated use get_soapbody instead
451
+ */
452
+ function get_response(){
453
+ return $this->soapresponse;
454
+ }
455
+
456
+ /**
457
+ * get the parsed SOAP Body (NULL if there was none)
458
+ *
459
+ * @return mixed
460
+ * @access public
461
+ */
462
+ function get_soapbody(){
463
+ return $this->soapresponse;
464
+ }
465
+
466
+ /**
467
+ * get the parsed SOAP Header (NULL if there was none)
468
+ *
469
+ * @return mixed
470
+ * @access public
471
+ */
472
+ function get_soapheader(){
473
+ return $this->soapheader;
474
+ }
475
+
476
+ /**
477
+ * get the unparsed SOAP Header
478
+ *
479
+ * @return string XML or empty if no Header
480
+ * @access public
481
+ */
482
+ function getHeaders(){
483
+ return $this->responseHeaders;
484
+ }
485
+
486
+ /**
487
+ * decodes simple types into PHP variables
488
+ *
489
+ * @param string $value value to decode
490
+ * @param string $type XML type to decode
491
+ * @param string $typens XML type namespace to decode
492
+ * @return mixed PHP value
493
+ * @access private
494
+ */
495
+ function decodeSimple($value, $type, $typens) {
496
+ // TODO: use the namespace!
497
+ if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {
498
+ return (string) $value;
499
+ }
500
+ if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {
501
+ return (int) $value;
502
+ }
503
+ if ($type == 'float' || $type == 'double' || $type == 'decimal') {
504
+ return (double) $value;
505
+ }
506
+ if ($type == 'boolean') {
507
+ if (strtolower($value) == 'false' || strtolower($value) == 'f') {
508
+ return false;
509
+ }
510
+ return (boolean) $value;
511
+ }
512
+ if ($type == 'base64' || $type == 'base64Binary') {
513
+ $this->debug('Decode base64 value');
514
+ return base64_decode($value);
515
+ }
516
+ // obscure numeric types
517
+ if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
518
+ || $type == 'nonNegativeInteger' || $type == 'positiveInteger'
519
+ || $type == 'unsignedInt'
520
+ || $type == 'unsignedShort' || $type == 'unsignedByte') {
521
+ return (int) $value;
522
+ }
523
+ // bogus: parser treats array with no elements as a simple type
524
+ if ($type == 'array') {
525
+ return array();
526
+ }
527
+ // everything else
528
+ return (string) $value;
529
+ }
530
+
531
+ /**
532
+ * builds response structures for compound values (arrays/structs)
533
+ * and scalars
534
+ *
535
+ * @param integer $pos position in node tree
536
+ * @return mixed PHP value
537
+ * @access private
538
+ */
539
+ function buildVal($pos){
540
+ if(!isset($this->message[$pos]['type'])){
541
+ $this->message[$pos]['type'] = '';
542
+ }
543
+ $this->debug('in buildVal() for '.$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]['type']);
544
+ // if there are children...
545
+ if($this->message[$pos]['children'] != ''){
546
+ $this->debug('in buildVal, there are children');
547
+ $children = explode('|',$this->message[$pos]['children']);
548
+ array_shift($children); // knock off empty
549
+ // md array
550
+ if(isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != ''){
551
+ $r=0; // rowcount
552
+ $c=0; // colcount
553
+ foreach($children as $child_pos){
554
+ $this->debug("in buildVal, got an MD array element: $r, $c");
555
+ $params[$r][] = $this->message[$child_pos]['result'];
556
+ $c++;
557
+ if($c == $this->message[$pos]['arrayCols']){
558
+ $c = 0;
559
+ $r++;
560
+ }
561
+ }
562
+ // array
563
+ } elseif($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array'){
564
+ $this->debug('in buildVal, adding array '.$this->message[$pos]['name']);
565
+ foreach($children as $child_pos){
566
+ $params[] = &$this->message[$child_pos]['result'];
567
+ }
568
+ // apache Map type: java hashtable
569
+ } elseif($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap'){
570
+ $this->debug('in buildVal, Java Map '.$this->message[$pos]['name']);
571
+ foreach($children as $child_pos){
572
+ $kv = explode("|",$this->message[$child_pos]['children']);
573
+ $params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];
574
+ }
575
+ // generic compound type
576
+ //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
577
+ } else {
578
+ // Apache Vector type: treat as an array
579
+ $this->debug('in buildVal, adding Java Vector or generic compound type '.$this->message[$pos]['name']);
580
+ if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
581
+ $notstruct = 1;
582
+ } else {
583
+ $notstruct = 0;
584
+ }
585
+ //
586
+ foreach($children as $child_pos){
587
+ if($notstruct){
588
+ $params[] = &$this->message[$child_pos]['result'];
589
+ } else {
590
+ if (isset($params[$this->message[$child_pos]['name']])) {
591
+ // de-serialize repeated element name into an array
592
+ if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) {
593
+ $params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]);
594
+ }
595
+ $params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result'];
596
+ } else {
597
+ $params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];
598
+ }
599
+ }
600
+ }
601
+ }
602
+ if (isset($this->message[$pos]['xattrs'])) {
603
+ $this->debug('in buildVal, handling attributes');
604
+ foreach ($this->message[$pos]['xattrs'] as $n => $v) {
605
+ $params[$n] = $v;
606
+ }
607
+ }
608
+ // handle simpleContent
609
+ if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
610
+ $this->debug('in buildVal, handling simpleContent');
611
+ if (isset($this->message[$pos]['type'])) {
612
+ $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
613
+ } else {
614
+ $parent = $this->message[$pos]['parent'];
615
+ if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
616
+ $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
617
+ } else {
618
+ $params['!'] = $this->message[$pos]['cdata'];
619
+ }
620
+ }
621
+ }
622
+ $ret = is_array($params) ? $params : array();
623
+ $this->debug('in buildVal, return:');
624
+ $this->appendDebug($this->varDump($ret));
625
+ return $ret;
626
+ } else {
627
+ $this->debug('in buildVal, no children, building scalar');
628
+ $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : '';
629
+ if (isset($this->message[$pos]['type'])) {
630
+ $ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
631
+ $this->debug("in buildVal, return: $ret");
632
+ return $ret;
633
+ }
634
+ $parent = $this->message[$pos]['parent'];
635
+ if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
636
+ $ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
637
+ $this->debug("in buildVal, return: $ret");
638
+ return $ret;
639
+ }
640
+ $ret = $this->message[$pos]['cdata'];
641
+ $this->debug("in buildVal, return: $ret");
642
+ return $ret;
643
+ }
644
+ }
645
+ }
646
+
647
+ /**
648
+ * Backward compatibility
649
+ */
650
+ class soap_parser extends nusoap_parser {
651
+ }
652
+
653
+
654
+ ?>
lib/nusoap/soap_server.php ADDED
@@ -0,0 +1,1088 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
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 suporte.developer@buscape-inc.com so we can send you a copy immediately.
14
+ *
15
+ * @category Buscape
16
+ * @package Buscape_Fcontrol
17
+ * @copyright Copyright (c) 2010 Buscapé Company (http://www.buscapecompany.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ /**
22
+ *
23
+ * nusoap_server allows the user to create a SOAP server
24
+ * that is capable of receiving messages and returning responses
25
+ *
26
+ * @author Dietrich Ayala <dietrich@ganx4.com>
27
+ * @author Scott Nichol <snichol@users.sourceforge.net>
28
+ * @version $Id: class.soap_server.php,v 1.58 2007/10/30 18:50:30 snichol Exp $
29
+ * @access public
30
+ */
31
+ class nusoap_server extends nusoap_base {
32
+ /**
33
+ * HTTP headers of request
34
+ * @var array
35
+ * @access private
36
+ */
37
+ var $headers = array();
38
+ /**
39
+ * HTTP request
40
+ * @var string
41
+ * @access private
42
+ */
43
+ var $request = '';
44
+ /**
45
+ * SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text)
46
+ * @var string
47
+ * @access public
48
+ */
49
+ var $requestHeaders = '';
50
+ /**
51
+ * SOAP Headers from request (parsed)
52
+ * @var mixed
53
+ * @access public
54
+ */
55
+ var $requestHeader = NULL;
56
+ /**
57
+ * SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text)
58
+ * @var string
59
+ * @access public
60
+ */
61
+ var $document = '';
62
+ /**
63
+ * SOAP payload for request (text)
64
+ * @var string
65
+ * @access public
66
+ */
67
+ var $requestSOAP = '';
68
+ /**
69
+ * requested method namespace URI
70
+ * @var string
71
+ * @access private
72
+ */
73
+ var $methodURI = '';
74
+ /**
75
+ * name of method requested
76
+ * @var string
77
+ * @access private
78
+ */
79
+ var $methodname = '';
80
+ /**
81
+ * method parameters from request
82
+ * @var array
83
+ * @access private
84
+ */
85
+ var $methodparams = array();
86
+ /**
87
+ * SOAP Action from request
88
+ * @var string
89
+ * @access private
90
+ */
91
+ var $SOAPAction = '';
92
+ /**
93
+ * character set encoding of incoming (request) messages
94
+ * @var string
95
+ * @access public
96
+ */
97
+ var $xml_encoding = '';
98
+ /**
99
+ * toggles whether the parser decodes element content w/ utf8_decode()
100
+ * @var boolean
101
+ * @access public
102
+ */
103
+ var $decode_utf8 = true;
104
+
105
+ /**
106
+ * HTTP headers of response
107
+ * @var array
108
+ * @access public
109
+ */
110
+ var $outgoing_headers = array();
111
+ /**
112
+ * HTTP response
113
+ * @var string
114
+ * @access private
115
+ */
116
+ var $response = '';
117
+ /**
118
+ * SOAP headers for response (text or array of soapval or associative array)
119
+ * @var mixed
120
+ * @access public
121
+ */
122
+ var $responseHeaders = '';
123
+ /**
124
+ * SOAP payload for response (text)
125
+ * @var string
126
+ * @access private
127
+ */
128
+ var $responseSOAP = '';
129
+ /**
130
+ * method return value to place in response
131
+ * @var mixed
132
+ * @access private
133
+ */
134
+ var $methodreturn = false;
135
+ /**
136
+ * whether $methodreturn is a string of literal XML
137
+ * @var boolean
138
+ * @access public
139
+ */
140
+ var $methodreturnisliteralxml = false;
141
+ /**
142
+ * SOAP fault for response (or false)
143
+ * @var mixed
144
+ * @access private
145
+ */
146
+ var $fault = false;
147
+ /**
148
+ * text indication of result (for debugging)
149
+ * @var string
150
+ * @access private
151
+ */
152
+ var $result = 'successful';
153
+
154
+ /**
155
+ * assoc array of operations => opData; operations are added by the register()
156
+ * method or by parsing an external WSDL definition
157
+ * @var array
158
+ * @access private
159
+ */
160
+ var $operations = array();
161
+ /**
162
+ * wsdl instance (if one)
163
+ * @var mixed
164
+ * @access private
165
+ */
166
+ var $wsdl = false;
167
+ /**
168
+ * URL for WSDL (if one)
169
+ * @var mixed
170
+ * @access private
171
+ */
172
+ var $externalWSDLURL = false;
173
+ /**
174
+ * whether to append debug to response as XML comment
175
+ * @var boolean
176
+ * @access public
177
+ */
178
+ var $debug_flag = false;
179
+
180
+
181
+ /**
182
+ * constructor
183
+ * the optional parameter is a path to a WSDL file that you'd like to bind the server instance to.
184
+ *
185
+ * @param mixed $wsdl file path or URL (string), or wsdl instance (object)
186
+ * @access public
187
+ */
188
+ function nusoap_server($wsdl=false){
189
+ parent::nusoap_base();
190
+ // turn on debugging?
191
+ global $debug;
192
+ global $HTTP_SERVER_VARS;
193
+
194
+ if (isset($_SERVER)) {
195
+ $this->debug("_SERVER is defined:");
196
+ $this->appendDebug($this->varDump($_SERVER));
197
+ } elseif (isset($HTTP_SERVER_VARS)) {
198
+ $this->debug("HTTP_SERVER_VARS is defined:");
199
+ $this->appendDebug($this->varDump($HTTP_SERVER_VARS));
200
+ } else {
201
+ $this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
202
+ }
203
+
204
+ if (isset($debug)) {
205
+ $this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
206
+ $this->debug_flag = $debug;
207
+ } elseif (isset($_SERVER['QUERY_STRING'])) {
208
+ $qs = explode('&', $_SERVER['QUERY_STRING']);
209
+ foreach ($qs as $v) {
210
+ if (substr($v, 0, 6) == 'debug=') {
211
+ $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
212
+ $this->debug_flag = substr($v, 6);
213
+ }
214
+ }
215
+ } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
216
+ $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
217
+ foreach ($qs as $v) {
218
+ if (substr($v, 0, 6) == 'debug=') {
219
+ $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
220
+ $this->debug_flag = substr($v, 6);
221
+ }
222
+ }
223
+ }
224
+
225
+ // wsdl
226
+ if($wsdl){
227
+ $this->debug("In nusoap_server, WSDL is specified");
228
+ if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
229
+ $this->wsdl = $wsdl;
230
+ $this->externalWSDLURL = $this->wsdl->wsdl;
231
+ $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
232
+ } else {
233
+ $this->debug('Create wsdl from ' . $wsdl);
234
+ $this->wsdl = new wsdl($wsdl);
235
+ $this->externalWSDLURL = $wsdl;
236
+ }
237
+ $this->appendDebug($this->wsdl->getDebug());
238
+ $this->wsdl->clearDebug();
239
+ if($err = $this->wsdl->getError()){
240
+ die('WSDL ERROR: '.$err);
241
+ }
242
+ }
243
+ }
244
+
245
+ /**
246
+ * processes request and returns response
247
+ *
248
+ * @param string $data usually is the value of $HTTP_RAW_POST_DATA
249
+ * @access public
250
+ */
251
+ function service($data){
252
+ global $HTTP_SERVER_VARS;
253
+
254
+ if (isset($_SERVER['QUERY_STRING'])) {
255
+ $qs = $_SERVER['QUERY_STRING'];
256
+ } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
257
+ $qs = $HTTP_SERVER_VARS['QUERY_STRING'];
258
+ } else {
259
+ $qs = '';
260
+ }
261
+ $this->debug("In service, query string=$qs");
262
+
263
+ if (ereg('wsdl', $qs) ){
264
+ $this->debug("In service, this is a request for WSDL");
265
+ if($this->externalWSDLURL){
266
+ if (strpos($this->externalWSDLURL,"://")!==false) { // assume URL
267
+ header('Location: '.$this->externalWSDLURL);
268
+ } else { // assume file
269
+ header("Content-Type: text/xml\r\n");
270
+ $fp = fopen($this->externalWSDLURL, 'r');
271
+ fpassthru($fp);
272
+ }
273
+ } elseif ($this->wsdl) {
274
+ header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
275
+ print $this->wsdl->serialize($this->debug_flag);
276
+ if ($this->debug_flag) {
277
+ $this->debug('wsdl:');
278
+ $this->appendDebug($this->varDump($this->wsdl));
279
+ print $this->getDebugAsXMLComment();
280
+ }
281
+ } else {
282
+ header("Content-Type: text/html; charset=ISO-8859-1\r\n");
283
+ print "This service does not provide WSDL";
284
+ }
285
+ } elseif ($data == '' && $this->wsdl) {
286
+ $this->debug("In service, there is no data, so return Web description");
287
+ print $this->wsdl->webDescription();
288
+ } else {
289
+ $this->debug("In service, invoke the request");
290
+ $this->parse_request($data);
291
+ if (! $this->fault) {
292
+ $this->invoke_method();
293
+ }
294
+ if (! $this->fault) {
295
+ $this->serialize_return();
296
+ }
297
+ $this->send_response();
298
+ }
299
+ }
300
+
301
+ /**
302
+ * parses HTTP request headers.
303
+ *
304
+ * The following fields are set by this function (when successful)
305
+ *
306
+ * headers
307
+ * request
308
+ * xml_encoding
309
+ * SOAPAction
310
+ *
311
+ * @access private
312
+ */
313
+ function parse_http_headers() {
314
+ global $HTTP_SERVER_VARS;
315
+
316
+ $this->request = '';
317
+ $this->SOAPAction = '';
318
+ if(function_exists('getallheaders')){
319
+ $this->debug("In parse_http_headers, use getallheaders");
320
+ $headers = getallheaders();
321
+ foreach($headers as $k=>$v){
322
+ $k = strtolower($k);
323
+ $this->headers[$k] = $v;
324
+ $this->request .= "$k: $v\r\n";
325
+ $this->debug("$k: $v");
326
+ }
327
+ // get SOAPAction header
328
+ if(isset($this->headers['soapaction'])){
329
+ $this->SOAPAction = str_replace('"','',$this->headers['soapaction']);
330
+ }
331
+ // get the character encoding of the incoming request
332
+ if(isset($this->headers['content-type']) && strpos($this->headers['content-type'],'=')){
333
+ $enc = str_replace('"','',substr(strstr($this->headers["content-type"],'='),1));
334
+ if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){
335
+ $this->xml_encoding = strtoupper($enc);
336
+ } else {
337
+ $this->xml_encoding = 'US-ASCII';
338
+ }
339
+ } else {
340
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
341
+ $this->xml_encoding = 'ISO-8859-1';
342
+ }
343
+ } elseif(isset($_SERVER) && is_array($_SERVER)){
344
+ $this->debug("In parse_http_headers, use _SERVER");
345
+ foreach ($_SERVER as $k => $v) {
346
+ if (substr($k, 0, 5) == 'HTTP_') {
347
+ $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
348
+ } else {
349
+ $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
350
+ }
351
+ if ($k == 'soapaction') {
352
+ // get SOAPAction header
353
+ $k = 'SOAPAction';
354
+ $v = str_replace('"', '', $v);
355
+ $v = str_replace('\\', '', $v);
356
+ $this->SOAPAction = $v;
357
+ } else if ($k == 'content-type') {
358
+ // get the character encoding of the incoming request
359
+ if (strpos($v, '=')) {
360
+ $enc = substr(strstr($v, '='), 1);
361
+ $enc = str_replace('"', '', $enc);
362
+ $enc = str_replace('\\', '', $enc);
363
+ if (eregi('^(ISO-8859-1|US-ASCII|UTF-8)$', $enc)) {
364
+ $this->xml_encoding = strtoupper($enc);
365
+ } else {
366
+ $this->xml_encoding = 'US-ASCII';
367
+ }
368
+ } else {
369
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
370
+ $this->xml_encoding = 'ISO-8859-1';
371
+ }
372
+ }
373
+ $this->headers[$k] = $v;
374
+ $this->request .= "$k: $v\r\n";
375
+ $this->debug("$k: $v");
376
+ }
377
+ } elseif (is_array($HTTP_SERVER_VARS)) {
378
+ $this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
379
+ foreach ($HTTP_SERVER_VARS as $k => $v) {
380
+ if (substr($k, 0, 5) == 'HTTP_') {
381
+ $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); $k = strtolower(substr($k, 5));
382
+ } else {
383
+ $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); $k = strtolower($k);
384
+ }
385
+ if ($k == 'soapaction') {
386
+ // get SOAPAction header
387
+ $k = 'SOAPAction';
388
+ $v = str_replace('"', '', $v);
389
+ $v = str_replace('\\', '', $v);
390
+ $this->SOAPAction = $v;
391
+ } else if ($k == 'content-type') {
392
+ // get the character encoding of the incoming request
393
+ if (strpos($v, '=')) {
394
+ $enc = substr(strstr($v, '='), 1);
395
+ $enc = str_replace('"', '', $enc);
396
+ $enc = str_replace('\\', '', $enc);
397
+ if (eregi('^(ISO-8859-1|US-ASCII|UTF-8)$', $enc)) {
398
+ $this->xml_encoding = strtoupper($enc);
399
+ } else {
400
+ $this->xml_encoding = 'US-ASCII';
401
+ }
402
+ } else {
403
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
404
+ $this->xml_encoding = 'ISO-8859-1';
405
+ }
406
+ }
407
+ $this->headers[$k] = $v;
408
+ $this->request .= "$k: $v\r\n";
409
+ $this->debug("$k: $v");
410
+ }
411
+ } else {
412
+ $this->debug("In parse_http_headers, HTTP headers not accessible");
413
+ $this->setError("HTTP headers not accessible");
414
+ }
415
+ }
416
+
417
+ /**
418
+ * parses a request
419
+ *
420
+ * The following fields are set by this function (when successful)
421
+ *
422
+ * headers
423
+ * request
424
+ * xml_encoding
425
+ * SOAPAction
426
+ * request
427
+ * requestSOAP
428
+ * methodURI
429
+ * methodname
430
+ * methodparams
431
+ * requestHeaders
432
+ * document
433
+ *
434
+ * This sets the fault field on error
435
+ *
436
+ * @param string $data XML string
437
+ * @access private
438
+ */
439
+ function parse_request($data='') {
440
+ $this->debug('entering parse_request()');
441
+ $this->parse_http_headers();
442
+ $this->debug('got character encoding: '.$this->xml_encoding);
443
+ // uncompress if necessary
444
+ if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
445
+ $this->debug('got content encoding: ' . $this->headers['content-encoding']);
446
+ if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
447
+ // if decoding works, use it. else assume data wasn't gzencoded
448
+ if (function_exists('gzuncompress')) {
449
+ if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
450
+ $data = $degzdata;
451
+ } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
452
+ $data = $degzdata;
453
+ } else {
454
+ $this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
455
+ return;
456
+ }
457
+ } else {
458
+ $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
459
+ return;
460
+ }
461
+ }
462
+ }
463
+ $this->request .= "\r\n".$data;
464
+ $data = $this->parseRequest($this->headers, $data);
465
+ $this->requestSOAP = $data;
466
+ $this->debug('leaving parse_request');
467
+ }
468
+
469
+ /**
470
+ * invokes a PHP function for the requested SOAP method
471
+ *
472
+ * The following fields are set by this function (when successful)
473
+ *
474
+ * methodreturn
475
+ *
476
+ * Note that the PHP function that is called may also set the following
477
+ * fields to affect the response sent to the client
478
+ *
479
+ * responseHeaders
480
+ * outgoing_headers
481
+ *
482
+ * This sets the fault field on error
483
+ *
484
+ * @access private
485
+ */
486
+ function invoke_method() {
487
+ $this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
488
+
489
+ if ($this->wsdl) {
490
+ if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
491
+ $this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
492
+ $this->appendDebug('opData=' . $this->varDump($this->opData));
493
+ } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
494
+ // Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
495
+ $this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
496
+ $this->appendDebug('opData=' . $this->varDump($this->opData));
497
+ $this->methodname = $this->opData['name'];
498
+ } else {
499
+ $this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
500
+ $this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
501
+ return;
502
+ }
503
+ } else {
504
+ $this->debug('in invoke_method, no WSDL to validate method');
505
+ }
506
+
507
+ // if a . is present in $this->methodname, we see if there is a class in scope,
508
+ // which could be referred to. We will also distinguish between two deliminators,
509
+ // to allow methods to be called a the class or an instance
510
+ $class = '';
511
+ $method = '';
512
+ if (strpos($this->methodname, '..') > 0) {
513
+ $delim = '..';
514
+ } else if (strpos($this->methodname, '.') > 0) {
515
+ $delim = '.';
516
+ } else {
517
+ $delim = '';
518
+ }
519
+
520
+ if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1 &&
521
+ class_exists(substr($this->methodname, 0, strpos($this->methodname, $delim)))) {
522
+ // get the class and method name
523
+ $class = substr($this->methodname, 0, strpos($this->methodname, $delim));
524
+ $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
525
+ $this->debug("in invoke_method, class=$class method=$method delim=$delim");
526
+ }
527
+
528
+ // does method exist?
529
+ if ($class == '') {
530
+ if (!function_exists($this->methodname)) {
531
+ $this->debug("in invoke_method, function '$this->methodname' not found!");
532
+ $this->result = 'fault: method not found';
533
+ $this->fault('SOAP-ENV:Client',"method '$this->methodname' not defined in service");
534
+ return;
535
+ }
536
+ } else {
537
+ $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
538
+ if (!in_array($method_to_compare, get_class_methods($class))) {
539
+ $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
540
+ $this->result = 'fault: method not found';
541
+ $this->fault('SOAP-ENV:Client',"method '$this->methodname' not defined in service");
542
+ return;
543
+ }
544
+ }
545
+
546
+ // evaluate message, getting back parameters
547
+ // verify that request parameters match the method's signature
548
+ if(! $this->verify_method($this->methodname,$this->methodparams)){
549
+ // debug
550
+ $this->debug('ERROR: request not verified against method signature');
551
+ $this->result = 'fault: request failed validation against method signature';
552
+ // return fault
553
+ $this->fault('SOAP-ENV:Client',"Operation '$this->methodname' not defined in service.");
554
+ return;
555
+ }
556
+
557
+ // if there are parameters to pass
558
+ $this->debug('in invoke_method, params:');
559
+ $this->appendDebug($this->varDump($this->methodparams));
560
+ $this->debug("in invoke_method, calling '$this->methodname'");
561
+ if (!function_exists('call_user_func_array')) {
562
+ if ($class == '') {
563
+ $this->debug('in invoke_method, calling function using eval()');
564
+ $funcCall = "\$this->methodreturn = $this->methodname(";
565
+ } else {
566
+ if ($delim == '..') {
567
+ $this->debug('in invoke_method, calling class method using eval()');
568
+ $funcCall = "\$this->methodreturn = ".$class."::".$method."(";
569
+ } else {
570
+ $this->debug('in invoke_method, calling instance method using eval()');
571
+ // generate unique instance name
572
+ $instname = "\$inst_".time();
573
+ $funcCall = $instname." = new ".$class."(); ";
574
+ $funcCall .= "\$this->methodreturn = ".$instname."->".$method."(";
575
+ }
576
+ }
577
+ if ($this->methodparams) {
578
+ foreach ($this->methodparams as $param) {
579
+ if (is_array($param) || is_object($param)) {
580
+ $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
581
+ return;
582
+ }
583
+ $funcCall .= "\"$param\",";
584
+ }
585
+ $funcCall = substr($funcCall, 0, -1);
586
+ }
587
+ $funcCall .= ');';
588
+ $this->debug('in invoke_method, function call: '.$funcCall);
589
+ @eval($funcCall);
590
+ } else {
591
+ if ($class == '') {
592
+ $this->debug('in invoke_method, calling function using call_user_func_array()');
593
+ $call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array()
594
+ } elseif ($delim == '..') {
595
+ $this->debug('in invoke_method, calling class method using call_user_func_array()');
596
+ $call_arg = array ($class, $method);
597
+ } else {
598
+ $this->debug('in invoke_method, calling instance method using call_user_func_array()');
599
+ $instance = new $class ();
600
+ $call_arg = array(&$instance, $method);
601
+ }
602
+ if (is_array($this->methodparams)) {
603
+ $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
604
+ } else {
605
+ $this->methodreturn = call_user_func_array($call_arg, array());
606
+ }
607
+ }
608
+ $this->debug('in invoke_method, methodreturn:');
609
+ $this->appendDebug($this->varDump($this->methodreturn));
610
+ $this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn));
611
+ }
612
+
613
+ /**
614
+ * serializes the return value from a PHP function into a full SOAP Envelope
615
+ *
616
+ * The following fields are set by this function (when successful)
617
+ *
618
+ * responseSOAP
619
+ *
620
+ * This sets the fault field on error
621
+ *
622
+ * @access private
623
+ */
624
+ function serialize_return() {
625
+ $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
626
+ // if fault
627
+ if (isset($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) {
628
+ $this->debug('got a fault object from method');
629
+ $this->fault = $this->methodreturn;
630
+ return;
631
+ } elseif ($this->methodreturnisliteralxml) {
632
+ $return_val = $this->methodreturn;
633
+ // returned value(s)
634
+ } else {
635
+ $this->debug('got a(n) '.gettype($this->methodreturn).' from method');
636
+ $this->debug('serializing return value');
637
+ if($this->wsdl){
638
+ if (sizeof($this->opData['output']['parts']) > 1) {
639
+ $this->debug('more than one output part, so use the method return unchanged');
640
+ $opParams = $this->methodreturn;
641
+ } elseif (sizeof($this->opData['output']['parts']) == 1) {
642
+ $this->debug('exactly one output part, so wrap the method return in a simple array');
643
+ // TODO: verify that it is not already wrapped!
644
+ //foreach ($this->opData['output']['parts'] as $name => $type) {
645
+ // $this->debug('wrap in element named ' . $name);
646
+ //}
647
+ $opParams = array($this->methodreturn);
648
+ }
649
+ $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams);
650
+ $this->appendDebug($this->wsdl->getDebug());
651
+ $this->wsdl->clearDebug();
652
+ if($errstr = $this->wsdl->getError()){
653
+ $this->debug('got wsdl error: '.$errstr);
654
+ $this->fault('SOAP-ENV:Server', 'unable to serialize result');
655
+ return;
656
+ }
657
+ } else {
658
+ if (isset($this->methodreturn)) {
659
+ $return_val = $this->serialize_val($this->methodreturn, 'return');
660
+ } else {
661
+ $return_val = '';
662
+ $this->debug('in absence of WSDL, assume void return for backward compatibility');
663
+ }
664
+ }
665
+ }
666
+ $this->debug('return value:');
667
+ $this->appendDebug($this->varDump($return_val));
668
+
669
+ $this->debug('serializing response');
670
+ if ($this->wsdl) {
671
+ $this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
672
+ if ($this->opData['style'] == 'rpc') {
673
+ $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
674
+ if ($this->opData['output']['use'] == 'literal') {
675
+ // 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
676
+ $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
677
+ } else {
678
+ $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
679
+ }
680
+ } else {
681
+ $this->debug('style is not rpc for serialization: assume document');
682
+ $payload = $return_val;
683
+ }
684
+ } else {
685
+ $this->debug('do not have WSDL for serialization: assume rpc/encoded');
686
+ $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
687
+ }
688
+ $this->result = 'successful';
689
+ if($this->wsdl){
690
+ //if($this->debug_flag){
691
+ $this->appendDebug($this->wsdl->getDebug());
692
+ // }
693
+ if (isset($opData['output']['encodingStyle'])) {
694
+ $encodingStyle = $opData['output']['encodingStyle'];
695
+ } else {
696
+ $encodingStyle = '';
697
+ }
698
+ // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
699
+ $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$this->opData['output']['use'],$encodingStyle);
700
+ } else {
701
+ $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders);
702
+ }
703
+ $this->debug("Leaving serialize_return");
704
+ }
705
+
706
+ /**
707
+ * sends an HTTP response
708
+ *
709
+ * The following fields are set by this function (when successful)
710
+ *
711
+ * outgoing_headers
712
+ * response
713
+ *
714
+ * @access private
715
+ */
716
+ function send_response() {
717
+ $this->debug('Enter send_response');
718
+ if ($this->fault) {
719
+ $payload = $this->fault->serialize();
720
+ $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
721
+ $this->outgoing_headers[] = "Status: 500 Internal Server Error";
722
+ } else {
723
+ $payload = $this->responseSOAP;
724
+ // Some combinations of PHP+Web server allow the Status
725
+ // to come through as a header. Since OK is the default
726
+ // just do nothing.
727
+ // $this->outgoing_headers[] = "HTTP/1.0 200 OK";
728
+ // $this->outgoing_headers[] = "Status: 200 OK";
729
+ }
730
+ // add debug data if in debug mode
731
+ if(isset($this->debug_flag) && $this->debug_flag){
732
+ $payload .= $this->getDebugAsXMLComment();
733
+ }
734
+ $this->outgoing_headers[] = "Server: $this->title Server v$this->version";
735
+ ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev);
736
+ $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")";
737
+ // Let the Web server decide about this
738
+ //$this->outgoing_headers[] = "Connection: Close\r\n";
739
+ $payload = $this->getHTTPBody($payload);
740
+ $type = $this->getHTTPContentType();
741
+ $charset = $this->getHTTPContentTypeCharset();
742
+ $this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
743
+ //begin code to compress payload - by John
744
+ // NOTE: there is no way to know whether the Web server will also compress
745
+ // this data.
746
+ if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {
747
+ if (strstr($this->headers['accept-encoding'], 'gzip')) {
748
+ if (function_exists('gzencode')) {
749
+ if (isset($this->debug_flag) && $this->debug_flag) {
750
+ $payload .= "<!-- Content being gzipped -->";
751
+ }
752
+ $this->outgoing_headers[] = "Content-Encoding: gzip";
753
+ $payload = gzencode($payload);
754
+ } else {
755
+ if (isset($this->debug_flag) && $this->debug_flag) {
756
+ $payload .= "<!-- Content will not be gzipped: no gzencode -->";
757
+ }
758
+ }
759
+ } elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
760
+ // Note: MSIE requires gzdeflate output (no Zlib header and checksum),
761
+ // instead of gzcompress output,
762
+ // which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
763
+ if (function_exists('gzdeflate')) {
764
+ if (isset($this->debug_flag) && $this->debug_flag) {
765
+ $payload .= "<!-- Content being deflated -->";
766
+ }
767
+ $this->outgoing_headers[] = "Content-Encoding: deflate";
768
+ $payload = gzdeflate($payload);
769
+ } else {
770
+ if (isset($this->debug_flag) && $this->debug_flag) {
771
+ $payload .= "<!-- Content will not be deflated: no gzcompress -->";
772
+ }
773
+ }
774
+ }
775
+ }
776
+ //end code
777
+ $this->outgoing_headers[] = "Content-Length: ".strlen($payload);
778
+ reset($this->outgoing_headers);
779
+ foreach($this->outgoing_headers as $hdr){
780
+ header($hdr, false);
781
+ }
782
+ print $payload;
783
+ $this->response = join("\r\n",$this->outgoing_headers)."\r\n\r\n".$payload;
784
+ }
785
+
786
+ /**
787
+ * takes the value that was created by parsing the request
788
+ * and compares to the method's signature, if available.
789
+ *
790
+ * @param string $operation The operation to be invoked
791
+ * @param array $request The array of parameter values
792
+ * @return boolean Whether the operation was found
793
+ * @access private
794
+ */
795
+ function verify_method($operation,$request){
796
+ if(isset($this->wsdl) && is_object($this->wsdl)){
797
+ if($this->wsdl->getOperationData($operation)){
798
+ return true;
799
+ }
800
+ } elseif(isset($this->operations[$operation])){
801
+ return true;
802
+ }
803
+ return false;
804
+ }
805
+
806
+ /**
807
+ * processes SOAP message received from client
808
+ *
809
+ * @param array $headers The HTTP headers
810
+ * @param string $data unprocessed request data from client
811
+ * @return mixed value of the message, decoded into a PHP type
812
+ * @access private
813
+ */
814
+ function parseRequest($headers, $data) {
815
+ $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' and type ' . $headers['content-type']);
816
+ if (!strstr($headers['content-type'], 'text/xml')) {
817
+ $this->setError('Request not of type text/xml');
818
+ return false;
819
+ }
820
+ if (strpos($headers['content-type'], '=')) {
821
+ $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
822
+ $this->debug('Got response encoding: ' . $enc);
823
+ if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){
824
+ $this->xml_encoding = strtoupper($enc);
825
+ } else {
826
+ $this->xml_encoding = 'US-ASCII';
827
+ }
828
+ } else {
829
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
830
+ $this->xml_encoding = 'ISO-8859-1';
831
+ }
832
+ $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
833
+ // parse response, get soap parser obj
834
+ $parser = new nusoap_parser($data,$this->xml_encoding,'',$this->decode_utf8);
835
+ // parser debug
836
+ $this->debug("parser debug: \n".$parser->getDebug());
837
+ // if fault occurred during message parsing
838
+ if($err = $parser->getError()){
839
+ $this->result = 'fault: error in msg parsing: '.$err;
840
+ $this->fault('SOAP-ENV:Client',"error in msg parsing:\n".$err);
841
+ // else successfully parsed request into soapval object
842
+ } else {
843
+ // get/set methodname
844
+ $this->methodURI = $parser->root_struct_namespace;
845
+ $this->methodname = $parser->root_struct_name;
846
+ $this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI);
847
+ $this->debug('calling parser->get_soapbody()');
848
+ $this->methodparams = $parser->get_soapbody();
849
+ // get SOAP headers
850
+ $this->requestHeaders = $parser->getHeaders();
851
+ // get SOAP Header
852
+ $this->requestHeader = $parser->get_soapheader();
853
+ // add document for doclit support
854
+ $this->document = $parser->document;
855
+ }
856
+ }
857
+
858
+ /**
859
+ * gets the HTTP body for the current response.
860
+ *
861
+ * @param string $soapmsg The SOAP payload
862
+ * @return string The HTTP body, which includes the SOAP payload
863
+ * @access private
864
+ */
865
+ function getHTTPBody($soapmsg) {
866
+ return $soapmsg;
867
+ }
868
+
869
+ /**
870
+ * gets the HTTP content type for the current response.
871
+ *
872
+ * Note: getHTTPBody must be called before this.
873
+ *
874
+ * @return string the HTTP content type for the current response.
875
+ * @access private
876
+ */
877
+ function getHTTPContentType() {
878
+ return 'text/xml';
879
+ }
880
+
881
+ /**
882
+ * gets the HTTP content type charset for the current response.
883
+ * returns false for non-text content types.
884
+ *
885
+ * Note: getHTTPBody must be called before this.
886
+ *
887
+ * @return string the HTTP content type charset for the current response.
888
+ * @access private
889
+ */
890
+ function getHTTPContentTypeCharset() {
891
+ return $this->soap_defencoding;
892
+ }
893
+
894
+ /**
895
+ * add a method to the dispatch map (this has been replaced by the register method)
896
+ *
897
+ * @param string $methodname
898
+ * @param string $in array of input values
899
+ * @param string $out array of output values
900
+ * @access public
901
+ * @deprecated
902
+ */
903
+ function add_to_map($methodname,$in,$out){
904
+ $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
905
+ }
906
+
907
+ /**
908
+ * register a service function with the server
909
+ *
910
+ * @param string $name the name of the PHP function, class.method or class..method
911
+ * @param array $in assoc array of input values: key = param name, value = param type
912
+ * @param array $out assoc array of output values: key = param name, value = param type
913
+ * @param mixed $namespace the element namespace for the method or false
914
+ * @param mixed $soapaction the soapaction for the method or false
915
+ * @param mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically
916
+ * @param mixed $use optional (encoded|literal) or false
917
+ * @param string $documentation optional Description to include in WSDL
918
+ * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
919
+ * @access public
920
+ */
921
+ function register($name,$in=array(),$out=array(),$namespace=false,$soapaction=false,$style=false,$use=false,$documentation='',$encodingStyle=''){
922
+ global $HTTP_SERVER_VARS;
923
+
924
+ if($this->externalWSDLURL){
925
+ die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
926
+ }
927
+ if (! $name) {
928
+ die('You must specify a name when you register an operation');
929
+ }
930
+ if (!is_array($in)) {
931
+ die('You must provide an array for operation inputs');
932
+ }
933
+ if (!is_array($out)) {
934
+ die('You must provide an array for operation outputs');
935
+ }
936
+ if(false == $namespace) {
937
+ }
938
+ if(false == $soapaction) {
939
+ if (isset($_SERVER)) {
940
+ $SERVER_NAME = $_SERVER['SERVER_NAME'];
941
+ $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
942
+ $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
943
+ } elseif (isset($HTTP_SERVER_VARS)) {
944
+ $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
945
+ $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
946
+ $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
947
+ } else {
948
+ $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
949
+ }
950
+ if ($HTTPS == '1' || $HTTPS == 'on') {
951
+ $SCHEME = 'https';
952
+ } else {
953
+ $SCHEME = 'http';
954
+ }
955
+ $soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
956
+ }
957
+ if(false == $style) {
958
+ $style = "rpc";
959
+ }
960
+ if(false == $use) {
961
+ $use = "encoded";
962
+ }
963
+ if ($use == 'encoded' && $encodingStyle = '') {
964
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
965
+ }
966
+
967
+ $this->operations[$name] = array(
968
+ 'name' => $name,
969
+ 'in' => $in,
970
+ 'out' => $out,
971
+ 'namespace' => $namespace,
972
+ 'soapaction' => $soapaction,
973
+ 'style' => $style);
974
+ if($this->wsdl){
975
+ $this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use,$documentation,$encodingStyle);
976
+ }
977
+ return true;
978
+ }
979
+
980
+ /**
981
+ * Specify a fault to be returned to the client.
982
+ * This also acts as a flag to the server that a fault has occured.
983
+ *
984
+ * @param string $faultcode
985
+ * @param string $faultstring
986
+ * @param string $faultactor
987
+ * @param string $faultdetail
988
+ * @access public
989
+ */
990
+ function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){
991
+ if ($faultdetail == '' && $this->debug_flag) {
992
+ $faultdetail = $this->getDebug();
993
+ }
994
+ $this->fault = new nusoap_fault($faultcode,$faultactor,$faultstring,$faultdetail);
995
+ $this->fault->soap_defencoding = $this->soap_defencoding;
996
+ }
997
+
998
+ /**
999
+ * Sets up wsdl object.
1000
+ * Acts as a flag to enable internal WSDL generation
1001
+ *
1002
+ * @param string $serviceName, name of the service
1003
+ * @param mixed $namespace optional 'tns' service namespace or false
1004
+ * @param mixed $endpoint optional URL of service endpoint or false
1005
+ * @param string $style optional (rpc|document) WSDL style (also specified by operation)
1006
+ * @param string $transport optional SOAP transport
1007
+ * @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false
1008
+ */
1009
+ function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
1010
+ {
1011
+ global $HTTP_SERVER_VARS;
1012
+
1013
+ if (isset($_SERVER)) {
1014
+ $SERVER_NAME = $_SERVER['SERVER_NAME'];
1015
+ $SERVER_PORT = $_SERVER['SERVER_PORT'];
1016
+ $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
1017
+ $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
1018
+ } elseif (isset($HTTP_SERVER_VARS)) {
1019
+ $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
1020
+ $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
1021
+ $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
1022
+ $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
1023
+ } else {
1024
+ $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
1025
+ }
1026
+ // If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)
1027
+ $colon = strpos($SERVER_NAME,":");
1028
+ if ($colon) {
1029
+ $SERVER_NAME = substr($SERVER_NAME, 0, $colon);
1030
+ }
1031
+ if ($SERVER_PORT == 80) {
1032
+ $SERVER_PORT = '';
1033
+ } else {
1034
+ $SERVER_PORT = ':' . $SERVER_PORT;
1035
+ }
1036
+ if(false == $namespace) {
1037
+ $namespace = "http://$SERVER_NAME/soap/$serviceName";
1038
+ }
1039
+
1040
+ if(false == $endpoint) {
1041
+ if ($HTTPS == '1' || $HTTPS == 'on') {
1042
+ $SCHEME = 'https';
1043
+ } else {
1044
+ $SCHEME = 'http';
1045
+ }
1046
+ $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
1047
+ }
1048
+
1049
+ if(false == $schemaTargetNamespace) {
1050
+ $schemaTargetNamespace = $namespace;
1051
+ }
1052
+
1053
+ $this->wsdl = new wsdl;
1054
+ $this->wsdl->serviceName = $serviceName;
1055
+ $this->wsdl->endpoint = $endpoint;
1056
+ $this->wsdl->namespaces['tns'] = $namespace;
1057
+ $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
1058
+ $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
1059
+ if ($schemaTargetNamespace != $namespace) {
1060
+ $this->wsdl->namespaces['types'] = $schemaTargetNamespace;
1061
+ }
1062
+ $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces);
1063
+ if ($style == 'document') {
1064
+ $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified';
1065
+ }
1066
+ $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
1067
+ $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
1068
+ $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
1069
+ $this->wsdl->bindings[$serviceName.'Binding'] = array(
1070
+ 'name'=>$serviceName.'Binding',
1071
+ 'style'=>$style,
1072
+ 'transport'=>$transport,
1073
+ 'portType'=>$serviceName.'PortType');
1074
+ $this->wsdl->ports[$serviceName.'Port'] = array(
1075
+ 'binding'=>$serviceName.'Binding',
1076
+ 'location'=>$endpoint,
1077
+ 'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/');
1078
+ }
1079
+ }
1080
+
1081
+ /**
1082
+ * Backward compatibility
1083
+ */
1084
+ class soap_server extends nusoap_server {
1085
+ }
1086
+
1087
+
1088
+ ?>
lib/nusoap/soap_transport_http.php ADDED
@@ -0,0 +1,1320 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
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 suporte.developer@buscape-inc.com so we can send you a copy immediately.
14
+ *
15
+ * @category Buscape
16
+ * @package Buscape_Fcontrol
17
+ * @copyright Copyright (c) 2010 Buscapé Company (http://www.buscapecompany.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ /**
22
+ * transport class for sending/receiving data via HTTP and HTTPS
23
+ * NOTE: PHP must be compiled with the CURL extension for HTTPS support
24
+ *
25
+ * @author Dietrich Ayala <dietrich@ganx4.com>
26
+ * @author Scott Nichol <snichol@users.sourceforge.net>
27
+ * @version $Id: class.soap_transport_http.php,v 1.66 2007/11/06 14:17:53 snichol Exp $
28
+ * @access public
29
+ */
30
+ class soap_transport_http extends nusoap_base {
31
+
32
+ var $url = '';
33
+ var $uri = '';
34
+ var $digest_uri = '';
35
+ var $scheme = '';
36
+ var $host = '';
37
+ var $port = '';
38
+ var $path = '';
39
+ var $request_method = 'POST';
40
+ var $protocol_version = '1.0';
41
+ var $encoding = '';
42
+ var $outgoing_headers = array();
43
+ var $incoming_headers = array();
44
+ var $incoming_cookies = array();
45
+ var $outgoing_payload = '';
46
+ var $incoming_payload = '';
47
+ var $response_status_line; // HTTP response status line
48
+ var $useSOAPAction = true;
49
+ var $persistentConnection = false;
50
+ var $ch = false; // cURL handle
51
+ var $ch_options = array(); // cURL custom options
52
+ var $use_curl = false; // force cURL use
53
+ var $proxy = null; // proxy information (associative array)
54
+ var $username = '';
55
+ var $password = '';
56
+ var $authtype = '';
57
+ var $digestRequest = array();
58
+ var $certRequest = array(); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional)
59
+ // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'
60
+ // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
61
+ // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'
62
+ // passphrase: SSL key password/passphrase
63
+ // certpassword: SSL certificate password
64
+ // verifypeer: default is 1
65
+ // verifyhost: default is 1
66
+
67
+ /**
68
+ * constructor
69
+ *
70
+ * @param string $url The URL to which to connect
71
+ * @param array $curl_options User-specified cURL options
72
+ * @param boolean $use_curl Whether to try to force cURL use
73
+ * @access public
74
+ */
75
+ function soap_transport_http($url, $curl_options = NULL, $use_curl = false){
76
+ parent::nusoap_base();
77
+ $this->debug("ctor url=$url use_curl=$use_curl curl_options:");
78
+ $this->appendDebug($this->varDump($curl_options));
79
+ $this->setURL($url);
80
+ if (is_array($curl_options)) {
81
+ $this->ch_options = $curl_options;
82
+ }
83
+ $this->use_curl = $use_curl;
84
+ ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev);
85
+ $this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')');
86
+ }
87
+
88
+ /**
89
+ * sets a cURL option
90
+ *
91
+ * @param mixed $option The cURL option (always integer?)
92
+ * @param mixed $value The cURL option value
93
+ * @access private
94
+ */
95
+ function setCurlOption($option, $value) {
96
+ $this->debug("setCurlOption option=$option, value=");
97
+ $this->appendDebug($this->varDump($value));
98
+ curl_setopt($this->ch, $option, $value);
99
+ }
100
+
101
+ /**
102
+ * sets an HTTP header
103
+ *
104
+ * @param string $name The name of the header
105
+ * @param string $value The value of the header
106
+ * @access private
107
+ */
108
+ function setHeader($name, $value) {
109
+ $this->outgoing_headers[$name] = $value;
110
+ $this->debug("set header $name: $value");
111
+ }
112
+
113
+ /**
114
+ * unsets an HTTP header
115
+ *
116
+ * @param string $name The name of the header
117
+ * @access private
118
+ */
119
+ function unsetHeader($name) {
120
+ if (isset($this->outgoing_headers[$name])) {
121
+ $this->debug("unset header $name");
122
+ unset($this->outgoing_headers[$name]);
123
+ }
124
+ }
125
+
126
+ /**
127
+ * sets the URL to which to connect
128
+ *
129
+ * @param string $url The URL to which to connect
130
+ * @access private
131
+ */
132
+ function setURL($url) {
133
+ $this->url = $url;
134
+
135
+ $u = parse_url($url);
136
+ foreach($u as $k => $v){
137
+ $this->debug("parsed URL $k = $v");
138
+ $this->$k = $v;
139
+ }
140
+
141
+ // add any GET params to path
142
+ if(isset($u['query']) && $u['query'] != ''){
143
+ $this->path .= '?' . $u['query'];
144
+ }
145
+
146
+ // set default port
147
+ if(!isset($u['port'])){
148
+ if($u['scheme'] == 'https'){
149
+ $this->port = 443;
150
+ } else {
151
+ $this->port = 80;
152
+ }
153
+ }
154
+
155
+ $this->uri = $this->path;
156
+ $this->digest_uri = $this->uri;
157
+
158
+ // build headers
159
+ if (!isset($u['port'])) {
160
+ $this->setHeader('Host', $this->host);
161
+ } else {
162
+ $this->setHeader('Host', $this->host.':'.$this->port);
163
+ }
164
+
165
+ if (isset($u['user']) && $u['user'] != '') {
166
+ $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : '');
167
+ }
168
+ }
169
+
170
+ /**
171
+ * gets the I/O method to use
172
+ *
173
+ * @return string I/O method to use (socket|curl|unknown)
174
+ * @access private
175
+ */
176
+ function io_method() {
177
+ if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm'))
178
+ return 'curl';
179
+ if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm'))
180
+ return 'socket';
181
+ return 'unknown';
182
+ }
183
+
184
+ /**
185
+ * establish an HTTP connection
186
+ *
187
+ * @param integer $timeout set connection timeout in seconds
188
+ * @param integer $response_timeout set response timeout in seconds
189
+ * @return boolean true if connected, false if not
190
+ * @access private
191
+ */
192
+ function connect($connection_timeout=0,$response_timeout=30){
193
+ // For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like
194
+ // "regular" socket.
195
+ // TODO: disabled for now because OpenSSL must be *compiled* in (not just
196
+ // loaded), and until PHP5 stream_get_wrappers is not available.
197
+ // if ($this->scheme == 'https') {
198
+ // if (version_compare(phpversion(), '4.3.0') >= 0) {
199
+ // if (extension_loaded('openssl')) {
200
+ // $this->scheme = 'ssl';
201
+ // $this->debug('Using SSL over OpenSSL');
202
+ // }
203
+ // }
204
+ // }
205
+ $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
206
+ if ($this->io_method() == 'socket') {
207
+ if (!is_array($this->proxy)) {
208
+ $host = $this->host;
209
+ $port = $this->port;
210
+ } else {
211
+ $host = $this->proxy['host'];
212
+ $port = $this->proxy['port'];
213
+ }
214
+
215
+ // use persistent connection
216
+ if($this->persistentConnection && isset($this->fp) && is_resource($this->fp)){
217
+ if (!feof($this->fp)) {
218
+ $this->debug('Re-use persistent connection');
219
+ return true;
220
+ }
221
+ fclose($this->fp);
222
+ $this->debug('Closed persistent connection at EOF');
223
+ }
224
+
225
+ // munge host if using OpenSSL
226
+ if ($this->scheme == 'ssl') {
227
+ $host = 'ssl://' . $host;
228
+ }
229
+ $this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);
230
+
231
+ // open socket
232
+ if($connection_timeout > 0){
233
+ $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str, $connection_timeout);
234
+ } else {
235
+ $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str);
236
+ }
237
+
238
+ // test pointer
239
+ if(!$this->fp) {
240
+ $msg = 'Couldn\'t open socket connection to server ' . $this->url;
241
+ if ($this->errno) {
242
+ $msg .= ', Error ('.$this->errno.'): '.$this->error_str;
243
+ } else {
244
+ $msg .= ' prior to connect(). This is often a problem looking up the host name.';
245
+ }
246
+ $this->debug($msg);
247
+ $this->setError($msg);
248
+ return false;
249
+ }
250
+
251
+ // set response timeout
252
+ $this->debug('set response timeout to ' . $response_timeout);
253
+ socket_set_timeout( $this->fp, $response_timeout);
254
+
255
+ $this->debug('socket connected');
256
+ return true;
257
+ } else if ($this->io_method() == 'curl') {
258
+ if (!extension_loaded('curl')) {
259
+ // $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
260
+ $this->setError('The PHP cURL Extension is required for HTTPS or NLTM. You will need to re-build or update your PHP to included cURL.');
261
+ return false;
262
+ }
263
+ // Avoid warnings when PHP does not have these options
264
+ if (defined('CURLOPT_CONNECTIONTIMEOUT'))
265
+ $CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT;
266
+ else
267
+ $CURLOPT_CONNECTIONTIMEOUT = 78;
268
+ if (defined('CURLOPT_HTTPAUTH'))
269
+ $CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH;
270
+ else
271
+ $CURLOPT_HTTPAUTH = 107;
272
+ if (defined('CURLOPT_PROXYAUTH'))
273
+ $CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH;
274
+ else
275
+ $CURLOPT_PROXYAUTH = 111;
276
+ if (defined('CURLAUTH_BASIC'))
277
+ $CURLAUTH_BASIC = CURLAUTH_BASIC;
278
+ else
279
+ $CURLAUTH_BASIC = 1;
280
+ if (defined('CURLAUTH_DIGEST'))
281
+ $CURLAUTH_DIGEST = CURLAUTH_DIGEST;
282
+ else
283
+ $CURLAUTH_DIGEST = 2;
284
+ if (defined('CURLAUTH_NTLM'))
285
+ $CURLAUTH_NTLM = CURLAUTH_NTLM;
286
+ else
287
+ $CURLAUTH_NTLM = 8;
288
+
289
+ $this->debug('connect using cURL');
290
+ // init CURL
291
+ $this->ch = curl_init();
292
+ // set url
293
+ $hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host";
294
+ // add path
295
+ $hostURL .= $this->path;
296
+ $this->setCurlOption(CURLOPT_URL, $hostURL);
297
+ // follow location headers (re-directs)
298
+ if (ini_get('safe_mode') || ini_get('open_basedir')) {
299
+ $this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION');
300
+ $this->debug('safe_mode = ');
301
+ $this->appendDebug($this->varDump(ini_get('safe_mode')));
302
+ $this->debug('open_basedir = ');
303
+ $this->appendDebug($this->varDump(ini_get('open_basedir')));
304
+ } else {
305
+ $this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1);
306
+ }
307
+ // ask for headers in the response output
308
+ $this->setCurlOption(CURLOPT_HEADER, 1);
309
+ // ask for the response output as the return value
310
+ $this->setCurlOption(CURLOPT_RETURNTRANSFER, 1);
311
+ // encode
312
+ // We manage this ourselves through headers and encoding
313
+ // if(function_exists('gzuncompress')){
314
+ // $this->setCurlOption(CURLOPT_ENCODING, 'deflate');
315
+ // }
316
+ // persistent connection
317
+ if ($this->persistentConnection) {
318
+ // I believe the following comment is now bogus, having applied to
319
+ // the code when it used CURLOPT_CUSTOMREQUEST to send the request.
320
+ // The way we send data, we cannot use persistent connections, since
321
+ // there will be some "junk" at the end of our request.
322
+ //$this->setCurlOption(CURL_HTTP_VERSION_1_1, true);
323
+ $this->persistentConnection = false;
324
+ $this->setHeader('Connection', 'close');
325
+ }
326
+ // set timeouts
327
+ if ($connection_timeout != 0) {
328
+ $this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);
329
+ }
330
+ if ($response_timeout != 0) {
331
+ $this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout);
332
+ }
333
+
334
+ if ($this->scheme == 'https') {
335
+ $this->debug('set cURL SSL verify options');
336
+ // recent versions of cURL turn on peer/host checking by default,
337
+ // while PHP binaries are not compiled with a default location for the
338
+ // CA cert bundle, so disable peer/host checking.
339
+ //$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');
340
+ $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0);
341
+ $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0);
342
+
343
+ // support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)
344
+ if ($this->authtype == 'certificate') {
345
+ $this->debug('set cURL certificate options');
346
+ if (isset($this->certRequest['cainfofile'])) {
347
+ $this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']);
348
+ }
349
+ if (isset($this->certRequest['verifypeer'])) {
350
+ $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);
351
+ } else {
352
+ $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1);
353
+ }
354
+ if (isset($this->certRequest['verifyhost'])) {
355
+ $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);
356
+ } else {
357
+ $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1);
358
+ }
359
+ if (isset($this->certRequest['sslcertfile'])) {
360
+ $this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);
361
+ }
362
+ if (isset($this->certRequest['sslkeyfile'])) {
363
+ $this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);
364
+ }
365
+ if (isset($this->certRequest['passphrase'])) {
366
+ $this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']);
367
+ }
368
+ if (isset($this->certRequest['certpassword'])) {
369
+ $this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']);
370
+ }
371
+ }
372
+ }
373
+ if ($this->authtype && ($this->authtype != 'certificate')) {
374
+ if ($this->username) {
375
+ $this->debug('set cURL username/password');
376
+ $this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password");
377
+ }
378
+ if ($this->authtype == 'basic') {
379
+ $this->debug('set cURL for Basic authentication');
380
+ $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC);
381
+ }
382
+ if ($this->authtype == 'digest') {
383
+ $this->debug('set cURL for digest authentication');
384
+ $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST);
385
+ }
386
+ if ($this->authtype == 'ntlm') {
387
+ $this->debug('set cURL for NTLM authentication');
388
+ $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM);
389
+ }
390
+ }
391
+ if (is_array($this->proxy)) {
392
+ $this->debug('set cURL proxy options');
393
+ if ($this->proxy['port'] != '') {
394
+ $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'].':'.$this->proxy['port']);
395
+ } else {
396
+ $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']);
397
+ }
398
+ if ($this->proxy['username'] || $this->proxy['password']) {
399
+ $this->debug('set cURL proxy authentication options');
400
+ $this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'].':'.$this->proxy['password']);
401
+ if ($this->proxy['authtype'] == 'basic') {
402
+ $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC);
403
+ }
404
+ if ($this->proxy['authtype'] == 'ntlm') {
405
+ $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM);
406
+ }
407
+ }
408
+ }
409
+ $this->debug('cURL connection set up');
410
+ return true;
411
+ } else {
412
+ $this->setError('Unknown scheme ' . $this->scheme);
413
+ $this->debug('Unknown scheme ' . $this->scheme);
414
+ return false;
415
+ }
416
+ }
417
+
418
+ /**
419
+ * sends the SOAP request and gets the SOAP response via HTTP[S]
420
+ *
421
+ * @param string $data message data
422
+ * @param integer $timeout set connection timeout in seconds
423
+ * @param integer $response_timeout set response timeout in seconds
424
+ * @param array $cookies cookies to send
425
+ * @return string data
426
+ * @access public
427
+ */
428
+ function send($data, $timeout=0, $response_timeout=30, $cookies=NULL) {
429
+
430
+ $this->debug('entered send() with data of length: '.strlen($data));
431
+
432
+ $this->tryagain = true;
433
+ $tries = 0;
434
+ while ($this->tryagain) {
435
+ $this->tryagain = false;
436
+ if ($tries++ < 2) {
437
+ // make connnection
438
+ if (!$this->connect($timeout, $response_timeout)){
439
+ return false;
440
+ }
441
+
442
+ // send request
443
+ if (!$this->sendRequest($data, $cookies)){
444
+ return false;
445
+ }
446
+
447
+ // get response
448
+ $respdata = $this->getResponse();
449
+ } else {
450
+ $this->setError("Too many tries to get an OK response ($this->response_status_line)");
451
+ }
452
+ }
453
+ $this->debug('end of send()');
454
+ return $respdata;
455
+ }
456
+
457
+
458
+ /**
459
+ * sends the SOAP request and gets the SOAP response via HTTPS using CURL
460
+ *
461
+ * @param string $data message data
462
+ * @param integer $timeout set connection timeout in seconds
463
+ * @param integer $response_timeout set response timeout in seconds
464
+ * @param array $cookies cookies to send
465
+ * @return string data
466
+ * @access public
467
+ * @deprecated
468
+ */
469
+ function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies) {
470
+ return $this->send($data, $timeout, $response_timeout, $cookies);
471
+ }
472
+
473
+ /**
474
+ * if authenticating, set user credentials here
475
+ *
476
+ * @param string $username
477
+ * @param string $password
478
+ * @param string $authtype (basic|digest|certificate|ntlm)
479
+ * @param array $digestRequest (keys must be nonce, nc, realm, qop)
480
+ * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
481
+ * @access public
482
+ */
483
+ function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array()) {
484
+ $this->debug("setCredentials username=$username authtype=$authtype digestRequest=");
485
+ $this->appendDebug($this->varDump($digestRequest));
486
+ $this->debug("certRequest=");
487
+ $this->appendDebug($this->varDump($certRequest));
488
+ // cf. RFC 2617
489
+ if ($authtype == 'basic') {
490
+ $this->setHeader('Authorization', 'Basic '.base64_encode(str_replace(':','',$username).':'.$password));
491
+ } elseif ($authtype == 'digest') {
492
+ if (isset($digestRequest['nonce'])) {
493
+ $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
494
+
495
+ // calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)
496
+
497
+ // A1 = unq(username-value) ":" unq(realm-value) ":" passwd
498
+ $A1 = $username. ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password;
499
+
500
+ // H(A1) = MD5(A1)
501
+ $HA1 = md5($A1);
502
+
503
+ // A2 = Method ":" digest-uri-value
504
+ $A2 = $this->request_method . ':' . $this->digest_uri;
505
+
506
+ // H(A2)
507
+ $HA2 = md5($A2);
508
+
509
+ // KD(secret, data) = H(concat(secret, ":", data))
510
+ // if qop == auth:
511
+ // request-digest = <"> < KD ( H(A1), unq(nonce-value)
512
+ // ":" nc-value
513
+ // ":" unq(cnonce-value)
514
+ // ":" unq(qop-value)
515
+ // ":" H(A2)
516
+ // ) <">
517
+ // if qop is missing,
518
+ // request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
519
+
520
+ $unhashedDigest = '';
521
+ $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';
522
+ $cnonce = $nonce;
523
+ if ($digestRequest['qop'] != '') {
524
+ $unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
525
+ } else {
526
+ $unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
527
+ }
528
+
529
+ $hashedDigest = md5($unhashedDigest);
530
+
531
+ $opaque = '';
532
+ if (isset($digestRequest['opaque'])) {
533
+ $opaque = ', opaque="' . $digestRequest['opaque'] . '"';
534
+ }
535
+
536
+ $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 . '"');
537
+ }
538
+ } elseif ($authtype == 'certificate') {
539
+ $this->certRequest = $certRequest;
540
+ $this->debug('Authorization header not set for certificate');
541
+ } elseif ($authtype == 'ntlm') {
542
+ // do nothing
543
+ $this->debug('Authorization header not set for ntlm');
544
+ }
545
+ $this->username = $username;
546
+ $this->password = $password;
547
+ $this->authtype = $authtype;
548
+ $this->digestRequest = $digestRequest;
549
+ }
550
+
551
+ /**
552
+ * set the soapaction value
553
+ *
554
+ * @param string $soapaction
555
+ * @access public
556
+ */
557
+ function setSOAPAction($soapaction) {
558
+ $this->setHeader('SOAPAction', '"' . $soapaction . '"');
559
+ }
560
+
561
+ /**
562
+ * use http encoding
563
+ *
564
+ * @param string $enc encoding style. supported values: gzip, deflate, or both
565
+ * @access public
566
+ */
567
+ function setEncoding($enc='gzip, deflate') {
568
+ if (function_exists('gzdeflate')) {
569
+ $this->protocol_version = '1.1';
570
+ $this->setHeader('Accept-Encoding', $enc);
571
+ if (!isset($this->outgoing_headers['Connection'])) {
572
+ $this->setHeader('Connection', 'close');
573
+ $this->persistentConnection = false;
574
+ }
575
+ set_magic_quotes_runtime(0);
576
+ // deprecated
577
+ $this->encoding = $enc;
578
+ }
579
+ }
580
+
581
+ /**
582
+ * set proxy info here
583
+ *
584
+ * @param string $proxyhost use an empty string to remove proxy
585
+ * @param string $proxyport
586
+ * @param string $proxyusername
587
+ * @param string $proxypassword
588
+ * @param string $proxyauthtype (basic|ntlm)
589
+ * @access public
590
+ */
591
+ function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic') {
592
+ if ($proxyhost) {
593
+ $this->proxy = array(
594
+ 'host' => $proxyhost,
595
+ 'port' => $proxyport,
596
+ 'username' => $proxyusername,
597
+ 'password' => $proxypassword,
598
+ 'authtype' => $proxyauthtype
599
+ );
600
+ if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') {
601
+ $this->setHeader('Proxy-Authorization', ' Basic '.base64_encode($proxyusername.':'.$proxypassword));
602
+ }
603
+ } else {
604
+ $this->debug('remove proxy');
605
+ $proxy = null;
606
+ unsetHeader('Proxy-Authorization');
607
+ }
608
+ }
609
+
610
+
611
+ /**
612
+ * Test if the given string starts with a header that is to be skipped.
613
+ * Skippable headers result from chunked transfer and proxy requests.
614
+ *
615
+ * @param string $data The string to check.
616
+ * @returns boolean Whether a skippable header was found.
617
+ * @access private
618
+ */
619
+ function isSkippableCurlHeader(&$data) {
620
+ $skipHeaders = array( 'HTTP/1.1 100',
621
+ 'HTTP/1.0 301',
622
+ 'HTTP/1.1 301',
623
+ 'HTTP/1.0 302',
624
+ 'HTTP/1.1 302',
625
+ 'HTTP/1.0 401',
626
+ 'HTTP/1.1 401',
627
+ 'HTTP/1.0 200 Connection established');
628
+ foreach ($skipHeaders as $hd) {
629
+ $prefix = substr($data, 0, strlen($hd));
630
+ if ($prefix == $hd) return true;
631
+ }
632
+
633
+ return false;
634
+ }
635
+
636
+ /**
637
+ * decode a string that is encoded w/ "chunked' transfer encoding
638
+ * as defined in RFC2068 19.4.6
639
+ *
640
+ * @param string $buffer
641
+ * @param string $lb
642
+ * @returns string
643
+ * @access public
644
+ * @deprecated
645
+ */
646
+ function decodeChunked($buffer, $lb){
647
+ // length := 0
648
+ $length = 0;
649
+ $new = '';
650
+
651
+ // read chunk-size, chunk-extension (if any) and CRLF
652
+ // get the position of the linebreak
653
+ $chunkend = strpos($buffer, $lb);
654
+ if ($chunkend == FALSE) {
655
+ $this->debug('no linebreak found in decodeChunked');
656
+ return $new;
657
+ }
658
+ $temp = substr($buffer,0,$chunkend);
659
+ $chunk_size = hexdec( trim($temp) );
660
+ $chunkstart = $chunkend + strlen($lb);
661
+ // while (chunk-size > 0) {
662
+ while ($chunk_size > 0) {
663
+ $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
664
+ $chunkend = strpos( $buffer, $lb, $chunkstart + $chunk_size);
665
+
666
+ // Just in case we got a broken connection
667
+ if ($chunkend == FALSE) {
668
+ $chunk = substr($buffer,$chunkstart);
669
+ // append chunk-data to entity-body
670
+ $new .= $chunk;
671
+ $length += strlen($chunk);
672
+ break;
673
+ }
674
+
675
+ // read chunk-data and CRLF
676
+ $chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart);
677
+ // append chunk-data to entity-body
678
+ $new .= $chunk;
679
+ // length := length + chunk-size
680
+ $length += strlen($chunk);
681
+ // read chunk-size and CRLF
682
+ $chunkstart = $chunkend + strlen($lb);
683
+
684
+ $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
685
+ if ($chunkend == FALSE) {
686
+ break; //Just in case we got a broken connection
687
+ }
688
+ $temp = substr($buffer,$chunkstart,$chunkend-$chunkstart);
689
+ $chunk_size = hexdec( trim($temp) );
690
+ $chunkstart = $chunkend;
691
+ }
692
+ return $new;
693
+ }
694
+
695
+ /**
696
+ * Writes the payload, including HTTP headers, to $this->outgoing_payload.
697
+ *
698
+ * @param string $data HTTP body
699
+ * @param string $cookie_str data for HTTP Cookie header
700
+ * @return void
701
+ * @access private
702
+ */
703
+ function buildPayload($data, $cookie_str = '') {
704
+ // Note: for cURL connections, $this->outgoing_payload is ignored,
705
+ // as is the Content-Length header, but these are still created as
706
+ // debugging guides.
707
+
708
+ // add content-length header
709
+ $this->setHeader('Content-Length', strlen($data));
710
+
711
+ // start building outgoing payload:
712
+ if ($this->proxy) {
713
+ $uri = $this->url;
714
+ } else {
715
+ $uri = $this->uri;
716
+ }
717
+ $req = "$this->request_method $uri HTTP/$this->protocol_version";
718
+ $this->debug("HTTP request: $req");
719
+ $this->outgoing_payload = "$req\r\n";
720
+
721
+ // loop thru headers, serializing
722
+ foreach($this->outgoing_headers as $k => $v){
723
+ $hdr = $k.': '.$v;
724
+ $this->debug("HTTP header: $hdr");
725
+ $this->outgoing_payload .= "$hdr\r\n";
726
+ }
727
+
728
+ // add any cookies
729
+ if ($cookie_str != '') {
730
+ $hdr = 'Cookie: '.$cookie_str;
731
+ $this->debug("HTTP header: $hdr");
732
+ $this->outgoing_payload .= "$hdr\r\n";
733
+ }
734
+
735
+ // header/body separator
736
+ $this->outgoing_payload .= "\r\n";
737
+
738
+ // add data
739
+ $this->outgoing_payload .= $data;
740
+ }
741
+
742
+ /**
743
+ * sends the SOAP request via HTTP[S]
744
+ *
745
+ * @param string $data message data
746
+ * @param array $cookies cookies to send
747
+ * @return boolean true if OK, false if problem
748
+ * @access private
749
+ */
750
+ function sendRequest($data, $cookies = NULL) {
751
+ // build cookie string
752
+ $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));
753
+
754
+ // build payload
755
+ $this->buildPayload($data, $cookie_str);
756
+
757
+ if ($this->io_method() == 'socket') {
758
+ // send payload
759
+ if(!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
760
+ $this->setError('couldn\'t write message data to socket');
761
+ $this->debug('couldn\'t write message data to socket');
762
+ return false;
763
+ }
764
+ $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
765
+ return true;
766
+ } else if ($this->io_method() == 'curl') {
767
+ // set payload
768
+ // cURL does say this should only be the verb, and in fact it
769
+ // turns out that the URI and HTTP version are appended to this, which
770
+ // some servers refuse to work with (so we no longer use this method!)
771
+ //$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
772
+ $curl_headers = array();
773
+ foreach($this->outgoing_headers as $k => $v){
774
+ if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') {
775
+ $this->debug("Skip cURL header $k: $v");
776
+ } else {
777
+ $curl_headers[] = "$k: $v";
778
+ }
779
+ }
780
+ if ($cookie_str != '') {
781
+ $curl_headers[] = 'Cookie: ' . $cookie_str;
782
+ }
783
+ $this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers);
784
+ $this->debug('set cURL HTTP headers');
785
+ if ($this->request_method == "POST") {
786
+ $this->setCurlOption(CURLOPT_POST, 1);
787
+ $this->setCurlOption(CURLOPT_POSTFIELDS, $data);
788
+ $this->debug('set cURL POST data');
789
+ } else {
790
+ }
791
+ // insert custom user-set cURL options
792
+ foreach ($this->ch_options as $key => $val) {
793
+ $this->setCurlOption($key, $val);
794
+ }
795
+
796
+ $this->debug('set cURL payload');
797
+ return true;
798
+ }
799
+ }
800
+
801
+ /**
802
+ * gets the SOAP response via HTTP[S]
803
+ *
804
+ * @return string the response (also sets member variables like incoming_payload)
805
+ * @access private
806
+ */
807
+ function getResponse(){
808
+ $this->incoming_payload = '';
809
+
810
+ if ($this->io_method() == 'socket') {
811
+ // loop until headers have been retrieved
812
+ $data = '';
813
+ while (!isset($lb)){
814
+
815
+ // We might EOF during header read.
816
+ if(feof($this->fp)) {
817
+ $this->incoming_payload = $data;
818
+ $this->debug('found no headers before EOF after length ' . strlen($data));
819
+ $this->debug("received before EOF:\n" . $data);
820
+ $this->setError('server failed to send headers');
821
+ return false;
822
+ }
823
+
824
+ $tmp = fgets($this->fp, 256);
825
+ $tmplen = strlen($tmp);
826
+ $this->debug("read line of $tmplen bytes: " . trim($tmp));
827
+
828
+ if ($tmplen == 0) {
829
+ $this->incoming_payload = $data;
830
+ $this->debug('socket read of headers timed out after length ' . strlen($data));
831
+ $this->debug("read before timeout: " . $data);
832
+ $this->setError('socket read of headers timed out');
833
+ return false;
834
+ }
835
+
836
+ $data .= $tmp;
837
+ $pos = strpos($data,"\r\n\r\n");
838
+ if($pos > 1){
839
+ $lb = "\r\n";
840
+ } else {
841
+ $pos = strpos($data,"\n\n");
842
+ if($pos > 1){
843
+ $lb = "\n";
844
+ }
845
+ }
846
+ // remove 100 headers
847
+ if (isset($lb) && ereg('^HTTP/1.1 100',$data)) {
848
+ unset($lb);
849
+ $data = '';
850
+ }//
851
+ }
852
+ // store header data
853
+ $this->incoming_payload .= $data;
854
+ $this->debug('found end of headers after length ' . strlen($data));
855
+ // process headers
856
+ $header_data = trim(substr($data,0,$pos));
857
+ $header_array = explode($lb,$header_data);
858
+ $this->incoming_headers = array();
859
+ $this->incoming_cookies = array();
860
+ foreach($header_array as $header_line){
861
+ $arr = explode(':',$header_line, 2);
862
+ if(count($arr) > 1){
863
+ $header_name = strtolower(trim($arr[0]));
864
+ $this->incoming_headers[$header_name] = trim($arr[1]);
865
+ if ($header_name == 'set-cookie') {
866
+ // TODO: allow multiple cookies from parseCookie
867
+ $cookie = $this->parseCookie(trim($arr[1]));
868
+ if ($cookie) {
869
+ $this->incoming_cookies[] = $cookie;
870
+ $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
871
+ } else {
872
+ $this->debug('did not find cookie in ' . trim($arr[1]));
873
+ }
874
+ }
875
+ } else if (isset($header_name)) {
876
+ // append continuation line to previous header
877
+ $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
878
+ }
879
+ }
880
+
881
+ // loop until msg has been received
882
+ if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') {
883
+ $content_length = 2147483647; // ignore any content-length header
884
+ $chunked = true;
885
+ $this->debug("want to read chunked content");
886
+ } elseif (isset($this->incoming_headers['content-length'])) {
887
+ $content_length = $this->incoming_headers['content-length'];
888
+ $chunked = false;
889
+ $this->debug("want to read content of length $content_length");
890
+ } else {
891
+ $content_length = 2147483647;
892
+ $chunked = false;
893
+ $this->debug("want to read content to EOF");
894
+ }
895
+ $data = '';
896
+ do {
897
+ if ($chunked) {
898
+ $tmp = fgets($this->fp, 256);
899
+ $tmplen = strlen($tmp);
900
+ $this->debug("read chunk line of $tmplen bytes");
901
+ if ($tmplen == 0) {
902
+ $this->incoming_payload = $data;
903
+ $this->debug('socket read of chunk length timed out after length ' . strlen($data));
904
+ $this->debug("read before timeout:\n" . $data);
905
+ $this->setError('socket read of chunk length timed out');
906
+ return false;
907
+ }
908
+ $content_length = hexdec(trim($tmp));
909
+ $this->debug("chunk length $content_length");
910
+ }
911
+ $strlen = 0;
912
+ while (($strlen < $content_length) && (!feof($this->fp))) {
913
+ $readlen = min(8192, $content_length - $strlen);
914
+ $tmp = fread($this->fp, $readlen);
915
+ $tmplen = strlen($tmp);
916
+ $this->debug("read buffer of $tmplen bytes");
917
+ if (($tmplen == 0) && (!feof($this->fp))) {
918
+ $this->incoming_payload = $data;
919
+ $this->debug('socket read of body timed out after length ' . strlen($data));
920
+ $this->debug("read before timeout:\n" . $data);
921
+ $this->setError('socket read of body timed out');
922
+ return false;
923
+ }
924
+ $strlen += $tmplen;
925
+ $data .= $tmp;
926
+ }
927
+ if ($chunked && ($content_length > 0)) {
928
+ $tmp = fgets($this->fp, 256);
929
+ $tmplen = strlen($tmp);
930
+ $this->debug("read chunk terminator of $tmplen bytes");
931
+ if ($tmplen == 0) {
932
+ $this->incoming_payload = $data;
933
+ $this->debug('socket read of chunk terminator timed out after length ' . strlen($data));
934
+ $this->debug("read before timeout:\n" . $data);
935
+ $this->setError('socket read of chunk terminator timed out');
936
+ return false;
937
+ }
938
+ }
939
+ } while ($chunked && ($content_length > 0) && (!feof($this->fp)));
940
+ if (feof($this->fp)) {
941
+ $this->debug('read to EOF');
942
+ }
943
+ $this->debug('read body of length ' . strlen($data));
944
+ $this->incoming_payload .= $data;
945
+ $this->debug('received a total of '.strlen($this->incoming_payload).' bytes of data from server');
946
+
947
+ // close filepointer
948
+ if(
949
+ (isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') ||
950
+ (! $this->persistentConnection) || feof($this->fp)){
951
+ fclose($this->fp);
952
+ $this->fp = false;
953
+ $this->debug('closed socket');
954
+ }
955
+
956
+ // connection was closed unexpectedly
957
+ if($this->incoming_payload == ''){
958
+ $this->setError('no response from server');
959
+ return false;
960
+ }
961
+
962
+ // decode transfer-encoding
963
+ // if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){
964
+ // if(!$data = $this->decodeChunked($data, $lb)){
965
+ // $this->setError('Decoding of chunked data failed');
966
+ // return false;
967
+ // }
968
+ //print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";
969
+ // set decoded payload
970
+ // $this->incoming_payload = $header_data.$lb.$lb.$data;
971
+ // }
972
+
973
+ } else if ($this->io_method() == 'curl') {
974
+ // send and receive
975
+ $this->debug('send and receive with cURL');
976
+ $this->incoming_payload = curl_exec($this->ch);
977
+ $data = $this->incoming_payload;
978
+
979
+ $cErr = curl_error($this->ch);
980
+ if ($cErr != '') {
981
+ $err = 'cURL ERROR: '.curl_errno($this->ch).': '.$cErr.'<br>';
982
+ // TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE
983
+ foreach(curl_getinfo($this->ch) as $k => $v){
984
+ $err .= "$k: $v<br>";
985
+ }
986
+ $this->debug($err);
987
+ $this->setError($err);
988
+ curl_close($this->ch);
989
+ return false;
990
+ } else {
991
+ //echo '<pre>';
992
+ //var_dump(curl_getinfo($this->ch));
993
+ //echo '</pre>';
994
+ }
995
+ // close curl
996
+ $this->debug('No cURL error, closing cURL');
997
+ curl_close($this->ch);
998
+
999
+ // try removing skippable headers
1000
+ $savedata = $data;
1001
+ while ($this->isSkippableCurlHeader($data)) {
1002
+ $this->debug("Found HTTP header to skip");
1003
+ if ($pos = strpos($data,"\r\n\r\n")) {
1004
+ $data = ltrim(substr($data,$pos));
1005
+ } elseif($pos = strpos($data,"\n\n") ) {
1006
+ $data = ltrim(substr($data,$pos));
1007
+ }
1008
+ }
1009
+
1010
+ if ($data == '') {
1011
+ // have nothing left; just remove 100 header(s)
1012
+ $data = $savedata;
1013
+ while (ereg('^HTTP/1.1 100',$data)) {
1014
+ if ($pos = strpos($data,"\r\n\r\n")) {
1015
+ $data = ltrim(substr($data,$pos));
1016
+ } elseif($pos = strpos($data,"\n\n") ) {
1017
+ $data = ltrim(substr($data,$pos));
1018
+ }
1019
+ }
1020
+ }
1021
+
1022
+ // separate content from HTTP headers
1023
+ if ($pos = strpos($data,"\r\n\r\n")) {
1024
+ $lb = "\r\n";
1025
+ } elseif( $pos = strpos($data,"\n\n")) {
1026
+ $lb = "\n";
1027
+ } else {
1028
+ $this->debug('no proper separation of headers and document');
1029
+ $this->setError('no proper separation of headers and document');
1030
+ return false;
1031
+ }
1032
+ $header_data = trim(substr($data,0,$pos));
1033
+ $header_array = explode($lb,$header_data);
1034
+ $data = ltrim(substr($data,$pos));
1035
+ $this->debug('found proper separation of headers and document');
1036
+ $this->debug('cleaned data, stringlen: '.strlen($data));
1037
+ // clean headers
1038
+ foreach ($header_array as $header_line) {
1039
+ $arr = explode(':',$header_line,2);
1040
+ if(count($arr) > 1){
1041
+ $header_name = strtolower(trim($arr[0]));
1042
+ $this->incoming_headers[$header_name] = trim($arr[1]);
1043
+ if ($header_name == 'set-cookie') {
1044
+ // TODO: allow multiple cookies from parseCookie
1045
+ $cookie = $this->parseCookie(trim($arr[1]));
1046
+ if ($cookie) {
1047
+ $this->incoming_cookies[] = $cookie;
1048
+ $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
1049
+ } else {
1050
+ $this->debug('did not find cookie in ' . trim($arr[1]));
1051
+ }
1052
+ }
1053
+ } else if (isset($header_name)) {
1054
+ // append continuation line to previous header
1055
+ $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
1056
+ }
1057
+ }
1058
+ }
1059
+
1060
+ $this->response_status_line = $header_array[0];
1061
+ $arr = explode(' ', $this->response_status_line, 3);
1062
+ $http_version = $arr[0];
1063
+ $http_status = intval($arr[1]);
1064
+ $http_reason = count($arr) > 2 ? $arr[2] : '';
1065
+
1066
+ // see if we need to resend the request with http digest authentication
1067
+ if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) {
1068
+ $this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']);
1069
+ $this->setURL($this->incoming_headers['location']);
1070
+ $this->tryagain = true;
1071
+ return false;
1072
+ }
1073
+
1074
+ // see if we need to resend the request with http digest authentication
1075
+ if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) {
1076
+ $this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']);
1077
+ if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) {
1078
+ $this->debug('Server wants digest authentication');
1079
+ // remove "Digest " from our elements
1080
+ $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);
1081
+
1082
+ // parse elements into array
1083
+ $digestElements = explode(',', $digestString);
1084
+ foreach ($digestElements as $val) {
1085
+ $tempElement = explode('=', trim($val), 2);
1086
+ $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);
1087
+ }
1088
+
1089
+ // should have (at least) qop, realm, nonce
1090
+ if (isset($digestRequest['nonce'])) {
1091
+ $this->setCredentials($this->username, $this->password, 'digest', $digestRequest);
1092
+ $this->tryagain = true;
1093
+ return false;
1094
+ }
1095
+ }
1096
+ $this->debug('HTTP authentication failed');
1097
+ $this->setError('HTTP authentication failed');
1098
+ return false;
1099
+ }
1100
+
1101
+ if (
1102
+ ($http_status >= 300 && $http_status <= 307) ||
1103
+ ($http_status >= 400 && $http_status <= 417) ||
1104
+ ($http_status >= 501 && $http_status <= 505)
1105
+ ) {
1106
+ $this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");
1107
+ return false;
1108
+ }
1109
+
1110
+ // decode content-encoding
1111
+ if(isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != ''){
1112
+ if(strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip'){
1113
+ // if decoding works, use it. else assume data wasn't gzencoded
1114
+ if(function_exists('gzinflate')){
1115
+ //$timer->setMarker('starting decoding of gzip/deflated content');
1116
+ // IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress)
1117
+ // this means there are no Zlib headers, although there should be
1118
+ $this->debug('The gzinflate function exists');
1119
+ $datalen = strlen($data);
1120
+ if ($this->incoming_headers['content-encoding'] == 'deflate') {
1121
+ if ($degzdata = @gzinflate($data)) {
1122
+ $data = $degzdata;
1123
+ $this->debug('The payload has been inflated to ' . strlen($data) . ' bytes');
1124
+ if (strlen($data) < $datalen) {
1125
+ // test for the case that the payload has been compressed twice
1126
+ $this->debug('The inflated payload is smaller than the gzipped one; try again');
1127
+ if ($degzdata = @gzinflate($data)) {
1128
+ $data = $degzdata;
1129
+ $this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes');
1130
+ }
1131
+ }
1132
+ } else {
1133
+ $this->debug('Error using gzinflate to inflate the payload');
1134
+ $this->setError('Error using gzinflate to inflate the payload');
1135
+ }
1136
+ } elseif ($this->incoming_headers['content-encoding'] == 'gzip') {
1137
+ if ($degzdata = @gzinflate(substr($data, 10))) { // do our best
1138
+ $data = $degzdata;
1139
+ $this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes');
1140
+ if (strlen($data) < $datalen) {
1141
+ // test for the case that the payload has been compressed twice
1142
+ $this->debug('The un-gzipped payload is smaller than the gzipped one; try again');
1143
+ if ($degzdata = @gzinflate(substr($data, 10))) {
1144
+ $data = $degzdata;
1145
+ $this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes');
1146
+ }
1147
+ }
1148
+ } else {
1149
+ $this->debug('Error using gzinflate to un-gzip the payload');
1150
+ $this->setError('Error using gzinflate to un-gzip the payload');
1151
+ }
1152
+ }
1153
+ //$timer->setMarker('finished decoding of gzip/deflated content');
1154
+ //print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";
1155
+ // set decoded payload
1156
+ $this->incoming_payload = $header_data.$lb.$lb.$data;
1157
+ } else {
1158
+ $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
1159
+ $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
1160
+ }
1161
+ } else {
1162
+ $this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
1163
+ $this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
1164
+ }
1165
+ } else {
1166
+ $this->debug('No Content-Encoding header');
1167
+ }
1168
+
1169
+ if(strlen($data) == 0){
1170
+ $this->debug('no data after headers!');
1171
+ $this->setError('no data present after HTTP headers');
1172
+ return false;
1173
+ }
1174
+
1175
+ return $data;
1176
+ }
1177
+
1178
+ /**
1179
+ * sets the content-type for the SOAP message to be sent
1180
+ *
1181
+ * @param string $type the content type, MIME style
1182
+ * @param mixed $charset character set used for encoding (or false)
1183
+ * @access public
1184
+ */
1185
+ function setContentType($type, $charset = false) {
1186
+ $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
1187
+ }
1188
+
1189
+ /**
1190
+ * specifies that an HTTP persistent connection should be used
1191
+ *
1192
+ * @return boolean whether the request was honored by this method.
1193
+ * @access public
1194
+ */
1195
+ function usePersistentConnection(){
1196
+ if (isset($this->outgoing_headers['Accept-Encoding'])) {
1197
+ return false;
1198
+ }
1199
+ $this->protocol_version = '1.1';
1200
+ $this->persistentConnection = true;
1201
+ $this->setHeader('Connection', 'Keep-Alive');
1202
+ return true;
1203
+ }
1204
+
1205
+ /**
1206
+ * parse an incoming Cookie into it's parts
1207
+ *
1208
+ * @param string $cookie_str content of cookie
1209
+ * @return array with data of that cookie
1210
+ * @access private
1211
+ */
1212
+ /*
1213
+ * TODO: allow a Set-Cookie string to be parsed into multiple cookies
1214
+ */
1215
+ function parseCookie($cookie_str) {
1216
+ $cookie_str = str_replace('; ', ';', $cookie_str) . ';';
1217
+ $data = split(';', $cookie_str);
1218
+ $value_str = $data[0];
1219
+
1220
+ $cookie_param = 'domain=';
1221
+ $start = strpos($cookie_str, $cookie_param);
1222
+ if ($start > 0) {
1223
+ $domain = substr($cookie_str, $start + strlen($cookie_param));
1224
+ $domain = substr($domain, 0, strpos($domain, ';'));
1225
+ } else {
1226
+ $domain = '';
1227
+ }
1228
+
1229
+ $cookie_param = 'expires=';
1230
+ $start = strpos($cookie_str, $cookie_param);
1231
+ if ($start > 0) {
1232
+ $expires = substr($cookie_str, $start + strlen($cookie_param));
1233
+ $expires = substr($expires, 0, strpos($expires, ';'));
1234
+ } else {
1235
+ $expires = '';
1236
+ }
1237
+
1238
+ $cookie_param = 'path=';
1239
+ $start = strpos($cookie_str, $cookie_param);
1240
+ if ( $start > 0 ) {
1241
+ $path = substr($cookie_str, $start + strlen($cookie_param));
1242
+ $path = substr($path, 0, strpos($path, ';'));
1243
+ } else {
1244
+ $path = '/';
1245
+ }
1246
+
1247
+ $cookie_param = ';secure;';
1248
+ if (strpos($cookie_str, $cookie_param) !== FALSE) {
1249
+ $secure = true;
1250
+ } else {
1251
+ $secure = false;
1252
+ }
1253
+
1254
+ $sep_pos = strpos($value_str, '=');
1255
+
1256
+ if ($sep_pos) {
1257
+ $name = substr($value_str, 0, $sep_pos);
1258
+ $value = substr($value_str, $sep_pos + 1);
1259
+ $cookie= array( 'name' => $name,
1260
+ 'value' => $value,
1261
+ 'domain' => $domain,
1262
+ 'path' => $path,
1263
+ 'expires' => $expires,
1264
+ 'secure' => $secure
1265
+ );
1266
+ return $cookie;
1267
+ }
1268
+ return false;
1269
+ }
1270
+
1271
+ /**
1272
+ * sort out cookies for the current request
1273
+ *
1274
+ * @param array $cookies array with all cookies
1275
+ * @param boolean $secure is the send-content secure or not?
1276
+ * @return string for Cookie-HTTP-Header
1277
+ * @access private
1278
+ */
1279
+ function getCookiesForRequest($cookies, $secure=false) {
1280
+ $cookie_str = '';
1281
+ if ((! is_null($cookies)) && (is_array($cookies))) {
1282
+ foreach ($cookies as $cookie) {
1283
+ if (! is_array($cookie)) {
1284
+ continue;
1285
+ }
1286
+ $this->debug("check cookie for validity: ".$cookie['name'].'='.$cookie['value']);
1287
+ if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
1288
+ if (strtotime($cookie['expires']) <= time()) {
1289
+ $this->debug('cookie has expired');
1290
+ continue;
1291
+ }
1292
+ }
1293
+ if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) {
1294
+ $domain = preg_quote($cookie['domain']);
1295
+ if (! preg_match("'.*$domain$'i", $this->host)) {
1296
+ $this->debug('cookie has different domain');
1297
+ continue;
1298
+ }
1299
+ }
1300
+ if ((isset($cookie['path'])) && (! empty($cookie['path']))) {
1301
+ $path = preg_quote($cookie['path']);
1302
+ if (! preg_match("'^$path.*'i", $this->path)) {
1303
+ $this->debug('cookie is for a different path');
1304
+ continue;
1305
+ }
1306
+ }
1307
+ if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) {
1308
+ $this->debug('cookie is secure, transport is not');
1309
+ continue;
1310
+ }
1311
+ $cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';
1312
+ $this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']);
1313
+ }
1314
+ }
1315
+ return $cookie_str;
1316
+ }
1317
+ }
1318
+
1319
+
1320
+ ?>
lib/nusoap/soap_val.php ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
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 suporte.developer@buscape-inc.com so we can send you a copy immediately.
14
+ *
15
+ * @category Buscape
16
+ * @package Buscape_Fcontrol
17
+ * @copyright Copyright (c) 2010 Buscapé Company (http://www.buscapecompany.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ /**
22
+ * For creating serializable abstractions of native PHP types. This class
23
+ * allows element name/namespace, XSD type, and XML attributes to be
24
+ * associated with a value. This is extremely useful when WSDL is not
25
+ * used, but is also useful when WSDL is used with polymorphic types, including
26
+ * xsd:anyType and user-defined types.
27
+ *
28
+ * @author Dietrich Ayala <dietrich@ganx4.com>
29
+ * @version $Id: class.soap_val.php,v 1.11 2007/04/06 13:56:32 snichol Exp $
30
+ * @access public
31
+ */
32
+ class soapval extends nusoap_base {
33
+ /**
34
+ * The XML element name
35
+ *
36
+ * @var string
37
+ * @access private
38
+ */
39
+ var $name;
40
+ /**
41
+ * The XML type name (string or false)
42
+ *
43
+ * @var mixed
44
+ * @access private
45
+ */
46
+ var $type;
47
+ /**
48
+ * The PHP value
49
+ *
50
+ * @var mixed
51
+ * @access private
52
+ */
53
+ var $value;
54
+ /**
55
+ * The XML element namespace (string or false)
56
+ *
57
+ * @var mixed
58
+ * @access private
59
+ */
60
+ var $element_ns;
61
+ /**
62
+ * The XML type namespace (string or false)
63
+ *
64
+ * @var mixed
65
+ * @access private
66
+ */
67
+ var $type_ns;
68
+ /**
69
+ * The XML element attributes (array or false)
70
+ *
71
+ * @var mixed
72
+ * @access private
73
+ */
74
+ var $attributes;
75
+
76
+ /**
77
+ * constructor
78
+ *
79
+ * @param string $name optional name
80
+ * @param mixed $type optional type name
81
+ * @param mixed $value optional value
82
+ * @param mixed $element_ns optional namespace of value
83
+ * @param mixed $type_ns optional namespace of type
84
+ * @param mixed $attributes associative array of attributes to add to element serialization
85
+ * @access public
86
+ */
87
+ function soapval($name='soapval',$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false) {
88
+ parent::nusoap_base();
89
+ $this->name = $name;
90
+ $this->type = $type;
91
+ $this->value = $value;
92
+ $this->element_ns = $element_ns;
93
+ $this->type_ns = $type_ns;
94
+ $this->attributes = $attributes;
95
+ }
96
+
97
+ /**
98
+ * return serialized value
99
+ *
100
+ * @param string $use The WSDL use value (encoded|literal)
101
+ * @return string XML data
102
+ * @access public
103
+ */
104
+ function serialize($use='encoded') {
105
+ return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true);
106
+ }
107
+
108
+ /**
109
+ * decodes a soapval object into a PHP native type
110
+ *
111
+ * @return mixed
112
+ * @access public
113
+ */
114
+ function decode(){
115
+ return $this->value;
116
+ }
117
+ }
118
+
119
+
120
+
121
+
122
+ ?>
lib/nusoap/soapclient.php ADDED
@@ -0,0 +1,992 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
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 suporte.developer@buscape-inc.com so we can send you a copy immediately.
14
+ *
15
+ * @category Buscape
16
+ * @package Buscape_Fcontrol
17
+ * @copyright Copyright (c) 2010 Buscapé Company (http://www.buscapecompany.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ /**
22
+ *
23
+ * [nu]soapclient higher level class for easy usage.
24
+ *
25
+ * usage:
26
+ *
27
+ * // instantiate client with server info
28
+ * $soapclient = new nusoap_client( string path [ ,mixed wsdl] );
29
+ *
30
+ * // call method, get results
31
+ * echo $soapclient->call( string methodname [ ,array parameters] );
32
+ *
33
+ * // bye bye client
34
+ * unset($soapclient);
35
+ *
36
+ * @author Dietrich Ayala <dietrich@ganx4.com>
37
+ * @author Scott Nichol <snichol@users.sourceforge.net>
38
+ * @version $Id: class.soapclient.php,v 1.64 2007/10/22 01:15:17 snichol Exp $
39
+ * @access public
40
+ */
41
+ class nusoap_client extends nusoap_base {
42
+
43
+ var $username = ''; // Username for HTTP authentication
44
+ var $password = ''; // Password for HTTP authentication
45
+ var $authtype = ''; // Type of HTTP authentication
46
+ var $certRequest = array(); // Certificate for HTTP SSL authentication
47
+ var $requestHeaders = false; // SOAP headers in request (text)
48
+ var $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (text)
49
+ var $responseHeader = NULL; // SOAP Header from response (parsed)
50
+ var $document = ''; // SOAP body response portion (incomplete namespace resolution) (text)
51
+ var $endpoint;
52
+ var $forceEndpoint = ''; // overrides WSDL endpoint
53
+ var $proxyhost = '';
54
+ var $proxyport = '';
55
+ var $proxyusername = '';
56
+ var $proxypassword = '';
57
+ var $xml_encoding = ''; // character set encoding of incoming (response) messages
58
+ var $http_encoding = false;
59
+ var $timeout = 0; // HTTP connection timeout
60
+ var $response_timeout = 30; // HTTP response timeout
61
+ var $endpointType = ''; // soap|wsdl, empty for WSDL initialization error
62
+ var $persistentConnection = false;
63
+ var $defaultRpcParams = false; // This is no longer used
64
+ var $request = ''; // HTTP request
65
+ var $response = ''; // HTTP response
66
+ var $responseData = ''; // SOAP payload of response
67
+ var $cookies = array(); // Cookies from response or for request
68
+ var $decode_utf8 = true; // toggles whether the parser decodes element content w/ utf8_decode()
69
+ var $operations = array(); // WSDL operations, empty for WSDL initialization error
70
+ var $curl_options = array(); // User-specified cURL options
71
+ var $bindingType = ''; // WSDL operation binding type
72
+ var $use_curl = false; // whether to always try to use cURL
73
+
74
+ /*
75
+ * fault related variables
76
+ */
77
+ /**
78
+ * @var fault
79
+ * @access public
80
+ */
81
+ var $fault;
82
+ /**
83
+ * @var faultcode
84
+ * @access public
85
+ */
86
+ var $faultcode;
87
+ /**
88
+ * @var faultstring
89
+ * @access public
90
+ */
91
+ var $faultstring;
92
+ /**
93
+ * @var faultdetail
94
+ * @access public
95
+ */
96
+ var $faultdetail;
97
+
98
+ /**
99
+ * constructor
100
+ *
101
+ * @param mixed $endpoint SOAP server or WSDL URL (string), or wsdl instance (object)
102
+ * @param bool $wsdl optional, set to true if using WSDL
103
+ * @param int $portName optional portName in WSDL document
104
+ * @param string $proxyhost
105
+ * @param string $proxyport
106
+ * @param string $proxyusername
107
+ * @param string $proxypassword
108
+ * @param integer $timeout set the connection timeout
109
+ * @param integer $response_timeout set the response timeout
110
+ * @access public
111
+ */
112
+ function nusoap_client($endpoint,$wsdl = false,$proxyhost = false,$proxyport = false,$proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30){
113
+ parent::nusoap_base();
114
+ $this->endpoint = $endpoint;
115
+ $this->proxyhost = $proxyhost;
116
+ $this->proxyport = $proxyport;
117
+ $this->proxyusername = $proxyusername;
118
+ $this->proxypassword = $proxypassword;
119
+ $this->timeout = $timeout;
120
+ $this->response_timeout = $response_timeout;
121
+
122
+ $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
123
+ $this->appendDebug('endpoint=' . $this->varDump($endpoint));
124
+
125
+ // make values
126
+ if($wsdl){
127
+ if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) {
128
+ $this->wsdl = $endpoint;
129
+ $this->endpoint = $this->wsdl->wsdl;
130
+ $this->wsdlFile = $this->endpoint;
131
+ $this->debug('existing wsdl instance created from ' . $this->endpoint);
132
+ $this->checkWSDL();
133
+ } else {
134
+ $this->wsdlFile = $this->endpoint;
135
+ $this->wsdl = null;
136
+ $this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint);
137
+ }
138
+ $this->endpointType = 'wsdl';
139
+ } else {
140
+ $this->debug("instantiate SOAP with endpoint at $endpoint");
141
+ $this->endpointType = 'soap';
142
+ }
143
+ }
144
+
145
+ /**
146
+ * calls method, returns PHP native type
147
+ *
148
+ * @param string $operation SOAP server URL or path
149
+ * @param mixed $params An array, associative or simple, of the parameters
150
+ * for the method call, or a string that is the XML
151
+ * for the call. For rpc style, this call will
152
+ * wrap the XML in a tag named after the method, as
153
+ * well as the SOAP Envelope and Body. For document
154
+ * style, this will only wrap with the Envelope and Body.
155
+ * IMPORTANT: when using an array with document style,
156
+ * in which case there
157
+ * is really one parameter, the root of the fragment
158
+ * used in the call, which encloses what programmers
159
+ * normally think of parameters. A parameter array
160
+ * *must* include the wrapper.
161
+ * @param string $namespace optional method namespace (WSDL can override)
162
+ * @param string $soapAction optional SOAPAction value (WSDL can override)
163
+ * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
164
+ * @param boolean $rpcParams optional (no longer used)
165
+ * @param string $style optional (rpc|document) the style to use when serializing parameters (WSDL can override)
166
+ * @param string $use optional (encoded|literal) the use when serializing parameters (WSDL can override)
167
+ * @return mixed response from SOAP call
168
+ * @access public
169
+ */
170
+ function call($operation,$params=array(),$namespace='http://tempuri.org',$soapAction='',$headers=false,$rpcParams=null,$style='rpc',$use='encoded'){
171
+ $this->operation = $operation;
172
+ $this->fault = false;
173
+ $this->setError('');
174
+ $this->request = '';
175
+ $this->response = '';
176
+ $this->responseData = '';
177
+ $this->faultstring = '';
178
+ $this->faultcode = '';
179
+ $this->opData = array();
180
+
181
+ $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType");
182
+ $this->appendDebug('params=' . $this->varDump($params));
183
+ $this->appendDebug('headers=' . $this->varDump($headers));
184
+ if ($headers) {
185
+ $this->requestHeaders = $headers;
186
+ }
187
+ if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
188
+ $this->loadWSDL();
189
+ if ($this->getError())
190
+ return false;
191
+ }
192
+ // serialize parameters
193
+ if($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)){
194
+ // use WSDL for operation
195
+ $this->opData = $opData;
196
+ $this->debug("found operation");
197
+ $this->appendDebug('opData=' . $this->varDump($opData));
198
+ if (isset($opData['soapAction'])) {
199
+ $soapAction = $opData['soapAction'];
200
+ }
201
+ if (! $this->forceEndpoint) {
202
+ $this->endpoint = $opData['endpoint'];
203
+ } else {
204
+ $this->endpoint = $this->forceEndpoint;
205
+ }
206
+ $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] : $namespace;
207
+ $style = $opData['style'];
208
+ $use = $opData['input']['use'];
209
+ // add ns to ns array
210
+ if($namespace != '' && !isset($this->wsdl->namespaces[$namespace])){
211
+ $nsPrefix = 'ns' . rand(1000, 9999);
212
+ $this->wsdl->namespaces[$nsPrefix] = $namespace;
213
+ }
214
+ $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);
215
+ // serialize payload
216
+ if (is_string($params)) {
217
+ $this->debug("serializing param string for WSDL operation $operation");
218
+ $payload = $params;
219
+ } elseif (is_array($params)) {
220
+ $this->debug("serializing param array for WSDL operation $operation");
221
+ $payload = $this->wsdl->serializeRPCParameters($operation,'input',$params,$this->bindingType);
222
+ } else {
223
+ $this->debug('params must be array or string');
224
+ $this->setError('params must be array or string');
225
+ return false;
226
+ }
227
+ $usedNamespaces = $this->wsdl->usedNamespaces;
228
+ if (isset($opData['input']['encodingStyle'])) {
229
+ $encodingStyle = $opData['input']['encodingStyle'];
230
+ } else {
231
+ $encodingStyle = '';
232
+ }
233
+ $this->appendDebug($this->wsdl->getDebug());
234
+ $this->wsdl->clearDebug();
235
+ if ($errstr = $this->wsdl->getError()) {
236
+ $this->debug('got wsdl error: '.$errstr);
237
+ $this->setError('wsdl error: '.$errstr);
238
+ return false;
239
+ }
240
+ } elseif($this->endpointType == 'wsdl') {
241
+ // operation not in WSDL
242
+ $this->appendDebug($this->wsdl->getDebug());
243
+ $this->wsdl->clearDebug();
244
+ $this->setError( 'operation '.$operation.' not present.');
245
+ $this->debug("operation '$operation' not present.");
246
+ return false;
247
+ } else {
248
+ // no WSDL
249
+ //$this->namespaces['ns1'] = $namespace;
250
+ $nsPrefix = 'ns' . rand(1000, 9999);
251
+ // serialize
252
+ $payload = '';
253
+ if (is_string($params)) {
254
+ $this->debug("serializing param string for operation $operation");
255
+ $payload = $params;
256
+ } elseif (is_array($params)) {
257
+ $this->debug("serializing param array for operation $operation");
258
+ foreach($params as $k => $v){
259
+ $payload .= $this->serialize_val($v,$k,false,false,false,false,$use);
260
+ }
261
+ } else {
262
+ $this->debug('params must be array or string');
263
+ $this->setError('params must be array or string');
264
+ return false;
265
+ }
266
+ $usedNamespaces = array();
267
+ if ($use == 'encoded') {
268
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
269
+ } else {
270
+ $encodingStyle = '';
271
+ }
272
+ }
273
+ // wrap RPC calls with method element
274
+ if ($style == 'rpc') {
275
+ if ($use == 'literal') {
276
+ $this->debug("wrapping RPC request with literal method element");
277
+ if ($namespace) {
278
+ // 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
279
+ $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
280
+ $payload .
281
+ "</$nsPrefix:$operation>";
282
+ } else {
283
+ $payload = "<$operation>" . $payload . "</$operation>";
284
+ }
285
+ } else {
286
+ $this->debug("wrapping RPC request with encoded method element");
287
+ if ($namespace) {
288
+ $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
289
+ $payload .
290
+ "</$nsPrefix:$operation>";
291
+ } else {
292
+ $payload = "<$operation>" .
293
+ $payload .
294
+ "</$operation>";
295
+ }
296
+ }
297
+ }
298
+ // serialize envelope
299
+ $soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders,$usedNamespaces,$style,$use,$encodingStyle);
300
+ $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
301
+ $this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
302
+ // send
303
+ $return = $this->send($this->getHTTPBody($soapmsg),$soapAction,$this->timeout,$this->response_timeout);
304
+ if($errstr = $this->getError()){
305
+ $this->debug('Error: '.$errstr);
306
+ return false;
307
+ } else {
308
+ $this->return = $return;
309
+ $this->debug('sent message successfully and got a(n) '.gettype($return));
310
+ $this->appendDebug('return=' . $this->varDump($return));
311
+
312
+ // fault?
313
+ if(is_array($return) && isset($return['faultcode'])){
314
+ $this->debug('got fault');
315
+ $this->setError($return['faultcode'].': '.$return['faultstring']);
316
+ $this->fault = true;
317
+ foreach($return as $k => $v){
318
+ $this->$k = $v;
319
+ $this->debug("$k = $v<br>");
320
+ }
321
+ return $return;
322
+ } elseif ($style == 'document') {
323
+ // NOTE: if the response is defined to have multiple parts (i.e. unwrapped),
324
+ // we are only going to return the first part here...sorry about that
325
+ return $return;
326
+ } else {
327
+ // array of return values
328
+ if(is_array($return)){
329
+ // multiple 'out' parameters, which we return wrapped up
330
+ // in the array
331
+ if(sizeof($return) > 1){
332
+ return $return;
333
+ }
334
+ // single 'out' parameter (normally the return value)
335
+ $return = array_shift($return);
336
+ $this->debug('return shifted value: ');
337
+ $this->appendDebug($this->varDump($return));
338
+ return $return;
339
+ // nothing returned (ie, echoVoid)
340
+ } else {
341
+ return "";
342
+ }
343
+ }
344
+ }
345
+ }
346
+
347
+ /**
348
+ * check WSDL passed as an instance or pulled from an endpoint
349
+ *
350
+ * @access private
351
+ */
352
+ function checkWSDL() {
353
+ $this->appendDebug($this->wsdl->getDebug());
354
+ $this->wsdl->clearDebug();
355
+ $this->debug('checkWSDL');
356
+ // catch errors
357
+ if ($errstr = $this->wsdl->getError()) {
358
+ $this->debug('got wsdl error: '.$errstr);
359
+ $this->setError('wsdl error: '.$errstr);
360
+ } elseif ($this->operations = $this->wsdl->getOperations('soap')) {
361
+ $this->bindingType = 'soap';
362
+ $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
363
+ } elseif ($this->operations = $this->wsdl->getOperations('soap12')) {
364
+ $this->bindingType = 'soap12';
365
+ $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
366
+ $this->debug('**************** WARNING: SOAP 1.2 BINDING *****************');
367
+ } else {
368
+ $this->debug('getOperations returned false');
369
+ $this->setError('no operations defined in the WSDL document!');
370
+ }
371
+ }
372
+
373
+ /**
374
+ * instantiate wsdl object and parse wsdl file
375
+ *
376
+ * @access public
377
+ */
378
+ function loadWSDL() {
379
+ $this->debug('instantiating wsdl class with doc: '.$this->wsdlFile);
380
+ $this->wsdl =& new wsdl('',$this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeout,$this->response_timeout,$this->curl_options,$this->use_curl);
381
+ $this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest);
382
+ $this->wsdl->fetchWSDL($this->wsdlFile);
383
+ $this->checkWSDL();
384
+ }
385
+
386
+ /**
387
+ * get available data pertaining to an operation
388
+ *
389
+ * @param string $operation operation name
390
+ * @return array array of data pertaining to the operation
391
+ * @access public
392
+ */
393
+ function getOperationData($operation){
394
+ if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
395
+ $this->loadWSDL();
396
+ if ($this->getError())
397
+ return false;
398
+ }
399
+ if(isset($this->operations[$operation])){
400
+ return $this->operations[$operation];
401
+ }
402
+ $this->debug("No data for operation: $operation");
403
+ }
404
+
405
+ /**
406
+ * send the SOAP message
407
+ *
408
+ * Note: if the operation has multiple return values
409
+ * the return value of this method will be an array
410
+ * of those values.
411
+ *
412
+ * @param string $msg a SOAPx4 soapmsg object
413
+ * @param string $soapaction SOAPAction value
414
+ * @param integer $timeout set connection timeout in seconds
415
+ * @param integer $response_timeout set response timeout in seconds
416
+ * @return mixed native PHP types.
417
+ * @access private
418
+ */
419
+ function send($msg, $soapaction = '', $timeout=0, $response_timeout=30) {
420
+ $this->checkCookies();
421
+ // detect transport
422
+ switch(true){
423
+ // http(s)
424
+ case ereg('^http',$this->endpoint):
425
+ $this->debug('transporting via HTTP');
426
+ if($this->persistentConnection == true && is_object($this->persistentConnection)){
427
+ $http =& $this->persistentConnection;
428
+ } else {
429
+ $http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl);
430
+ if ($this->persistentConnection) {
431
+ $http->usePersistentConnection();
432
+ }
433
+ }
434
+ $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset());
435
+ $http->setSOAPAction($soapaction);
436
+ if($this->proxyhost && $this->proxyport){
437
+ $http->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
438
+ }
439
+ if($this->authtype != '') {
440
+ $http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
441
+ }
442
+ if($this->http_encoding != ''){
443
+ $http->setEncoding($this->http_encoding);
444
+ }
445
+ $this->debug('sending message, length='.strlen($msg));
446
+ if(ereg('^http:',$this->endpoint)){
447
+ //if(strpos($this->endpoint,'http:')){
448
+ $this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies);
449
+ } elseif(ereg('^https',$this->endpoint)){
450
+ //} elseif(strpos($this->endpoint,'https:')){
451
+ //if(phpversion() == '4.3.0-dev'){
452
+ //$response = $http->send($msg,$timeout,$response_timeout);
453
+ //$this->request = $http->outgoing_payload;
454
+ //$this->response = $http->incoming_payload;
455
+ //} else
456
+ $this->responseData = $http->sendHTTPS($msg,$timeout,$response_timeout,$this->cookies);
457
+ } else {
458
+ $this->setError('no http/s in endpoint url');
459
+ }
460
+ $this->request = $http->outgoing_payload;
461
+ $this->response = $http->incoming_payload;
462
+ $this->appendDebug($http->getDebug());
463
+ $this->UpdateCookies($http->incoming_cookies);
464
+
465
+ // save transport object if using persistent connections
466
+ if ($this->persistentConnection) {
467
+ $http->clearDebug();
468
+ if (!is_object($this->persistentConnection)) {
469
+ $this->persistentConnection = $http;
470
+ }
471
+ }
472
+
473
+ if($err = $http->getError()){
474
+ $this->setError('HTTP Error: '.$err);
475
+ return false;
476
+ } elseif($this->getError()){
477
+ return false;
478
+ } else {
479
+ $this->debug('got response, length='. strlen($this->responseData).' type='.$http->incoming_headers['content-type']);
480
+ return $this->parseResponse($http->incoming_headers, $this->responseData);
481
+ }
482
+ break;
483
+ default:
484
+ $this->setError('no transport found, or selected transport is not yet supported!');
485
+ return false;
486
+ break;
487
+ }
488
+ }
489
+
490
+ /**
491
+ * processes SOAP message returned from server
492
+ *
493
+ * @param array $headers The HTTP headers
494
+ * @param string $data unprocessed response data from server
495
+ * @return mixed value of the message, decoded into a PHP type
496
+ * @access private
497
+ */
498
+ function parseResponse($headers, $data) {
499
+ $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:');
500
+ $this->appendDebug($this->varDump($headers));
501
+ if (!strstr($headers['content-type'], 'text/xml')) {
502
+ $this->setError('Response not of type text/xml: ' . $headers['content-type']);
503
+ return false;
504
+ }
505
+ if (strpos($headers['content-type'], '=')) {
506
+ $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
507
+ $this->debug('Got response encoding: ' . $enc);
508
+ if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){
509
+ $this->xml_encoding = strtoupper($enc);
510
+ } else {
511
+ $this->xml_encoding = 'US-ASCII';
512
+ }
513
+ } else {
514
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
515
+ $this->xml_encoding = 'ISO-8859-1';
516
+ }
517
+ $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
518
+ $parser = new nusoap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8);
519
+ // add parser debug data to our debug
520
+ $this->appendDebug($parser->getDebug());
521
+ // if parse errors
522
+ if($errstr = $parser->getError()){
523
+ $this->setError( $errstr);
524
+ // destroy the parser object
525
+ unset($parser);
526
+ return false;
527
+ } else {
528
+ // get SOAP headers
529
+ $this->responseHeaders = $parser->getHeaders();
530
+ // get SOAP headers
531
+ $this->responseHeader = $parser->get_soapheader();
532
+ // get decoded message
533
+ $return = $parser->get_soapbody();
534
+ // add document for doclit support
535
+ $this->document = $parser->document;
536
+ // destroy the parser object
537
+ unset($parser);
538
+ // return decode message
539
+ return $return;
540
+ }
541
+ }
542
+
543
+ /**
544
+ * sets user-specified cURL options
545
+ *
546
+ * @param mixed $option The cURL option (always integer?)
547
+ * @param mixed $value The cURL option value
548
+ * @access public
549
+ */
550
+ function setCurlOption($option, $value) {
551
+ $this->debug("setCurlOption option=$option, value=");
552
+ $this->appendDebug($this->varDump($value));
553
+ $this->curl_options[$option] = $value;
554
+ }
555
+
556
+ /**
557
+ * sets the SOAP endpoint, which can override WSDL
558
+ *
559
+ * @param string $endpoint The endpoint URL to use, or empty string or false to prevent override
560
+ * @access public
561
+ */
562
+ function setEndpoint($endpoint) {
563
+ $this->debug("setEndpoint(\"$endpoint\")");
564
+ $this->forceEndpoint = $endpoint;
565
+ }
566
+
567
+ /**
568
+ * set the SOAP headers
569
+ *
570
+ * @param mixed $headers String of XML with SOAP header content, or array of soapval objects for SOAP headers
571
+ * @access public
572
+ */
573
+ function setHeaders($headers){
574
+ $this->debug("setHeaders headers=");
575
+ $this->appendDebug($this->varDump($headers));
576
+ $this->requestHeaders = $headers;
577
+ }
578
+
579
+ /**
580
+ * get the SOAP response headers (namespace resolution incomplete)
581
+ *
582
+ * @return string
583
+ * @access public
584
+ */
585
+ function getHeaders(){
586
+ return $this->responseHeaders;
587
+ }
588
+
589
+ /**
590
+ * get the SOAP response Header (parsed)
591
+ *
592
+ * @return mixed
593
+ * @access public
594
+ */
595
+ function getHeader(){
596
+ return $this->responseHeader;
597
+ }
598
+
599
+ /**
600
+ * set proxy info here
601
+ *
602
+ * @param string $proxyhost
603
+ * @param string $proxyport
604
+ * @param string $proxyusername
605
+ * @param string $proxypassword
606
+ * @access public
607
+ */
608
+ function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') {
609
+ $this->proxyhost = $proxyhost;
610
+ $this->proxyport = $proxyport;
611
+ $this->proxyusername = $proxyusername;
612
+ $this->proxypassword = $proxypassword;
613
+ }
614
+
615
+ /**
616
+ * if authenticating, set user credentials here
617
+ *
618
+ * @param string $username
619
+ * @param string $password
620
+ * @param string $authtype (basic|digest|certificate|ntlm)
621
+ * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
622
+ * @access public
623
+ */
624
+ function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
625
+ $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
626
+ $this->appendDebug($this->varDump($certRequest));
627
+ $this->username = $username;
628
+ $this->password = $password;
629
+ $this->authtype = $authtype;
630
+ $this->certRequest = $certRequest;
631
+ }
632
+
633
+ /**
634
+ * use HTTP encoding
635
+ *
636
+ * @param string $enc HTTP encoding
637
+ * @access public
638
+ */
639
+ function setHTTPEncoding($enc='gzip, deflate'){
640
+ $this->debug("setHTTPEncoding(\"$enc\")");
641
+ $this->http_encoding = $enc;
642
+ }
643
+
644
+ /**
645
+ * Set whether to try to use cURL connections if possible
646
+ *
647
+ * @param boolean $use Whether to try to use cURL
648
+ * @access public
649
+ */
650
+ function setUseCURL($use) {
651
+ $this->debug("setUseCURL($use)");
652
+ $this->use_curl = $use;
653
+ }
654
+
655
+ /**
656
+ * use HTTP persistent connections if possible
657
+ *
658
+ * @access public
659
+ */
660
+ function useHTTPPersistentConnection(){
661
+ $this->debug("useHTTPPersistentConnection");
662
+ $this->persistentConnection = true;
663
+ }
664
+
665
+ /**
666
+ * gets the default RPC parameter setting.
667
+ * If true, default is that call params are like RPC even for document style.
668
+ * Each call() can override this value.
669
+ *
670
+ * This is no longer used.
671
+ *
672
+ * @return boolean
673
+ * @access public
674
+ * @deprecated
675
+ */
676
+ function getDefaultRpcParams() {
677
+ return $this->defaultRpcParams;
678
+ }
679
+
680
+ /**
681
+ * sets the default RPC parameter setting.
682
+ * If true, default is that call params are like RPC even for document style
683
+ * Each call() can override this value.
684
+ *
685
+ * This is no longer used.
686
+ *
687
+ * @param boolean $rpcParams
688
+ * @access public
689
+ * @deprecated
690
+ */
691
+ function setDefaultRpcParams($rpcParams) {
692
+ $this->defaultRpcParams = $rpcParams;
693
+ }
694
+
695
+ /**
696
+ * dynamically creates an instance of a proxy class,
697
+ * allowing user to directly call methods from wsdl
698
+ *
699
+ * @return object soap_proxy object
700
+ * @access public
701
+ */
702
+ function getProxy() {
703
+ $r = rand();
704
+ $evalStr = $this->_getProxyClassCode($r);
705
+ //$this->debug("proxy class: $evalStr");
706
+ if ($this->getError()) {
707
+ $this->debug("Error from _getProxyClassCode, so return NULL");
708
+ return null;
709
+ }
710
+ // eval the class
711
+ eval($evalStr);
712
+ // instantiate proxy object
713
+ eval("\$proxy = new nusoap_proxy_$r('');");
714
+ // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
715
+ $proxy->endpointType = 'wsdl';
716
+ $proxy->wsdlFile = $this->wsdlFile;
717
+ $proxy->wsdl = $this->wsdl;
718
+ $proxy->operations = $this->operations;
719
+ $proxy->defaultRpcParams = $this->defaultRpcParams;
720
+ // transfer other state
721
+ $proxy->soap_defencoding = $this->soap_defencoding;
722
+ $proxy->username = $this->username;
723
+ $proxy->password = $this->password;
724
+ $proxy->authtype = $this->authtype;
725
+ $proxy->certRequest = $this->certRequest;
726
+ $proxy->requestHeaders = $this->requestHeaders;
727
+ $proxy->endpoint = $this->endpoint;
728
+ $proxy->forceEndpoint = $this->forceEndpoint;
729
+ $proxy->proxyhost = $this->proxyhost;
730
+ $proxy->proxyport = $this->proxyport;
731
+ $proxy->proxyusername = $this->proxyusername;
732
+ $proxy->proxypassword = $this->proxypassword;
733
+ $proxy->http_encoding = $this->http_encoding;
734
+ $proxy->timeout = $this->timeout;
735
+ $proxy->response_timeout = $this->response_timeout;
736
+ $proxy->persistentConnection = &$this->persistentConnection;
737
+ $proxy->decode_utf8 = $this->decode_utf8;
738
+ $proxy->curl_options = $this->curl_options;
739
+ $proxy->bindingType = $this->bindingType;
740
+ $proxy->use_curl = $this->use_curl;
741
+ return $proxy;
742
+ }
743
+
744
+ /**
745
+ * dynamically creates proxy class code
746
+ *
747
+ * @return string PHP/NuSOAP code for the proxy class
748
+ * @access private
749
+ */
750
+ function _getProxyClassCode($r) {
751
+ $this->debug("in getProxy endpointType=$this->endpointType");
752
+ $this->appendDebug("wsdl=" . $this->varDump($this->wsdl));
753
+ if ($this->endpointType != 'wsdl') {
754
+ $evalStr = 'A proxy can only be created for a WSDL client';
755
+ $this->setError($evalStr);
756
+ $evalStr = "echo \"$evalStr\";";
757
+ return $evalStr;
758
+ }
759
+ if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
760
+ $this->loadWSDL();
761
+ if ($this->getError()) {
762
+ return "echo \"" . $this->getError() . "\";";
763
+ }
764
+ }
765
+ $evalStr = '';
766
+ foreach ($this->operations as $operation => $opData) {
767
+ if ($operation != '') {
768
+ // create param string and param comment string
769
+ if (sizeof($opData['input']['parts']) > 0) {
770
+ $paramStr = '';
771
+ $paramArrayStr = '';
772
+ $paramCommentStr = '';
773
+ foreach ($opData['input']['parts'] as $name => $type) {
774
+ $paramStr .= "\$$name, ";
775
+ $paramArrayStr .= "'$name' => \$$name, ";
776
+ $paramCommentStr .= "$type \$$name, ";
777
+ }
778
+ $paramStr = substr($paramStr, 0, strlen($paramStr)-2);
779
+ $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr)-2);
780
+ $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2);
781
+ } else {
782
+ $paramStr = '';
783
+ $paramArrayStr = '';
784
+ $paramCommentStr = 'void';
785
+ }
786
+ $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
787
+ $evalStr .= "// $paramCommentStr
788
+ function " . str_replace('.', '__', $operation) . "($paramStr) {
789
+ \$params = array($paramArrayStr);
790
+ return \$this->call('$operation', \$params, '".$opData['namespace']."', '".(isset($opData['soapAction']) ? $opData['soapAction'] : '')."');
791
+ }
792
+ ";
793
+ unset($paramStr);
794
+ unset($paramCommentStr);
795
+ }
796
+ }
797
+ $evalStr = 'class nusoap_proxy_'.$r.' extends nusoap_client {
798
+ '.$evalStr.'
799
+ }';
800
+ return $evalStr;
801
+ }
802
+
803
+ /**
804
+ * dynamically creates proxy class code
805
+ *
806
+ * @return string PHP/NuSOAP code for the proxy class
807
+ * @access public
808
+ */
809
+ function getProxyClassCode() {
810
+ $r = rand();
811
+ return $this->_getProxyClassCode($r);
812
+ }
813
+
814
+ /**
815
+ * gets the HTTP body for the current request.
816
+ *
817
+ * @param string $soapmsg The SOAP payload
818
+ * @return string The HTTP body, which includes the SOAP payload
819
+ * @access private
820
+ */
821
+ function getHTTPBody($soapmsg) {
822
+ return $soapmsg;
823
+ }
824
+
825
+ /**
826
+ * gets the HTTP content type for the current request.
827
+ *
828
+ * Note: getHTTPBody must be called before this.
829
+ *
830
+ * @return string the HTTP content type for the current request.
831
+ * @access private
832
+ */
833
+ function getHTTPContentType() {
834
+ return 'text/xml';
835
+ }
836
+
837
+ /**
838
+ * gets the HTTP content type charset for the current request.
839
+ * returns false for non-text content types.
840
+ *
841
+ * Note: getHTTPBody must be called before this.
842
+ *
843
+ * @return string the HTTP content type charset for the current request.
844
+ * @access private
845
+ */
846
+ function getHTTPContentTypeCharset() {
847
+ return $this->soap_defencoding;
848
+ }
849
+
850
+ /*
851
+ * whether or not parser should decode utf8 element content
852
+ *
853
+ * @return always returns true
854
+ * @access public
855
+ */
856
+ function decodeUTF8($bool){
857
+ $this->decode_utf8 = $bool;
858
+ return true;
859
+ }
860
+
861
+ /**
862
+ * adds a new Cookie into $this->cookies array
863
+ *
864
+ * @param string $name Cookie Name
865
+ * @param string $value Cookie Value
866
+ * @return boolean if cookie-set was successful returns true, else false
867
+ * @access public
868
+ */
869
+ function setCookie($name, $value) {
870
+ if (strlen($name) == 0) {
871
+ return false;
872
+ }
873
+ $this->cookies[] = array('name' => $name, 'value' => $value);
874
+ return true;
875
+ }
876
+
877
+ /**
878
+ * gets all Cookies
879
+ *
880
+ * @return array with all internal cookies
881
+ * @access public
882
+ */
883
+ function getCookies() {
884
+ return $this->cookies;
885
+ }
886
+
887
+ /**
888
+ * checks all Cookies and delete those which are expired
889
+ *
890
+ * @return boolean always return true
891
+ * @access private
892
+ */
893
+ function checkCookies() {
894
+ if (sizeof($this->cookies) == 0) {
895
+ return true;
896
+ }
897
+ $this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies');
898
+ $curr_cookies = $this->cookies;
899
+ $this->cookies = array();
900
+ foreach ($curr_cookies as $cookie) {
901
+ if (! is_array($cookie)) {
902
+ $this->debug('Remove cookie that is not an array');
903
+ continue;
904
+ }
905
+ if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
906
+ if (strtotime($cookie['expires']) > time()) {
907
+ $this->cookies[] = $cookie;
908
+ } else {
909
+ $this->debug('Remove expired cookie ' . $cookie['name']);
910
+ }
911
+ } else {
912
+ $this->cookies[] = $cookie;
913
+ }
914
+ }
915
+ $this->debug('checkCookie: '.sizeof($this->cookies).' cookies left in array');
916
+ return true;
917
+ }
918
+
919
+ /**
920
+ * updates the current cookies with a new set
921
+ *
922
+ * @param array $cookies new cookies with which to update current ones
923
+ * @return boolean always return true
924
+ * @access private
925
+ */
926
+ function UpdateCookies($cookies) {
927
+ if (sizeof($this->cookies) == 0) {
928
+ // no existing cookies: take whatever is new
929
+ if (sizeof($cookies) > 0) {
930
+ $this->debug('Setting new cookie(s)');
931
+ $this->cookies = $cookies;
932
+ }
933
+ return true;
934
+ }
935
+ if (sizeof($cookies) == 0) {
936
+ // no new cookies: keep what we've got
937
+ return true;
938
+ }
939
+ // merge
940
+ foreach ($cookies as $newCookie) {
941
+ if (!is_array($newCookie)) {
942
+ continue;
943
+ }
944
+ if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) {
945
+ continue;
946
+ }
947
+ $newName = $newCookie['name'];
948
+
949
+ $found = false;
950
+ for ($i = 0; $i < count($this->cookies); $i++) {
951
+ $cookie = $this->cookies[$i];
952
+ if (!is_array($cookie)) {
953
+ continue;
954
+ }
955
+ if (!isset($cookie['name'])) {
956
+ continue;
957
+ }
958
+ if ($newName != $cookie['name']) {
959
+ continue;
960
+ }
961
+ $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN';
962
+ $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN';
963
+ if ($newDomain != $domain) {
964
+ continue;
965
+ }
966
+ $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH';
967
+ $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH';
968
+ if ($newPath != $path) {
969
+ continue;
970
+ }
971
+ $this->cookies[$i] = $newCookie;
972
+ $found = true;
973
+ $this->debug('Update cookie ' . $newName . '=' . $newCookie['value']);
974
+ break;
975
+ }
976
+ if (! $found) {
977
+ $this->debug('Add cookie ' . $newName . '=' . $newCookie['value']);
978
+ $this->cookies[] = $newCookie;
979
+ }
980
+ }
981
+ return true;
982
+ }
983
+ }
984
+
985
+ if (!extension_loaded('soap')) {
986
+ /**
987
+ * For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded.
988
+ */
989
+ class soapclient extends nusoap_client {
990
+ }
991
+ }
992
+ ?>
lib/nusoap/wsdl.php ADDED
@@ -0,0 +1,1919 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
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 suporte.developer@buscape-inc.com so we can send you a copy immediately.
14
+ *
15
+ * @category Buscape
16
+ * @package Buscape_Fcontrol
17
+ * @copyright Copyright (c) 2010 Buscapé Company (http://www.buscapecompany.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ /**
22
+ * parses a WSDL file, allows access to it's data, other utility methods.
23
+ * also builds WSDL structures programmatically.
24
+ *
25
+ * @author Dietrich Ayala <dietrich@ganx4.com>
26
+ * @author Scott Nichol <snichol@users.sourceforge.net>
27
+ * @version $Id: class.wsdl.php,v 1.69 2007/11/06 15:17:46 snichol Exp $
28
+ * @access public
29
+ */
30
+ class wsdl extends nusoap_base {
31
+ // URL or filename of the root of this WSDL
32
+ var $wsdl;
33
+ // define internal arrays of bindings, ports, operations, messages, etc.
34
+ var $schemas = array();
35
+ var $currentSchema;
36
+ var $message = array();
37
+ var $complexTypes = array();
38
+ var $messages = array();
39
+ var $currentMessage;
40
+ var $currentOperation;
41
+ var $portTypes = array();
42
+ var $currentPortType;
43
+ var $bindings = array();
44
+ var $currentBinding;
45
+ var $ports = array();
46
+ var $currentPort;
47
+ var $opData = array();
48
+ var $status = '';
49
+ var $documentation = false;
50
+ var $endpoint = '';
51
+ // array of wsdl docs to import
52
+ var $import = array();
53
+ // parser vars
54
+ var $parser;
55
+ var $position = 0;
56
+ var $depth = 0;
57
+ var $depth_array = array();
58
+ // for getting wsdl
59
+ var $proxyhost = '';
60
+ var $proxyport = '';
61
+ var $proxyusername = '';
62
+ var $proxypassword = '';
63
+ var $timeout = 0;
64
+ var $response_timeout = 30;
65
+ var $curl_options = array(); // User-specified cURL options
66
+ var $use_curl = false; // whether to always try to use cURL
67
+ // for HTTP authentication
68
+ var $username = ''; // Username for HTTP authentication
69
+ var $password = ''; // Password for HTTP authentication
70
+ var $authtype = ''; // Type of HTTP authentication
71
+ var $certRequest = array(); // Certificate for HTTP SSL authentication
72
+
73
+ /**
74
+ * constructor
75
+ *
76
+ * @param string $wsdl WSDL document URL
77
+ * @param string $proxyhost
78
+ * @param string $proxyport
79
+ * @param string $proxyusername
80
+ * @param string $proxypassword
81
+ * @param integer $timeout set the connection timeout
82
+ * @param integer $response_timeout set the response timeout
83
+ * @param array $curl_options user-specified cURL options
84
+ * @param boolean $use_curl try to use cURL
85
+ * @access public
86
+ */
87
+ function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30,$curl_options=null,$use_curl=false){
88
+ parent::nusoap_base();
89
+ $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
90
+ $this->proxyhost = $proxyhost;
91
+ $this->proxyport = $proxyport;
92
+ $this->proxyusername = $proxyusername;
93
+ $this->proxypassword = $proxypassword;
94
+ $this->timeout = $timeout;
95
+ $this->response_timeout = $response_timeout;
96
+ if (is_array($curl_options))
97
+ $this->curl_options = $curl_options;
98
+ $this->use_curl = $use_curl;
99
+ $this->fetchWSDL($wsdl);
100
+ }
101
+
102
+ /**
103
+ * fetches the WSDL document and parses it
104
+ *
105
+ * @access public
106
+ */
107
+ function fetchWSDL($wsdl) {
108
+ $this->debug("parse and process WSDL path=$wsdl");
109
+ $this->wsdl = $wsdl;
110
+ // parse wsdl file
111
+ if ($this->wsdl != "") {
112
+ $this->parseWSDL($this->wsdl);
113
+ }
114
+ // imports
115
+ // TODO: handle imports more properly, grabbing them in-line and nesting them
116
+ $imported_urls = array();
117
+ $imported = 1;
118
+ while ($imported > 0) {
119
+ $imported = 0;
120
+ // Schema imports
121
+ foreach ($this->schemas as $ns => $list) {
122
+ foreach ($list as $xs) {
123
+ $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
124
+ foreach ($xs->imports as $ns2 => $list2) {
125
+ for ($ii = 0; $ii < count($list2); $ii++) {
126
+ if (! $list2[$ii]['loaded']) {
127
+ $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
128
+ $url = $list2[$ii]['location'];
129
+ if ($url != '') {
130
+ $urlparts = parse_url($url);
131
+ if (!isset($urlparts['host'])) {
132
+ $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') .
133
+ substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
134
+ }
135
+ if (! in_array($url, $imported_urls)) {
136
+ $this->parseWSDL($url);
137
+ $imported++;
138
+ $imported_urls[] = $url;
139
+ }
140
+ } else {
141
+ $this->debug("Unexpected scenario: empty URL for unloaded import");
142
+ }
143
+ }
144
+ }
145
+ }
146
+ }
147
+ }
148
+ // WSDL imports
149
+ $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
150
+ foreach ($this->import as $ns => $list) {
151
+ for ($ii = 0; $ii < count($list); $ii++) {
152
+ if (! $list[$ii]['loaded']) {
153
+ $this->import[$ns][$ii]['loaded'] = true;
154
+ $url = $list[$ii]['location'];
155
+ if ($url != '') {
156
+ $urlparts = parse_url($url);
157
+ if (!isset($urlparts['host'])) {
158
+ $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
159
+ substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
160
+ }
161
+ if (! in_array($url, $imported_urls)) {
162
+ $this->parseWSDL($url);
163
+ $imported++;
164
+ $imported_urls[] = $url;
165
+ }
166
+ } else {
167
+ $this->debug("Unexpected scenario: empty URL for unloaded import");
168
+ }
169
+ }
170
+ }
171
+ }
172
+ }
173
+ // add new data to operation data
174
+ foreach($this->bindings as $binding => $bindingData) {
175
+ if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
176
+ foreach($bindingData['operations'] as $operation => $data) {
177
+ $this->debug('post-parse data gathering for ' . $operation);
178
+ $this->bindings[$binding]['operations'][$operation]['input'] =
179
+ isset($this->bindings[$binding]['operations'][$operation]['input']) ?
180
+ array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
181
+ $this->portTypes[ $bindingData['portType'] ][$operation]['input'];
182
+ $this->bindings[$binding]['operations'][$operation]['output'] =
183
+ isset($this->bindings[$binding]['operations'][$operation]['output']) ?
184
+ array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
185
+ $this->portTypes[ $bindingData['portType'] ][$operation]['output'];
186
+ if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])){
187
+ $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
188
+ }
189
+ if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])){
190
+ $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
191
+ }
192
+ // Set operation style if necessary, but do not override one already provided
193
+ if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) {
194
+ $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
195
+ }
196
+ $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
197
+ $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
198
+ $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
199
+ }
200
+ }
201
+ }
202
+ }
203
+
204
+ /**
205
+ * parses the wsdl document
206
+ *
207
+ * @param string $wsdl path or URL
208
+ * @access private
209
+ */
210
+ function parseWSDL($wsdl = '') {
211
+ $this->debug("parse WSDL at path=$wsdl");
212
+
213
+ if ($wsdl == '') {
214
+ $this->debug('no wsdl passed to parseWSDL()!!');
215
+ $this->setError('no wsdl passed to parseWSDL()!!');
216
+ return false;
217
+ }
218
+
219
+ // parse $wsdl for url format
220
+ $wsdl_props = parse_url($wsdl);
221
+
222
+ if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
223
+ $this->debug('getting WSDL http(s) URL ' . $wsdl);
224
+ // get wsdl
225
+ $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl);
226
+ $tr->request_method = 'GET';
227
+ $tr->useSOAPAction = false;
228
+ if($this->proxyhost && $this->proxyport){
229
+ $tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
230
+ }
231
+ if ($this->authtype != '') {
232
+ $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
233
+ }
234
+ $tr->setEncoding('gzip, deflate');
235
+ $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
236
+ //$this->debug("WSDL request\n" . $tr->outgoing_payload);
237
+ //$this->debug("WSDL response\n" . $tr->incoming_payload);
238
+ $this->appendDebug($tr->getDebug());
239
+ // catch errors
240
+ if($err = $tr->getError() ){
241
+ $errstr = 'HTTP ERROR: '.$err;
242
+ $this->debug($errstr);
243
+ $this->setError($errstr);
244
+ unset($tr);
245
+ return false;
246
+ }
247
+ unset($tr);
248
+ $this->debug("got WSDL URL");
249
+ } else {
250
+ // $wsdl is not http(s), so treat it as a file URL or plain file path
251
+ if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
252
+ $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
253
+ } else {
254
+ $path = $wsdl;
255
+ }
256
+ $this->debug('getting WSDL file ' . $path);
257
+ if ($fp = @fopen($path, 'r')) {
258
+ $wsdl_string = '';
259
+ while ($data = fread($fp, 32768)) {
260
+ $wsdl_string .= $data;
261
+ }
262
+ fclose($fp);
263
+ } else {
264
+ $errstr = "Bad path to WSDL file $path";
265
+ $this->debug($errstr);
266
+ $this->setError($errstr);
267
+ return false;
268
+ }
269
+ }
270
+ $this->debug('Parse WSDL');
271
+ // end new code added
272
+ // Create an XML parser.
273
+ $this->parser = xml_parser_create();
274
+ // Set the options for parsing the XML data.
275
+ // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
276
+ xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
277
+ // Set the object for the parser.
278
+ xml_set_object($this->parser, $this);
279
+ // Set the element handlers for the parser.
280
+ xml_set_element_handler($this->parser, 'start_element', 'end_element');
281
+ xml_set_character_data_handler($this->parser, 'character_data');
282
+ // Parse the XML file.
283
+ if (!xml_parse($this->parser, $wsdl_string, true)) {
284
+ // Display an error message.
285
+ $errstr = sprintf(
286
+ 'XML error parsing WSDL from %s on line %d: %s',
287
+ $wsdl,
288
+ xml_get_current_line_number($this->parser),
289
+ xml_error_string(xml_get_error_code($this->parser))
290
+ );
291
+ $this->debug($errstr);
292
+ $this->debug("XML payload:\n" . $wsdl_string);
293
+ $this->setError($errstr);
294
+ return false;
295
+ }
296
+ // free the parser
297
+ xml_parser_free($this->parser);
298
+ $this->debug('Parsing WSDL done');
299
+ // catch wsdl parse errors
300
+ if($this->getError()){
301
+ return false;
302
+ }
303
+ return true;
304
+ }
305
+
306
+ /**
307
+ * start-element handler
308
+ *
309
+ * @param string $parser XML parser object
310
+ * @param string $name element name
311
+ * @param string $attrs associative array of attributes
312
+ * @access private
313
+ */
314
+ function start_element($parser, $name, $attrs)
315
+ {
316
+ if ($this->status == 'schema') {
317
+ $this->currentSchema->schemaStartElement($parser, $name, $attrs);
318
+ $this->appendDebug($this->currentSchema->getDebug());
319
+ $this->currentSchema->clearDebug();
320
+ } elseif (ereg('schema$', $name)) {
321
+ $this->debug('Parsing WSDL schema');
322
+ // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
323
+ $this->status = 'schema';
324
+ $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
325
+ $this->currentSchema->schemaStartElement($parser, $name, $attrs);
326
+ $this->appendDebug($this->currentSchema->getDebug());
327
+ $this->currentSchema->clearDebug();
328
+ } else {
329
+ // position in the total number of elements, starting from 0
330
+ $pos = $this->position++;
331
+ $depth = $this->depth++;
332
+ // set self as current value for this depth
333
+ $this->depth_array[$depth] = $pos;
334
+ $this->message[$pos] = array('cdata' => '');
335
+ // process attributes
336
+ if (count($attrs) > 0) {
337
+ // register namespace declarations
338
+ foreach($attrs as $k => $v) {
339
+ if (ereg("^xmlns", $k)) {
340
+ if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
341
+ $this->namespaces[$ns_prefix] = $v;
342
+ } else {
343
+ $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
344
+ }
345
+ if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
346
+ $this->XMLSchemaVersion = $v;
347
+ $this->namespaces['xsi'] = $v . '-instance';
348
+ }
349
+ }
350
+ }
351
+ // expand each attribute prefix to its namespace
352
+ foreach($attrs as $k => $v) {
353
+ $k = strpos($k, ':') ? $this->expandQname($k) : $k;
354
+ if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
355
+ $v = strpos($v, ':') ? $this->expandQname($v) : $v;
356
+ }
357
+ $eAttrs[$k] = $v;
358
+ }
359
+ $attrs = $eAttrs;
360
+ } else {
361
+ $attrs = array();
362
+ }
363
+ // get element prefix, namespace and name
364
+ if (ereg(':', $name)) {
365
+ // get ns prefix
366
+ $prefix = substr($name, 0, strpos($name, ':'));
367
+ // get ns
368
+ $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : '';
369
+ // get unqualified name
370
+ $name = substr(strstr($name, ':'), 1);
371
+ }
372
+ // process attributes, expanding any prefixes to namespaces
373
+ // find status, register data
374
+ switch ($this->status) {
375
+ case 'message':
376
+ if ($name == 'part') {
377
+ if (isset($attrs['type'])) {
378
+ $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs));
379
+ $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
380
+ }
381
+ if (isset($attrs['element'])) {
382
+ $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));
383
+ $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';
384
+ }
385
+ }
386
+ break;
387
+ case 'portType':
388
+ switch ($name) {
389
+ case 'operation':
390
+ $this->currentPortOperation = $attrs['name'];
391
+ $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
392
+ if (isset($attrs['parameterOrder'])) {
393
+ $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
394
+ }
395
+ break;
396
+ case 'documentation':
397
+ $this->documentation = true;
398
+ break;
399
+ // merge input/output data
400
+ default:
401
+ $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
402
+ $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
403
+ break;
404
+ }
405
+ break;
406
+ case 'binding':
407
+ switch ($name) {
408
+ case 'binding':
409
+ // get ns prefix
410
+ if (isset($attrs['style'])) {
411
+ $this->bindings[$this->currentBinding]['prefix'] = $prefix;
412
+ }
413
+ $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
414
+ break;
415
+ case 'header':
416
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
417
+ break;
418
+ case 'operation':
419
+ if (isset($attrs['soapAction'])) {
420
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
421
+ }
422
+ if (isset($attrs['style'])) {
423
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
424
+ }
425
+ if (isset($attrs['name'])) {
426
+ $this->currentOperation = $attrs['name'];
427
+ $this->debug("current binding operation: $this->currentOperation");
428
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
429
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
430
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
431
+ }
432
+ break;
433
+ case 'input':
434
+ $this->opStatus = 'input';
435
+ break;
436
+ case 'output':
437
+ $this->opStatus = 'output';
438
+ break;
439
+ case 'body':
440
+ if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
441
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
442
+ } else {
443
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
444
+ }
445
+ break;
446
+ }
447
+ break;
448
+ case 'service':
449
+ switch ($name) {
450
+ case 'port':
451
+ $this->currentPort = $attrs['name'];
452
+ $this->debug('current port: ' . $this->currentPort);
453
+ $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
454
+
455
+ break;
456
+ case 'address':
457
+ $this->ports[$this->currentPort]['location'] = $attrs['location'];
458
+ $this->ports[$this->currentPort]['bindingType'] = $namespace;
459
+ $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;
460
+ $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
461
+ break;
462
+ }
463
+ break;
464
+ }
465
+ // set status
466
+ switch ($name) {
467
+ case 'import':
468
+ if (isset($attrs['location'])) {
469
+ $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
470
+ $this->debug('parsing import ' . $attrs['namespace']. ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]).')');
471
+ } else {
472
+ $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
473
+ if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
474
+ $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
475
+ }
476
+ $this->debug('parsing import ' . $attrs['namespace']. ' - [no location] (' . count($this->import[$attrs['namespace']]).')');
477
+ }
478
+ break;
479
+ //wait for schema
480
+ //case 'types':
481
+ // $this->status = 'schema';
482
+ // break;
483
+ case 'message':
484
+ $this->status = 'message';
485
+ $this->messages[$attrs['name']] = array();
486
+ $this->currentMessage = $attrs['name'];
487
+ break;
488
+ case 'portType':
489
+ $this->status = 'portType';
490
+ $this->portTypes[$attrs['name']] = array();
491
+ $this->currentPortType = $attrs['name'];
492
+ break;
493
+ case "binding":
494
+ if (isset($attrs['name'])) {
495
+ // get binding name
496
+ if (strpos($attrs['name'], ':')) {
497
+ $this->currentBinding = $this->getLocalPart($attrs['name']);
498
+ } else {
499
+ $this->currentBinding = $attrs['name'];
500
+ }
501
+ $this->status = 'binding';
502
+ $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
503
+ $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
504
+ }
505
+ break;
506
+ case 'service':
507
+ $this->serviceName = $attrs['name'];
508
+ $this->status = 'service';
509
+ $this->debug('current service: ' . $this->serviceName);
510
+ break;
511
+ case 'definitions':
512
+ foreach ($attrs as $name => $value) {
513
+ $this->wsdl_info[$name] = $value;
514
+ }
515
+ break;
516
+ }
517
+ }
518
+ }
519
+
520
+ /**
521
+ * end-element handler
522
+ *
523
+ * @param string $parser XML parser object
524
+ * @param string $name element name
525
+ * @access private
526
+ */
527
+ function end_element($parser, $name){
528
+ // unset schema status
529
+ if (/*ereg('types$', $name) ||*/ ereg('schema$', $name)) {
530
+ $this->status = "";
531
+ $this->appendDebug($this->currentSchema->getDebug());
532
+ $this->currentSchema->clearDebug();
533
+ $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
534
+ $this->debug('Parsing WSDL schema done');
535
+ }
536
+ if ($this->status == 'schema') {
537
+ $this->currentSchema->schemaEndElement($parser, $name);
538
+ } else {
539
+ // bring depth down a notch
540
+ $this->depth--;
541
+ }
542
+ // end documentation
543
+ if ($this->documentation) {
544
+ //TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
545
+ //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
546
+ $this->documentation = false;
547
+ }
548
+ }
549
+
550
+ /**
551
+ * element content handler
552
+ *
553
+ * @param string $parser XML parser object
554
+ * @param string $data element content
555
+ * @access private
556
+ */
557
+ function character_data($parser, $data)
558
+ {
559
+ $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
560
+ if (isset($this->message[$pos]['cdata'])) {
561
+ $this->message[$pos]['cdata'] .= $data;
562
+ }
563
+ if ($this->documentation) {
564
+ $this->documentation .= $data;
565
+ }
566
+ }
567
+
568
+ /**
569
+ * if authenticating, set user credentials here
570
+ *
571
+ * @param string $username
572
+ * @param string $password
573
+ * @param string $authtype (basic|digest|certificate|ntlm)
574
+ * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
575
+ * @access public
576
+ */
577
+ function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
578
+ $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
579
+ $this->appendDebug($this->varDump($certRequest));
580
+ $this->username = $username;
581
+ $this->password = $password;
582
+ $this->authtype = $authtype;
583
+ $this->certRequest = $certRequest;
584
+ }
585
+
586
+ function getBindingData($binding)
587
+ {
588
+ if (is_array($this->bindings[$binding])) {
589
+ return $this->bindings[$binding];
590
+ }
591
+ }
592
+
593
+ /**
594
+ * returns an assoc array of operation names => operation data
595
+ *
596
+ * @param string $bindingType eg: soap, smtp, dime (only soap and soap12 are currently supported)
597
+ * @return array
598
+ * @access public
599
+ */
600
+ function getOperations($bindingType = 'soap') {
601
+ $ops = array();
602
+ if ($bindingType == 'soap') {
603
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
604
+ } elseif ($bindingType == 'soap12') {
605
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
606
+ }
607
+ // loop thru ports
608
+ foreach($this->ports as $port => $portData) {
609
+ // binding type of port matches parameter
610
+ if ($portData['bindingType'] == $bindingType) {
611
+ //$this->debug("getOperations for port $port");
612
+ //$this->debug("port data: " . $this->varDump($portData));
613
+ //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
614
+ // merge bindings
615
+ if (isset($this->bindings[ $portData['binding'] ]['operations'])) {
616
+ $ops = array_merge ($ops, $this->bindings[ $portData['binding'] ]['operations']);
617
+ }
618
+ }
619
+ }
620
+ return $ops;
621
+ }
622
+
623
+ /**
624
+ * returns an associative array of data necessary for calling an operation
625
+ *
626
+ * @param string $operation name of operation
627
+ * @param string $bindingType type of binding eg: soap, soap12
628
+ * @return array
629
+ * @access public
630
+ */
631
+ function getOperationData($operation, $bindingType = 'soap')
632
+ {
633
+ if ($bindingType == 'soap') {
634
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
635
+ } elseif ($bindingType == 'soap12') {
636
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
637
+ }
638
+ // loop thru ports
639
+ foreach($this->ports as $port => $portData) {
640
+ // binding type of port matches parameter
641
+ if ($portData['bindingType'] == $bindingType) {
642
+ // get binding
643
+ //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
644
+ foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {
645
+ // note that we could/should also check the namespace here
646
+ if ($operation == $bOperation) {
647
+ $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];
648
+ return $opData;
649
+ }
650
+ }
651
+ }
652
+ }
653
+ }
654
+
655
+ /**
656
+ * returns an associative array of data necessary for calling an operation
657
+ *
658
+ * @param string $soapAction soapAction for operation
659
+ * @param string $bindingType type of binding eg: soap, soap12
660
+ * @return array
661
+ * @access public
662
+ */
663
+ function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') {
664
+ if ($bindingType == 'soap') {
665
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
666
+ } elseif ($bindingType == 'soap12') {
667
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
668
+ }
669
+ // loop thru ports
670
+ foreach($this->ports as $port => $portData) {
671
+ // binding type of port matches parameter
672
+ if ($portData['bindingType'] == $bindingType) {
673
+ // loop through operations for the binding
674
+ foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
675
+ if ($opData['soapAction'] == $soapAction) {
676
+ return $opData;
677
+ }
678
+ }
679
+ }
680
+ }
681
+ }
682
+
683
+ /**
684
+ * returns an array of information about a given type
685
+ * returns false if no type exists by the given name
686
+ *
687
+ * typeDef = array(
688
+ * 'elements' => array(), // refs to elements array
689
+ * 'restrictionBase' => '',
690
+ * 'phpType' => '',
691
+ * 'order' => '(sequence|all)',
692
+ * 'attrs' => array() // refs to attributes array
693
+ * )
694
+ *
695
+ * @param string $type the type
696
+ * @param string $ns namespace (not prefix) of the type
697
+ * @return mixed
698
+ * @access public
699
+ * @see nusoap_xmlschema
700
+ */
701
+ function getTypeDef($type, $ns) {
702
+ $this->debug("in getTypeDef: type=$type, ns=$ns");
703
+ if ((! $ns) && isset($this->namespaces['tns'])) {
704
+ $ns = $this->namespaces['tns'];
705
+ $this->debug("in getTypeDef: type namespace forced to $ns");
706
+ }
707
+ if (!isset($this->schemas[$ns])) {
708
+ foreach ($this->schemas as $ns0 => $schema0) {
709
+ if (strcasecmp($ns, $ns0) == 0) {
710
+ $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0");
711
+ $ns = $ns0;
712
+ break;
713
+ }
714
+ }
715
+ }
716
+ if (isset($this->schemas[$ns])) {
717
+ $this->debug("in getTypeDef: have schema for namespace $ns");
718
+ for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
719
+ $xs = &$this->schemas[$ns][$i];
720
+ $t = $xs->getTypeDef($type);
721
+ //$this->appendDebug($xs->getDebug());
722
+ //$xs->clearDebug();
723
+ if ($t) {
724
+ if (!isset($t['phpType'])) {
725
+ // get info for type to tack onto the element
726
+ $uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
727
+ $ns = substr($t['type'], 0, strrpos($t['type'], ':'));
728
+ $etype = $this->getTypeDef($uqType, $ns);
729
+ if ($etype) {
730
+ $this->debug("found type for [element] $type:");
731
+ $this->debug($this->varDump($etype));
732
+ if (isset($etype['phpType'])) {
733
+ $t['phpType'] = $etype['phpType'];
734
+ }
735
+ if (isset($etype['elements'])) {
736
+ $t['elements'] = $etype['elements'];
737
+ }
738
+ if (isset($etype['attrs'])) {
739
+ $t['attrs'] = $etype['attrs'];
740
+ }
741
+ }
742
+ }
743
+ return $t;
744
+ }
745
+ }
746
+ } else {
747
+ $this->debug("in getTypeDef: do not have schema for namespace $ns");
748
+ }
749
+ return false;
750
+ }
751
+
752
+ /**
753
+ * prints html description of services
754
+ *
755
+ * @access private
756
+ */
757
+ function webDescription(){
758
+ global $HTTP_SERVER_VARS;
759
+
760
+ if (isset($_SERVER)) {
761
+ $PHP_SELF = $_SERVER['PHP_SELF'];
762
+ } elseif (isset($HTTP_SERVER_VARS)) {
763
+ $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
764
+ } else {
765
+ $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
766
+ }
767
+
768
+ $b = '
769
+ <html><head><title>NuSOAP: '.$this->serviceName.'</title>
770
+ <style type="text/css">
771
+ body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
772
+ p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
773
+ pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
774
+ ul { margin-top: 10px; margin-left: 20px; }
775
+ li { list-style-type: none; margin-top: 10px; color: #000000; }
776
+ .content{
777
+ margin-left: 0px; padding-bottom: 2em; }
778
+ .nav {
779
+ padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
780
+ margin-top: 10px; margin-left: 0px; color: #000000;
781
+ background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
782
+ .title {
783
+ font-family: arial; font-size: 26px; color: #ffffff;
784
+ background-color: #999999; width: 105%; margin-left: 0px;
785
+ padding-top: 10px; padding-bottom: 10px; padding-left: 15px;}
786
+ .hidden {
787
+ position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
788
+ font-family: arial; overflow: hidden; width: 600;
789
+ padding: 20px; font-size: 10px; background-color: #999999;
790
+ layer-background-color:#FFFFFF; }
791
+ a,a:active { color: charcoal; font-weight: bold; }
792
+ a:visited { color: #666666; font-weight: bold; }
793
+ a:hover { color: cc3300; font-weight: bold; }
794
+ </style>
795
+ <script language="JavaScript" type="text/javascript">
796
+ <!--
797
+ // POP-UP CAPTIONS...
798
+ function lib_bwcheck(){ //Browsercheck (needed)
799
+ this.ver=navigator.appVersion
800
+ this.agent=navigator.userAgent
801
+ this.dom=document.getElementById?1:0
802
+ this.opera5=this.agent.indexOf("Opera 5")>-1
803
+ this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
804
+ this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
805
+ this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
806
+ this.ie=this.ie4||this.ie5||this.ie6
807
+ this.mac=this.agent.indexOf("Mac")>-1
808
+ this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
809
+ this.ns4=(document.layers && !this.dom)?1:0;
810
+ this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
811
+ return this
812
+ }
813
+ var bw = new lib_bwcheck()
814
+ //Makes crossbrowser object.
815
+ function makeObj(obj){
816
+ this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
817
+ if(!this.evnt) return false
818
+ this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
819
+ this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
820
+ this.writeIt=b_writeIt;
821
+ return this
822
+ }
823
+ // A unit of measure that will be added when setting the position of a layer.
824
+ //var px = bw.ns4||window.opera?"":"px";
825
+ function b_writeIt(text){
826
+ if (bw.ns4){this.wref.write(text);this.wref.close()}
827
+ else this.wref.innerHTML = text
828
+ }
829
+ //Shows the messages
830
+ var oDesc;
831
+ function popup(divid){
832
+ if(oDesc = new makeObj(divid)){
833
+ oDesc.css.visibility = "visible"
834
+ }
835
+ }
836
+ function popout(){ // Hides message
837
+ if(oDesc) oDesc.css.visibility = "hidden"
838
+ }
839
+ //-->
840
+ </script>
841
+ </head>
842
+ <body>
843
+ <div class=content>
844
+ <br><br>
845
+ <div class=title>'.$this->serviceName.'</div>
846
+ <div class=nav>
847
+ <p>View the <a href="'.$PHP_SELF.'?wsdl">WSDL</a> for the service.
848
+ Click on an operation name to view it&apos;s details.</p>
849
+ <ul>';
850
+ foreach($this->getOperations() as $op => $data){
851
+ $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
852
+ // create hidden div
853
+ $b .= "<div id='$op' class='hidden'>
854
+ <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
855
+ foreach($data as $donnie => $marie){ // loop through opdata
856
+ if($donnie == 'input' || $donnie == 'output'){ // show input/output data
857
+ $b .= "<font color='white'>".ucfirst($donnie).':</font><br>';
858
+ foreach($marie as $captain => $tenille){ // loop through data
859
+ if($captain == 'parts'){ // loop thru parts
860
+ $b .= "&nbsp;&nbsp;$captain:<br>";
861
+ //if(is_array($tenille)){
862
+ foreach($tenille as $joanie => $chachi){
863
+ $b .= "&nbsp;&nbsp;&nbsp;&nbsp;$joanie: $chachi<br>";
864
+ }
865
+ //}
866
+ } else {
867
+ $b .= "&nbsp;&nbsp;$captain: $tenille<br>";
868
+ }
869
+ }
870
+ } else {
871
+ $b .= "<font color='white'>".ucfirst($donnie).":</font> $marie<br>";
872
+ }
873
+ }
874
+ $b .= '</div>';
875
+ }
876
+ $b .= '
877
+ <ul>
878
+ </div>
879
+ </div></body></html>';
880
+ return $b;
881
+ }
882
+
883
+ /**
884
+ * serialize the parsed wsdl
885
+ *
886
+ * @param mixed $debug whether to put debug=1 in endpoint URL
887
+ * @return string serialization of WSDL
888
+ * @access public
889
+ */
890
+ function serialize($debug = 0)
891
+ {
892
+ $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
893
+ $xml .= "\n<definitions";
894
+ foreach($this->namespaces as $k => $v) {
895
+ $xml .= " xmlns:$k=\"$v\"";
896
+ }
897
+ // 10.9.02 - add poulter fix for wsdl and tns declarations
898
+ if (isset($this->namespaces['wsdl'])) {
899
+ $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
900
+ }
901
+ if (isset($this->namespaces['tns'])) {
902
+ $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
903
+ }
904
+ $xml .= '>';
905
+ // imports
906
+ if (sizeof($this->import) > 0) {
907
+ foreach($this->import as $ns => $list) {
908
+ foreach ($list as $ii) {
909
+ if ($ii['location'] != '') {
910
+ $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
911
+ } else {
912
+ $xml .= '<import namespace="' . $ns . '" />';
913
+ }
914
+ }
915
+ }
916
+ }
917
+ // types
918
+ if (count($this->schemas)>=1) {
919
+ $xml .= "\n<types>\n";
920
+ foreach ($this->schemas as $ns => $list) {
921
+ foreach ($list as $xs) {
922
+ $xml .= $xs->serializeSchema();
923
+ }
924
+ }
925
+ $xml .= '</types>';
926
+ }
927
+ // messages
928
+ if (count($this->messages) >= 1) {
929
+ foreach($this->messages as $msgName => $msgParts) {
930
+ $xml .= "\n<message name=\"" . $msgName . '">';
931
+ if(is_array($msgParts)){
932
+ foreach($msgParts as $partName => $partType) {
933
+ // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
934
+ if (strpos($partType, ':')) {
935
+ $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
936
+ } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
937
+ // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
938
+ $typePrefix = 'xsd';
939
+ } else {
940
+ foreach($this->typemap as $ns => $types) {
941
+ if (isset($types[$partType])) {
942
+ $typePrefix = $this->getPrefixFromNamespace($ns);
943
+ }
944
+ }
945
+ if (!isset($typePrefix)) {
946
+ die("$partType has no namespace!");
947
+ }
948
+ }
949
+ $ns = $this->getNamespaceFromPrefix($typePrefix);
950
+ $localPart = $this->getLocalPart($partType);
951
+ $typeDef = $this->getTypeDef($localPart, $ns);
952
+ if ($typeDef['typeClass'] == 'element') {
953
+ $elementortype = 'element';
954
+ if (substr($localPart, -1) == '^') {
955
+ $localPart = substr($localPart, 0, -1);
956
+ }
957
+ } else {
958
+ $elementortype = 'type';
959
+ }
960
+ $xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
961
+ }
962
+ }
963
+ $xml .= '</message>';
964
+ }
965
+ }
966
+ // bindings & porttypes
967
+ if (count($this->bindings) >= 1) {
968
+ $binding_xml = '';
969
+ $portType_xml = '';
970
+ foreach($this->bindings as $bindingName => $attrs) {
971
+ $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
972
+ $binding_xml .= "\n" . ' <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
973
+ $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
974
+ foreach($attrs['operations'] as $opName => $opParts) {
975
+ $binding_xml .= "\n" . ' <operation name="' . $opName . '">';
976
+ $binding_xml .= "\n" . ' <soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $opParts['style'] . '"/>';
977
+ if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
978
+ $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
979
+ } else {
980
+ $enc_style = '';
981
+ }
982
+ $binding_xml .= "\n" . ' <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
983
+ if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
984
+ $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
985
+ } else {
986
+ $enc_style = '';
987
+ }
988
+ $binding_xml .= "\n" . ' <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
989
+ $binding_xml .= "\n" . ' </operation>';
990
+ $portType_xml .= "\n" . ' <operation name="' . $opParts['name'] . '"';
991
+ if (isset($opParts['parameterOrder'])) {
992
+ $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
993
+ }
994
+ $portType_xml .= '>';
995
+ if(isset($opParts['documentation']) && $opParts['documentation'] != '') {
996
+ $portType_xml .= "\n" . ' <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
997
+ }
998
+ $portType_xml .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>';
999
+ $portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>';
1000
+ $portType_xml .= "\n" . ' </operation>';
1001
+ }
1002
+ $portType_xml .= "\n" . '</portType>';
1003
+ $binding_xml .= "\n" . '</binding>';
1004
+ }
1005
+ $xml .= $portType_xml . $binding_xml;
1006
+ }
1007
+ // services
1008
+ $xml .= "\n<service name=\"" . $this->serviceName . '">';
1009
+ if (count($this->ports) >= 1) {
1010
+ foreach($this->ports as $pName => $attrs) {
1011
+ $xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
1012
+ $xml .= "\n" . ' <soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>';
1013
+ $xml .= "\n" . ' </port>';
1014
+ }
1015
+ }
1016
+ $xml .= "\n" . '</service>';
1017
+ return $xml . "\n</definitions>";
1018
+ }
1019
+
1020
+ /**
1021
+ * determine whether a set of parameters are unwrapped
1022
+ * when they are expect to be wrapped, Microsoft-style.
1023
+ *
1024
+ * @param string $type the type (element name) of the wrapper
1025
+ * @param array $parameters the parameter values for the SOAP call
1026
+ * @return boolean whether they parameters are unwrapped (and should be wrapped)
1027
+ * @access private
1028
+ */
1029
+ function parametersMatchWrapped($type, &$parameters) {
1030
+ $this->debug("in parametersMatchWrapped type=$type, parameters=");
1031
+ $this->appendDebug($this->varDump($parameters));
1032
+
1033
+ // split type into namespace:unqualified-type
1034
+ if (strpos($type, ':')) {
1035
+ $uqType = substr($type, strrpos($type, ':') + 1);
1036
+ $ns = substr($type, 0, strrpos($type, ':'));
1037
+ $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns");
1038
+ if ($this->getNamespaceFromPrefix($ns)) {
1039
+ $ns = $this->getNamespaceFromPrefix($ns);
1040
+ $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns");
1041
+ }
1042
+ } else {
1043
+ // TODO: should the type be compared to types in XSD, and the namespace
1044
+ // set to XSD if the type matches?
1045
+ $this->debug("in parametersMatchWrapped: No namespace for type $type");
1046
+ $ns = '';
1047
+ $uqType = $type;
1048
+ }
1049
+
1050
+ // get the type information
1051
+ if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
1052
+ $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type.");
1053
+ return false;
1054
+ }
1055
+ $this->debug("in parametersMatchWrapped: found typeDef=");
1056
+ $this->appendDebug($this->varDump($typeDef));
1057
+ if (substr($uqType, -1) == '^') {
1058
+ $uqType = substr($uqType, 0, -1);
1059
+ }
1060
+ $phpType = $typeDef['phpType'];
1061
+ $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '');
1062
+ $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType");
1063
+
1064
+ // we expect a complexType or element of complexType
1065
+ if ($phpType != 'struct') {
1066
+ $this->debug("in parametersMatchWrapped: not a struct");
1067
+ return false;
1068
+ }
1069
+
1070
+ // see whether the parameter names match the elements
1071
+ if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
1072
+ $elements = 0;
1073
+ $matches = 0;
1074
+ $change = false;
1075
+ if ($this->isArraySimpleOrStruct($parameters) == 'arraySimple' && count($parameters) == count($typeDef['elements'])) {
1076
+ $this->debug("in parametersMatchWrapped: (wrapped return value kludge) correct number of elements in simple array, so change array and wrap");
1077
+ $change = true;
1078
+ }
1079
+ foreach ($typeDef['elements'] as $name => $attrs) {
1080
+ if ($change) {
1081
+ $this->debug("in parametersMatchWrapped: change parameter $element to name $name");
1082
+ $parameters[$name] = $parameters[$elements];
1083
+ unset($parameters[$elements]);
1084
+ $matches++;
1085
+ } elseif (isset($parameters[$name])) {
1086
+ $this->debug("in parametersMatchWrapped: have parameter named $name");
1087
+ $matches++;
1088
+ } else {
1089
+ $this->debug("in parametersMatchWrapped: do not have parameter named $name");
1090
+ }
1091
+ $elements++;
1092
+ }
1093
+
1094
+ $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names");
1095
+ if ($matches == 0) {
1096
+ return false;
1097
+ }
1098
+ return true;
1099
+ }
1100
+
1101
+ // since there are no elements for the type, if the user passed no
1102
+ // parameters, the parameters match wrapped.
1103
+ $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType");
1104
+ return count($parameters) == 0;
1105
+ }
1106
+
1107
+ /**
1108
+ * serialize PHP values according to a WSDL message definition
1109
+ * contrary to the method name, this is not limited to RPC
1110
+ *
1111
+ * TODO
1112
+ * - multi-ref serialization
1113
+ * - validate PHP values against type definitions, return errors if invalid
1114
+ *
1115
+ * @param string $operation operation name
1116
+ * @param string $direction (input|output)
1117
+ * @param mixed $parameters parameter value(s)
1118
+ * @param string $bindingType (soap|soap12)
1119
+ * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
1120
+ * @access public
1121
+ */
1122
+ function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap') {
1123
+ $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");
1124
+ $this->appendDebug('parameters=' . $this->varDump($parameters));
1125
+
1126
+ if ($direction != 'input' && $direction != 'output') {
1127
+ $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
1128
+ $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
1129
+ return false;
1130
+ }
1131
+ if (!$opData = $this->getOperationData($operation, $bindingType)) {
1132
+ $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
1133
+ $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
1134
+ return false;
1135
+ }
1136
+ $this->debug('in serializeRPCParameters: opData:');
1137
+ $this->appendDebug($this->varDump($opData));
1138
+
1139
+ // Get encoding style for output and set to current
1140
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
1141
+ if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
1142
+ $encodingStyle = $opData['output']['encodingStyle'];
1143
+ $enc_style = $encodingStyle;
1144
+ }
1145
+
1146
+ // set input params
1147
+ $xml = '';
1148
+ if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
1149
+ $parts = &$opData[$direction]['parts'];
1150
+ $part_count = sizeof($parts);
1151
+ $style = $opData['style'];
1152
+ $use = $opData[$direction]['use'];
1153
+ $this->debug("have $part_count part(s) to serialize using $style/$use");
1154
+ if (is_array($parameters)) {
1155
+ $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
1156
+ $parameter_count = count($parameters);
1157
+ $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize");
1158
+ // check for Microsoft-style wrapped parameters
1159
+ if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) {
1160
+ $this->debug('check whether the caller has wrapped the parameters');
1161
+ if ((($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) || ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1)) {
1162
+ $this->debug('check whether caller\'s parameters match the wrapped ones');
1163
+ if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) {
1164
+ $this->debug('wrap the parameters for the caller');
1165
+ $parameters = array('parameters' => $parameters);
1166
+ $parameter_count = 1;
1167
+ }
1168
+ }
1169
+ }
1170
+ foreach ($parts as $name => $type) {
1171
+ $this->debug("serializing part $name of type $type");
1172
+ // Track encoding style
1173
+ if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
1174
+ $encodingStyle = $opData[$direction]['encodingStyle'];
1175
+ $enc_style = $encodingStyle;
1176
+ } else {
1177
+ $enc_style = false;
1178
+ }
1179
+ // NOTE: add error handling here
1180
+ // if serializeType returns false, then catch global error and fault
1181
+ if ($parametersArrayType == 'arraySimple') {
1182
+ $p = array_shift($parameters);
1183
+ $this->debug('calling serializeType w/indexed param');
1184
+ $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
1185
+ } elseif (isset($parameters[$name])) {
1186
+ $this->debug('calling serializeType w/named param');
1187
+ $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
1188
+ } else {
1189
+ // TODO: only send nillable
1190
+ $this->debug('calling serializeType w/null param');
1191
+ $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
1192
+ }
1193
+ }
1194
+ } else {
1195
+ $this->debug('no parameters passed.');
1196
+ }
1197
+ }
1198
+ $this->debug("serializeRPCParameters returning: $xml");
1199
+ return $xml;
1200
+ }
1201
+
1202
+ /**
1203
+ * serialize a PHP value according to a WSDL message definition
1204
+ *
1205
+ * TODO
1206
+ * - multi-ref serialization
1207
+ * - validate PHP values against type definitions, return errors if invalid
1208
+ *
1209
+ * @param string $operation operation name
1210
+ * @param string $direction (input|output)
1211
+ * @param mixed $parameters parameter value(s)
1212
+ * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
1213
+ * @access public
1214
+ * @deprecated
1215
+ */
1216
+ function serializeParameters($operation, $direction, $parameters)
1217
+ {
1218
+ $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
1219
+ $this->appendDebug('parameters=' . $this->varDump($parameters));
1220
+
1221
+ if ($direction != 'input' && $direction != 'output') {
1222
+ $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
1223
+ $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
1224
+ return false;
1225
+ }
1226
+ if (!$opData = $this->getOperationData($operation)) {
1227
+ $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
1228
+ $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
1229
+ return false;
1230
+ }
1231
+ $this->debug('opData:');
1232
+ $this->appendDebug($this->varDump($opData));
1233
+
1234
+ // Get encoding style for output and set to current
1235
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
1236
+ if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
1237
+ $encodingStyle = $opData['output']['encodingStyle'];
1238
+ $enc_style = $encodingStyle;
1239
+ }
1240
+
1241
+ // set input params
1242
+ $xml = '';
1243
+ if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
1244
+
1245
+ $use = $opData[$direction]['use'];
1246
+ $this->debug("use=$use");
1247
+ $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
1248
+ if (is_array($parameters)) {
1249
+ $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
1250
+ $this->debug('have ' . $parametersArrayType . ' parameters');
1251
+ foreach($opData[$direction]['parts'] as $name => $type) {
1252
+ $this->debug('serializing part "'.$name.'" of type "'.$type.'"');
1253
+ // Track encoding style
1254
+ if(isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
1255
+ $encodingStyle = $opData[$direction]['encodingStyle'];
1256
+ $enc_style = $encodingStyle;
1257
+ } else {
1258
+ $enc_style = false;
1259
+ }
1260
+ // NOTE: add error handling here
1261
+ // if serializeType returns false, then catch global error and fault
1262
+ if ($parametersArrayType == 'arraySimple') {
1263
+ $p = array_shift($parameters);
1264
+ $this->debug('calling serializeType w/indexed param');
1265
+ $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
1266
+ } elseif (isset($parameters[$name])) {
1267
+ $this->debug('calling serializeType w/named param');
1268
+ $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
1269
+ } else {
1270
+ // TODO: only send nillable
1271
+ $this->debug('calling serializeType w/null param');
1272
+ $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
1273
+ }
1274
+ }
1275
+ } else {
1276
+ $this->debug('no parameters passed.');
1277
+ }
1278
+ }
1279
+ $this->debug("serializeParameters returning: $xml");
1280
+ return $xml;
1281
+ }
1282
+
1283
+ /**
1284
+ * serializes a PHP value according a given type definition
1285
+ *
1286
+ * @param string $name name of value (part or element)
1287
+ * @param string $type XML schema type of value (type or element)
1288
+ * @param mixed $value a native PHP value (parameter value)
1289
+ * @param string $use use for part (encoded|literal)
1290
+ * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
1291
+ * @param boolean $unqualified a kludge for what should be XML namespace form handling
1292
+ * @return string value serialized as an XML string
1293
+ * @access private
1294
+ */
1295
+ function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
1296
+ {
1297
+ $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));
1298
+ $this->appendDebug("value=" . $this->varDump($value));
1299
+ if($use == 'encoded' && $encodingStyle) {
1300
+ $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
1301
+ }
1302
+
1303
+ // if a soapval has been supplied, let its type override the WSDL
1304
+ if (is_object($value) && get_class($value) == 'soapval') {
1305
+ if ($value->type_ns) {
1306
+ $type = $value->type_ns . ':' . $value->type;
1307
+ $forceType = true;
1308
+ $this->debug("in serializeType: soapval overrides type to $type");
1309
+ } elseif ($value->type) {
1310
+ $type = $value->type;
1311
+ $forceType = true;
1312
+ $this->debug("in serializeType: soapval overrides type to $type");
1313
+ } else {
1314
+ $forceType = false;
1315
+ $this->debug("in serializeType: soapval does not override type");
1316
+ }
1317
+ $attrs = $value->attributes;
1318
+ $value = $value->value;
1319
+ $this->debug("in serializeType: soapval overrides value to $value");
1320
+ if ($attrs) {
1321
+ if (!is_array($value)) {
1322
+ $value['!'] = $value;
1323
+ }
1324
+ foreach ($attrs as $n => $v) {
1325
+ $value['!' . $n] = $v;
1326
+ }
1327
+ $this->debug("in serializeType: soapval provides attributes");
1328
+ }
1329
+ } else {
1330
+ $forceType = false;
1331
+ }
1332
+
1333
+ $xml = '';
1334
+ if (strpos($type, ':')) {
1335
+ $uqType = substr($type, strrpos($type, ':') + 1);
1336
+ $ns = substr($type, 0, strrpos($type, ':'));
1337
+ $this->debug("in serializeType: got a prefixed type: $uqType, $ns");
1338
+ if ($this->getNamespaceFromPrefix($ns)) {
1339
+ $ns = $this->getNamespaceFromPrefix($ns);
1340
+ $this->debug("in serializeType: expanded prefixed type: $uqType, $ns");
1341
+ }
1342
+
1343
+ if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/'){
1344
+ $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
1345
+ if ($unqualified && $use == 'literal') {
1346
+ $elementNS = " xmlns=\"\"";
1347
+ } else {
1348
+ $elementNS = '';
1349
+ }
1350
+ if (is_null($value)) {
1351
+ if ($use == 'literal') {
1352
+ // TODO: depends on minOccurs
1353
+ $xml = "<$name$elementNS/>";
1354
+ } else {
1355
+ // TODO: depends on nillable, which should be checked before calling this method
1356
+ $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
1357
+ }
1358
+ $this->debug("in serializeType: returning: $xml");
1359
+ return $xml;
1360
+ }
1361
+ if ($uqType == 'Array') {
1362
+ // JBoss/Axis does this sometimes
1363
+ return $this->serialize_val($value, $name, false, false, false, false, $use);
1364
+ }
1365
+ if ($uqType == 'boolean') {
1366
+ if ((is_string($value) && $value == 'false') || (! $value)) {
1367
+ $value = 'false';
1368
+ } else {
1369
+ $value = 'true';
1370
+ }
1371
+ }
1372
+ if ($uqType == 'string' && gettype($value) == 'string') {
1373
+ $value = $this->expandEntities($value);
1374
+ }
1375
+ if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {
1376
+ $value = sprintf("%.0lf", $value);
1377
+ }
1378
+ // it's a scalar
1379
+ // TODO: what about null/nil values?
1380
+ // check type isn't a custom type extending xmlschema namespace
1381
+ if (!$this->getTypeDef($uqType, $ns)) {
1382
+ if ($use == 'literal') {
1383
+ if ($forceType) {
1384
+ $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
1385
+ } else {
1386
+ $xml = "<$name$elementNS>$value</$name>";
1387
+ }
1388
+ } else {
1389
+ $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
1390
+ }
1391
+ $this->debug("in serializeType: returning: $xml");
1392
+ return $xml;
1393
+ }
1394
+ $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');
1395
+ } else if ($ns == 'http://xml.apache.org/xml-soap') {
1396
+ $this->debug('in serializeType: appears to be Apache SOAP type');
1397
+ if ($uqType == 'Map') {
1398
+ $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
1399
+ if (! $tt_prefix) {
1400
+ $this->debug('in serializeType: Add namespace for Apache SOAP type');
1401
+ $tt_prefix = 'ns' . rand(1000, 9999);
1402
+ $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap';
1403
+ // force this to be added to usedNamespaces
1404
+ $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
1405
+ }
1406
+ $contents = '';
1407
+ foreach($value as $k => $v) {
1408
+ $this->debug("serializing map element: key $k, value $v");
1409
+ $contents .= '<item>';
1410
+ $contents .= $this->serialize_val($k,'key',false,false,false,false,$use);
1411
+ $contents .= $this->serialize_val($v,'value',false,false,false,false,$use);
1412
+ $contents .= '</item>';
1413
+ }
1414
+ if ($use == 'literal') {
1415
+ if ($forceType) {
1416
+ $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
1417
+ } else {
1418
+ $xml = "<$name>$contents</$name>";
1419
+ }
1420
+ } else {
1421
+ $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
1422
+ }
1423
+ $this->debug("in serializeType: returning: $xml");
1424
+ return $xml;
1425
+ }
1426
+ $this->debug('in serializeType: Apache SOAP type, but only support Map');
1427
+ }
1428
+ } else {
1429
+ // TODO: should the type be compared to types in XSD, and the namespace
1430
+ // set to XSD if the type matches?
1431
+ $this->debug("in serializeType: No namespace for type $type");
1432
+ $ns = '';
1433
+ $uqType = $type;
1434
+ }
1435
+ if(!$typeDef = $this->getTypeDef($uqType, $ns)){
1436
+ $this->setError("$type ($uqType) is not a supported type.");
1437
+ $this->debug("in serializeType: $type ($uqType) is not a supported type.");
1438
+ return false;
1439
+ } else {
1440
+ $this->debug("in serializeType: found typeDef");
1441
+ $this->appendDebug('typeDef=' . $this->varDump($typeDef));
1442
+ if (substr($uqType, -1) == '^') {
1443
+ $uqType = substr($uqType, 0, -1);
1444
+ }
1445
+ }
1446
+ $phpType = $typeDef['phpType'];
1447
+ $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') );
1448
+ // if php type == struct, map value to the <all> element names
1449
+ if ($phpType == 'struct') {
1450
+ if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
1451
+ $elementName = $uqType;
1452
+ if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
1453
+ $elementNS = " xmlns=\"$ns\"";
1454
+ } else {
1455
+ $elementNS = " xmlns=\"\"";
1456
+ }
1457
+ } else {
1458
+ $elementName = $name;
1459
+ if ($unqualified) {
1460
+ $elementNS = " xmlns=\"\"";
1461
+ } else {
1462
+ $elementNS = '';
1463
+ }
1464
+ }
1465
+ if (is_null($value)) {
1466
+ if ($use == 'literal') {
1467
+ // TODO: depends on minOccurs
1468
+ $xml = "<$elementName$elementNS/>";
1469
+ } else {
1470
+ $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
1471
+ }
1472
+ $this->debug("in serializeType: returning: $xml");
1473
+ return $xml;
1474
+ }
1475
+ if (is_object($value)) {
1476
+ $value = get_object_vars($value);
1477
+ }
1478
+ if (is_array($value)) {
1479
+ $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
1480
+ if ($use == 'literal') {
1481
+ if ($forceType) {
1482
+ $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
1483
+ } else {
1484
+ $xml = "<$elementName$elementNS$elementAttrs>";
1485
+ }
1486
+ } else {
1487
+ $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
1488
+ }
1489
+
1490
+ $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
1491
+ $xml .= "</$elementName>";
1492
+ } else {
1493
+ $this->debug("in serializeType: phpType is struct, but value is not an array");
1494
+ $this->setError("phpType is struct, but value is not an array: see debug output for details");
1495
+ $xml = '';
1496
+ }
1497
+ } elseif ($phpType == 'array') {
1498
+ if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
1499
+ $elementNS = " xmlns=\"$ns\"";
1500
+ } else {
1501
+ if ($unqualified) {
1502
+ $elementNS = " xmlns=\"\"";
1503
+ } else {
1504
+ $elementNS = '';
1505
+ }
1506
+ }
1507
+ if (is_null($value)) {
1508
+ if ($use == 'literal') {
1509
+ // TODO: depends on minOccurs
1510
+ $xml = "<$name$elementNS/>";
1511
+ } else {
1512
+ $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
1513
+ $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
1514
+ ":Array\" " .
1515
+ $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
1516
+ ':arrayType="' .
1517
+ $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .
1518
+ ':' .
1519
+ $this->getLocalPart($typeDef['arrayType'])."[0]\"/>";
1520
+ }
1521
+ $this->debug("in serializeType: returning: $xml");
1522
+ return $xml;
1523
+ }
1524
+ if (isset($typeDef['multidimensional'])) {
1525
+ $nv = array();
1526
+ foreach($value as $v) {
1527
+ $cols = ',' . sizeof($v);
1528
+ $nv = array_merge($nv, $v);
1529
+ }
1530
+ $value = $nv;
1531
+ } else {
1532
+ $cols = '';
1533
+ }
1534
+ if (is_array($value) && sizeof($value) >= 1) {
1535
+ $rows = sizeof($value);
1536
+ $contents = '';
1537
+ foreach($value as $k => $v) {
1538
+ $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");
1539
+ //if (strpos($typeDef['arrayType'], ':') ) {
1540
+ if (!in_array($typeDef['arrayType'],$this->typemap['http://www.w3.org/2001/XMLSchema'])) {
1541
+ $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
1542
+ } else {
1543
+ $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
1544
+ }
1545
+ }
1546
+ } else {
1547
+ $rows = 0;
1548
+ $contents = null;
1549
+ }
1550
+ // TODO: for now, an empty value will be serialized as a zero element
1551
+ // array. Revisit this when coding the handling of null/nil values.
1552
+ if ($use == 'literal') {
1553
+ $xml = "<$name$elementNS>"
1554
+ .$contents
1555
+ ."</$name>";
1556
+ } else {
1557
+ $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '.
1558
+ $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
1559
+ .':arrayType="'
1560
+ .$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
1561
+ .":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">"
1562
+ .$contents
1563
+ ."</$name>";
1564
+ }
1565
+ } elseif ($phpType == 'scalar') {
1566
+ if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
1567
+ $elementNS = " xmlns=\"$ns\"";
1568
+ } else {
1569
+ if ($unqualified) {
1570
+ $elementNS = " xmlns=\"\"";
1571
+ } else {
1572
+ $elementNS = '';
1573
+ }
1574
+ }
1575
+ if ($use == 'literal') {
1576
+ if ($forceType) {
1577
+ $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
1578
+ } else {
1579
+ $xml = "<$name$elementNS>$value</$name>";
1580
+ }
1581
+ } else {
1582
+ $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
1583
+ }
1584
+ }
1585
+ $this->debug("in serializeType: returning: $xml");
1586
+ return $xml;
1587
+ }
1588
+
1589
+ /**
1590
+ * serializes the attributes for a complexType
1591
+ *
1592
+ * @param array $typeDef our internal representation of an XML schema type (or element)
1593
+ * @param mixed $value a native PHP value (parameter value)
1594
+ * @param string $ns the namespace of the type
1595
+ * @param string $uqType the local part of the type
1596
+ * @return string value serialized as an XML string
1597
+ * @access private
1598
+ */
1599
+ function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) {
1600
+ $xml = '';
1601
+ if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
1602
+ $this->debug("serialize attributes for XML Schema type $ns:$uqType");
1603
+ if (is_array($value)) {
1604
+ $xvalue = $value;
1605
+ } elseif (is_object($value)) {
1606
+ $xvalue = get_object_vars($value);
1607
+ } else {
1608
+ $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
1609
+ $xvalue = array();
1610
+ }
1611
+ foreach ($typeDef['attrs'] as $aName => $attrs) {
1612
+ if (isset($xvalue['!' . $aName])) {
1613
+ $xname = '!' . $aName;
1614
+ $this->debug("value provided for attribute $aName with key $xname");
1615
+ } elseif (isset($xvalue[$aName])) {
1616
+ $xname = $aName;
1617
+ $this->debug("value provided for attribute $aName with key $xname");
1618
+ } elseif (isset($attrs['default'])) {
1619
+ $xname = '!' . $aName;
1620
+ $xvalue[$xname] = $attrs['default'];
1621
+ $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);
1622
+ } else {
1623
+ $xname = '';
1624
+ $this->debug("no value provided for attribute $aName");
1625
+ }
1626
+ if ($xname) {
1627
+ $xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";
1628
+ }
1629
+ }
1630
+ } else {
1631
+ $this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
1632
+ }
1633
+ if (isset($typeDef['extensionBase'])) {
1634
+ $ns = $this->getPrefix($typeDef['extensionBase']);
1635
+ $uqType = $this->getLocalPart($typeDef['extensionBase']);
1636
+ if ($this->getNamespaceFromPrefix($ns)) {
1637
+ $ns = $this->getNamespaceFromPrefix($ns);
1638
+ }
1639
+ if ($typeDef = $this->getTypeDef($uqType, $ns)) {
1640
+ $this->debug("serialize attributes for extension base $ns:$uqType");
1641
+ $xml .= $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
1642
+ } else {
1643
+ $this->debug("extension base $ns:$uqType is not a supported type");
1644
+ }
1645
+ }
1646
+ return $xml;
1647
+ }
1648
+
1649
+ /**
1650
+ * serializes the elements for a complexType
1651
+ *
1652
+ * @param array $typeDef our internal representation of an XML schema type (or element)
1653
+ * @param mixed $value a native PHP value (parameter value)
1654
+ * @param string $ns the namespace of the type
1655
+ * @param string $uqType the local part of the type
1656
+ * @param string $use use for part (encoded|literal)
1657
+ * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
1658
+ * @return string value serialized as an XML string
1659
+ * @access private
1660
+ */
1661
+ function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) {
1662
+ $xml = '';
1663
+ if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
1664
+ $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
1665
+ if (is_array($value)) {
1666
+ $xvalue = $value;
1667
+ } elseif (is_object($value)) {
1668
+ $xvalue = get_object_vars($value);
1669
+ } else {
1670
+ $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
1671
+ $xvalue = array();
1672
+ }
1673
+ // toggle whether all elements are present - ideally should validate against schema
1674
+ if (count($typeDef['elements']) != count($xvalue)){
1675
+ $optionals = true;
1676
+ }
1677
+ foreach ($typeDef['elements'] as $eName => $attrs) {
1678
+ if (!isset($xvalue[$eName])) {
1679
+ if (isset($attrs['default'])) {
1680
+ $xvalue[$eName] = $attrs['default'];
1681
+ $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);
1682
+ }
1683
+ }
1684
+ // if user took advantage of a minOccurs=0, then only serialize named parameters
1685
+ if (isset($optionals)
1686
+ && (!isset($xvalue[$eName]))
1687
+ && ( (!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')
1688
+ ){
1689
+ if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {
1690
+ $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
1691
+ }
1692
+ // do nothing
1693
+ $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");
1694
+ } else {
1695
+ // get value
1696
+ if (isset($xvalue[$eName])) {
1697
+ $v = $xvalue[$eName];
1698
+ } else {
1699
+ $v = null;
1700
+ }
1701
+ if (isset($attrs['form'])) {
1702
+ $unqualified = ($attrs['form'] == 'unqualified');
1703
+ } else {
1704
+ $unqualified = false;
1705
+ }
1706
+ if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
1707
+ $vv = $v;
1708
+ foreach ($vv as $k => $v) {
1709
+ if (isset($attrs['type']) || isset($attrs['ref'])) {
1710
+ // serialize schema-defined type
1711
+ $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
1712
+ } else {
1713
+ // serialize generic type (can this ever really happen?)
1714
+ $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
1715
+ $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
1716
+ }
1717
+ }
1718
+ } else {
1719
+ if (isset($attrs['type']) || isset($attrs['ref'])) {
1720
+ // serialize schema-defined type
1721
+ $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
1722
+ } else {
1723
+ // serialize generic type (can this ever really happen?)
1724
+ $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
1725
+ $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
1726
+ }
1727
+ }
1728
+ }
1729
+ }
1730
+ } else {
1731
+ $this->debug("no elements to serialize for XML Schema type $ns:$uqType");
1732
+ }
1733
+ if (isset($typeDef['extensionBase'])) {
1734
+ $ns = $this->getPrefix($typeDef['extensionBase']);
1735
+ $uqType = $this->getLocalPart($typeDef['extensionBase']);
1736
+ if ($this->getNamespaceFromPrefix($ns)) {
1737
+ $ns = $this->getNamespaceFromPrefix($ns);
1738
+ }
1739
+ if ($typeDef = $this->getTypeDef($uqType, $ns)) {
1740
+ $this->debug("serialize elements for extension base $ns:$uqType");
1741
+ $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
1742
+ } else {
1743
+ $this->debug("extension base $ns:$uqType is not a supported type");
1744
+ }
1745
+ }
1746
+ return $xml;
1747
+ }
1748
+
1749
+ /**
1750
+ * adds an XML Schema complex type to the WSDL types
1751
+ *
1752
+ * @param string $name
1753
+ * @param string $typeClass (complexType|simpleType|attribute)
1754
+ * @param string $phpType currently supported are array and struct (php assoc array)
1755
+ * @param string $compositor (all|sequence|choice)
1756
+ * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
1757
+ * @param array $elements e.g. array ( name => array(name=>'',type=>'') )
1758
+ * @param array $attrs e.g. array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]'))
1759
+ * @param string $arrayType as namespace:name (xsd:string)
1760
+ * @see nusoap_xmlschema
1761
+ * @access public
1762
+ */
1763
+ function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') {
1764
+ if (count($elements) > 0) {
1765
+ $eElements = array();
1766
+ foreach($elements as $n => $e){
1767
+ // expand each element
1768
+ $ee = array();
1769
+ foreach ($e as $k => $v) {
1770
+ $k = strpos($k,':') ? $this->expandQname($k) : $k;
1771
+ $v = strpos($v,':') ? $this->expandQname($v) : $v;
1772
+ $ee[$k] = $v;
1773
+ }
1774
+ $eElements[$n] = $ee;
1775
+ }
1776
+ $elements = $eElements;
1777
+ }
1778
+
1779
+ if (count($attrs) > 0) {
1780
+ foreach($attrs as $n => $a){
1781
+ // expand each attribute
1782
+ foreach ($a as $k => $v) {
1783
+ $k = strpos($k,':') ? $this->expandQname($k) : $k;
1784
+ $v = strpos($v,':') ? $this->expandQname($v) : $v;
1785
+ $aa[$k] = $v;
1786
+ }
1787
+ $eAttrs[$n] = $aa;
1788
+ }
1789
+ $attrs = $eAttrs;
1790
+ }
1791
+
1792
+ $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
1793
+ $arrayType = strpos($arrayType,':') ? $this->expandQname($arrayType) : $arrayType;
1794
+
1795
+ $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
1796
+ $this->schemas[$typens][0]->addComplexType($name,$typeClass,$phpType,$compositor,$restrictionBase,$elements,$attrs,$arrayType);
1797
+ }
1798
+
1799
+ /**
1800
+ * adds an XML Schema simple type to the WSDL types
1801
+ *
1802
+ * @param string $name
1803
+ * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
1804
+ * @param string $typeClass (should always be simpleType)
1805
+ * @param string $phpType (should always be scalar)
1806
+ * @param array $enumeration array of values
1807
+ * @see nusoap_xmlschema
1808
+ * @access public
1809
+ */
1810
+ function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
1811
+ $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
1812
+
1813
+ $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
1814
+ $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
1815
+ }
1816
+
1817
+ /**
1818
+ * adds an element to the WSDL types
1819
+ *
1820
+ * @param array $attrs attributes that must include name and type
1821
+ * @see nusoap_xmlschema
1822
+ * @access public
1823
+ */
1824
+ function addElement($attrs) {
1825
+ $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
1826
+ $this->schemas[$typens][0]->addElement($attrs);
1827
+ }
1828
+
1829
+ /**
1830
+ * register an operation with the server
1831
+ *
1832
+ * @param string $name operation (method) name
1833
+ * @param array $in assoc array of input values: key = param name, value = param type
1834
+ * @param array $out assoc array of output values: key = param name, value = param type
1835
+ * @param string $namespace optional The namespace for the operation
1836
+ * @param string $soapaction optional The soapaction for the operation
1837
+ * @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
1838
+ * @param string $use (encoded|literal) optional The use for the parameters (cannot mix right now)
1839
+ * @param string $documentation optional The description to include in the WSDL
1840
+ * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
1841
+ * @access public
1842
+ */
1843
+ function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = ''){
1844
+ if ($use == 'encoded' && $encodingStyle == '') {
1845
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
1846
+ }
1847
+
1848
+ if ($style == 'document') {
1849
+ $elements = array();
1850
+ foreach ($in as $n => $t) {
1851
+ $elements[$n] = array('name' => $n, 'type' => $t);
1852
+ }
1853
+ $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
1854
+ $this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
1855
+ $in = array('parameters' => 'tns:' . $name . '^');
1856
+
1857
+ $elements = array();
1858
+ foreach ($out as $n => $t) {
1859
+ $elements[$n] = array('name' => $n, 'type' => $t);
1860
+ }
1861
+ $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
1862
+ $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
1863
+ $out = array('parameters' => 'tns:' . $name . 'Response' . '^');
1864
+ }
1865
+
1866
+ // get binding
1867
+ $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =
1868
+ array(
1869
+ 'name' => $name,
1870
+ 'binding' => $this->serviceName . 'Binding',
1871
+ 'endpoint' => $this->endpoint,
1872
+ 'soapAction' => $soapaction,
1873
+ 'style' => $style,
1874
+ 'input' => array(
1875
+ 'use' => $use,
1876
+ 'namespace' => $namespace,
1877
+ 'encodingStyle' => $encodingStyle,
1878
+ 'message' => $name . 'Request',
1879
+ 'parts' => $in),
1880
+ 'output' => array(
1881
+ 'use' => $use,
1882
+ 'namespace' => $namespace,
1883
+ 'encodingStyle' => $encodingStyle,
1884
+ 'message' => $name . 'Response',
1885
+ 'parts' => $out),
1886
+ 'namespace' => $namespace,
1887
+ 'transport' => 'http://schemas.xmlsoap.org/soap/http',
1888
+ 'documentation' => $documentation);
1889
+ // add portTypes
1890
+ // add messages
1891
+ if($in)
1892
+ {
1893
+ foreach($in as $pName => $pType)
1894
+ {
1895
+ if(strpos($pType,':')) {
1896
+ $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
1897
+ }
1898
+ $this->messages[$name.'Request'][$pName] = $pType;
1899
+ }
1900
+ } else {
1901
+ $this->messages[$name.'Request']= '0';
1902
+ }
1903
+ if($out)
1904
+ {
1905
+ foreach($out as $pName => $pType)
1906
+ {
1907
+ if(strpos($pType,':')) {
1908
+ $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
1909
+ }
1910
+ $this->messages[$name.'Response'][$pName] = $pType;
1911
+ }
1912
+ } else {
1913
+ $this->messages[$name.'Response']= '0';
1914
+ }
1915
+ return true;
1916
+ }
1917
+ }
1918
+
1919
+ ?>
lib/nusoap/wsdlcache.php ADDED
@@ -0,0 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
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 suporte.developer@buscape-inc.com so we can send you a copy immediately.
14
+ *
15
+ * @category Buscape
16
+ * @package Buscape_Fcontrol
17
+ * @copyright Copyright (c) 2010 Buscapé Company (http://www.buscapecompany.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ /*
22
+ The NuSOAP project home is:
23
+ http://sourceforge.net/projects/nusoap/
24
+
25
+ The primary support for NuSOAP is the mailing list:
26
+ nusoap-general@lists.sourceforge.net
27
+ */
28
+
29
+ /**
30
+ * caches instances of the wsdl class
31
+ *
32
+ * @author Scott Nichol <snichol@users.sourceforge.net>
33
+ * @author Ingo Fischer <ingo@apollon.de>
34
+ * @version $Id: class.wsdlcache.php,v 1.7 2007/04/17 16:34:03 snichol Exp $
35
+ * @access public
36
+ */
37
+ class nusoap_wsdlcache {
38
+ /**
39
+ * @var resource
40
+ * @access private
41
+ */
42
+ var $fplock;
43
+ /**
44
+ * @var integer
45
+ * @access private
46
+ */
47
+ var $cache_lifetime;
48
+ /**
49
+ * @var string
50
+ * @access private
51
+ */
52
+ var $cache_dir;
53
+ /**
54
+ * @var string
55
+ * @access public
56
+ */
57
+ var $debug_str = '';
58
+
59
+ /**
60
+ * constructor
61
+ *
62
+ * @param string $cache_dir directory for cache-files
63
+ * @param integer $cache_lifetime lifetime for caching-files in seconds or 0 for unlimited
64
+ * @access public
65
+ */
66
+ function nusoap_wsdlcache($cache_dir='.', $cache_lifetime=0) {
67
+ $this->fplock = array();
68
+ $this->cache_dir = $cache_dir != '' ? $cache_dir : '.';
69
+ $this->cache_lifetime = $cache_lifetime;
70
+ }
71
+
72
+ /**
73
+ * creates the filename used to cache a wsdl instance
74
+ *
75
+ * @param string $wsdl The URL of the wsdl instance
76
+ * @return string The filename used to cache the instance
77
+ * @access private
78
+ */
79
+ function createFilename($wsdl) {
80
+ return $this->cache_dir.'/wsdlcache-' . md5($wsdl);
81
+ }
82
+
83
+ /**
84
+ * adds debug data to the class level debug string
85
+ *
86
+ * @param string $string debug data
87
+ * @access private
88
+ */
89
+ function debug($string){
90
+ $this->debug_str .= get_class($this).": $string\n";
91
+ }
92
+
93
+ /**
94
+ * gets a wsdl instance from the cache
95
+ *
96
+ * @param string $wsdl The URL of the wsdl instance
97
+ * @return object wsdl The cached wsdl instance, null if the instance is not in the cache
98
+ * @access public
99
+ */
100
+ function get($wsdl) {
101
+ $filename = $this->createFilename($wsdl);
102
+ if ($this->obtainMutex($filename, "r")) {
103
+ // check for expired WSDL that must be removed from the cache
104
+ if ($this->cache_lifetime > 0) {
105
+ if (file_exists($filename) && (time() - filemtime($filename) > $this->cache_lifetime)) {
106
+ unlink($filename);
107
+ $this->debug("Expired $wsdl ($filename) from cache");
108
+ $this->releaseMutex($filename);
109
+ return null;
110
+ }
111
+ }
112
+ // see what there is to return
113
+ if (!file_exists($filename)) {
114
+ $this->debug("$wsdl ($filename) not in cache (1)");
115
+ $this->releaseMutex($filename);
116
+ return null;
117
+ }
118
+ $fp = @fopen($filename, "r");
119
+ if ($fp) {
120
+ $s = implode("", @file($filename));
121
+ fclose($fp);
122
+ $this->debug("Got $wsdl ($filename) from cache");
123
+ } else {
124
+ $s = null;
125
+ $this->debug("$wsdl ($filename) not in cache (2)");
126
+ }
127
+ $this->releaseMutex($filename);
128
+ return (!is_null($s)) ? unserialize($s) : null;
129
+ } else {
130
+ $this->debug("Unable to obtain mutex for $filename in get");
131
+ }
132
+ return null;
133
+ }
134
+
135
+ /**
136
+ * obtains the local mutex
137
+ *
138
+ * @param string $filename The Filename of the Cache to lock
139
+ * @param string $mode The open-mode ("r" or "w") or the file - affects lock-mode
140
+ * @return boolean Lock successfully obtained ?!
141
+ * @access private
142
+ */
143
+ function obtainMutex($filename, $mode) {
144
+ if (isset($this->fplock[md5($filename)])) {
145
+ $this->debug("Lock for $filename already exists");
146
+ return false;
147
+ }
148
+ $this->fplock[md5($filename)] = fopen($filename.".lock", "w");
149
+ if ($mode == "r") {
150
+ return flock($this->fplock[md5($filename)], LOCK_SH);
151
+ } else {
152
+ return flock($this->fplock[md5($filename)], LOCK_EX);
153
+ }
154
+ }
155
+
156
+ /**
157
+ * adds a wsdl instance to the cache
158
+ *
159
+ * @param object wsdl $wsdl_instance The wsdl instance to add
160
+ * @return boolean WSDL successfully cached
161
+ * @access public
162
+ */
163
+ function put($wsdl_instance) {
164
+ $filename = $this->createFilename($wsdl_instance->wsdl);
165
+ $s = serialize($wsdl_instance);
166
+ if ($this->obtainMutex($filename, "w")) {
167
+ $fp = fopen($filename, "w");
168
+ if (! $fp) {
169
+ $this->debug("Cannot write $wsdl_instance->wsdl ($filename) in cache");
170
+ $this->releaseMutex($filename);
171
+ return false;
172
+ }
173
+ fputs($fp, $s);
174
+ fclose($fp);
175
+ $this->debug("Put $wsdl_instance->wsdl ($filename) in cache");
176
+ $this->releaseMutex($filename);
177
+ return true;
178
+ } else {
179
+ $this->debug("Unable to obtain mutex for $filename in put");
180
+ }
181
+ return false;
182
+ }
183
+
184
+ /**
185
+ * releases the local mutex
186
+ *
187
+ * @param string $filename The Filename of the Cache to lock
188
+ * @return boolean Lock successfully released
189
+ * @access private
190
+ */
191
+ function releaseMutex($filename) {
192
+ $ret = flock($this->fplock[md5($filename)], LOCK_UN);
193
+ fclose($this->fplock[md5($filename)]);
194
+ unset($this->fplock[md5($filename)]);
195
+ if (! $ret) {
196
+ $this->debug("Not able to release lock for $filename");
197
+ }
198
+ return $ret;
199
+ }
200
+
201
+ /**
202
+ * removes a wsdl instance from the cache
203
+ *
204
+ * @param string $wsdl The URL of the wsdl instance
205
+ * @return boolean Whether there was an instance to remove
206
+ * @access public
207
+ */
208
+ function remove($wsdl) {
209
+ $filename = $this->createFilename($wsdl);
210
+ if (!file_exists($filename)) {
211
+ $this->debug("$wsdl ($filename) not in cache to be removed");
212
+ return false;
213
+ }
214
+ // ignore errors obtaining mutex
215
+ $this->obtainMutex($filename, "w");
216
+ $ret = unlink($filename);
217
+ $this->debug("Removed ($ret) $wsdl ($filename) from cache");
218
+ $this->releaseMutex($filename);
219
+ return $ret;
220
+ }
221
+ }
222
+
223
+ /**
224
+ * For backward compatibility
225
+ */
226
+ class wsdlcache extends nusoap_wsdlcache {
227
+ }
228
+ ?>
lib/nusoap/xmlschema.php ADDED
@@ -0,0 +1,953 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
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 suporte.developer@buscape-inc.com so we can send you a copy immediately.
14
+ *
15
+ * @category Buscape
16
+ * @package Buscape_Fcontrol
17
+ * @copyright Copyright (c) 2010 Buscapé Company (http://www.buscapecompany.com)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ /**
22
+ * parses an XML Schema, allows access to it's data, other utility methods.
23
+ * imperfect, no validation... yet, but quite functional.
24
+ *
25
+ * @author Dietrich Ayala <dietrich@ganx4.com>
26
+ * @author Scott Nichol <snichol@users.sourceforge.net>
27
+ * @version $Id: class.xmlschema.php,v 1.49 2007/11/06 14:17:53 snichol Exp $
28
+ * @access public
29
+ */
30
+ class nusoap_xmlschema extends nusoap_base {
31
+
32
+ // files
33
+ var $schema = '';
34
+ var $xml = '';
35
+ // namespaces
36
+ var $enclosingNamespaces;
37
+ // schema info
38
+ var $schemaInfo = array();
39
+ var $schemaTargetNamespace = '';
40
+ // types, elements, attributes defined by the schema
41
+ var $attributes = array();
42
+ var $complexTypes = array();
43
+ var $complexTypeStack = array();
44
+ var $currentComplexType = null;
45
+ var $elements = array();
46
+ var $elementStack = array();
47
+ var $currentElement = null;
48
+ var $simpleTypes = array();
49
+ var $simpleTypeStack = array();
50
+ var $currentSimpleType = null;
51
+ // imports
52
+ var $imports = array();
53
+ // parser vars
54
+ var $parser;
55
+ var $position = 0;
56
+ var $depth = 0;
57
+ var $depth_array = array();
58
+ var $message = array();
59
+ var $defaultNamespace = array();
60
+
61
+ /**
62
+ * constructor
63
+ *
64
+ * @param string $schema schema document URI
65
+ * @param string $xml xml document URI
66
+ * @param string $namespaces namespaces defined in enclosing XML
67
+ * @access public
68
+ */
69
+ function nusoap_xmlschema($schema='',$xml='',$namespaces=array()){
70
+ parent::nusoap_base();
71
+ $this->debug('nusoap_xmlschema class instantiated, inside constructor');
72
+ // files
73
+ $this->schema = $schema;
74
+ $this->xml = $xml;
75
+
76
+ // namespaces
77
+ $this->enclosingNamespaces = $namespaces;
78
+ $this->namespaces = array_merge($this->namespaces, $namespaces);
79
+
80
+ // parse schema file
81
+ if($schema != ''){
82
+ $this->debug('initial schema file: '.$schema);
83
+ $this->parseFile($schema, 'schema');
84
+ }
85
+
86
+ // parse xml file
87
+ if($xml != ''){
88
+ $this->debug('initial xml file: '.$xml);
89
+ $this->parseFile($xml, 'xml');
90
+ }
91
+
92
+ }
93
+
94
+ /**
95
+ * parse an XML file
96
+ *
97
+ * @param string $xml path/URL to XML file
98
+ * @param string $type (schema | xml)
99
+ * @return boolean
100
+ * @access public
101
+ */
102
+ function parseFile($xml,$type){
103
+ // parse xml file
104
+ if($xml != ""){
105
+ $xmlStr = @join("",@file($xml));
106
+ if($xmlStr == ""){
107
+ $msg = 'Error reading XML from '.$xml;
108
+ $this->setError($msg);
109
+ $this->debug($msg);
110
+ return false;
111
+ } else {
112
+ $this->debug("parsing $xml");
113
+ $this->parseString($xmlStr,$type);
114
+ $this->debug("done parsing $xml");
115
+ return true;
116
+ }
117
+ }
118
+ return false;
119
+ }
120
+
121
+ /**
122
+ * parse an XML string
123
+ *
124
+ * @param string $xml path or URL
125
+ * @param string $type (schema|xml)
126
+ * @access private
127
+ */
128
+ function parseString($xml,$type){
129
+ // parse xml string
130
+ if($xml != ""){
131
+
132
+ // Create an XML parser.
133
+ $this->parser = xml_parser_create();
134
+ // Set the options for parsing the XML data.
135
+ xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
136
+
137
+ // Set the object for the parser.
138
+ xml_set_object($this->parser, $this);
139
+
140
+ // Set the element handlers for the parser.
141
+ if($type == "schema"){
142
+ xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
143
+ xml_set_character_data_handler($this->parser,'schemaCharacterData');
144
+ } elseif($type == "xml"){
145
+ xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');
146
+ xml_set_character_data_handler($this->parser,'xmlCharacterData');
147
+ }
148
+
149
+ // Parse the XML file.
150
+ if(!xml_parse($this->parser,$xml,true)){
151
+ // Display an error message.
152
+ $errstr = sprintf('XML error parsing XML schema on line %d: %s',
153
+ xml_get_current_line_number($this->parser),
154
+ xml_error_string(xml_get_error_code($this->parser))
155
+ );
156
+ $this->debug($errstr);
157
+ $this->debug("XML payload:\n" . $xml);
158
+ $this->setError($errstr);
159
+ }
160
+
161
+ xml_parser_free($this->parser);
162
+ } else{
163
+ $this->debug('no xml passed to parseString()!!');
164
+ $this->setError('no xml passed to parseString()!!');
165
+ }
166
+ }
167
+
168
+ /**
169
+ * gets a type name for an unnamed type
170
+ *
171
+ * @param string Element name
172
+ * @return string A type name for an unnamed type
173
+ * @access private
174
+ */
175
+ function CreateTypeName($ename) {
176
+ $scope = '';
177
+ for ($i = 0; $i < count($this->complexTypeStack); $i++) {
178
+ $scope .= $this->complexTypeStack[$i] . '_';
179
+ }
180
+ return $scope . $ename . '_ContainedType';
181
+ }
182
+
183
+ /**
184
+ * start-element handler
185
+ *
186
+ * @param string $parser XML parser object
187
+ * @param string $name element name
188
+ * @param string $attrs associative array of attributes
189
+ * @access private
190
+ */
191
+ function schemaStartElement($parser, $name, $attrs) {
192
+
193
+ // position in the total number of elements, starting from 0
194
+ $pos = $this->position++;
195
+ $depth = $this->depth++;
196
+ // set self as current value for this depth
197
+ $this->depth_array[$depth] = $pos;
198
+ $this->message[$pos] = array('cdata' => '');
199
+ if ($depth > 0) {
200
+ $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
201
+ } else {
202
+ $this->defaultNamespace[$pos] = false;
203
+ }
204
+
205
+ // get element prefix
206
+ if($prefix = $this->getPrefix($name)){
207
+ // get unqualified name
208
+ $name = $this->getLocalPart($name);
209
+ } else {
210
+ $prefix = '';
211
+ }
212
+
213
+ // loop thru attributes, expanding, and registering namespace declarations
214
+ if(count($attrs) > 0){
215
+ foreach($attrs as $k => $v){
216
+ // if ns declarations, add to class level array of valid namespaces
217
+ if(ereg("^xmlns",$k)){
218
+ //$this->xdebug("$k: $v");
219
+ //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
220
+ if($ns_prefix = substr(strrchr($k,':'),1)){
221
+ //$this->xdebug("Add namespace[$ns_prefix] = $v");
222
+ $this->namespaces[$ns_prefix] = $v;
223
+ } else {
224
+ $this->defaultNamespace[$pos] = $v;
225
+ if (! $this->getPrefixFromNamespace($v)) {
226
+ $this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
227
+ }
228
+ }
229
+ if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){
230
+ $this->XMLSchemaVersion = $v;
231
+ $this->namespaces['xsi'] = $v.'-instance';
232
+ }
233
+ }
234
+ }
235
+ foreach($attrs as $k => $v){
236
+ // expand each attribute
237
+ $k = strpos($k,':') ? $this->expandQname($k) : $k;
238
+ $v = strpos($v,':') ? $this->expandQname($v) : $v;
239
+ $eAttrs[$k] = $v;
240
+ }
241
+ $attrs = $eAttrs;
242
+ } else {
243
+ $attrs = array();
244
+ }
245
+ // find status, register data
246
+ switch($name){
247
+ case 'all': // (optional) compositor content for a complexType
248
+ case 'choice':
249
+ case 'group':
250
+ case 'sequence':
251
+ //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
252
+ $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
253
+ //if($name == 'all' || $name == 'sequence'){
254
+ // $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
255
+ //}
256
+ break;
257
+ case 'attribute': // complexType attribute
258
+ //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
259
+ $this->xdebug("parsing attribute:");
260
+ $this->appendDebug($this->varDump($attrs));
261
+ if (!isset($attrs['form'])) {
262
+ $attrs['form'] = $this->schemaInfo['attributeFormDefault'];
263
+ }
264
+ if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
265
+ $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
266
+ if (!strpos($v, ':')) {
267
+ // no namespace in arrayType attribute value...
268
+ if ($this->defaultNamespace[$pos]) {
269
+ // ...so use the default
270
+ $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
271
+ }
272
+ }
273
+ }
274
+ if(isset($attrs['name'])){
275
+ $this->attributes[$attrs['name']] = $attrs;
276
+ $aname = $attrs['name'];
277
+ } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
278
+ if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
279
+ $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
280
+ } else {
281
+ $aname = '';
282
+ }
283
+ } elseif(isset($attrs['ref'])){
284
+ $aname = $attrs['ref'];
285
+ $this->attributes[$attrs['ref']] = $attrs;
286
+ }
287
+
288
+ if($this->currentComplexType){ // This should *always* be
289
+ $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
290
+ }
291
+ // arrayType attribute
292
+ if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){
293
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
294
+ $prefix = $this->getPrefix($aname);
295
+ if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
296
+ $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
297
+ } else {
298
+ $v = '';
299
+ }
300
+ if(strpos($v,'[,]')){
301
+ $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
302
+ }
303
+ $v = substr($v,0,strpos($v,'[')); // clip the []
304
+ if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
305
+ $v = $this->XMLSchemaVersion.':'.$v;
306
+ }
307
+ $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
308
+ }
309
+ break;
310
+ case 'complexContent': // (optional) content for a complexType
311
+ break;
312
+ case 'complexType':
313
+ array_push($this->complexTypeStack, $this->currentComplexType);
314
+ if(isset($attrs['name'])){
315
+ // TODO: what is the scope of named complexTypes that appear
316
+ // nested within other c complexTypes?
317
+ $this->xdebug('processing named complexType '.$attrs['name']);
318
+ //$this->currentElement = false;
319
+ $this->currentComplexType = $attrs['name'];
320
+ $this->complexTypes[$this->currentComplexType] = $attrs;
321
+ $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
322
+ // This is for constructs like
323
+ // <complexType name="ListOfString" base="soap:Array">
324
+ // <sequence>
325
+ // <element name="string" type="xsd:string"
326
+ // minOccurs="0" maxOccurs="unbounded" />
327
+ // </sequence>
328
+ // </complexType>
329
+ if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){
330
+ $this->xdebug('complexType is unusual array');
331
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
332
+ } else {
333
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
334
+ }
335
+ } else {
336
+ $name = $this->CreateTypeName($this->currentElement);
337
+ $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
338
+ $this->currentComplexType = $name;
339
+ //$this->currentElement = false;
340
+ $this->complexTypes[$this->currentComplexType] = $attrs;
341
+ $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
342
+ // This is for constructs like
343
+ // <complexType name="ListOfString" base="soap:Array">
344
+ // <sequence>
345
+ // <element name="string" type="xsd:string"
346
+ // minOccurs="0" maxOccurs="unbounded" />
347
+ // </sequence>
348
+ // </complexType>
349
+ if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){
350
+ $this->xdebug('complexType is unusual array');
351
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
352
+ } else {
353
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
354
+ }
355
+ }
356
+ break;
357
+ case 'element':
358
+ array_push($this->elementStack, $this->currentElement);
359
+ if (!isset($attrs['form'])) {
360
+ $attrs['form'] = $this->schemaInfo['elementFormDefault'];
361
+ }
362
+ if(isset($attrs['type'])){
363
+ $this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']);
364
+ if (! $this->getPrefix($attrs['type'])) {
365
+ if ($this->defaultNamespace[$pos]) {
366
+ $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
367
+ $this->xdebug('used default namespace to make type ' . $attrs['type']);
368
+ }
369
+ }
370
+ // This is for constructs like
371
+ // <complexType name="ListOfString" base="soap:Array">
372
+ // <sequence>
373
+ // <element name="string" type="xsd:string"
374
+ // minOccurs="0" maxOccurs="unbounded" />
375
+ // </sequence>
376
+ // </complexType>
377
+ if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
378
+ $this->xdebug('arrayType for unusual array is ' . $attrs['type']);
379
+ $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
380
+ }
381
+ $this->currentElement = $attrs['name'];
382
+ $ename = $attrs['name'];
383
+ } elseif(isset($attrs['ref'])){
384
+ $this->xdebug("processing element as ref to ".$attrs['ref']);
385
+ $this->currentElement = "ref to ".$attrs['ref'];
386
+ $ename = $this->getLocalPart($attrs['ref']);
387
+ } else {
388
+ $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
389
+ $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
390
+ $this->currentElement = $attrs['name'];
391
+ $attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
392
+ $ename = $attrs['name'];
393
+ }
394
+ if (isset($ename) && $this->currentComplexType) {
395
+ $this->xdebug("add element $ename to complexType $this->currentComplexType");
396
+ $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
397
+ } elseif (!isset($attrs['ref'])) {
398
+ $this->xdebug("add element $ename to elements array");
399
+ $this->elements[ $attrs['name'] ] = $attrs;
400
+ $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
401
+ }
402
+ break;
403
+ case 'enumeration': // restriction value list member
404
+ $this->xdebug('enumeration ' . $attrs['value']);
405
+ if ($this->currentSimpleType) {
406
+ $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
407
+ } elseif ($this->currentComplexType) {
408
+ $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
409
+ }
410
+ break;
411
+ case 'extension': // simpleContent or complexContent type extension
412
+ $this->xdebug('extension ' . $attrs['base']);
413
+ if ($this->currentComplexType) {
414
+ $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
415
+ }
416
+ break;
417
+ case 'import':
418
+ if (isset($attrs['schemaLocation'])) {
419
+ //$this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
420
+ $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
421
+ } else {
422
+ //$this->xdebug('import namespace ' . $attrs['namespace']);
423
+ $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
424
+ if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
425
+ $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
426
+ }
427
+ }
428
+ break;
429
+ case 'list': // simpleType value list
430
+ break;
431
+ case 'restriction': // simpleType, simpleContent or complexContent value restriction
432
+ $this->xdebug('restriction ' . $attrs['base']);
433
+ if($this->currentSimpleType){
434
+ $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
435
+ } elseif($this->currentComplexType){
436
+ $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
437
+ if(strstr($attrs['base'],':') == ':Array'){
438
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
439
+ }
440
+ }
441
+ break;
442
+ case 'schema':
443
+ $this->schemaInfo = $attrs;
444
+ $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
445
+ if (isset($attrs['targetNamespace'])) {
446
+ $this->schemaTargetNamespace = $attrs['targetNamespace'];
447
+ }
448
+ if (!isset($attrs['elementFormDefault'])) {
449
+ $this->schemaInfo['elementFormDefault'] = 'unqualified';
450
+ }
451
+ if (!isset($attrs['attributeFormDefault'])) {
452
+ $this->schemaInfo['attributeFormDefault'] = 'unqualified';
453
+ }
454
+ break;
455
+ case 'simpleContent': // (optional) content for a complexType
456
+ break;
457
+ case 'simpleType':
458
+ array_push($this->simpleTypeStack, $this->currentSimpleType);
459
+ if(isset($attrs['name'])){
460
+ $this->xdebug("processing simpleType for name " . $attrs['name']);
461
+ $this->currentSimpleType = $attrs['name'];
462
+ $this->simpleTypes[ $attrs['name'] ] = $attrs;
463
+ $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
464
+ $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
465
+ } else {
466
+ $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
467
+ $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
468
+ $this->currentSimpleType = $name;
469
+ //$this->currentElement = false;
470
+ $this->simpleTypes[$this->currentSimpleType] = $attrs;
471
+ $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
472
+ }
473
+ break;
474
+ case 'union': // simpleType type list
475
+ break;
476
+ default:
477
+ //$this->xdebug("do not have anything to do for element $name");
478
+ }
479
+ }
480
+
481
+ /**
482
+ * end-element handler
483
+ *
484
+ * @param string $parser XML parser object
485
+ * @param string $name element name
486
+ * @access private
487
+ */
488
+ function schemaEndElement($parser, $name) {
489
+ // bring depth down a notch
490
+ $this->depth--;
491
+ // position of current element is equal to the last value left in depth_array for my depth
492
+ if(isset($this->depth_array[$this->depth])){
493
+ $pos = $this->depth_array[$this->depth];
494
+ }
495
+ // get element prefix
496
+ if ($prefix = $this->getPrefix($name)){
497
+ // get unqualified name
498
+ $name = $this->getLocalPart($name);
499
+ } else {
500
+ $prefix = '';
501
+ }
502
+ // move on...
503
+ if($name == 'complexType'){
504
+ $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
505
+ $this->currentComplexType = array_pop($this->complexTypeStack);
506
+ //$this->currentElement = false;
507
+ }
508
+ if($name == 'element'){
509
+ $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
510
+ $this->currentElement = array_pop($this->elementStack);
511
+ }
512
+ if($name == 'simpleType'){
513
+ $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
514
+ $this->currentSimpleType = array_pop($this->simpleTypeStack);
515
+ }
516
+ }
517
+
518
+ /**
519
+ * element content handler
520
+ *
521
+ * @param string $parser XML parser object
522
+ * @param string $data element content
523
+ * @access private
524
+ */
525
+ function schemaCharacterData($parser, $data){
526
+ $pos = $this->depth_array[$this->depth - 1];
527
+ $this->message[$pos]['cdata'] .= $data;
528
+ }
529
+
530
+ /**
531
+ * serialize the schema
532
+ *
533
+ * @access public
534
+ */
535
+ function serializeSchema(){
536
+
537
+ $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
538
+ $xml = '';
539
+ // imports
540
+ if (sizeof($this->imports) > 0) {
541
+ foreach($this->imports as $ns => $list) {
542
+ foreach ($list as $ii) {
543
+ if ($ii['location'] != '') {
544
+ $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
545
+ } else {
546
+ $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
547
+ }
548
+ }
549
+ }
550
+ }
551
+ // complex types
552
+ foreach($this->complexTypes as $typeName => $attrs){
553
+ $contentStr = '';
554
+ // serialize child elements
555
+ if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){
556
+ foreach($attrs['elements'] as $element => $eParts){
557
+ if(isset($eParts['ref'])){
558
+ $contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n";
559
+ } else {
560
+ $contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
561
+ foreach ($eParts as $aName => $aValue) {
562
+ // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
563
+ if ($aName != 'name' && $aName != 'type') {
564
+ $contentStr .= " $aName=\"$aValue\"";
565
+ }
566
+ }
567
+ $contentStr .= "/>\n";
568
+ }
569
+ }
570
+ // compositor wraps elements
571
+ if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
572
+ $contentStr = " <$schemaPrefix:$attrs[compositor]>\n".$contentStr." </$schemaPrefix:$attrs[compositor]>\n";
573
+ }
574
+ }
575
+ // attributes
576
+ if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){
577
+ foreach($attrs['attrs'] as $attr => $aParts){
578
+ $contentStr .= " <$schemaPrefix:attribute";
579
+ foreach ($aParts as $a => $v) {
580
+ if ($a == 'ref' || $a == 'type') {
581
+ $contentStr .= " $a=\"".$this->contractQName($v).'"';
582
+ } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
583
+ $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
584
+ $contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"';
585
+ } else {
586
+ $contentStr .= " $a=\"$v\"";
587
+ }
588
+ }
589
+ $contentStr .= "/>\n";
590
+ }
591
+ }
592
+ // if restriction
593
+ if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){
594
+ $contentStr = " <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr." </$schemaPrefix:restriction>\n";
595
+ // complex or simple content
596
+ if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){
597
+ $contentStr = " <$schemaPrefix:complexContent>\n".$contentStr." </$schemaPrefix:complexContent>\n";
598
+ }
599
+ }
600
+ // finalize complex type
601
+ if($contentStr != ''){
602
+ $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n";
603
+ } else {
604
+ $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
605
+ }
606
+ $xml .= $contentStr;
607
+ }
608
+ // simple types
609
+ if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){
610
+ foreach($this->simpleTypes as $typeName => $eParts){
611
+ $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\">\n";
612
+ if (isset($eParts['enumeration'])) {
613
+ foreach ($eParts['enumeration'] as $e) {
614
+ $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n";
615
+ }
616
+ }
617
+ $xml .= " </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
618
+ }
619
+ }
620
+ // elements
621
+ if(isset($this->elements) && count($this->elements) > 0){
622
+ foreach($this->elements as $element => $eParts){
623
+ $xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n";
624
+ }
625
+ }
626
+ // attributes
627
+ if(isset($this->attributes) && count($this->attributes) > 0){
628
+ foreach($this->attributes as $attr => $aParts){
629
+ $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>";
630
+ }
631
+ }
632
+ // finish 'er up
633
+ $attr = '';
634
+ foreach ($this->schemaInfo as $k => $v) {
635
+ if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {
636
+ $attr .= " $k=\"$v\"";
637
+ }
638
+ }
639
+ $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
640
+ foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
641
+ $el .= " xmlns:$nsp=\"$ns\"";
642
+ }
643
+ $xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
644
+ return $xml;
645
+ }
646
+
647
+ /**
648
+ * adds debug data to the clas level debug string
649
+ *
650
+ * @param string $string debug data
651
+ * @access private
652
+ */
653
+ function xdebug($string){
654
+ $this->debug('<' . $this->schemaTargetNamespace . '> '.$string);
655
+ }
656
+
657
+ /**
658
+ * get the PHP type of a user defined type in the schema
659
+ * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays
660
+ * returns false if no type exists, or not w/ the given namespace
661
+ * else returns a string that is either a native php type, or 'struct'
662
+ *
663
+ * @param string $type name of defined type
664
+ * @param string $ns namespace of type
665
+ * @return mixed
666
+ * @access public
667
+ * @deprecated
668
+ */
669
+ function getPHPType($type,$ns){
670
+ if(isset($this->typemap[$ns][$type])){
671
+ //print "found type '$type' and ns $ns in typemap<br>";
672
+ return $this->typemap[$ns][$type];
673
+ } elseif(isset($this->complexTypes[$type])){
674
+ //print "getting type '$type' and ns $ns from complexTypes array<br>";
675
+ return $this->complexTypes[$type]['phpType'];
676
+ }
677
+ return false;
678
+ }
679
+
680
+ /**
681
+ * returns an associative array of information about a given type
682
+ * returns false if no type exists by the given name
683
+ *
684
+ * For a complexType typeDef = array(
685
+ * 'restrictionBase' => '',
686
+ * 'phpType' => '',
687
+ * 'compositor' => '(sequence|all)',
688
+ * 'elements' => array(), // refs to elements array
689
+ * 'attrs' => array() // refs to attributes array
690
+ * ... and so on (see addComplexType)
691
+ * )
692
+ *
693
+ * For simpleType or element, the array has different keys.
694
+ *
695
+ * @param string $type
696
+ * @return mixed
697
+ * @access public
698
+ * @see addComplexType
699
+ * @see addSimpleType
700
+ * @see addElement
701
+ */
702
+ function getTypeDef($type){
703
+ //$this->debug("in getTypeDef for type $type");
704
+ if (substr($type, -1) == '^') {
705
+ $is_element = 1;
706
+ $type = substr($type, 0, -1);
707
+ } else {
708
+ $is_element = 0;
709
+ }
710
+
711
+ if((! $is_element) && isset($this->complexTypes[$type])){
712
+ $this->xdebug("in getTypeDef, found complexType $type");
713
+ return $this->complexTypes[$type];
714
+ } elseif((! $is_element) && isset($this->simpleTypes[$type])){
715
+ $this->xdebug("in getTypeDef, found simpleType $type");
716
+ if (!isset($this->simpleTypes[$type]['phpType'])) {
717
+ // get info for type to tack onto the simple type
718
+ // TODO: can this ever really apply (i.e. what is a simpleType really?)
719
+ $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
720
+ $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
721
+ $etype = $this->getTypeDef($uqType);
722
+ if ($etype) {
723
+ $this->xdebug("in getTypeDef, found type for simpleType $type:");
724
+ $this->xdebug($this->varDump($etype));
725
+ if (isset($etype['phpType'])) {
726
+ $this->simpleTypes[$type]['phpType'] = $etype['phpType'];
727
+ }
728
+ if (isset($etype['elements'])) {
729
+ $this->simpleTypes[$type]['elements'] = $etype['elements'];
730
+ }
731
+ }
732
+ }
733
+ return $this->simpleTypes[$type];
734
+ } elseif(isset($this->elements[$type])){
735
+ $this->xdebug("in getTypeDef, found element $type");
736
+ if (!isset($this->elements[$type]['phpType'])) {
737
+ // get info for type to tack onto the element
738
+ $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
739
+ $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
740
+ $etype = $this->getTypeDef($uqType);
741
+ if ($etype) {
742
+ $this->xdebug("in getTypeDef, found type for element $type:");
743
+ $this->xdebug($this->varDump($etype));
744
+ if (isset($etype['phpType'])) {
745
+ $this->elements[$type]['phpType'] = $etype['phpType'];
746
+ }
747
+ if (isset($etype['elements'])) {
748
+ $this->elements[$type]['elements'] = $etype['elements'];
749
+ }
750
+ } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
751
+ $this->xdebug("in getTypeDef, element $type is an XSD type");
752
+ $this->elements[$type]['phpType'] = 'scalar';
753
+ }
754
+ }
755
+ return $this->elements[$type];
756
+ } elseif(isset($this->attributes[$type])){
757
+ $this->xdebug("in getTypeDef, found attribute $type");
758
+ return $this->attributes[$type];
759
+ } elseif (ereg('_ContainedType$', $type)) {
760
+ $this->xdebug("in getTypeDef, have an untyped element $type");
761
+ $typeDef['typeClass'] = 'simpleType';
762
+ $typeDef['phpType'] = 'scalar';
763
+ $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
764
+ return $typeDef;
765
+ }
766
+ $this->xdebug("in getTypeDef, did not find $type");
767
+ return false;
768
+ }
769
+
770
+ /**
771
+ * returns a sample serialization of a given type, or false if no type by the given name
772
+ *
773
+ * @param string $type name of type
774
+ * @return mixed
775
+ * @access public
776
+ * @deprecated
777
+ */
778
+ function serializeTypeDef($type){
779
+ //print "in sTD() for type $type<br>";
780
+ if($typeDef = $this->getTypeDef($type)){
781
+ $str .= '<'.$type;
782
+ if(is_array($typeDef['attrs'])){
783
+ foreach($typeDef['attrs'] as $attName => $data){
784
+ $str .= " $attName=\"{type = ".$data['type']."}\"";
785
+ }
786
+ }
787
+ $str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
788
+ if(count($typeDef['elements']) > 0){
789
+ $str .= ">";
790
+ foreach($typeDef['elements'] as $element => $eData){
791
+ $str .= $this->serializeTypeDef($element);
792
+ }
793
+ $str .= "</$type>";
794
+ } elseif($typeDef['typeClass'] == 'element') {
795
+ $str .= "></$type>";
796
+ } else {
797
+ $str .= "/>";
798
+ }
799
+ return $str;
800
+ }
801
+ return false;
802
+ }
803
+
804
+ /**
805
+ * returns HTML form elements that allow a user
806
+ * to enter values for creating an instance of the given type.
807
+ *
808
+ * @param string $name name for type instance
809
+ * @param string $type name of type
810
+ * @return string
811
+ * @access public
812
+ * @deprecated
813
+ */
814
+ function typeToForm($name,$type){
815
+ // get typedef
816
+ if($typeDef = $this->getTypeDef($type)){
817
+ // if struct
818
+ if($typeDef['phpType'] == 'struct'){
819
+ $buffer .= '<table>';
820
+ foreach($typeDef['elements'] as $child => $childDef){
821
+ $buffer .= "
822
+ <tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>
823
+ <td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";
824
+ }
825
+ $buffer .= '</table>';
826
+ // if array
827
+ } elseif($typeDef['phpType'] == 'array'){
828
+ $buffer .= '<table>';
829
+ for($i=0;$i < 3; $i++){
830
+ $buffer .= "
831
+ <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
832
+ <td><input type='text' name='parameters[".$name."][]'></td></tr>";
833
+ }
834
+ $buffer .= '</table>';
835
+ // if scalar
836
+ } else {
837
+ $buffer .= "<input type='text' name='parameters[$name]'>";
838
+ }
839
+ } else {
840
+ $buffer .= "<input type='text' name='parameters[$name]'>";
841
+ }
842
+ return $buffer;
843
+ }
844
+
845
+ /**
846
+ * adds a complex type to the schema
847
+ *
848
+ * example: array
849
+ *
850
+ * addType(
851
+ * 'ArrayOfstring',
852
+ * 'complexType',
853
+ * 'array',
854
+ * '',
855
+ * 'SOAP-ENC:Array',
856
+ * array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),
857
+ * 'xsd:string'
858
+ * );
859
+ *
860
+ * example: PHP associative array ( SOAP Struct )
861
+ *
862
+ * addType(
863
+ * 'SOAPStruct',
864
+ * 'complexType',
865
+ * 'struct',
866
+ * 'all',
867
+ * array('myVar'=> array('name'=>'myVar','type'=>'string')
868
+ * );
869
+ *
870
+ * @param name
871
+ * @param typeClass (complexType|simpleType|attribute)
872
+ * @param phpType: currently supported are array and struct (php assoc array)
873
+ * @param compositor (all|sequence|choice)
874
+ * @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
875
+ * @param elements = array ( name = array(name=>'',type=>'') )
876
+ * @param attrs = array(
877
+ * array(
878
+ * 'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",
879
+ * "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"
880
+ * )
881
+ * )
882
+ * @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)
883
+ * @access public
884
+ * @see getTypeDef
885
+ */
886
+ function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){
887
+ $this->complexTypes[$name] = array(
888
+ 'name' => $name,
889
+ 'typeClass' => $typeClass,
890
+ 'phpType' => $phpType,
891
+ 'compositor'=> $compositor,
892
+ 'restrictionBase' => $restrictionBase,
893
+ 'elements' => $elements,
894
+ 'attrs' => $attrs,
895
+ 'arrayType' => $arrayType
896
+ );
897
+
898
+ $this->xdebug("addComplexType $name:");
899
+ $this->appendDebug($this->varDump($this->complexTypes[$name]));
900
+ }
901
+
902
+ /**
903
+ * adds a simple type to the schema
904
+ *
905
+ * @param string $name
906
+ * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
907
+ * @param string $typeClass (should always be simpleType)
908
+ * @param string $phpType (should always be scalar)
909
+ * @param array $enumeration array of values
910
+ * @access public
911
+ * @see nusoap_xmlschema
912
+ * @see getTypeDef
913
+ */
914
+ function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
915
+ $this->simpleTypes[$name] = array(
916
+ 'name' => $name,
917
+ 'typeClass' => $typeClass,
918
+ 'phpType' => $phpType,
919
+ 'type' => $restrictionBase,
920
+ 'enumeration' => $enumeration
921
+ );
922
+
923
+ $this->xdebug("addSimpleType $name:");
924
+ $this->appendDebug($this->varDump($this->simpleTypes[$name]));
925
+ }
926
+
927
+ /**
928
+ * adds an element to the schema
929
+ *
930
+ * @param array $attrs attributes that must include name and type
931
+ * @see nusoap_xmlschema
932
+ * @access public
933
+ */
934
+ function addElement($attrs) {
935
+ if (! $this->getPrefix($attrs['type'])) {
936
+ $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
937
+ }
938
+ $this->elements[ $attrs['name'] ] = $attrs;
939
+ $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
940
+
941
+ $this->xdebug("addElement " . $attrs['name']);
942
+ $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
943
+ }
944
+ }
945
+
946
+ /**
947
+ * Backward compatibility
948
+ */
949
+ class XMLSchema extends nusoap_xmlschema {
950
+ }
951
+
952
+
953
+ ?>
package.xml ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>Buscape_Fcontrol</name>
4
+ <version>0.1.0</version>
5
+ <stability>stable</stability>
6
+ <license uri="http://www.opensource.org/licenses/osl-3.0.php">OSL v3.0</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Extens&#xE3;o Buscap&#xE9; Fcontrol para Magento</summary>
10
+ <description>O FControl &#xE9; um sofisticado sistema que utiliza redes neurais e intelig&#xEA;ncia artificial para detectar fraudes em tempo real.</description>
11
+ <notes>Buscap&#xE9; Fcontrol &#xE9; compat&#xED;vel com Magento Enterprise Edition 1.7.0.0 ou superior, Professional Edition 1.9.0.0 ou superior, e Magento Community Edition 1.3.3.0 ou superior.</notes>
12
+ <authors><author><name>Adriano Aguiar</name><user>adrianoaguiar</user><email>adrianoaguiaralves@gmail.com</email></author></authors>
13
+ <date>2011-12-20</date>
14
+ <time>18:12:16</time>
15
+ <contents><target name="mageetc"><dir name="modules"><file name="Buscape_Fcontrol.xml" hash="1883e6e4a5f712adbb28fc48b91b77ed"/></dir></target><target name="magecommunity"><dir name="Buscape"><dir name="Fcontrol"><dir name="Block"><dir name="Adminhtml"><dir name="Sales"><dir name="Order"><file name="Grid.php" hash="8a9cd394c7d05c875353b9a6a9c509f8"/><dir name="View"><file name="Info.php" hash="68b7966bd053a03994c88748612e3263"/></dir></dir><file name="Order.php" hash="306f634ac46d7dec061fd18e76f11e34"/></dir></dir></dir><dir name="Helper"><file name="Data.php" hash="533804f2631993dbfd1d2cbb978510a1"/></dir><dir name="Model"><dir name="Adapter"><file name="Payment.php" hash="5057e13e99367803ce7c76e834f4c2c7"/><file name="Shipping.php" hash="d40c268415ec2a2c50870bf811176b44"/></dir><dir name="Api"><file name="Abstract.php" hash="0786c29e83c34d1199f1e17f37d79751"/></dir><file name="Api.php" hash="635befcf547671471a8b68401e377d5d"/><file name="Config.php" hash="fab005089945576b2b6cf4ecf076d3af"/><file name="Observer.php" hash="8b68046645290c9f91957fa38a1df290"/><dir name="Source"><file name="Service.php" hash="ce9458ee8419c55346ab96ead62915de"/></dir></dir><dir name="controllers"><dir name="Adminhtml"><dir name="Sales"><file name="OrderController.php" hash="db12a93be59057875d4c488fde37956d"/></dir></dir></dir><dir name="etc"><file name="config.xml" hash="72092724339217c38dd568280e487001"/><file name="system.xml" hash="6991f325fb680eb0bfedc9e4a8ae88da"/></dir></dir></dir></target><target name="magelib"><dir name="nusoap"><file name="nusoap.php" hash="be25f8f414d3bc104fa32fd33d1ca670"/><file name="nusoap_base.php" hash="2b58ef48c2588c9eb1e197e609cf3578"/><file name="nusoap_fault.php" hash="b1e071de96ac6ec4401fc3378985b915"/><file name="nusoapmime.php" hash="385906df53d95e99d44a3ccf826657b0"/><file name="soap_parser.php" hash="5fd16dfe735ba059a2bcd6f13b2e4200"/><file name="soap_server.php" hash="7335a46989fcb2e6a0cb094bea9636f6"/><file name="soap_transport_http.php" hash="47e7e9295559211833aa733259ae4426"/><file name="soap_val.php" hash="bfe395c44feee1833806ffb87f53d301"/><file name="soapclient.php" hash="a386ecd977dcef79dacebd596808773f"/><file name="wsdl.php" hash="848f9fce1e0da0d88584d0e6ca1f242d"/><file name="wsdlcache.php" hash="e06853ca25271b5cb4b8a7016c960a40"/><file name="xmlschema.php" hash="5d5c67fd3e30dd96a186551a7c7221c8"/></dir></target></contents>
16
+ <compatible/>
17
+ <dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php></required></dependencies>
18
+ </package>