Version Notes
.
Download this release
Release Info
Developer | Waterstone |
Extension | Waterstone_Winvoice |
Version | 1.0.1.1 |
Comparing to | |
See all releases |
Code changes from version 1.0.1 to 1.0.1.1
- app/code/local/Waterstone/Winvoice +0 -1
- app/code/local/Waterstone/winvoice/Helper/Data.php +18 -0
- app/code/local/Waterstone/winvoice/Model/AddInvoice.php +390 -0
- app/code/local/Waterstone/winvoice/Model/Email/Template/Mailer.php +228 -0
- app/code/local/Waterstone/winvoice/Model/Log.php +65 -0
- app/code/local/Waterstone/winvoice/Model/Mysql4/Winvoice.php +31 -0
- app/code/local/Waterstone/winvoice/Model/Mysql4/Winvoice/Collection.php +31 -0
- app/code/local/Waterstone/winvoice/Model/Order/Invoice.php +1142 -0
- app/code/local/Waterstone/winvoice/Model/Status.php +37 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/lib/changelog +648 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.nusoap_base.php +996 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.soap_fault.php +90 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.soap_parser.php +643 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.soap_server.php +1127 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.soap_transport_http.php +1307 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.soap_val.php +107 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.soapclient.php +991 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.wsdl.php +1938 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.wsdlcache.php +209 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.xmlschema.php +973 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/lib/nusoap.php +8148 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/lib/nusoapmime.php +501 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/samples/client1.php +51 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/samples/client2.php +57 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/samples/client3.php +56 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/samples/getfile1client.php +37 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/samples/getfile2client.php +37 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/samples/index.html +67 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/samples/mimeclient.php +53 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/samples/sslclient.php +37 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient1.php +47 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient10.php +44 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient11.php +50 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient12.php +225 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient13.php +99 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient14.php +83 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient15.php +60 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient2.php +58 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient3.php +56 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient3b.php +46 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient3c.php +46 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient4.php +176 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient5.php +69 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient6.php +66 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient7.php +51 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient8.php +74 -0
- app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient9.php +63 -0
- app/code/local/Waterstone/winvoice/controllers/Adminhtml/WinvoiceController.php +335 -0
- app/code/local/Waterstone/winvoice/etc/adminhtml.xml +41 -0
- app/code/local/Waterstone/winvoice/etc/config.xml +138 -0
- app/code/local/Waterstone/winvoice/etc/system.xml +71 -0
- app/code/local/Waterstone/winvoice/sql/winvoice_setup/mysql4-install-0.1.0.php +58 -0
- package.xml +9 -73
app/code/local/Waterstone/Winvoice
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
Subproject commit 7bcf094288e6bec8b1ef5f2093877d8345463719
|
|
app/code/local/Waterstone/winvoice/Helper/Data.php
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* DISCLAIMER
|
4 |
+
*
|
5 |
+
* Do not edit or add to this file if you wish to upgrade the extension to newer
|
6 |
+
* versions in the future. If you need personal customization please contact us
|
7 |
+
* on http://www.waterstone.pt for more information.
|
8 |
+
*
|
9 |
+
* @category Waterstone
|
10 |
+
* @package Waterstone_Winvoice
|
11 |
+
* @copyright Copyright (c) 2014 Waterstone Consulting, Lda. (http://www.waterstone.pt)
|
12 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
13 |
+
*/
|
14 |
+
|
15 |
+
class Waterstone_Winvoice_Helper_Data extends Mage_Core_Helper_Abstract
|
16 |
+
{
|
17 |
+
|
18 |
+
}
|
app/code/local/Waterstone/winvoice/Model/AddInvoice.php
ADDED
@@ -0,0 +1,390 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* DISCLAIMER
|
5 |
+
*
|
6 |
+
* Do not edit or add to this file if you wish to upgrade the extension to newer
|
7 |
+
* versions in the future. If you need personal customization please contact us
|
8 |
+
* on http://www.waterstone.pt for more information.
|
9 |
+
*
|
10 |
+
* @category Waterstone
|
11 |
+
* @package Waterstone_Winvoice
|
12 |
+
* @copyright Copyright (c) 2014 Waterstone Consulting, Lda. (http://www.waterstone.pt)
|
13 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
14 |
+
*/
|
15 |
+
|
16 |
+
class Waterstone_Winvoice_Model_AddInvoice extends Mage_Core_Model_Abstract
|
17 |
+
{
|
18 |
+
/* Private variables */
|
19 |
+
var $client;
|
20 |
+
var $password;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Winvoice internal log class.
|
24 |
+
*
|
25 |
+
* @since 1.0.1
|
26 |
+
*
|
27 |
+
* @var Waterstone_Winvoice_Model_Log
|
28 |
+
*/
|
29 |
+
private $wLog;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* weoInvoice error codes list.
|
33 |
+
*
|
34 |
+
* @var array
|
35 |
+
*/
|
36 |
+
private $errorMessages = array(
|
37 |
+
'300' => 'Falha na autenticação no weoInvoice.',
|
38 |
+
'301' => 'Parâmetros insuficientes.',
|
39 |
+
'302' => 'Código de cliente já existente ou inválido.',
|
40 |
+
'303' => 'Número de contribuinte inválido.',
|
41 |
+
'304' => 'Email inválido.',
|
42 |
+
'305' => 'Sem permissões para alterar o cliente.',
|
43 |
+
'306' => 'Sem permissões para usar o cliente.',
|
44 |
+
'307' => 'Empresa sem as informações mínimas necessárias.',
|
45 |
+
'308' => 'Empresa sem a tabela de IVA correctamente preenchida.',
|
46 |
+
'309' => 'Data inválida.',
|
47 |
+
'310' => 'Data de pagamento inválida.',
|
48 |
+
'311' => 'Data do documento não sequencial.',
|
49 |
+
'312' => 'Tipo de documento inválido.',
|
50 |
+
'320' => 'Não é possível criar um documento com um existente em aberto.',
|
51 |
+
'321' => 'Documento não disponível.',
|
52 |
+
'322' => 'Documento já fechado.',
|
53 |
+
'323' => 'Informação de produtos/serviços no documento insuficiente.',
|
54 |
+
'324' => 'Taxa de IVA do produto/serviço incorrecta.',
|
55 |
+
'325' => 'Sem permissões para usar o documento.',
|
56 |
+
'326' => 'Documento ainda está aberto.',
|
57 |
+
'327' => 'Motivo da anulação do documento inexistente.',
|
58 |
+
'328' => 'Motivo de isenção de IVA incorrecto ou inexistente.',
|
59 |
+
'340' => 'Código de cliente inexistente.',
|
60 |
+
'341' => 'Erro ao obter dados do cliente.',
|
61 |
+
'350' => 'Pagamento de factura com valor inferior a zero.',
|
62 |
+
'351' => 'Factura já paga.',
|
63 |
+
'352' => 'Recibo com valor inferior a zero.'
|
64 |
+
);
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Constructor.
|
68 |
+
* - Connect to weoInvoice api using nusoap.
|
69 |
+
*
|
70 |
+
* @since 1.0.0
|
71 |
+
*
|
72 |
+
* @return void
|
73 |
+
*/
|
74 |
+
public function __construct()
|
75 |
+
{
|
76 |
+
$this->wLog = Mage::getModel('winvoice/log');
|
77 |
+
date_default_timezone_set('Europe/Berlin');
|
78 |
+
require_once(Mage::getBaseDir("code").'/local/Waterstone/Winvoice/Model/nusoap/lib/nusoap.php');
|
79 |
+
|
80 |
+
$this->client = new nusoap_client(Mage::getStoreConfig('winvoice/wconfig/wapi'));
|
81 |
+
$this->password = Mage::getStoreConfig('winvoice/wconfig/wpassword');
|
82 |
+
|
83 |
+
$this->wLog->log("info", $this->client);
|
84 |
+
$this->wLog->log("info", $this->password);
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Add invoice method.
|
89 |
+
* - Gets the client products, creates a winvoice and sends to email.
|
90 |
+
*
|
91 |
+
* @since 1.0.0
|
92 |
+
*
|
93 |
+
* @param Mage_Sales_Model_Observer $observer
|
94 |
+
* @return void
|
95 |
+
*/
|
96 |
+
public function AddInvoice($observer)
|
97 |
+
{
|
98 |
+
$invoice = $observer->getEvent()->getInvoice();
|
99 |
+
$invoiceNumber = $invoice->getEntityId();
|
100 |
+
|
101 |
+
$this->wLog->log("info","Invoice Created $invoiceNumber");
|
102 |
+
$useCURL = isset($_POST['usecurl']) ? $_POST['usecurl'] : '0';
|
103 |
+
$err = $this->client->getError();
|
104 |
+
|
105 |
+
if ($err) {
|
106 |
+
Mage::throwException(Mage::helper('adminhtml')->__('Erro ao criar factura.'));
|
107 |
+
$this->wLog->log("error", Mage::helper('adminhtml')->__('Erro ao criar factura.'));
|
108 |
+
}
|
109 |
+
|
110 |
+
// Get client items
|
111 |
+
$this->client->setUseCurl($useCURL);
|
112 |
+
$this->client->soap_defencoding = 'UTF-8';
|
113 |
+
$items = $invoice->getAllItems();
|
114 |
+
|
115 |
+
foreach ($items as $item) {
|
116 |
+
if ($item->getBase_price() == 0) {
|
117 |
+
continue;
|
118 |
+
}
|
119 |
+
|
120 |
+
$Product = array (
|
121 |
+
'item' => $item->getName(), //string (*) Nome do produto/serviço
|
122 |
+
'type' => 'P', //char (*) Tipo (P ou S) consoante seja produto ou serviço
|
123 |
+
'quantity' => number_format((float)$item->getQty(), 0, '.', ''), //double (*) Quantidade (ex: 2)
|
124 |
+
'price' => number_format((float)$item->getBase_price(), 2, '.', ''), //double (*) Preço (ex: 99.99)
|
125 |
+
'discount' => $item->getDiscountAmount(), //double Desconto (ex: 19.99)
|
126 |
+
'tax' => number_format((float)$item->getOrderItem()->getTaxPercent(), 0, '.', ''), //int (*)Taxa de IVA (ex: 23)
|
127 |
+
'taxreason' => '', // string Motivo de isenção de Taxa, caso aplicável (ver tabela Motivos de isenção de IVA)
|
128 |
+
);
|
129 |
+
|
130 |
+
$Products[] = $Product;
|
131 |
+
|
132 |
+
|
133 |
+
$this->wLog->log("info","Item: ".$item->getName());
|
134 |
+
$this->wLog->log("info", "Item Quantity: ".number_format((float)$item->getQty(), 0, '.', ''));
|
135 |
+
$this->wLog->log("info", "Item Base price: ".number_format((float)$item->getBase_price(), 2, '.', ''));
|
136 |
+
$this->wLog->log("info", "Item Tax: ".number_format((float)$item->getOrderItem()->getTaxPercent(), 2, '.', ''));
|
137 |
+
} $this->wLog->log("info","Item discount: ".$item->getDiscountAmount());
|
138 |
+
|
139 |
+
// Shipping tax value in percentage
|
140 |
+
$vat = Mage::getStoreConfig('winvoice/wconfig/wshiptax');
|
141 |
+
|
142 |
+
$Product = array (
|
143 |
+
'item' => $invoice->getOrder()->getShippingDescription(),
|
144 |
+
'type' => 'S',
|
145 |
+
'quantity' => '1',
|
146 |
+
'price' => number_format((float)$invoice->getOrder()->getBaseShippingAmount(), 2, '.', ''),
|
147 |
+
'discount' => '0.00',
|
148 |
+
'tax' => $vat,
|
149 |
+
'taxreason' => '',
|
150 |
+
);
|
151 |
+
|
152 |
+
$Products[] = $Product;
|
153 |
+
|
154 |
+
$params = array(
|
155 |
+
'client' => $this->getClientNumber($invoice),
|
156 |
+
'type' => '1', //Tipo de documento (ver tabela Tipos de Documento)
|
157 |
+
'date' => date("Y-m-d"), //Data do documento (ex: 2011-01-01)
|
158 |
+
'payment_date' => date("Y-m-d"), //date (*) Data de vencimento do documento (ex: 2011-01-01)
|
159 |
+
'description' => 'F'.$invoice->getEntityId(),
|
160 |
+
'footer' => 'Numero Interno '.$invoice->getEntityId(),
|
161 |
+
'products' => $Products,
|
162 |
+
'password' => $this->password,
|
163 |
+
);
|
164 |
+
|
165 |
+
$result = $this->client->call("AddDocument", $params);
|
166 |
+
|
167 |
+
if ($this->client->fault) {
|
168 |
+
Mage::throwException(Mage::helper('adminhtml')->__('Erro ao criar factura.'));
|
169 |
+
$this->wLog->log("error", Mage::helper('adminhtml')->__('Erro ao criar factura.'));
|
170 |
+
} else {
|
171 |
+
$err = $this->client->getError();
|
172 |
+
|
173 |
+
if ($err) {
|
174 |
+
Mage::throwException(Mage::helper('adminhtml')->__('Erro ao criar factura.'));
|
175 |
+
$this->wLog->log("error", Mage::helper('adminhtml')->__('Erro ao criar factura.'));
|
176 |
+
} else {
|
177 |
+
$this->wLog->log("info", "Invoice Create Reply: ".$result['answer']);
|
178 |
+
$this->wLog->log("info", "Invoice id: ".$result['description1']);
|
179 |
+
$this->wLog->log("info", "Invoice URL: ".$result['description2']);
|
180 |
+
|
181 |
+
|
182 |
+
if ( $result['answer'] <> 0 && $result['answer'] <> 1 ) {
|
183 |
+
if (array_key_exists($result['answer'], $this->errorMessages)){
|
184 |
+
Mage::throwException(Mage::helper('adminhtml')->__($this->errorMessages[$result['answer']]));
|
185 |
+
$this->wLog->log("error", Mage::helper('adminhtml')->__($this->errorMessages[$result['answer']]));
|
186 |
+
} else {
|
187 |
+
Mage::throwException(Mage::helper('adminhtml')->__('Erro ao criar factura.'));
|
188 |
+
$this->wLog->log("error", Mage::helper('adminhtml')->__('Erro ao criar factura.'));
|
189 |
+
}
|
190 |
+
}
|
191 |
+
$invoice->setWsinvoiceurl($result['description2']);
|
192 |
+
}
|
193 |
+
}
|
194 |
+
$invoice->sendEmail(true, "Factura enviada ao cliente");
|
195 |
+
$this->wLog->log("info", "Factura enviada ao cliente");
|
196 |
+
}
|
197 |
+
|
198 |
+
/**
|
199 |
+
* Get invoice url method.
|
200 |
+
* - Returns the invoice url from weoInvoice service.
|
201 |
+
*
|
202 |
+
* @since 1.0.0
|
203 |
+
*
|
204 |
+
* @param Mage_Sales_Model_Observer $observer
|
205 |
+
* @return string
|
206 |
+
*/
|
207 |
+
public function getInvoiceURL($observer)
|
208 |
+
{
|
209 |
+
$invoice = $observer->getEvent()->getInvoice();
|
210 |
+
|
211 |
+
return $invoice->getWsinvoiceurl();
|
212 |
+
}
|
213 |
+
|
214 |
+
/**
|
215 |
+
* Get client number method.
|
216 |
+
* - Returns the invoice url from weoInvoice service.
|
217 |
+
*
|
218 |
+
* @since 1.0.0
|
219 |
+
*
|
220 |
+
* @param Mage_Sales_Model_Order_Invoice $invoice
|
221 |
+
* @return string
|
222 |
+
*/
|
223 |
+
private function getClientNumber($invoice)
|
224 |
+
{
|
225 |
+
$address = $invoice->getBillingAddress();
|
226 |
+
if (!$address->getCountryId() == 'PT') {
|
227 |
+
Mage::throwException(Mage::helper('adminhtml')->__( $invoice->getOrder()->getCustomerTaxvat().' Numero de contribuinte invalido.'));
|
228 |
+
$this->wLog->log("error", Mage::helper('adminhtml')->__( $invoice->getOrder()->getCustomerTaxvat().' Numero de contribuinte invalido.'));
|
229 |
+
}
|
230 |
+
if (!$this->isValidNif($invoice->getOrder()->getCustomerTaxvat())) {
|
231 |
+
Mage::throwException(Mage::helper('adminhtml')->__( $invoice->getOrder()->getCustomerTaxvat().' Numero de contribuinte invalido.'));
|
232 |
+
$this->wLog->log("error", Mage::helper('adminhtml')->__( $invoice->getOrder()->getCustomerTaxvat().' Numero de contribuinte invalido.'));
|
233 |
+
}
|
234 |
+
|
235 |
+
$customer = Mage::getModel('customer/customer')->load($invoice->getOrder()->getCustomerId());
|
236 |
+
|
237 |
+
$this->wLog->log("info", "Invoicing Customer name:".$invoice->getOrder()->getCustomerName());
|
238 |
+
$this->wLog->log("info", "Invoicing Customer Id:".$invoice->getOrder()->getCustomerId());
|
239 |
+
$this->wLog->log("info", "Invoicing Customer VAT:".$invoice->getOrder()->getCustomerTaxvat());
|
240 |
+
$this->wLog->log("info", "Invoicing Customer WSClient:".$customer->getWsclient());
|
241 |
+
$this->wLog->log("info", "Invoicing Customer WSClient:".$invoice->getOrder()->getCustomerWsclient());
|
242 |
+
$this->wLog->log("info", "Customer address data: ".$address->getStreetFull());
|
243 |
+
$this->wLog->log("info", "Customer address data: ".$address->getPostcode());
|
244 |
+
$this->wLog->log("info", "Customer address data: ".$address->getCity());
|
245 |
+
$this->wLog->log("info", "Customer address data: ".$address->getCountryId());
|
246 |
+
|
247 |
+
if ( is_numeric( $customer->getWsclient() ) ) {
|
248 |
+
return $customer->getWsclient();
|
249 |
+
}
|
250 |
+
|
251 |
+
$useCURL = isset($_POST['usecurl']) ? $_POST['usecurl'] : '0';
|
252 |
+
$err = $this->client->getError();
|
253 |
+
|
254 |
+
if ($err) {
|
255 |
+
Mage::throwException(Mage::helper('adminhtml')->__('Erro ao criar factura.'));
|
256 |
+
$this->wLog->log("error", Mage::helper('adminhtml')->__('Erro ao criar factura.'));
|
257 |
+
exit();
|
258 |
+
}
|
259 |
+
|
260 |
+
$this->client->setUseCurl($useCURL);
|
261 |
+
$this->client->soap_defencoding = 'UTF-8';
|
262 |
+
|
263 |
+
if ( is_numeric($invoice->getOrder()->getCustomerTaxvat()) ) {
|
264 |
+
$vatnumber = $invoice->getOrder()->getCustomerTaxvat();
|
265 |
+
} else {
|
266 |
+
$vatnumber = '999999900';
|
267 |
+
}
|
268 |
+
|
269 |
+
$AddClientIn = array (
|
270 |
+
'code' => "MAG".$invoice->getOrder()->getCustomerId().rand(1,999999),
|
271 |
+
'name' => $invoice->getOrder()->getCustomerName(),
|
272 |
+
'nif' => $vatnumber,
|
273 |
+
// email string Endereço de email
|
274 |
+
// url string Página web
|
275 |
+
'address' => $address->getStreetFull(),
|
276 |
+
'postcode' => $address->getPostcode(),
|
277 |
+
'city' => $address->getCity(),
|
278 |
+
'country' => $address->getCountryId(),
|
279 |
+
// telephone string Telefone do cliente (ex: 212109902)
|
280 |
+
// mobile string Telemóvel do cliente
|
281 |
+
// fax string Fax do cliente
|
282 |
+
// description string Descrição
|
283 |
+
);
|
284 |
+
|
285 |
+
$params = array(
|
286 |
+
'data' => $AddClientIn,
|
287 |
+
'password'=> $this->password,
|
288 |
+
);
|
289 |
+
|
290 |
+
$result = $this->client->call("AddClient", $params);
|
291 |
+
|
292 |
+
if ($this->client->fault) {
|
293 |
+
Mage::throwException(Mage::helper('adminhtml')->__('Erro ao criar factura.'));
|
294 |
+
$this->wLog->log("error", Mage::helper('adminhtml')->__('Erro ao criar factura.'));
|
295 |
+
} else {
|
296 |
+
$err = $this->client->getError();
|
297 |
+
|
298 |
+
if ($err) {
|
299 |
+
Mage::throwException(Mage::helper('adminhtml')->__('Erro ao criar factura.'));
|
300 |
+
$this->wLog->log("error", Mage::helper('adminhtml')->__('Erro ao criar factura.'));
|
301 |
+
} else {
|
302 |
+
if ( $invoice->getOrder()->getCustomerId() ) {
|
303 |
+
$customer = Mage::getModel('customer/customer')->load($invoice->getOrder()->getCustomerId());
|
304 |
+
$customer->setWsclient($result['description1']);
|
305 |
+
$customer->save();
|
306 |
+
} else {
|
307 |
+
$this->wLog->log("info", "One time costumer processed");
|
308 |
+
}
|
309 |
+
|
310 |
+
$this->wLog->log("info", "Created new WSClient ".$result['description1']);
|
311 |
+
$this->wLog->log("info", "Created new WSClient api code ".$result['answer']);
|
312 |
+
|
313 |
+
return $result['description1'];
|
314 |
+
}
|
315 |
+
}
|
316 |
+
}
|
317 |
+
|
318 |
+
/**
|
319 |
+
* Auto invoice method.
|
320 |
+
* - Prepares order to create and send invoice to client.
|
321 |
+
*
|
322 |
+
* @since 1.0.0
|
323 |
+
*
|
324 |
+
* @param Mage_Sales_Model_Observer $observer
|
325 |
+
* @return void
|
326 |
+
*/
|
327 |
+
public function AutoInvoice($observer)
|
328 |
+
{
|
329 |
+
return;
|
330 |
+
|
331 |
+
$this->wLog->Log("info", "AutoInvoice trigger for order".$observer->getEvent()->getOrder());
|
332 |
+
|
333 |
+
$order = $observer->getEvent()->getShipment()->getOrder();
|
334 |
+
|
335 |
+
$invoice = $order->prepareInvoice();
|
336 |
+
$invoice->setRequestedCaptureCase(Mage_Sales_Model_Order_Invoice::CAPTURE_OFFLINE);
|
337 |
+
$invoice->register();
|
338 |
+
$invoice->getOrder()->setCustomerNoteNotify(true);
|
339 |
+
$invoice->getOrder()->setIsInProcess(true);
|
340 |
+
|
341 |
+
$order->addStatusHistoryComment('AutoInvoice by Winvoice.', false);
|
342 |
+
|
343 |
+
$transactionSave = Mage::getModel('core/resource_transaction')
|
344 |
+
->addObject($invoice)
|
345 |
+
->addObject($invoice->getOrder());
|
346 |
+
|
347 |
+
$transactionSave->save();
|
348 |
+
|
349 |
+
$invoice->sendEmail(true, "Factura enviada ao cliente");
|
350 |
+
}
|
351 |
+
|
352 |
+
/**
|
353 |
+
* Is valid nif method.
|
354 |
+
* - Checks if nif number is valid.
|
355 |
+
*
|
356 |
+
* @since 1.0.0
|
357 |
+
*
|
358 |
+
* @param string $nif
|
359 |
+
* @return bool
|
360 |
+
*/
|
361 |
+
public function isValidNif($nif)
|
362 |
+
{
|
363 |
+
if (!is_numeric($nif) || strlen($nif) != 9) return false;
|
364 |
+
|
365 |
+
$narray = str_split($nif);
|
366 |
+
|
367 |
+
if ($narray[0] != 1 && $narray[0] != 2 && $narray[0] != 5 && $narray[0] != 6 && $narray[0] != 8 && $narray[0] != 9) {
|
368 |
+
return false;
|
369 |
+
}
|
370 |
+
|
371 |
+
$checkbit = $narray[0] * 9;
|
372 |
+
|
373 |
+
for ($i=2; $i<=8; $i++) {
|
374 |
+
$checkbit += $nif[$i-1] * (10 - $i);
|
375 |
+
}
|
376 |
+
|
377 |
+
$checkbit = 11 - ($checkbit % 11);
|
378 |
+
|
379 |
+
if ($checkbit >= 10) {
|
380 |
+
$checkbit = 0;
|
381 |
+
}
|
382 |
+
|
383 |
+
if($nif[8] == $checkbit) {
|
384 |
+
return true;
|
385 |
+
}
|
386 |
+
|
387 |
+
return false;
|
388 |
+
}
|
389 |
+
|
390 |
+
}
|
app/code/local/Waterstone/winvoice/Model/Email/Template/Mailer.php
ADDED
@@ -0,0 +1,228 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* DISCLAIMER
|
4 |
+
*
|
5 |
+
* Do not edit or add to this file if you wish to upgrade the extension to newer
|
6 |
+
* versions in the future. If you need personal customization please contact us
|
7 |
+
* on http://www.waterstone.pt for more information.
|
8 |
+
*
|
9 |
+
* @category Waterstone
|
10 |
+
* @package Waterstone_Winvoice
|
11 |
+
* @copyright Copyright (c) 2014 Waterstone Consulting, Lda. (http://www.waterstone.pt)
|
12 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
13 |
+
*/
|
14 |
+
|
15 |
+
class Waterstone_Winvoice_Model_Email_Template_Mailer extends Mage_Core_Model_Email_Template_Mailer
|
16 |
+
{
|
17 |
+
|
18 |
+
/**
|
19 |
+
* List of email infos
|
20 |
+
* @see Mage_Core_Model_Email_Info
|
21 |
+
*
|
22 |
+
* @since 1.0.0
|
23 |
+
*
|
24 |
+
* @var array
|
25 |
+
*/
|
26 |
+
protected $_emailInfos = array();
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Email template
|
30 |
+
*
|
31 |
+
* @since 1.0.0
|
32 |
+
*
|
33 |
+
* @var Waterstone_Winvoice_Model_Email_Template
|
34 |
+
*/
|
35 |
+
protected $emailTemplate;
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Add email info method.
|
39 |
+
* - Add new email info to corresponding list
|
40 |
+
*
|
41 |
+
* @since 1.0.0
|
42 |
+
*
|
43 |
+
* @param Mage_Core_Model_Email_Info $emailInfo
|
44 |
+
* @return Waterstone_Winvoice_Model_Email_Template_Mailer
|
45 |
+
*/
|
46 |
+
public function addEmailInfo(Mage_Core_Model_Email_Info $emailInfo)
|
47 |
+
{
|
48 |
+
array_push($this->_emailInfos, $emailInfo);
|
49 |
+
|
50 |
+
return $this;
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Send method.
|
55 |
+
* - Send all emails from email list
|
56 |
+
* @see self::$_emailInfos
|
57 |
+
*
|
58 |
+
* @since 1.0.0
|
59 |
+
*
|
60 |
+
* @return Waterstone_Winvoice_Model_Email_Template_Mailer
|
61 |
+
*/
|
62 |
+
public function send()
|
63 |
+
{
|
64 |
+
if ($this->emailTemplate) {
|
65 |
+
$emailTemplate = $this->emailTemplate;
|
66 |
+
} else {
|
67 |
+
$emailTemplate = Mage::getModel('core/email_template');
|
68 |
+
}
|
69 |
+
|
70 |
+
// Send all emails from corresponding list
|
71 |
+
while (!empty($this->_emailInfos)) {
|
72 |
+
|
73 |
+
$emailInfo = array_pop($this->_emailInfos);
|
74 |
+
|
75 |
+
// Handle "Bcc" recepients of the current email
|
76 |
+
$emailTemplate->addBcc($emailInfo->getBccEmails());
|
77 |
+
|
78 |
+
// Set required design parameters and delegate email sending to Mage_Core_Model_Email_Template
|
79 |
+
$emailTemplate->setDesignConfig(array('area' => 'frontend', 'store' => $this->getStoreId()))->sendTransactional(
|
80 |
+
$this->getTemplateId(),
|
81 |
+
$this->getSender(),
|
82 |
+
$emailInfo->getToEmails(),
|
83 |
+
$emailInfo->getToNames(),
|
84 |
+
$this->getTemplateParams(),
|
85 |
+
$this->getStoreId()
|
86 |
+
);
|
87 |
+
}
|
88 |
+
|
89 |
+
return $this;
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Set sender method.
|
94 |
+
* - Set email sender.
|
95 |
+
*
|
96 |
+
* @since 1.0.0
|
97 |
+
*
|
98 |
+
* @param string|array $sender
|
99 |
+
* @return Waterstone_Winvoice_Model_Email_Template_Mailer
|
100 |
+
*/
|
101 |
+
public function setSender($sender)
|
102 |
+
{
|
103 |
+
return $this->setData('sender', $sender);
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Get sender method.
|
108 |
+
* - Get email sender.
|
109 |
+
*
|
110 |
+
* @since 1.0.0
|
111 |
+
*
|
112 |
+
* @return string|array|null
|
113 |
+
*/
|
114 |
+
public function getSender()
|
115 |
+
{
|
116 |
+
return $this->_getData('sender');
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Set store id method.
|
121 |
+
*
|
122 |
+
* @since 1.0.0
|
123 |
+
*
|
124 |
+
* @param int $storeId
|
125 |
+
* @return Waterstone_Winvoice_Model_Email_Template_Mailer
|
126 |
+
*/
|
127 |
+
public function setStoreId($storeId)
|
128 |
+
{
|
129 |
+
return $this->setData('store_id', $storeId);
|
130 |
+
}
|
131 |
+
|
132 |
+
/**
|
133 |
+
* Get store id method.
|
134 |
+
*
|
135 |
+
* @since 1.0.0
|
136 |
+
*
|
137 |
+
* @return int|null
|
138 |
+
*/
|
139 |
+
public function getStoreId()
|
140 |
+
{
|
141 |
+
return $this->_getData('store_id');
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Set template id method.
|
146 |
+
*
|
147 |
+
* @since 1.0.0
|
148 |
+
*
|
149 |
+
* @param int $templateId
|
150 |
+
* @return Waterstone_Winvoice_Model_Email_Template_Mailer
|
151 |
+
*/
|
152 |
+
public function setTemplateId($templateId)
|
153 |
+
{
|
154 |
+
return $this->setData('template_id', $templateId);
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Get template id method.
|
159 |
+
*
|
160 |
+
* @since 1.0.0
|
161 |
+
*
|
162 |
+
* @return int|null
|
163 |
+
*/
|
164 |
+
public function getTemplateId()
|
165 |
+
{
|
166 |
+
return $this->_getData('template_id');
|
167 |
+
}
|
168 |
+
|
169 |
+
/**
|
170 |
+
* Set template parameters method.
|
171 |
+
*
|
172 |
+
* @since 1.0.0
|
173 |
+
*
|
174 |
+
* @param array $templateParams
|
175 |
+
* @return Waterstone_Winvoice_Model_Email_Template_Mailer
|
176 |
+
*/
|
177 |
+
public function setTemplateParams(array $templateParams)
|
178 |
+
{
|
179 |
+
return $this->setData('template_params', $templateParams);
|
180 |
+
}
|
181 |
+
|
182 |
+
/**
|
183 |
+
* Get template parameters method.
|
184 |
+
*
|
185 |
+
* @since 1.0.0
|
186 |
+
*
|
187 |
+
* @return array|null
|
188 |
+
*/
|
189 |
+
public function getTemplateParams()
|
190 |
+
{
|
191 |
+
return $this->_getData('template_params');
|
192 |
+
}
|
193 |
+
|
194 |
+
/**
|
195 |
+
* Add attachment method.
|
196 |
+
* - Add attachment to email template.
|
197 |
+
*
|
198 |
+
* @since 1.0.0
|
199 |
+
*
|
200 |
+
* @param string $filename
|
201 |
+
* @param string $url
|
202 |
+
* @return void
|
203 |
+
*/
|
204 |
+
public function addAttachment($filename, $url)
|
205 |
+
{
|
206 |
+
$ch = curl_init();
|
207 |
+
|
208 |
+
curl_setopt($ch, CURLOPT_URL, $url);
|
209 |
+
curl_setopt($ch, CURLOPT_VERBOSE, 1);
|
210 |
+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
211 |
+
curl_setopt($ch, CURLOPT_AUTOREFERER, false);
|
212 |
+
curl_setopt($ch, CURLOPT_REFERER, "http://www.weoinvoice.com");
|
213 |
+
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
|
214 |
+
curl_setopt($ch, CURLOPT_HEADER, 0);
|
215 |
+
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
216 |
+
|
217 |
+
$file_content = curl_exec($ch);
|
218 |
+
|
219 |
+
curl_close($ch);
|
220 |
+
|
221 |
+
$this->emailTemplate = Mage::getModel('core/email_template');
|
222 |
+
$attachment = $this->emailTemplate->getMail()->createAttachment($file_content);
|
223 |
+
$attachment->type = 'application/pdf';
|
224 |
+
$attachment->filename = $filename;
|
225 |
+
}
|
226 |
+
|
227 |
+
}
|
228 |
+
|
app/code/local/Waterstone/winvoice/Model/Log.php
ADDED
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* DISCLAIMER
|
4 |
+
*
|
5 |
+
* Do not edit or add to this file if you wish to upgrade the extension to newer
|
6 |
+
* versions in the future. If you need personal customization please contact us
|
7 |
+
* on http://www.waterstone.pt for more information.
|
8 |
+
*
|
9 |
+
* @category Waterstone
|
10 |
+
* @package Waterstone_Winvoice
|
11 |
+
* @copyright Copyright (c) 2014 Waterstone Consulting, Lda. (http://www.waterstone.pt)
|
12 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
13 |
+
*/
|
14 |
+
|
15 |
+
class Waterstone_Winvoice_Model_Log extends Mage_Core_Model_Abstract
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* construtor para a classe log
|
19 |
+
*
|
20 |
+
* @since 1.0.1
|
21 |
+
*
|
22 |
+
* @return Waterstone_Winvoice_Model_Log
|
23 |
+
*/
|
24 |
+
public function __construct() {
|
25 |
+
|
26 |
+
if(!is_dir(Mage::getBaseDir('log'))) {
|
27 |
+
mkdir(Mage::getBaseDir('var').DS.'log', 0777);
|
28 |
+
$file = fopen($dir, "a");
|
29 |
+
|
30 |
+
if ($file == false) {
|
31 |
+
Mage::throwException(Mage::helper('adminhtml')->__('Erro ao criar ficheiro de log.'));
|
32 |
+
}
|
33 |
+
} else {
|
34 |
+
$dir = Mage::getBaseDir('log') . '/winvoice.log';
|
35 |
+
$file = fopen($dir, "a");
|
36 |
+
|
37 |
+
if ($file == false) {
|
38 |
+
Mage::throwException(Mage::helper('adminhtml')->__('Erro ao criar ficheiro de log.'));
|
39 |
+
}
|
40 |
+
}
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Função chamada noutras classes para efectuar os logs.
|
45 |
+
*
|
46 |
+
* @since 1.0.1
|
47 |
+
*
|
48 |
+
* @param string $type tipo de log a ser escrito
|
49 |
+
* @param string $message messagem a ser impressa
|
50 |
+
* @return file output escrita no ficheiro winvoice.log
|
51 |
+
*/
|
52 |
+
public function log($type, $message) {
|
53 |
+
|
54 |
+
$date = date("Y-m-d H:i:s");
|
55 |
+
$file = fopen(Mage::getBaseDir('log').'/winvoice.log', "a");
|
56 |
+
|
57 |
+
if ($file == true) {
|
58 |
+
$write = fwrite($file, "$date: $type: $message \n");
|
59 |
+
} else {
|
60 |
+
Mage::throwException(Mage::helper('adminhtml')->__('Erro ao escrever no ficheiro de log.'));
|
61 |
+
}
|
62 |
+
|
63 |
+
fclose($file);
|
64 |
+
}
|
65 |
+
}
|
app/code/local/Waterstone/winvoice/Model/Mysql4/Winvoice.php
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* DISCLAIMER
|
4 |
+
*
|
5 |
+
* Do not edit or add to this file if you wish to upgrade the extension to newer
|
6 |
+
* versions in the future. If you need personal customization please contact us
|
7 |
+
* on http://www.waterstone.pt for more information.
|
8 |
+
*
|
9 |
+
* @category Waterstone
|
10 |
+
* @package Waterstone_Winvoice
|
11 |
+
* @copyright Copyright (c) 2014 Waterstone Consulting, Lda. (http://www.waterstone.pt)
|
12 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
13 |
+
*/
|
14 |
+
|
15 |
+
class Waterstone_Winvoice_Model_Mysql4_Winvoice extends Mage_Core_Model_Mysql4_Abstract
|
16 |
+
{
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Constructor.
|
20 |
+
*
|
21 |
+
* @since 1.0.0
|
22 |
+
*
|
23 |
+
* @return void
|
24 |
+
*/
|
25 |
+
public function _construct()
|
26 |
+
{
|
27 |
+
// Note that the winvoice_id refers to the key field in your database table.
|
28 |
+
$this->_init('winvoice/winvoice', 'winvoice_id');
|
29 |
+
}
|
30 |
+
|
31 |
+
}
|
app/code/local/Waterstone/winvoice/Model/Mysql4/Winvoice/Collection.php
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* DISCLAIMER
|
4 |
+
*
|
5 |
+
* Do not edit or add to this file if you wish to upgrade the extension to newer
|
6 |
+
* versions in the future. If you need personal customization please contact us
|
7 |
+
* on http://www.waterstone.pt for more information.
|
8 |
+
*
|
9 |
+
* @category Waterstone
|
10 |
+
* @package Waterstone_Winvoice
|
11 |
+
* @copyright Copyright (c) 2014 Waterstone Consulting, Lda. (http://www.waterstone.pt)
|
12 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
13 |
+
*/
|
14 |
+
|
15 |
+
class Waterstone_Winvoice_Model_Mysql4_Winvoice_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* Constructor.
|
19 |
+
*
|
20 |
+
* @since 1.0.0
|
21 |
+
*
|
22 |
+
* @return void
|
23 |
+
*/
|
24 |
+
public function _construct()
|
25 |
+
{
|
26 |
+
parent::_construct();
|
27 |
+
|
28 |
+
$this->_init('winvoice/winvoice');
|
29 |
+
}
|
30 |
+
|
31 |
+
}
|
app/code/local/Waterstone/winvoice/Model/Order/Invoice.php
ADDED
@@ -0,0 +1,1142 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* DISCLAIMER
|
4 |
+
*
|
5 |
+
* Do not edit or add to this file if you wish to upgrade the extension to newer
|
6 |
+
* versions in the future. If you need personal customization please contact us
|
7 |
+
* on http://www.waterstone.pt for more information.
|
8 |
+
*
|
9 |
+
* @category Waterstone
|
10 |
+
* @package Waterstone_Winvoice
|
11 |
+
* @copyright Copyright (c) 2014 Waterstone Consulting, Lda. (http://www.waterstone.pt)
|
12 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
13 |
+
*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Enter description here ...
|
17 |
+
*
|
18 |
+
* @method Mage_Sales_Model_Resource_Order_Invoice _getResource()
|
19 |
+
* @method Mage_Sales_Model_Resource_Order_Invoice getResource()
|
20 |
+
* @method int getStoreId()
|
21 |
+
* @method Mage_Sales_Model_Order_Invoice setStoreId(int $value)
|
22 |
+
* @method float getBaseGrandTotal()
|
23 |
+
* @method Mage_Sales_Model_Order_Invoice setBaseGrandTotal(float $value)
|
24 |
+
* @method float getShippingTaxAmount()
|
25 |
+
* @method Mage_Sales_Model_Order_Invoice setShippingTaxAmount(float $value)
|
26 |
+
* @method float getTaxAmount()
|
27 |
+
* @method Mage_Sales_Model_Order_Invoice setTaxAmount(float $value)
|
28 |
+
* @method float getBaseTaxAmount()
|
29 |
+
* @method Mage_Sales_Model_Order_Invoice setBaseTaxAmount(float $value)
|
30 |
+
* @method float getStoreToOrderRate()
|
31 |
+
* @method Mage_Sales_Model_Order_Invoice setStoreToOrderRate(float $value)
|
32 |
+
* @method float getBaseShippingTaxAmount()
|
33 |
+
* @method Mage_Sales_Model_Order_Invoice setBaseShippingTaxAmount(float $value)
|
34 |
+
* @method float getBaseDiscountAmount()
|
35 |
+
* @method Mage_Sales_Model_Order_Invoice setBaseDiscountAmount(float $value)
|
36 |
+
* @method float getBaseToOrderRate()
|
37 |
+
* @method Mage_Sales_Model_Order_Invoice setBaseToOrderRate(float $value)
|
38 |
+
* @method float getGrandTotal()
|
39 |
+
* @method Mage_Sales_Model_Order_Invoice setGrandTotal(float $value)
|
40 |
+
* @method float getShippingAmount()
|
41 |
+
* @method Mage_Sales_Model_Order_Invoice setShippingAmount(float $value)
|
42 |
+
* @method float getSubtotalInclTax()
|
43 |
+
* @method Mage_Sales_Model_Order_Invoice setSubtotalInclTax(float $value)
|
44 |
+
* @method float getBaseSubtotalInclTax()
|
45 |
+
* @method Mage_Sales_Model_Order_Invoice setBaseSubtotalInclTax(float $value)
|
46 |
+
* @method float getStoreToBaseRate()
|
47 |
+
* @method Mage_Sales_Model_Order_Invoice setStoreToBaseRate(float $value)
|
48 |
+
* @method float getBaseShippingAmount()
|
49 |
+
* @method Mage_Sales_Model_Order_Invoice setBaseShippingAmount(float $value)
|
50 |
+
* @method float getTotalQty()
|
51 |
+
* @method Mage_Sales_Model_Order_Invoice setTotalQty(float $value)
|
52 |
+
* @method float getBaseToGlobalRate()
|
53 |
+
* @method Mage_Sales_Model_Order_Invoice setBaseToGlobalRate(float $value)
|
54 |
+
* @method float getSubtotal()
|
55 |
+
* @method Mage_Sales_Model_Order_Invoice setSubtotal(float $value)
|
56 |
+
* @method float getBaseSubtotal()
|
57 |
+
* @method Mage_Sales_Model_Order_Invoice setBaseSubtotal(float $value)
|
58 |
+
* @method float getDiscountAmount()
|
59 |
+
* @method Mage_Sales_Model_Order_Invoice setDiscountAmount(float $value)
|
60 |
+
* @method int getBillingAddressId()
|
61 |
+
* @method Mage_Sales_Model_Order_Invoice setBillingAddressId(int $value)
|
62 |
+
* @method int getIsUsedForRefund()
|
63 |
+
* @method Mage_Sales_Model_Order_Invoice setIsUsedForRefund(int $value)
|
64 |
+
* @method int getOrderId()
|
65 |
+
* @method Mage_Sales_Model_Order_Invoice setOrderId(int $value)
|
66 |
+
* @method int getEmailSent()
|
67 |
+
* @method Mage_Sales_Model_Order_Invoice setEmailSent(int $value)
|
68 |
+
* @method int getCanVoidFlag()
|
69 |
+
* @method Mage_Sales_Model_Order_Invoice setCanVoidFlag(int $value)
|
70 |
+
* @method int getState()
|
71 |
+
* @method Mage_Sales_Model_Order_Invoice setState(int $value)
|
72 |
+
* @method int getShippingAddressId()
|
73 |
+
* @method Mage_Sales_Model_Order_Invoice setShippingAddressId(int $value)
|
74 |
+
* @method string getCybersourceToken()
|
75 |
+
* @method Mage_Sales_Model_Order_Invoice setCybersourceToken(string $value)
|
76 |
+
* @method string getStoreCurrencyCode()
|
77 |
+
* @method Mage_Sales_Model_Order_Invoice setStoreCurrencyCode(string $value)
|
78 |
+
* @method string getTransactionId()
|
79 |
+
* @method Mage_Sales_Model_Order_Invoice setTransactionId(string $value)
|
80 |
+
* @method string getOrderCurrencyCode()
|
81 |
+
* @method Mage_Sales_Model_Order_Invoice setOrderCurrencyCode(string $value)
|
82 |
+
* @method string getBaseCurrencyCode()
|
83 |
+
* @method Mage_Sales_Model_Order_Invoice setBaseCurrencyCode(string $value)
|
84 |
+
* @method string getGlobalCurrencyCode()
|
85 |
+
* @method Mage_Sales_Model_Order_Invoice setGlobalCurrencyCode(string $value)
|
86 |
+
* @method string getIncrementId()
|
87 |
+
* @method Mage_Sales_Model_Order_Invoice setIncrementId(string $value)
|
88 |
+
* @method string getCreatedAt()
|
89 |
+
* @method Mage_Sales_Model_Order_Invoice setCreatedAt(string $value)
|
90 |
+
* @method string getUpdatedAt()
|
91 |
+
* @method Mage_Sales_Model_Order_Invoice setUpdatedAt(string $value)
|
92 |
+
* @method float getHiddenTaxAmount()
|
93 |
+
* @method Mage_Sales_Model_Order_Invoice setHiddenTaxAmount(float $value)
|
94 |
+
* @method float getBaseHiddenTaxAmount()
|
95 |
+
* @method Mage_Sales_Model_Order_Invoice setBaseHiddenTaxAmount(float $value)
|
96 |
+
* @method float getShippingHiddenTaxAmount()
|
97 |
+
* @method Mage_Sales_Model_Order_Invoice setShippingHiddenTaxAmount(float $value)
|
98 |
+
* @method float getBaseShippingHiddenTaxAmount()
|
99 |
+
* @method Mage_Sales_Model_Order_Invoice setBaseShippingHiddenTaxAmount(float $value)
|
100 |
+
* @method float getShippingInclTax()
|
101 |
+
* @method Mage_Sales_Model_Order_Invoice setShippingInclTax(float $value)
|
102 |
+
* @method float getBaseShippingInclTax()
|
103 |
+
* @method Mage_Sales_Model_Order_Invoice setBaseShippingInclTax(float $value)
|
104 |
+
*/
|
105 |
+
|
106 |
+
class Waterstone_Winvoice_Model_Order_Invoice extends Mage_Sales_Model_Order_Invoice
|
107 |
+
{
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Invoice states
|
111 |
+
*/
|
112 |
+
|
113 |
+
const STATE_OPEN = 1;
|
114 |
+
const STATE_PAID = 2;
|
115 |
+
const STATE_CANCELED = 3;
|
116 |
+
|
117 |
+
const CAPTURE_ONLINE = 'online';
|
118 |
+
const CAPTURE_OFFLINE = 'offline';
|
119 |
+
const NOT_CAPTURE = 'not_capture';
|
120 |
+
|
121 |
+
const XML_PATH_EMAIL_TEMPLATE = 'sales_email/invoice/template';
|
122 |
+
const XML_PATH_EMAIL_GUEST_TEMPLATE = 'sales_email/invoice/guest_template';
|
123 |
+
const XML_PATH_EMAIL_IDENTITY = 'sales_email/invoice/identity';
|
124 |
+
const XML_PATH_EMAIL_COPY_TO = 'sales_email/invoice/copy_to';
|
125 |
+
const XML_PATH_EMAIL_COPY_METHOD = 'sales_email/invoice/copy_method';
|
126 |
+
const XML_PATH_EMAIL_ENABLED = 'sales_email/invoice/enabled';
|
127 |
+
const XML_PATH_UPDATE_EMAIL_TEMPLATE = 'sales_email/invoice_comment/template';
|
128 |
+
const XML_PATH_UPDATE_EMAIL_GUEST_TEMPLATE = 'sales_email/invoice_comment/guest_template';
|
129 |
+
const XML_PATH_UPDATE_EMAIL_IDENTITY = 'sales_email/invoice_comment/identity';
|
130 |
+
const XML_PATH_UPDATE_EMAIL_COPY_TO = 'sales_email/invoice_comment/copy_to';
|
131 |
+
const XML_PATH_UPDATE_EMAIL_COPY_METHOD = 'sales_email/invoice_comment/copy_method';
|
132 |
+
const XML_PATH_UPDATE_EMAIL_ENABLED = 'sales_email/invoice_comment/enabled';
|
133 |
+
|
134 |
+
const REPORT_DATE_TYPE_ORDER_CREATED = 'order_created';
|
135 |
+
const REPORT_DATE_TYPE_INVOICE_CREATED = 'invoice_created';
|
136 |
+
|
137 |
+
/*
|
138 |
+
* Identifier for order history item
|
139 |
+
*/
|
140 |
+
const HISTORY_ENTITY_NAME = 'invoice';
|
141 |
+
|
142 |
+
protected static $_states;
|
143 |
+
protected $_items;
|
144 |
+
protected $_comments;
|
145 |
+
protected $_order;
|
146 |
+
|
147 |
+
/**
|
148 |
+
* Calculator instances for delta rounding of prices
|
149 |
+
*
|
150 |
+
* @var array
|
151 |
+
*/
|
152 |
+
protected $_rounders = array();
|
153 |
+
protected $_saveBeforeDestruct = false;
|
154 |
+
protected $_eventPrefix = 'sales_order_invoice';
|
155 |
+
protected $_eventObject = 'invoice';
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Whether the pay() was called
|
159 |
+
* @var bool
|
160 |
+
*/
|
161 |
+
protected $_wasPayCalled = false;
|
162 |
+
|
163 |
+
|
164 |
+
public function __destruct()
|
165 |
+
{
|
166 |
+
if ($this->_saveBeforeDestruct) {
|
167 |
+
$this->save();
|
168 |
+
}
|
169 |
+
}
|
170 |
+
|
171 |
+
/**
|
172 |
+
* Initialize invoice resource model
|
173 |
+
*
|
174 |
+
* @since 1.0.0
|
175 |
+
*
|
176 |
+
* @return void
|
177 |
+
*/
|
178 |
+
protected function _construct()
|
179 |
+
{
|
180 |
+
$this->_init('sales/order_invoice');
|
181 |
+
}
|
182 |
+
|
183 |
+
/**
|
184 |
+
* Init mapping array of short fields to its full names
|
185 |
+
*
|
186 |
+
* @since 1.0.0
|
187 |
+
*
|
188 |
+
* @return Waterstone_Winvoice_Model_Order_Invoice
|
189 |
+
*/
|
190 |
+
protected function _initOldFieldsMap()
|
191 |
+
{
|
192 |
+
$this->_oldFieldsMap = Mage::helper('sales')->getOldFieldMap('order_invoice');
|
193 |
+
|
194 |
+
return $this;
|
195 |
+
}
|
196 |
+
|
197 |
+
/**
|
198 |
+
* Load invoice by increment id
|
199 |
+
*
|
200 |
+
* @since 1.0.0
|
201 |
+
*
|
202 |
+
* @param string $incrementId
|
203 |
+
* @return Waterstone_Winvoice_Model_Order_Invoice
|
204 |
+
*/
|
205 |
+
public function loadByIncrementId($incrementId)
|
206 |
+
{
|
207 |
+
$ids = $this->getCollection()
|
208 |
+
->addAttributeToFilter('increment_id', $incrementId)
|
209 |
+
->getAllIds();
|
210 |
+
|
211 |
+
if (!empty($ids)) {
|
212 |
+
reset($ids);
|
213 |
+
$this->load(current($ids));
|
214 |
+
}
|
215 |
+
|
216 |
+
return $this;
|
217 |
+
}
|
218 |
+
|
219 |
+
/**
|
220 |
+
* Retrieve invoice configuration model
|
221 |
+
*
|
222 |
+
* @since 1.0.0
|
223 |
+
*
|
224 |
+
* @return Mage_Sales_Model_Order_Invoice_Config
|
225 |
+
*/
|
226 |
+
public function getConfig()
|
227 |
+
{
|
228 |
+
return Mage::getSingleton('sales/order_invoice_config');
|
229 |
+
}
|
230 |
+
|
231 |
+
/**
|
232 |
+
* Retrieve store model instance
|
233 |
+
*
|
234 |
+
* @since 1.0.0
|
235 |
+
*
|
236 |
+
* @return Mage_Core_Model_Store
|
237 |
+
*/
|
238 |
+
public function getStore()
|
239 |
+
{
|
240 |
+
return $this->getOrder()->getStore();
|
241 |
+
}
|
242 |
+
|
243 |
+
/**
|
244 |
+
* Declare order for invoice
|
245 |
+
*
|
246 |
+
* @since 1.0.0
|
247 |
+
*
|
248 |
+
* @param Mage_Sales_Model_Order $order
|
249 |
+
* @return Waterstone_Winvoice_Model_Order_Invoice
|
250 |
+
*/
|
251 |
+
public function setOrder(Mage_Sales_Model_Order $order)
|
252 |
+
{
|
253 |
+
$this->_order = $order;
|
254 |
+
$this->setOrderId($order->getId())->setStoreId($order->getStoreId());
|
255 |
+
|
256 |
+
return $this;
|
257 |
+
}
|
258 |
+
|
259 |
+
/**
|
260 |
+
* Retrieve the order the invoice for created for
|
261 |
+
*
|
262 |
+
* @since 1.0.0
|
263 |
+
*
|
264 |
+
* @return Mage_Sales_Model_Order
|
265 |
+
*/
|
266 |
+
public function getOrder()
|
267 |
+
{
|
268 |
+
if (!$this->_order instanceof Mage_Sales_Model_Order) {
|
269 |
+
$this->_order = Mage::getModel('sales/order')->load($this->getOrderId());
|
270 |
+
}
|
271 |
+
|
272 |
+
return $this->_order->setHistoryEntityName(self::HISTORY_ENTITY_NAME);
|
273 |
+
}
|
274 |
+
|
275 |
+
/**
|
276 |
+
* Retrieve the increment_id of the order
|
277 |
+
*
|
278 |
+
* @since 1.0.0
|
279 |
+
*
|
280 |
+
* @return string
|
281 |
+
*/
|
282 |
+
public function getOrderIncrementId()
|
283 |
+
{
|
284 |
+
return Mage::getModel('sales/order')->getResource()->getIncrementId($this->getOrderId());
|
285 |
+
}
|
286 |
+
|
287 |
+
/**
|
288 |
+
* Retrieve billing address
|
289 |
+
*
|
290 |
+
* @since 1.0.0
|
291 |
+
*
|
292 |
+
* @return Mage_Sales_Model_Order_Address
|
293 |
+
*/
|
294 |
+
public function getBillingAddress()
|
295 |
+
{
|
296 |
+
return $this->getOrder()->getBillingAddress();
|
297 |
+
}
|
298 |
+
|
299 |
+
/**
|
300 |
+
* Retrieve shipping address
|
301 |
+
*
|
302 |
+
* @since 1.0.0
|
303 |
+
*
|
304 |
+
* @return Mage_Sales_Model_Order_Address
|
305 |
+
*/
|
306 |
+
public function getShippingAddress()
|
307 |
+
{
|
308 |
+
return $this->getOrder()->getShippingAddress();
|
309 |
+
}
|
310 |
+
|
311 |
+
/**
|
312 |
+
* Check invoice cancel state
|
313 |
+
*
|
314 |
+
* @since 1.0.0
|
315 |
+
*
|
316 |
+
* @return bool
|
317 |
+
*/
|
318 |
+
public function isCanceled()
|
319 |
+
{
|
320 |
+
return $this->getState() == self::STATE_CANCELED;
|
321 |
+
}
|
322 |
+
|
323 |
+
/**
|
324 |
+
* Check invice capture action availability
|
325 |
+
*
|
326 |
+
* @since 1.0.0
|
327 |
+
*
|
328 |
+
* @return bool
|
329 |
+
*/
|
330 |
+
public function canCapture()
|
331 |
+
{
|
332 |
+
return $this->getState() != self::STATE_CANCELED
|
333 |
+
&& $this->getState() != self::STATE_PAID
|
334 |
+
&& $this->getOrder()->getPayment()->canCapture();
|
335 |
+
}
|
336 |
+
|
337 |
+
/**
|
338 |
+
* Check invice void action availability
|
339 |
+
*
|
340 |
+
* @since 1.0.0
|
341 |
+
*
|
342 |
+
* @return bool
|
343 |
+
*/
|
344 |
+
public function canVoid()
|
345 |
+
{
|
346 |
+
$canVoid = false;
|
347 |
+
|
348 |
+
if ($this->getState() == self::STATE_PAID) {
|
349 |
+
|
350 |
+
$canVoid = $this->getCanVoidFlag();
|
351 |
+
|
352 |
+
/**
|
353 |
+
* If we not retrieve negative answer from payment yet
|
354 |
+
*/
|
355 |
+
if (is_null($canVoid)) {
|
356 |
+
$canVoid = $this->getOrder()->getPayment()->canVoid($this);
|
357 |
+
|
358 |
+
if ($canVoid === false) {
|
359 |
+
$this->setCanVoidFlag(false);
|
360 |
+
$this->_saveBeforeDestruct = true;
|
361 |
+
}
|
362 |
+
} else {
|
363 |
+
$canVoid = (bool) $canVoid;
|
364 |
+
}
|
365 |
+
}
|
366 |
+
|
367 |
+
return $canVoid;
|
368 |
+
}
|
369 |
+
|
370 |
+
/**
|
371 |
+
* Check invoice cancel action availability
|
372 |
+
*
|
373 |
+
* @since 1.0.0
|
374 |
+
*
|
375 |
+
* @return bool
|
376 |
+
*/
|
377 |
+
public function canCancel()
|
378 |
+
{
|
379 |
+
return $this->getState() == self::STATE_OPEN;
|
380 |
+
}
|
381 |
+
|
382 |
+
/**
|
383 |
+
* Check invoice refund action availability
|
384 |
+
*
|
385 |
+
* @since 1.0.0
|
386 |
+
*
|
387 |
+
* @return bool
|
388 |
+
*/
|
389 |
+
public function canRefund()
|
390 |
+
{
|
391 |
+
if ($this->getState() != self::STATE_PAID) {
|
392 |
+
return false;
|
393 |
+
}
|
394 |
+
|
395 |
+
if (abs($this->getBaseGrandTotal() - $this->getBaseTotalRefunded()) < .0001) {
|
396 |
+
return false;
|
397 |
+
}
|
398 |
+
|
399 |
+
return true;
|
400 |
+
}
|
401 |
+
|
402 |
+
/**
|
403 |
+
* Capture invoice
|
404 |
+
*
|
405 |
+
* @since 1.0.0
|
406 |
+
*
|
407 |
+
* @return Waterstone_Winvoice_Model_Order_Invoice
|
408 |
+
*/
|
409 |
+
public function capture()
|
410 |
+
{
|
411 |
+
$this->getOrder()->getPayment()->capture($this);
|
412 |
+
|
413 |
+
if ($this->getIsPaid()) {
|
414 |
+
$this->pay();
|
415 |
+
}
|
416 |
+
|
417 |
+
return $this;
|
418 |
+
}
|
419 |
+
|
420 |
+
/**
|
421 |
+
* Pay invoice
|
422 |
+
*
|
423 |
+
* @since 1.0.0
|
424 |
+
*
|
425 |
+
* @return Waterstone_Winvoice_Model_Order_Invoice
|
426 |
+
*/
|
427 |
+
public function pay()
|
428 |
+
{
|
429 |
+
if ($this->_wasPayCalled) {
|
430 |
+
return $this;
|
431 |
+
}
|
432 |
+
|
433 |
+
$this->_wasPayCalled = true;
|
434 |
+
|
435 |
+
$invoiceState = self::STATE_PAID;
|
436 |
+
|
437 |
+
if ($this->getOrder()->getPayment()->hasForcedState()) {
|
438 |
+
$invoiceState = $this->getOrder()->getPayment()->getForcedState();
|
439 |
+
}
|
440 |
+
|
441 |
+
$this->setState($invoiceState);
|
442 |
+
|
443 |
+
$this->getOrder()->getPayment()->pay($this);
|
444 |
+
$this->getOrder()->setTotalPaid(
|
445 |
+
$this->getOrder()->getTotalPaid()+$this->getGrandTotal()
|
446 |
+
);
|
447 |
+
$this->getOrder()->setBaseTotalPaid(
|
448 |
+
$this->getOrder()->getBaseTotalPaid()+$this->getBaseGrandTotal()
|
449 |
+
);
|
450 |
+
|
451 |
+
Mage::dispatchEvent('sales_order_invoice_pay', array($this->_eventObject=>$this));
|
452 |
+
|
453 |
+
return $this;
|
454 |
+
}
|
455 |
+
|
456 |
+
/**
|
457 |
+
* Whether pay() method was called (whether order and payment totals were updated)
|
458 |
+
*
|
459 |
+
* @since 1.0.0
|
460 |
+
*
|
461 |
+
* @return bool
|
462 |
+
*/
|
463 |
+
public function wasPayCalled()
|
464 |
+
{
|
465 |
+
return $this->_wasPayCalled;
|
466 |
+
}
|
467 |
+
|
468 |
+
/**
|
469 |
+
* Void invoice
|
470 |
+
*
|
471 |
+
* @return Waterstone_Winvoice_Model_Order_Invoice
|
472 |
+
*/
|
473 |
+
public function void()
|
474 |
+
{
|
475 |
+
$this->getOrder()->getPayment()->void($this);
|
476 |
+
$this->cancel();
|
477 |
+
|
478 |
+
return $this;
|
479 |
+
}
|
480 |
+
|
481 |
+
/**
|
482 |
+
* Cancel invoice action
|
483 |
+
*
|
484 |
+
* @since 1.0.0
|
485 |
+
*
|
486 |
+
* @return Waterstone_Winvoice_Model_Order_Invoice
|
487 |
+
*/
|
488 |
+
public function cancel()
|
489 |
+
{
|
490 |
+
$order = $this->getOrder();
|
491 |
+
$order->getPayment()->cancelInvoice($this);
|
492 |
+
|
493 |
+
foreach ($this->getAllItems() as $item) {
|
494 |
+
$item->cancel();
|
495 |
+
}
|
496 |
+
|
497 |
+
/**
|
498 |
+
* Unregister order totals only for invoices in state PAID
|
499 |
+
*/
|
500 |
+
$order->setTotalInvoiced($order->getTotalInvoiced() - $this->getGrandTotal());
|
501 |
+
$order->setBaseTotalInvoiced($order->getBaseTotalInvoiced() - $this->getBaseGrandTotal());
|
502 |
+
|
503 |
+
$order->setSubtotalInvoiced($order->getSubtotalInvoiced() - $this->getSubtotal());
|
504 |
+
$order->setBaseSubtotalInvoiced($order->getBaseSubtotalInvoiced() - $this->getBaseSubtotal());
|
505 |
+
|
506 |
+
$order->setTaxInvoiced($order->getTaxInvoiced() - $this->getTaxAmount());
|
507 |
+
$order->setBaseTaxInvoiced($order->getBaseTaxInvoiced() - $this->getBaseTaxAmount());
|
508 |
+
|
509 |
+
$order->setHiddenTaxInvoiced($order->getHiddenTaxInvoiced() - $this->getHiddenTaxAmount());
|
510 |
+
$order->setBaseHiddenTaxInvoiced($order->getBaseHiddenTaxInvoiced() - $this->getBaseHiddenTaxAmount());
|
511 |
+
|
512 |
+
$order->setShippingTaxInvoiced($order->getShippingTaxInvoiced() - $this->getShippingTaxAmount());
|
513 |
+
$order->setBaseShippingTaxInvoiced($order->getBaseShippingTaxInvoiced() - $this->getBaseShippingTaxAmount());
|
514 |
+
|
515 |
+
$order->setShippingInvoiced($order->getShippingInvoiced() - $this->getShippingAmount());
|
516 |
+
$order->setBaseShippingInvoiced($order->getBaseShippingInvoiced() - $this->getBaseShippingAmount());
|
517 |
+
|
518 |
+
$order->setDiscountInvoiced($order->getDiscountInvoiced() - $this->getDiscountAmount());
|
519 |
+
$order->setBaseDiscountInvoiced($order->getBaseDiscountInvoiced() - $this->getBaseDiscountAmount());
|
520 |
+
$order->setBaseTotalInvoicedCost($order->getBaseTotalInvoicedCost() - $this->getBaseCost());
|
521 |
+
|
522 |
+
if ($this->getState() == self::STATE_PAID) {
|
523 |
+
$this->getOrder()->setTotalPaid($this->getOrder()->getTotalPaid()-$this->getGrandTotal());
|
524 |
+
$this->getOrder()->setBaseTotalPaid($this->getOrder()->getBaseTotalPaid()-$this->getBaseGrandTotal());
|
525 |
+
}
|
526 |
+
|
527 |
+
$this->setState(self::STATE_CANCELED);
|
528 |
+
$this->getOrder()->setState(Mage_Sales_Model_Order::STATE_PROCESSING, true);
|
529 |
+
|
530 |
+
Mage::dispatchEvent('sales_order_invoice_cancel', array($this->_eventObject=>$this));
|
531 |
+
|
532 |
+
return $this;
|
533 |
+
}
|
534 |
+
|
535 |
+
/**
|
536 |
+
* Invoice totals collecting
|
537 |
+
*
|
538 |
+
* @since 1.0.0
|
539 |
+
*
|
540 |
+
* @return Waterstone_Winvoice_Model_Order_Invoice
|
541 |
+
*/
|
542 |
+
public function collectTotals()
|
543 |
+
{
|
544 |
+
foreach ($this->getConfig()->getTotalModels() as $model) {
|
545 |
+
$model->collect($this);
|
546 |
+
}
|
547 |
+
|
548 |
+
return $this;
|
549 |
+
}
|
550 |
+
|
551 |
+
/**
|
552 |
+
* Round price considering delta
|
553 |
+
*
|
554 |
+
* @since 1.0.0
|
555 |
+
*
|
556 |
+
* @param float $price
|
557 |
+
* @param string $type
|
558 |
+
* @param bool $negative Indicates if we perform addition (true) or subtraction (false) of rounded value
|
559 |
+
* @return float
|
560 |
+
*/
|
561 |
+
public function roundPrice($price, $type = 'regular', $negative = false)
|
562 |
+
{
|
563 |
+
if ($price) {
|
564 |
+
if (!isset($this->_rounders[$type])) {
|
565 |
+
$this->_rounders[$type] = Mage::getModel('core/calculator', $this->getStore());
|
566 |
+
}
|
567 |
+
|
568 |
+
$price = $this->_rounders[$type]->deltaRound($price, $negative);
|
569 |
+
}
|
570 |
+
|
571 |
+
return $price;
|
572 |
+
}
|
573 |
+
|
574 |
+
/**
|
575 |
+
* Get invoice items collection
|
576 |
+
*
|
577 |
+
* @since 1.0.0
|
578 |
+
*
|
579 |
+
* @return Mage_Sales_Model_Mysql4_Order_Invoice_Item_Collection
|
580 |
+
*/
|
581 |
+
public function getItemsCollection()
|
582 |
+
{
|
583 |
+
if (empty($this->_items)) {
|
584 |
+
$this->_items = Mage::getResourceModel('sales/order_invoice_item_collection')
|
585 |
+
->setInvoiceFilter($this->getId());
|
586 |
+
|
587 |
+
if ($this->getId()) {
|
588 |
+
foreach ($this->_items as $item) {
|
589 |
+
$item->setInvoice($this);
|
590 |
+
}
|
591 |
+
}
|
592 |
+
}
|
593 |
+
|
594 |
+
return $this->_items;
|
595 |
+
}
|
596 |
+
|
597 |
+
/**
|
598 |
+
* Get all items.
|
599 |
+
*
|
600 |
+
* @since 1.0.0
|
601 |
+
*
|
602 |
+
* @return array
|
603 |
+
*/
|
604 |
+
public function getAllItems()
|
605 |
+
{
|
606 |
+
$items = array();
|
607 |
+
|
608 |
+
foreach ($this->getItemsCollection() as $item) {
|
609 |
+
if (!$item->isDeleted()) {
|
610 |
+
$items[] = $item;
|
611 |
+
}
|
612 |
+
}
|
613 |
+
|
614 |
+
return $items;
|
615 |
+
}
|
616 |
+
|
617 |
+
/**
|
618 |
+
* Get item by id.
|
619 |
+
*
|
620 |
+
* @since 1.0.0
|
621 |
+
*
|
622 |
+
* @return Mage_Sales_Model_Order_Invoice_Item | bool
|
623 |
+
*/
|
624 |
+
public function getItemById($itemId)
|
625 |
+
{
|
626 |
+
foreach ($this->getItemsCollection() as $item) {
|
627 |
+
if ($item->getId()==$itemId) {
|
628 |
+
return $item;
|
629 |
+
}
|
630 |
+
}
|
631 |
+
|
632 |
+
return false;
|
633 |
+
}
|
634 |
+
|
635 |
+
/**
|
636 |
+
* Get all items.
|
637 |
+
*
|
638 |
+
* @since 1.0.0
|
639 |
+
*
|
640 |
+
* @param Mage_Sales_Model_Order_Invoice_Item $item
|
641 |
+
* @return array
|
642 |
+
*/
|
643 |
+
public function addItem(Mage_Sales_Model_Order_Invoice_Item $item)
|
644 |
+
{
|
645 |
+
$item->setInvoice($this)
|
646 |
+
->setParentId($this->getId())
|
647 |
+
->setStoreId($this->getStoreId());
|
648 |
+
|
649 |
+
if (!$item->getId()) {
|
650 |
+
$this->getItemsCollection()->addItem($item);
|
651 |
+
}
|
652 |
+
|
653 |
+
return $this;
|
654 |
+
}
|
655 |
+
|
656 |
+
/**
|
657 |
+
* Retrieve invoice states array
|
658 |
+
*
|
659 |
+
* @since 1.0.0
|
660 |
+
*
|
661 |
+
* @return array
|
662 |
+
*/
|
663 |
+
public static function getStates()
|
664 |
+
{
|
665 |
+
if (is_null(self::$_states)) {
|
666 |
+
self::$_states = array(
|
667 |
+
self::STATE_OPEN => Mage::helper('sales')->__('Pending'),
|
668 |
+
self::STATE_PAID => Mage::helper('sales')->__('Paid'),
|
669 |
+
self::STATE_CANCELED => Mage::helper('sales')->__('Canceled'),
|
670 |
+
);
|
671 |
+
}
|
672 |
+
|
673 |
+
return self::$_states;
|
674 |
+
}
|
675 |
+
|
676 |
+
/**
|
677 |
+
* Retrieve invoice state name by state identifier
|
678 |
+
*
|
679 |
+
* @since 1.0.0
|
680 |
+
*
|
681 |
+
* @param int $stateId
|
682 |
+
* @return string
|
683 |
+
*/
|
684 |
+
public function getStateName($stateId = null)
|
685 |
+
{
|
686 |
+
if (is_null($stateId)) {
|
687 |
+
$stateId = $this->getState();
|
688 |
+
}
|
689 |
+
|
690 |
+
if (is_null(self::$_states)) {
|
691 |
+
self::getStates();
|
692 |
+
}
|
693 |
+
|
694 |
+
if (isset(self::$_states[$stateId])) {
|
695 |
+
return self::$_states[$stateId];
|
696 |
+
}
|
697 |
+
|
698 |
+
return Mage::helper('sales')->__('Unknown State');
|
699 |
+
}
|
700 |
+
|
701 |
+
/**
|
702 |
+
* Register invoice
|
703 |
+
*
|
704 |
+
* Apply to order, order items etc.
|
705 |
+
*
|
706 |
+
* @since 1.0.0
|
707 |
+
*
|
708 |
+
* @return unknown
|
709 |
+
*/
|
710 |
+
public function register()
|
711 |
+
{
|
712 |
+
if ($this->getId()) {
|
713 |
+
Mage::throwException(Mage::helper('sales')->__('Cannot register existing invoice'));
|
714 |
+
}
|
715 |
+
|
716 |
+
foreach ($this->getAllItems() as $item) {
|
717 |
+
if ($item->getQty()>0) {
|
718 |
+
$item->register();
|
719 |
+
} else {
|
720 |
+
$item->isDeleted(true);
|
721 |
+
}
|
722 |
+
}
|
723 |
+
|
724 |
+
$order = $this->getOrder();
|
725 |
+
$captureCase = $this->getRequestedCaptureCase();
|
726 |
+
|
727 |
+
if ($this->canCapture()) {
|
728 |
+
if ($captureCase) {
|
729 |
+
if ($captureCase == self::CAPTURE_ONLINE) {
|
730 |
+
$this->capture();
|
731 |
+
} elseif ($captureCase == self::CAPTURE_OFFLINE) {
|
732 |
+
$this->setCanVoidFlag(false);
|
733 |
+
$this->pay();
|
734 |
+
}
|
735 |
+
}
|
736 |
+
} elseif(!$order->getPayment()->getMethodInstance()->isGateway() || $captureCase == self::CAPTURE_OFFLINE) {
|
737 |
+
if (!$order->getPayment()->getIsTransactionPending()) {
|
738 |
+
$this->setCanVoidFlag(false);
|
739 |
+
$this->pay();
|
740 |
+
}
|
741 |
+
}
|
742 |
+
|
743 |
+
$order->setTotalInvoiced($order->getTotalInvoiced() + $this->getGrandTotal());
|
744 |
+
$order->setBaseTotalInvoiced($order->getBaseTotalInvoiced() + $this->getBaseGrandTotal());
|
745 |
+
|
746 |
+
$order->setSubtotalInvoiced($order->getSubtotalInvoiced() + $this->getSubtotal());
|
747 |
+
$order->setBaseSubtotalInvoiced($order->getBaseSubtotalInvoiced() + $this->getBaseSubtotal());
|
748 |
+
|
749 |
+
$order->setTaxInvoiced($order->getTaxInvoiced() + $this->getTaxAmount());
|
750 |
+
$order->setBaseTaxInvoiced($order->getBaseTaxInvoiced() + $this->getBaseTaxAmount());
|
751 |
+
|
752 |
+
$order->setHiddenTaxInvoiced($order->getHiddenTaxInvoiced() + $this->getHiddenTaxAmount());
|
753 |
+
$order->setBaseHiddenTaxInvoiced($order->getBaseHiddenTaxInvoiced() + $this->getBaseHiddenTaxAmount());
|
754 |
+
|
755 |
+
$order->setShippingTaxInvoiced($order->getShippingTaxInvoiced() + $this->getShippingTaxAmount());
|
756 |
+
$order->setBaseShippingTaxInvoiced($order->getBaseShippingTaxInvoiced() + $this->getBaseShippingTaxAmount());
|
757 |
+
|
758 |
+
$order->setShippingInvoiced($order->getShippingInvoiced() + $this->getShippingAmount());
|
759 |
+
$order->setBaseShippingInvoiced($order->getBaseShippingInvoiced() + $this->getBaseShippingAmount());
|
760 |
+
|
761 |
+
$order->setDiscountInvoiced($order->getDiscountInvoiced() + $this->getDiscountAmount());
|
762 |
+
$order->setBaseDiscountInvoiced($order->getBaseDiscountInvoiced() + $this->getBaseDiscountAmount());
|
763 |
+
$order->setBaseTotalInvoicedCost($order->getBaseTotalInvoicedCost() + $this->getBaseCost());
|
764 |
+
|
765 |
+
$state = $this->getState();
|
766 |
+
|
767 |
+
if (is_null($state)) {
|
768 |
+
$this->setState(self::STATE_OPEN);
|
769 |
+
}
|
770 |
+
|
771 |
+
Mage::dispatchEvent('sales_order_invoice_register', array($this->_eventObject=>$this, 'order' => $order));
|
772 |
+
|
773 |
+
return $this;
|
774 |
+
}
|
775 |
+
|
776 |
+
/**
|
777 |
+
* Checking if the invoice is last
|
778 |
+
*
|
779 |
+
* @since 1.0.0
|
780 |
+
*
|
781 |
+
* @return bool
|
782 |
+
*/
|
783 |
+
public function isLast()
|
784 |
+
{
|
785 |
+
foreach ($this->getAllItems() as $item) {
|
786 |
+
if (!$item->isLast()) {
|
787 |
+
return false;
|
788 |
+
}
|
789 |
+
}
|
790 |
+
|
791 |
+
return true;
|
792 |
+
}
|
793 |
+
|
794 |
+
/**
|
795 |
+
* Adds comment to invoice with additional possibility to send it to customer via email
|
796 |
+
* and show it in customer account
|
797 |
+
*
|
798 |
+
* @since 1.0.0
|
799 |
+
*
|
800 |
+
* @param bool $notify
|
801 |
+
* @param bool $visibleOnFront
|
802 |
+
*
|
803 |
+
* @return Waterstone_Winvoice_Model_Order_Invoice
|
804 |
+
*/
|
805 |
+
public function addComment($comment, $notify=false, $visibleOnFront=false)
|
806 |
+
{
|
807 |
+
if (!($comment instanceof Mage_Sales_Model_Order_Invoice_Comment)) {
|
808 |
+
$comment = Mage::getModel('sales/order_invoice_comment')
|
809 |
+
->setComment($comment)
|
810 |
+
->setIsCustomerNotified($notify)
|
811 |
+
->setIsVisibleOnFront($visibleOnFront);
|
812 |
+
}
|
813 |
+
|
814 |
+
$comment->setInvoice($this)
|
815 |
+
->setStoreId($this->getStoreId())
|
816 |
+
->setParentId($this->getId());
|
817 |
+
|
818 |
+
if (!$comment->getId()) {
|
819 |
+
$this->getCommentsCollection()->addItem($comment);
|
820 |
+
}
|
821 |
+
|
822 |
+
$this->_hasDataChanges = true;
|
823 |
+
|
824 |
+
return $this;
|
825 |
+
}
|
826 |
+
|
827 |
+
/**
|
828 |
+
* Get the comments collection
|
829 |
+
*
|
830 |
+
* @since 1.0.0
|
831 |
+
*
|
832 |
+
* @param bool $reload
|
833 |
+
*
|
834 |
+
* @return unknown
|
835 |
+
*/
|
836 |
+
public function getCommentsCollection($reload=false)
|
837 |
+
{
|
838 |
+
if (is_null($this->_comments) || $reload) {
|
839 |
+
$this->_comments = Mage::getResourceModel('sales/order_invoice_comment_collection')
|
840 |
+
->setInvoiceFilter($this->getId())
|
841 |
+
->setCreatedAtOrder();
|
842 |
+
|
843 |
+
/**
|
844 |
+
* When invoice created with adding comment, comments collection
|
845 |
+
* must be loaded before we added this comment.
|
846 |
+
*/
|
847 |
+
$this->_comments->load();
|
848 |
+
|
849 |
+
if ($this->getId()) {
|
850 |
+
foreach ($this->_comments as $comment) {
|
851 |
+
$comment->setInvoice($this);
|
852 |
+
}
|
853 |
+
}
|
854 |
+
}
|
855 |
+
|
856 |
+
return $this->_comments;
|
857 |
+
}
|
858 |
+
|
859 |
+
/**
|
860 |
+
* Send email with invoice data
|
861 |
+
*
|
862 |
+
* @since 1.0.0
|
863 |
+
*
|
864 |
+
* @param boolean $notifyCustomer
|
865 |
+
* @param string $comment
|
866 |
+
* @return Waterstone_Winvoice_Model_Order_Invoice
|
867 |
+
*/
|
868 |
+
public function sendEmail($notifyCustomer = true, $comment = '')
|
869 |
+
{
|
870 |
+
$order = $this->getOrder();
|
871 |
+
$storeId = $order->getStore()->getId();
|
872 |
+
|
873 |
+
if (!Mage::helper('sales')->canSendNewInvoiceEmail($storeId)) {
|
874 |
+
return $this;
|
875 |
+
}
|
876 |
+
|
877 |
+
// Get the destination email addresses to send copies to
|
878 |
+
$copyTo = $this->_getEmails(self::XML_PATH_EMAIL_COPY_TO);
|
879 |
+
$copyMethod = Mage::getStoreConfig(self::XML_PATH_EMAIL_COPY_METHOD, $storeId);
|
880 |
+
|
881 |
+
// Check if at least one recepient is found
|
882 |
+
if (!$notifyCustomer && !$copyTo) {
|
883 |
+
return $this;
|
884 |
+
}
|
885 |
+
|
886 |
+
// Start store emulation process
|
887 |
+
$appEmulation = Mage::getSingleton('core/app_emulation');
|
888 |
+
$initialEnvironmentInfo = $appEmulation->startEnvironmentEmulation($storeId);
|
889 |
+
|
890 |
+
try {
|
891 |
+
// Retrieve specified view block from appropriate design package (depends on emulated store)
|
892 |
+
$paymentBlock = Mage::helper('payment')->getInfoBlock($order->getPayment())
|
893 |
+
->setIsSecureMode(true);
|
894 |
+
|
895 |
+
$paymentBlock->getMethod()->setStore($storeId);
|
896 |
+
$paymentBlockHtml = $paymentBlock->toHtml();
|
897 |
+
} catch (Exception $exception) {
|
898 |
+
// Stop store emulation process
|
899 |
+
$appEmulation->stopEnvironmentEmulation($initialEnvironmentInfo);
|
900 |
+
|
901 |
+
throw $exception;
|
902 |
+
}
|
903 |
+
|
904 |
+
// Stop store emulation process
|
905 |
+
$appEmulation->stopEnvironmentEmulation($initialEnvironmentInfo);
|
906 |
+
|
907 |
+
// Retrieve corresponding email template id and customer name
|
908 |
+
if ($order->getCustomerIsGuest()) {
|
909 |
+
$templateId = Mage::getStoreConfig(self::XML_PATH_EMAIL_GUEST_TEMPLATE, $storeId);
|
910 |
+
$customerName = $order->getBillingAddress()->getName();
|
911 |
+
} else {
|
912 |
+
$templateId = Mage::getStoreConfig(self::XML_PATH_EMAIL_TEMPLATE, $storeId);
|
913 |
+
$customerName = $order->getCustomerName();
|
914 |
+
}
|
915 |
+
|
916 |
+
$mailer = Mage::getModel('core/email_template_mailer');
|
917 |
+
$mailer->addAttachment('factura_'.$this->getIncrementId().'.pdf', $this->getWsinvoiceurl());
|
918 |
+
|
919 |
+
if ($notifyCustomer) {
|
920 |
+
$emailInfo = Mage::getModel('core/email_info');
|
921 |
+
$emailInfo->addTo($order->getCustomerEmail(), $customerName);
|
922 |
+
|
923 |
+
if ($copyTo && $copyMethod == 'bcc') {
|
924 |
+
// Add bcc to customer email
|
925 |
+
foreach ($copyTo as $email) {
|
926 |
+
$emailInfo->addBcc($email);
|
927 |
+
}
|
928 |
+
}
|
929 |
+
|
930 |
+
$mailer->addEmailInfo($emailInfo);
|
931 |
+
}
|
932 |
+
|
933 |
+
// Email copies are sent as separated emails if their copy method is 'copy' or a customer should not be notified
|
934 |
+
if ($copyTo && ($copyMethod == 'copy' || !$notifyCustomer)) {
|
935 |
+
foreach ($copyTo as $email) {
|
936 |
+
$emailInfo = Mage::getModel('core/email_info');
|
937 |
+
$emailInfo->addTo($email);
|
938 |
+
$mailer->addEmailInfo($emailInfo);
|
939 |
+
}
|
940 |
+
}
|
941 |
+
|
942 |
+
// Set all required params and send emails
|
943 |
+
$mailer->setSender(Mage::getStoreConfig(self::XML_PATH_EMAIL_IDENTITY, $storeId));
|
944 |
+
$mailer->setStoreId($storeId);
|
945 |
+
$mailer->setTemplateId($templateId);
|
946 |
+
$mailer->setTemplateParams(array(
|
947 |
+
'order' => $order,
|
948 |
+
'invoice' => $this,
|
949 |
+
'comment' => $comment,
|
950 |
+
'billing' => $order->getBillingAddress(),
|
951 |
+
'payment_html' => $paymentBlockHtml
|
952 |
+
)
|
953 |
+
|
954 |
+
);
|
955 |
+
|
956 |
+
$mailer->send();
|
957 |
+
|
958 |
+
$this->setEmailSent(true);
|
959 |
+
$this->_getResource()->saveAttribute($this, 'email_sent');
|
960 |
+
|
961 |
+
return $this;
|
962 |
+
}
|
963 |
+
|
964 |
+
/**
|
965 |
+
* Send email with invoice update information
|
966 |
+
*
|
967 |
+
* @since 1.0.0
|
968 |
+
*
|
969 |
+
* @param boolean $notifyCustomer
|
970 |
+
* @param string $comment
|
971 |
+
* @return Waterstone_Winvoice_Model_Order_Invoice
|
972 |
+
*/
|
973 |
+
public function sendUpdateEmail($notifyCustomer = true, $comment = '')
|
974 |
+
{
|
975 |
+
$order = $this->getOrder();
|
976 |
+
$storeId = $order->getStore()->getId();
|
977 |
+
|
978 |
+
if (!Mage::helper('sales')->canSendInvoiceCommentEmail($storeId)) {
|
979 |
+
return $this;
|
980 |
+
}
|
981 |
+
|
982 |
+
// Get the destination email addresses to send copies to
|
983 |
+
$copyTo = $this->_getEmails(self::XML_PATH_UPDATE_EMAIL_COPY_TO);
|
984 |
+
$copyMethod = Mage::getStoreConfig(self::XML_PATH_UPDATE_EMAIL_COPY_METHOD, $storeId);
|
985 |
+
|
986 |
+
// Check if at least one recepient is found
|
987 |
+
if (!$notifyCustomer && !$copyTo) {
|
988 |
+
return $this;
|
989 |
+
}
|
990 |
+
|
991 |
+
// Retrieve corresponding email template id and customer name
|
992 |
+
if ($order->getCustomerIsGuest()) {
|
993 |
+
$templateId = Mage::getStoreConfig(self::XML_PATH_UPDATE_EMAIL_GUEST_TEMPLATE, $storeId);
|
994 |
+
$customerName = $order->getBillingAddress()->getName();
|
995 |
+
} else {
|
996 |
+
$templateId = Mage::getStoreConfig(self::XML_PATH_UPDATE_EMAIL_TEMPLATE, $storeId);
|
997 |
+
$customerName = $order->getCustomerName();
|
998 |
+
}
|
999 |
+
|
1000 |
+
$mailer = Mage::getModel('core/email_template_mailer');
|
1001 |
+
|
1002 |
+
if ($notifyCustomer) {
|
1003 |
+
$emailInfo = Mage::getModel('core/email_info');
|
1004 |
+
$emailInfo->addTo($order->getCustomerEmail(), $customerName);
|
1005 |
+
|
1006 |
+
if ($copyTo && $copyMethod == 'bcc') {
|
1007 |
+
// Add bcc to customer email
|
1008 |
+
foreach ($copyTo as $email) {
|
1009 |
+
$emailInfo->addBcc($email);
|
1010 |
+
}
|
1011 |
+
}
|
1012 |
+
|
1013 |
+
$mailer->addEmailInfo($emailInfo);
|
1014 |
+
}
|
1015 |
+
|
1016 |
+
// Email copies are sent as separated emails if their copy method is 'copy' or a customer should not be notified
|
1017 |
+
if ($copyTo && ($copyMethod == 'copy' || !$notifyCustomer)) {
|
1018 |
+
foreach ($copyTo as $email) {
|
1019 |
+
$emailInfo = Mage::getModel('core/email_info');
|
1020 |
+
$emailInfo->addTo($email);
|
1021 |
+
$mailer->addEmailInfo($emailInfo);
|
1022 |
+
}
|
1023 |
+
}
|
1024 |
+
|
1025 |
+
// Set all required params and send emails
|
1026 |
+
$mailer->setSender(Mage::getStoreConfig(self::XML_PATH_UPDATE_EMAIL_IDENTITY, $storeId));
|
1027 |
+
$mailer->setStoreId($storeId);
|
1028 |
+
$mailer->setTemplateId($templateId);
|
1029 |
+
$mailer->setTemplateParams(array(
|
1030 |
+
'order' => $order,
|
1031 |
+
'invoice' => $this,
|
1032 |
+
'comment' => $comment,
|
1033 |
+
'billing' => $order->getBillingAddress()
|
1034 |
+
)
|
1035 |
+
);
|
1036 |
+
|
1037 |
+
$mailer->send();
|
1038 |
+
|
1039 |
+
return $this;
|
1040 |
+
}
|
1041 |
+
|
1042 |
+
/**
|
1043 |
+
* Get emails.
|
1044 |
+
*
|
1045 |
+
* @since 1.0.0
|
1046 |
+
*
|
1047 |
+
* @param string $configPath
|
1048 |
+
* @return string | bool
|
1049 |
+
*/
|
1050 |
+
protected function _getEmails($configPath)
|
1051 |
+
{
|
1052 |
+
$data = Mage::getStoreConfig($configPath, $this->getStoreId());
|
1053 |
+
|
1054 |
+
if (!empty($data)) {
|
1055 |
+
return explode(',', $data);
|
1056 |
+
}
|
1057 |
+
|
1058 |
+
return false;
|
1059 |
+
}
|
1060 |
+
|
1061 |
+
/**
|
1062 |
+
* Before delete.
|
1063 |
+
*
|
1064 |
+
* @since 1.0.0
|
1065 |
+
*
|
1066 |
+
* @return void
|
1067 |
+
*/
|
1068 |
+
protected function _beforeDelete()
|
1069 |
+
{
|
1070 |
+
$this->_protectFromNonAdmin();
|
1071 |
+
|
1072 |
+
return parent::_beforeDelete();
|
1073 |
+
}
|
1074 |
+
|
1075 |
+
/**
|
1076 |
+
* Reset invoice object
|
1077 |
+
*
|
1078 |
+
* @since 1.0.0
|
1079 |
+
*
|
1080 |
+
* @return Waterstone_Winvoice_Model_Order_Invoice
|
1081 |
+
*/
|
1082 |
+
public function reset()
|
1083 |
+
{
|
1084 |
+
$this->unsetData();
|
1085 |
+
$this->_origData = null;
|
1086 |
+
$this->_items = null;
|
1087 |
+
$this->_comments = null;
|
1088 |
+
$this->_order = null;
|
1089 |
+
$this->_saveBeforeDestruct = false;
|
1090 |
+
$this->_wasPayCalled = false;
|
1091 |
+
|
1092 |
+
return $this;
|
1093 |
+
}
|
1094 |
+
|
1095 |
+
/**
|
1096 |
+
* Before object save manipulations
|
1097 |
+
*
|
1098 |
+
* @since 1.0.0
|
1099 |
+
*
|
1100 |
+
* @return Mage_Sales_Model_Order_Shipment
|
1101 |
+
*/
|
1102 |
+
protected function _beforeSave()
|
1103 |
+
{
|
1104 |
+
parent::_beforeSave();
|
1105 |
+
|
1106 |
+
if (!$this->getOrderId() && $this->getOrder()) {
|
1107 |
+
$this->setOrderId($this->getOrder()->getId());
|
1108 |
+
$this->setBillingAddressId($this->getOrder()->getBillingAddress()->getId());
|
1109 |
+
}
|
1110 |
+
|
1111 |
+
return $this;
|
1112 |
+
}
|
1113 |
+
|
1114 |
+
/**
|
1115 |
+
* After object save manipulation
|
1116 |
+
*
|
1117 |
+
* @since 1.0.0
|
1118 |
+
*
|
1119 |
+
* @return Mage_Sales_Model_Order_Shipment
|
1120 |
+
*/
|
1121 |
+
protected function _afterSave()
|
1122 |
+
{
|
1123 |
+
if (null !== $this->_items) {
|
1124 |
+
/**
|
1125 |
+
* Save invoice items
|
1126 |
+
*/
|
1127 |
+
foreach ($this->_items as $item) {
|
1128 |
+
$item->setOrderItem($item->getOrderItem());
|
1129 |
+
$item->save();
|
1130 |
+
}
|
1131 |
+
}
|
1132 |
+
|
1133 |
+
if (null !== $this->_comments) {
|
1134 |
+
foreach($this->_comments as $comment) {
|
1135 |
+
$comment->save();
|
1136 |
+
}
|
1137 |
+
}
|
1138 |
+
|
1139 |
+
return parent::_afterSave();
|
1140 |
+
}
|
1141 |
+
|
1142 |
+
}
|
app/code/local/Waterstone/winvoice/Model/Status.php
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* DISCLAIMER
|
4 |
+
*
|
5 |
+
* Do not edit or add to this file if you wish to upgrade the extension to newer
|
6 |
+
* versions in the future. If you need personal customization please contact us
|
7 |
+
* on http://www.waterstone.pt for more information.
|
8 |
+
*
|
9 |
+
* @category Waterstone
|
10 |
+
* @package Waterstone_Winvoice
|
11 |
+
* @copyright Copyright (c) 2014 Waterstone Consulting, Lda. (http://www.waterstone.pt)
|
12 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
13 |
+
*/
|
14 |
+
|
15 |
+
class Waterstone_Winvoice_Model_Status extends Varien_Object
|
16 |
+
{
|
17 |
+
/* Constants */
|
18 |
+
const STATUS_ENABLED = 1;
|
19 |
+
const STATUS_DISABLED = 2;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Get options array method.
|
23 |
+
* - Returns an array with the model status options.
|
24 |
+
*
|
25 |
+
* @since 1.0.0
|
26 |
+
*
|
27 |
+
* @return array
|
28 |
+
*/
|
29 |
+
static public function getOptionArray()
|
30 |
+
{
|
31 |
+
return array(
|
32 |
+
self::STATUS_ENABLED => Mage::helper('winvoice')->__('Enabled'),
|
33 |
+
self::STATUS_DISABLED => Mage::helper('winvoice')->__('Disabled')
|
34 |
+
);
|
35 |
+
}
|
36 |
+
|
37 |
+
}
|
app/code/local/Waterstone/winvoice/Model/nusoap/lib/changelog
ADDED
@@ -0,0 +1,648 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
2003-07-21, version 0.6.5
|
2 |
+
- soap_transport_http: SOAPAction header is quoted again, fixes problem w/ Weblogic Server
|
3 |
+
- applied Jason Levitt patch for proper array serialization, fixes problem w/ Amazon shopping cart services
|
4 |
+
- fixed null value serialization
|
5 |
+
- applied patch from "BZC ToOn'S" - fixes wsdl serialization when no parameters
|
6 |
+
- applied John's patch, implementing compression for the server
|
7 |
+
|
8 |
+
2003-07-22, version 0.6.5
|
9 |
+
- soap_server: fixed bug causing charset encoding not to be passed to the parser
|
10 |
+
- soap_fault: added default encoding to the fault serialization
|
11 |
+
- soap_parser: changed the parser to pre-load the parent's result array when processing scalar values. This increases parsing speed.
|
12 |
+
|
13 |
+
2003-07-23, version 0.6.5
|
14 |
+
- soap_base: fix code that overwrites user-supplied attributes in serialize_val
|
15 |
+
- soap_base: use arrays-of-arrays rather than attempting multi-dimensional in serialize_val
|
16 |
+
- xmlschema: emit import statements and qualify all elements with prefix in serializeSchema (better interop with validation tools)
|
17 |
+
- soapclient: get xml character encoding from HTTP Content-Type header if provided, e.g. text/xml;charset="UTF-8"
|
18 |
+
- soapclient: use headers in call if provided (previously ignored this parameter)
|
19 |
+
- soap_server: in parse_request, if neither getallheaders nor $_SERVER are available, use $HTTP_SERVER_VARS to get SOAPAction and xml encoding
|
20 |
+
|
21 |
+
2003-07-24, version 0.6.5
|
22 |
+
- soap_transport_http: apply patch from Steven Brown "if the server closes connection prematurely, nusoap would spin trying to read data that isn't there"
|
23 |
+
|
24 |
+
2003-07-25, version 0.6.5
|
25 |
+
- wsdl: apply patch from Sven to workaround single schema limitation
|
26 |
+
- wsdl: apply a variant of the patch from Holger to handle empty values for array by serializing an array with 0 elements
|
27 |
+
- xmlschema: remove the redundant default namespace attribute on the schema element; everything in xsd is explicitly specified as being from xsd
|
28 |
+
- soap_transport_http: fix setCredentials and add TODO comments in sendHTTPS about what to change if this setCredentials stays
|
29 |
+
|
30 |
+
2003-07-30, version 0.6.5
|
31 |
+
- nusoap_base: change documentation of soap_defencoding to specify it is the encoding for outgoing messages
|
32 |
+
- nusoap_base: only change &, <, > to entities, not all HTML entities
|
33 |
+
- soap_transport_http: update the Content-Type header in sendRequest, since soap_defencoding could be changed after ctor is called
|
34 |
+
- soap_server: use soap_defencoding instead of charset_encoding
|
35 |
+
- soap_server: read encoding from _SERVER if available
|
36 |
+
- nusoap_base: do entity translation for string parameters with an xsd type specified (thanks David Derr)
|
37 |
+
|
38 |
+
2003-07-31, version 0.6.5
|
39 |
+
- soap_transport_http: add proxy authentication
|
40 |
+
- soap_transport_http: build payload the same way for http and https
|
41 |
+
- wsdl: add proxy authentication
|
42 |
+
- soapclient: add proxy authentication
|
43 |
+
- soapclient: allow proxy information in ctor, so that it can be used for wsdl
|
44 |
+
|
45 |
+
2003-08-01, version 0.6.5
|
46 |
+
- soap_transport_http: close a persistent connection that's at EOF
|
47 |
+
- soap_transport_http: prevent conflicts between setEncoding and usePersistentConnection
|
48 |
+
- soap_transport_http: fix use of $headers instead of $this->incoming_headers in getResponse
|
49 |
+
- soapclient: improve handling of persistent connections
|
50 |
+
- soapclient: force xml_encoding to upper case
|
51 |
+
- soap_server: let the Web server decide whether to close the connection (no Connection: close header)
|
52 |
+
- soap_server: force xml_encoding to upper case
|
53 |
+
|
54 |
+
2003-08-04, version 0.6.5
|
55 |
+
- soap_parser: use XML type information to pick a PHP data type; also decode base64
|
56 |
+
- soap_server: read all HTTP headers when using _SERVER or HTTP_SERVER_VARS
|
57 |
+
- soap_server: add gzip encoding support for outgoing messages
|
58 |
+
- soap_transport_http: deflate is gzcompress/gzuncompress (cf. http://archive.develooper.com/libwww@perl.org/msg04650.html)
|
59 |
+
- soap_transport_http: clean use of persistentConnection so it's always a set boolean
|
60 |
+
- soapclient: add responseData member to access deflated/gunzipped payload
|
61 |
+
|
62 |
+
2003-08-05, version 0.6.5
|
63 |
+
- soap_server: look multiple places when setting debug_flag
|
64 |
+
|
65 |
+
2003-08-07, version 0.6.5
|
66 |
+
- nusoap_base: serialize specified type (e.g. ArrayOfString) even for simple array
|
67 |
+
- wsdl: only specify encodingStyle in the input/output soap bindings when it is not empty (thanks Guillaume)
|
68 |
+
|
69 |
+
2003-08-15, version 0.6.5
|
70 |
+
- soap_parser: fix parsing of elements with no XSD type specified
|
71 |
+
- soap_parser: use PHP string type for XSD long and unsignedLong types
|
72 |
+
|
73 |
+
2003-08-16, version 0.6.5
|
74 |
+
- soap_parser: fix code generating warning (thanks Torsten)
|
75 |
+
|
76 |
+
2003-08-19, version 0.6.5
|
77 |
+
- soap_parser: fix another line of code generating a warning (thanks Torsten)
|
78 |
+
|
79 |
+
2003-08-22, version 0.6.5
|
80 |
+
- soap_server: remove all '--' from debug_str; previous code changed '---' to '- --'
|
81 |
+
- wsdl, soapclient, soap_parser: patch submitted by Mark Spavin as described by
|
82 |
+
the following...
|
83 |
+
> Changes for the multiple/nested imports from the wsdl file. This builds an
|
84 |
+
> array of files not just the last one and also checks for relative paths to
|
85 |
+
> the parent. This will then get the imported files from the remote site
|
86 |
+
> instead of your local disk. Local wsdl files should still work (untested).
|
87 |
+
>
|
88 |
+
> Changes for multiple encoding sytles as previously posted
|
89 |
+
|
90 |
+
2003-08-24, version 0.6.5
|
91 |
+
- wsdl, soapclient: fix some PHP notices from previous update
|
92 |
+
|
93 |
+
2003-08-26, version 0.6.5
|
94 |
+
- wsdl: support multiple SOAP ports
|
95 |
+
- soapclient, soap_server: when no charset is specified, use UTF-8, even though HTTP specifies US-ASCII.
|
96 |
+
- soap_transport_http: do not prepend $host with 'ssl://' for https (is this required for older cURL versions?)
|
97 |
+
|
98 |
+
2003-08-27, version 0.6.5
|
99 |
+
- soap_server: support compressed request messages (thanks John Huong)
|
100 |
+
- soap_parser: deserialize Apache Vector as an array
|
101 |
+
- xmlschema: use $this->typemap in getPHPType (which is not used)
|
102 |
+
- soapclient, wsdl: check for WSDL errors after serializing parameters
|
103 |
+
- nusoap_base: add serialization of Apache Map (when not using WSDL)
|
104 |
+
- wsdl: add serialization of Apache Map (when using WSDL)
|
105 |
+
- wsdl: only change &, <, > to entities, not all HTML entities
|
106 |
+
|
107 |
+
2003-08-28, version 0.6.5
|
108 |
+
- soap_transport_http: disable cURL verification of peer and server (formerly the cURL default)
|
109 |
+
- soap_transport_http: mingle cURL code with straight http, so sendHTTP is no longer needed
|
110 |
+
|
111 |
+
2003-08-29, version 0.6.6
|
112 |
+
- soap_transport_http: add setContentType
|
113 |
+
- soapclient: call setContentType using new getHTTPContentType and getHTTPContentTypeCharset
|
114 |
+
|
115 |
+
2003-09-05, version 0.6.6
|
116 |
+
- wsdl: add some more code to handle null/nil values (but there's still a way to go)
|
117 |
+
|
118 |
+
2003-10-21, version 0.6.6
|
119 |
+
- soap_transport_http: only include port in Host header if it was specified in the URL
|
120 |
+
- soap_transport_http: add some code to use OpenSSL for PHP ssl:// scheme, but comment out since it's not ready
|
121 |
+
- soap_server: use $_SERVER['PHP_SELF'] if $GLOBALS['PHP_SELF'] is not set
|
122 |
+
- wsdl: add WSDL request and response and transport debug to debug
|
123 |
+
- wsdl: handle custom type extending xmlschema namespace (GLUE ... Thanks Matt)
|
124 |
+
- soap_parser: add param to docs
|
125 |
+
- soapclient: add getHTTPBody, getHTTPContentType, getHTTPContentTypeCharset (anticipating MIME subclass)
|
126 |
+
|
127 |
+
2003-10-28, version 0.6.6
|
128 |
+
- nusoap_base: add expandEntities method
|
129 |
+
- wsdl: use expandEntities
|
130 |
+
- soap_fault: use expandEntities
|
131 |
+
- soap_transport_http: Allow credentials to be included in URL, rather than requiring setCredentials
|
132 |
+
- soap_transport_http: Merge HTTP headers that span multiple lines
|
133 |
+
- soap_parser: Properly set errors in ctor
|
134 |
+
- soapclient: Pass headers to parseResponse and parse them in that method
|
135 |
+
|
136 |
+
2003-10-30, version 0.6.6
|
137 |
+
- xmlschema: Add some information for the related type to an element
|
138 |
+
|
139 |
+
2003-12-09, version 0.6.6
|
140 |
+
- nusoap_base: Add some namespace methods previously in xmlschema
|
141 |
+
- xmlschema: Improve parsing of complexType, element and simpleType
|
142 |
+
- xmlschema: Improve serialization
|
143 |
+
- xmlschema: Track imports
|
144 |
+
- xmlschema: Track elementFormDefault and form attributes
|
145 |
+
- wsdl: Support multiple <schema> (note that setting $server->wsdl->schemaTargetNamespace no longer does anything! Use configureWSDL instead.)
|
146 |
+
- wsdl: Use form attribute of element to control namespace specification
|
147 |
+
- wsdl: Support chained imports (A imports B which imports C)
|
148 |
+
- wsdl: Include port in endpoint address when serializing
|
149 |
+
- soap_server: Fix use of style (rpc|document) and use (encoded|literal)
|
150 |
+
- soap_server: Support _SERVER[CONTENT_TYPE] in addition to _SERVER[HTTP_CONTENT_TYPE]
|
151 |
+
- soap_server: Support wsdl with multiple <schema>
|
152 |
+
- soap_client: Remove a var_dump
|
153 |
+
- soap_client: Add style and use parameters to call method to support doc/lit without WSDL
|
154 |
+
- soap_transport_http: Check that $this->fp exists when doing persistent connections
|
155 |
+
|
156 |
+
2003-12-17, version 0.6.6
|
157 |
+
- soap_server: pass namespaces to xmlschema constructor
|
158 |
+
- wsdl: post-process after all imports
|
159 |
+
- wsdl: remove some debug, add some error handling
|
160 |
+
- xmlschema: allow enclosing namespaces to be specified in constructor
|
161 |
+
- xmlschema: improve handling of compositors and simple types
|
162 |
+
|
163 |
+
2004-01-08, version 0.6.6
|
164 |
+
- soap_server: when requested WSDL is in a file, return to client using passthru (thanks Ingo Fischer)
|
165 |
+
- soapclient: have proxy inherit more client state
|
166 |
+
- soapclient: allow timeout and response timeout to be specified in the constructor
|
167 |
+
- wsdl: allow timeout and response timeout to be specified in the constructor
|
168 |
+
- soap_transport_http: allow response timeout to be specified in send and sendHTTPS
|
169 |
+
|
170 |
+
2004-01-28, version 0.6.6
|
171 |
+
- wsdl: add namespace for array and scalar when form is qualified
|
172 |
+
- wsdl: fix a bug in which data type of complexType elements were ignored in serialization
|
173 |
+
- wsdl: enhance handling of URLs with file scheme
|
174 |
+
- wsdl: add addSimpleType
|
175 |
+
- xmlschema: add addSimpleType
|
176 |
+
- xmlschema: always set phpType elements
|
177 |
+
- soapclient: allow a wsdl instance to be specified in constructor
|
178 |
+
- soap_server: allow a wsdl instance to be specified in constructor (not tested!)
|
179 |
+
- soap_server: fix default SOAPAction created in register method
|
180 |
+
- soap_transport_http: accept chunking with LF separators in addition to CRLF.
|
181 |
+
- wsdlcache: added class
|
182 |
+
- nusoapmime: fix comments
|
183 |
+
|
184 |
+
2004-02-23, version 0.6.6
|
185 |
+
- soap_transport_http: don't try to unchunk cURL data, since cURL already does it
|
186 |
+
- soap_transport_http: append CVS revision to version in User-Agent
|
187 |
+
- wsdl: serialize boolean as true|false, not 1|0, to agree with XML Schema
|
188 |
+
- soap_server: always exit() after returning WSDL
|
189 |
+
- soap_server: use the WSDL URL scheme as the default endpoint URL scheme
|
190 |
+
- soap_server: append CVS revision to version in X-SOAP-Server
|
191 |
+
- nusoap_base: add (CVS) revision
|
192 |
+
- wsdlcache: synchronize using a per-WSDL lock file (Thanks Ingo)
|
193 |
+
- wsdlcache: add cache lifetime, after which cache contents are invalidated (Thanks Ingo)
|
194 |
+
|
195 |
+
2004-03-15, version 0.6.6
|
196 |
+
- nusoap_base: add isArraySimpleOrStruct method
|
197 |
+
- soap_server: improve WSDL URL scheme determination
|
198 |
+
- soap_server: only deflate/gzip payloads > 1024 bytes
|
199 |
+
- soap_server: fix parameter order in fault method (always used as faultcode, faultstring)
|
200 |
+
- soap_server: refactor parse_request into multiple functions (for sanity)
|
201 |
+
- soap_server: set the namespace on the Response element to the same as the request
|
202 |
+
- soap_server: name the return value element 'return' by default
|
203 |
+
- soap_server: added and documented data fields, so that service programmers can use them if desired
|
204 |
+
- soap_parser: standardize parsing error message
|
205 |
+
- soap_parser: fix document and responseHeaders so they are the correct XML text (as documented)
|
206 |
+
- soap_transport_http: fix read from persistent connection
|
207 |
+
- soapclient: clean up debugging for persistent connection
|
208 |
+
- wsdl: enforce correct naming of messages parts when an associative array is used for parameters
|
209 |
+
- wsdl: better serialization of null values
|
210 |
+
- wsdl: standardize parsing error message
|
211 |
+
- xmlschema: standardize parsing error message
|
212 |
+
|
213 |
+
2004-03-24, version 0.6.7
|
214 |
+
- soap_transport_http: add digest authentication (based on code by Kevin A. Miller)
|
215 |
+
- xmlschema: improve parsing of import elements
|
216 |
+
- wsdl: do schema imports even if there are no wsdl imports
|
217 |
+
|
218 |
+
2004-04-12, version 0.6.7
|
219 |
+
- wsdl: serialize multiple elements when maxOccurs="unbounded" and value is an array
|
220 |
+
- wsdl: serialize soapval values (used to force an XML type, e.g. when WSDL uses an abstract type)
|
221 |
+
- nusoapmime: do not require nusoap.php (it is now the programmer's responsibility)
|
222 |
+
|
223 |
+
2004-04-21, version 0.6.7
|
224 |
+
- soap_parser: parse repeated element name into an array (de-serializes doc/lit array into a PHP array when there is more than 1 array element)
|
225 |
+
- soap_server: do not wrap response in a response element for a document style service
|
226 |
+
|
227 |
+
2004-04-30, version 0.6.7
|
228 |
+
- soap_transport_http: allow digest auth params to be separated by "," as well as ", "
|
229 |
+
- soap_transport_http: re-initialize incoming headers for each response
|
230 |
+
- soap_server: add methodreturnisliteralxml property to allow service function to return XML as a string
|
231 |
+
- soapclient: improve rpc/literal support
|
232 |
+
- soapclient: allow XML string as call params in addition to array
|
233 |
+
- soapclient: support document style and literal encoding when not using WSDL
|
234 |
+
|
235 |
+
2004-05-05, version 0.6.7
|
236 |
+
- wsdl: serialize PHP objects for WSDL XML Schema complexTypes, in addition to associative arrays
|
237 |
+
- wsdl: fix WSDL generation when there is no encodingStyle
|
238 |
+
- soap_transport_http: suppress fsockopen warnings
|
239 |
+
- soap_transport_http: detect socket timeouts when reading (0 bytes returned)
|
240 |
+
- soap_transport_http: read chunked content "in-line" so it works on a persistent connection
|
241 |
+
- nusoap_base: serialize boolean as true|false, not 1|0, to agree with XML Schema
|
242 |
+
- nusoap_base: serialize array of struct differently than array of array
|
243 |
+
|
244 |
+
2004-06-25, version 0.6.8
|
245 |
+
- soap_server: prefer gzip to deflate, since IE does not like our deflate
|
246 |
+
- soap_server: move webDescription to the wsdl class
|
247 |
+
- soap_server: allow class and instance method calls for service (thanks Ingo Fischer and Roland Knall)
|
248 |
+
- wsdl: get webDescription from the soap_server class
|
249 |
+
- wsdl: allow compression from the server
|
250 |
+
- wsdl: fix serialization of soapval without a type
|
251 |
+
- wsdl: propagate debug value from query string to SOAP endpoint in programmatic WSDL generation
|
252 |
+
- nusoap_base: add anyType, anySimpleType for 2001 XML Schema
|
253 |
+
- nusoap_base: provide additional debug functions
|
254 |
+
- soap_transport_http: ignore Content-Length when chunked encoding is used
|
255 |
+
- soap_transport_http: remove ':' from username for Basic authentication (cf. RFC 2617)
|
256 |
+
- soap_transport_http: urldecode username and password taken from URL
|
257 |
+
- soap_transport_http: use raw inflate/deflate for IE/IIS compatibility, rather than having Zlib headers according to HTTP 1.1 spec
|
258 |
+
- soap_transport_http: attempt to handle the case when both the service application and Web server compress the response
|
259 |
+
- soapclient: when creating proxy methods, replace '.' in operation name with '__' in function name
|
260 |
+
- soapclient: initialize requestHeaders in proxy
|
261 |
+
- general: use new debug methods; never access debug_str directly
|
262 |
+
|
263 |
+
2004-09-30, version 0.6.8
|
264 |
+
- soapclient: do not allow getProxy call when WSDL is not used
|
265 |
+
- soapclient: use ISO-8859-1 as the charset if not specified in the Content-Type header
|
266 |
+
- soapclient: when an empty string is specified for the call namespace, do not put the method element in a namespace
|
267 |
+
- soapclient: let soap_transport_http check for SSL support
|
268 |
+
- soapclient: have proxy inherit soap_defencoding from the client from which it is generated
|
269 |
+
- soapclient: do not assume that 'ns1' is an unused namespace prefix; always generate namespace prefixes randomly
|
270 |
+
- soap_parser: compare any encoding in the XML declaration to the charset from the HTTP Content-Type header (thanks Ingo Fischer)
|
271 |
+
- soap_parser: improve parse repeated element name into an array (de-serializes doc/lit array into a PHP array when there is more than 1 array element)
|
272 |
+
- soap_server: use ISO-8859-1 as the charset if not specified in the Content-Type header
|
273 |
+
- soap_server: allow suppression of automatic UTF-8 decoding
|
274 |
+
- soap_server: fix a bug when call_user_func_array() is used
|
275 |
+
- soap_transport_http: correct digest authentication through a proxy
|
276 |
+
- wsdl: serialize SOAP-ENC types similarly to XSD types
|
277 |
+
- xmlschema: force unprefixed type into default namespace
|
278 |
+
- xmlschema: fix serialization of definition of simple types
|
279 |
+
|
280 |
+
2004-10-01, version 0.6.8
|
281 |
+
- soap_parser: handle default namespace attributes
|
282 |
+
- soap_server: add default_utf8 field
|
283 |
+
- soap_server: support literal encoding (with RPC style)
|
284 |
+
- soap_transport_http: parse HTTP status and generate error for 300, 302-307, 400, 401-417, 501-505 (thanks for the idea Ghislain)
|
285 |
+
- soap_transport_http: follow HTTP redirection (HTTP status 301 and Location header) (thanks for the idea Ghislain)
|
286 |
+
- xmlschema: allow any attributes to be specified in an element of a complexType, e.g., abstract, default, form, minOccurs, maxOccurs, nillable (thanks Jirka Pech for the original patch)
|
287 |
+
|
288 |
+
2004-10-02, version 0.6.8
|
289 |
+
- soapclient: read/write cookies (thanks Ingo)
|
290 |
+
- soap_server: change faultcode on non-resendable faults to Client
|
291 |
+
- soap_transport_http: read/write cookies (thanks Ingo)
|
292 |
+
|
293 |
+
2004-10-05, version 0.6.8
|
294 |
+
- wsdl: add addElement method
|
295 |
+
- wsdl: support the document style in the register method
|
296 |
+
- xmlschema: parse unnamed simpleTypes, rather than ignoring them
|
297 |
+
- xmlschema: include untyped elements when parsing a complexType
|
298 |
+
- xmlschema: add addElement method
|
299 |
+
|
300 |
+
2004-10-14, version 0.6.8
|
301 |
+
- soapclient: support client certificates
|
302 |
+
- soap_parser: deserialize attributes, prefixing names with "!"
|
303 |
+
- soap_server: notify the client with HTML when WSDL is requested but not supported by service
|
304 |
+
- soap_transport_http: support client certificates
|
305 |
+
- wsdl: support defaults for elements of a complexType
|
306 |
+
- wsdl: serialize elements from complexType extension base
|
307 |
+
- wsdl: serialize data (associative array elements) as attributes according to XML Schema
|
308 |
+
- xmlschema: record extension base if present for a complexType
|
309 |
+
|
310 |
+
2004-12-15, version 0.6.8
|
311 |
+
- nusoap_base: add 2000 XML Schema (rare, but used by Akamai)
|
312 |
+
- soap_parser: avoid deserializing more common attributes that are not data
|
313 |
+
- soap_parser: be lax when HTTP specifies ISO-8859-1 (the default) and XML specifies UTF-8 (the norm)
|
314 |
+
- soap_server: account for the fact that get_class_methods returns methods in all lower case (thanks Steve Haldane)
|
315 |
+
- soap_transport_http: parse digest info that includes '=' in the data (thanks Jinsuk Kim)
|
316 |
+
- wsdl: feably handle some cases for literal serialization of form="unqualified" elements
|
317 |
+
- wsdl: don't serialize the decimal portion of a PHP double when the XML type is long
|
318 |
+
- wsdl: fix serialization of attributes for complexType that is an extension
|
319 |
+
- wsdlcache: enhance diagnostics
|
320 |
+
- xmlschema: handle untyped elements
|
321 |
+
- xmlschema: handle WSDL for SOAP Array that uses the base attribute plus a sequence of element
|
322 |
+
|
323 |
+
2005-01-22, version 0.6.8
|
324 |
+
- wsdl: allow an element in one schema to have a type from another schema
|
325 |
+
|
326 |
+
2005-01-24, version 0.6.8
|
327 |
+
- xmlschema: correctly parse nested complexType definitions
|
328 |
+
|
329 |
+
2005-02-14, version 0.6.8
|
330 |
+
- nusoap_base: fix a bug in which attributes were sometimes not serialized with a value
|
331 |
+
- nusoap_base: improve serialization of null values (thanks Dominique Stender)
|
332 |
+
- soap_parser: parse null values by handling the nil attribute (thanks Dominique Stender)
|
333 |
+
- soap_server: set character encoding for a fault to be the same as for the server (thanks Mark Scott)
|
334 |
+
- soap_server: correctly check for null value returned from method when WSDL is used (without WSDL, cannot distinguish whether NULL or void return is desired)
|
335 |
+
- soapclient: for document style, call should always return an array rooted at the response part (all bets are off when there are multiple parts)
|
336 |
+
- xmlschema: save enumeration values parsed from WSDL
|
337 |
+
|
338 |
+
2005-02-10, version 0.6.9
|
339 |
+
- soapclient: only set SOAP headers when they are specified in call params (so setHeaders still works)
|
340 |
+
|
341 |
+
2005-04-04, version 0.6.9
|
342 |
+
- soap_server: use get_class instead of is_a (thanks Thomas Noel)
|
343 |
+
- soapclient: use get_class instead of is_a (thanks Thomas Noel)
|
344 |
+
- soapclient: add setEndpoint method
|
345 |
+
- soap_transport_http: fix client certificates (thanks Doug Anarino and Eryan Eriobowo)
|
346 |
+
|
347 |
+
2005-04-29, version 0.6.9
|
348 |
+
- nusoap_base: add global variable and methods for setting debug level
|
349 |
+
- nusoap_base: use xsd:anyType instead of xsd:ur-type to serialize arrays with multiple element types (thanks Ingo Fischer)
|
350 |
+
- nusoap_base: expand entities in attributes (thanks Gaetano Giunta)
|
351 |
+
- soapclient: call parent constructor
|
352 |
+
- soapval: call parent constructor
|
353 |
+
- soap_fault: call parent constructor
|
354 |
+
- soap_parser: call parent constructor
|
355 |
+
- soap_server: assume get_class_methods always returns lower case for PHP 4.x only
|
356 |
+
- soap_server: call parent constructor
|
357 |
+
- soap_transport_http: do nothing in setEncoding if gzdeflate is not present (thanks Franck Touanen for pointing this out)
|
358 |
+
- soap_transport_http: fix check for server request for digest authentication (thanks Mark Spavin)
|
359 |
+
- soap_transport_http: call parent constructor
|
360 |
+
- wsdl: fix documentation page popup of one method after another (thanks Owen)
|
361 |
+
- wsdl: call parent constructor
|
362 |
+
- wsdl: expand entities in attributes (thanks Gaetano Giunta)
|
363 |
+
- xmlschema: call parent constructor
|
364 |
+
|
365 |
+
2005-06-03, version 0.6.9
|
366 |
+
- nusoap_base: serialize empty arrays as having elements xsd:anyType[0]
|
367 |
+
- nusoap_base: add encodingStyle parameter to serializeEnvelope
|
368 |
+
- nusoap_base: serialize xsi:type with nil values
|
369 |
+
- nusoap_base: improve debug and comments
|
370 |
+
- soap_parser: correctly parse an empty array to an empty array, not an empty string
|
371 |
+
- soap_parser: improve debug and comments
|
372 |
+
- soap_server: specify encodingStyle for envelope when WSDL is used
|
373 |
+
- soapclient: factor out new getProxyClassCode method
|
374 |
+
- soapclient: specify encodingStyle for envelope
|
375 |
+
- soapclient: improve debug and comments
|
376 |
+
- wsdl: add namespace for Apache SOAP types if a variable of such type is serialized
|
377 |
+
- wsdl: serialize nil value for nillable elements when no value is provided
|
378 |
+
- wsdl: serialize xsi:type with nil values
|
379 |
+
- wsdl: copy attributes as well as elements to an element from its complexType
|
380 |
+
- wsdl: specify encodingStyle for operations
|
381 |
+
- wsdl: improve debug and comments
|
382 |
+
- xmlschema: improve debug and comments
|
383 |
+
|
384 |
+
2005-06-03, version 0.7.0
|
385 |
+
- nusoap_base: improve debug and comments
|
386 |
+
- nusoap_base: fix version, which should have been 0.7.0 since 2005-03-04
|
387 |
+
|
388 |
+
2005-06-06, version 0.7.1
|
389 |
+
- nusoap_base: adjust numeric element names for serialization, instead of forcing them to 'soapVal'
|
390 |
+
- nusoapmime: add type=text/xml to multipart/related (thanks Emmanuel Cordonnier)
|
391 |
+
- soap_fault: fix serialization of detail
|
392 |
+
- soap_server: check required parameters for register method
|
393 |
+
- soap_server: when getallheaders is used, massage header names
|
394 |
+
- soap_server: use SOAPAction to determine operation when doc/lit service does not wrap parameters in an element with the method name (thanks Peter Hrastnik)
|
395 |
+
- soap_transport_http: correctly handle multiple HTTP/1.1 100 responses for https (thanks Jan Slabon)
|
396 |
+
- wsdl: fixed documentation for addComplexType (thanks Csintalan �d�m)
|
397 |
+
- wsdl: serialize array data when maxOccurs = 'unbounded' OR maxOccurs > 1 (thanks Dominique Schreckling)
|
398 |
+
- wsdl: when serializing a string == 'false' as a boolean, set the value to false
|
399 |
+
- wsdl: when serializing a complexType, require the PHP value supplied to be an array
|
400 |
+
|
401 |
+
2005-07-01, version 0.7.1
|
402 |
+
- nusoap_base: Allow SOAP headers to be supplied as an array like parameters
|
403 |
+
- soap_parser: de-serialize simpleContent that accompanies complexContent
|
404 |
+
- soap_server: append debug information when programmatically-defined WSDL is returned
|
405 |
+
- soap_transport_http: Add debug when an outgoing header is set
|
406 |
+
- soapclient: Allow SOAP headers to be supplied as an array like parameters
|
407 |
+
- xmlschema: serialize attributes more generally, rather than assuming they are for SOAP 1.1 Array
|
408 |
+
- wsdl: when serializing, look up types by namespace, not prefix (simple programmatic doc/lit WSDL now seems to work)
|
409 |
+
- wsdl: process namespace declarations first when parsing an element
|
410 |
+
|
411 |
+
2005-07-27, version 0.7.1
|
412 |
+
- nusoap_base: do not override supplied element name with class name when serializing an object in serialize_val
|
413 |
+
- nusoap_base: remove http://soapinterop.org/xsd (si) from namespaces array
|
414 |
+
- nusoapmime: add nusoapservermime class to implement MIME attachments on the server
|
415 |
+
- soap_fault: improve documentation
|
416 |
+
- soap_server: improve documentation
|
417 |
+
- soap_server: make consistent use of _SERVER and HTTP_SERVER_VARS
|
418 |
+
- soap_server: make all incoming HTTP header keys lower case
|
419 |
+
- soap_server: add hook functions to support subclassing for MIME attachments
|
420 |
+
- soap_transport_http: remove an unnecessary global statement
|
421 |
+
- soapclient: when creating a proxy, make $params within each function an associative array
|
422 |
+
- soapval: improve documentation
|
423 |
+
- wsdl: when serializing complexType elements, used typed serialization if there is either a type or a reference for the element
|
424 |
+
- wsdl: allow PHP objects to be serialized as SOAP structs in serializeType
|
425 |
+
- wsdl: for WSDL and XML Schema imports, don't forget to use the TCP port number (thanks Luca GIOPPO)
|
426 |
+
- wsdl: make consistent use of _SERVER and HTTP_SERVER_VARS
|
427 |
+
- xmlschema: improve documentation
|
428 |
+
|
429 |
+
2005-07-31, version 0.7.2
|
430 |
+
- nusoap_base: correctly serialize attributes in serialize_val (thanks Hidran Arias)
|
431 |
+
- soap_parser: when resolving references, do not assume that buildVal returns an array (thanks Akshell)
|
432 |
+
- soap_parser: removed decode_entities, which does not work (thanks Martin Sarsale)
|
433 |
+
- soap_server: fix a bug parsing headers from _SERVER and HTTP_SERVER_VARS (thanks Bert Catsburg)
|
434 |
+
- soap_server: parse all "headers" from HTTP_SERVER_VARS (not just HTTP_*)
|
435 |
+
- soap_server: use PHP_SELF instead of SCRIPT_NAME for WSDL endpoint
|
436 |
+
- soap_server: when generating a fault while debug_flag is true, put debug into faultdetail
|
437 |
+
- wsdl: add enumeration parameter to addSimpleType
|
438 |
+
- xmlschema: add enumeration parameter to addSimpleType
|
439 |
+
|
440 |
+
2006-02-02, version 0.7.2
|
441 |
+
- soapclient: initialize paramArrayStr to improve proxy generation
|
442 |
+
- soap_parser: handle PHP5 soapclient's incorrect transmission of WSDL-described SOAP encoded arrays.
|
443 |
+
- soap_server: don't assume _SERVER['HTTPS'] is set; try HTTP_SERVER_VARS['HTTPS'] if it is not
|
444 |
+
- soap_server: "flatten out" the parameter array to call_user_func_array (thanks Andr� Mamitzsch)
|
445 |
+
- soap_server: make thrown exceptions conform to specs
|
446 |
+
- wsdl: use serialize_val to serialize an array when the XSD type is soapenc:Array (JBoss/Axis does this)
|
447 |
+
- wsdl: change formatting of serialized XML for the WSDL
|
448 |
+
- xmlschema: change formatting of namespaces when serializing XML for the schema
|
449 |
+
|
450 |
+
2006-04-07, version 0.7.2
|
451 |
+
- soap_server: if methodparams is not an array, call call_user_func_array with an empty array (thanks Eric Grossi)
|
452 |
+
- wsdl: distinguish parts with element specified from those with type specified by suffixing element names with ^
|
453 |
+
- wsdl: do a case-insensitive match on schema URI when looking for type
|
454 |
+
- xmlschema: only get element (not type) when name has ^ suffix
|
455 |
+
|
456 |
+
2006-05-16, version 0.7.2
|
457 |
+
- soapclient: add getHeader to get parsed SOAP Header
|
458 |
+
- soap_parser: check status when receiving Header or Body element
|
459 |
+
- soap_parser: add soapheader
|
460 |
+
- soap_server: add requestHeader with parsed SOAP Header
|
461 |
+
|
462 |
+
2006-06-15, version 0.7.2
|
463 |
+
- wsdl: fix bug in addComplexType (thanks Maarten Meijer)
|
464 |
+
- soap_transport_http: change cURL message
|
465 |
+
|
466 |
+
2007-03-19, version 0.7.2
|
467 |
+
- soapclient: declare as nusoapclient, then also subclass soapclient if SOAP extension not loaded
|
468 |
+
- soapclientmime: declare as nusoapclientmime, then also subclass soapclientmime if SOAP extension not loaded
|
469 |
+
|
470 |
+
2007-03-28, version 0.7.2
|
471 |
+
- nusoap_base: fix serialization of a soapval when its value is a soapval
|
472 |
+
- soapval: fix serialization of a soapval when its value is a soapval
|
473 |
+
- soapval: add __toString (cf. http://article.gmane.org/gmane.comp.php.nusoap.general/2776)
|
474 |
+
- nusoapclient: use lazy retrieval of WSDL instead of always getting it in the constructor
|
475 |
+
- nusoapclient: fix getProxy that was broken in last revision
|
476 |
+
- wsdl: add ability to set authorization credentials and retrieve WSDL outside of constructor
|
477 |
+
|
478 |
+
2007-04-05, version 0.7.2
|
479 |
+
- nusoapclientmime: don't rely exclusively on Content-Disposition to distinguish the root part from attachment; also check Content-Type (thanks Ben Bosman)
|
480 |
+
- nusoapclientmime: obey RFC 2045 Section 5.1 (thanks Chris Butler)
|
481 |
+
- nusoapservermime: don't rely exclusively on Content-Disposition to distinguish the root part from attachment; also check Content-Type (thanks Ben Bosman)
|
482 |
+
- nusoapservermime: obey RFC 2045 Section 5.1 (thanks Chris Butler)
|
483 |
+
- nusoap_base: remove extra whitespace from some XML elements
|
484 |
+
- nusoap_base: allow SOAP headers to be specified as an associative array (thanks Unique)
|
485 |
+
- nusoap_base: implement __toString
|
486 |
+
- nusoap_base: improve doc accuracy and consistency (thanks Martin K?gler)
|
487 |
+
- iso8601_to_timestamp: avoid problem with negative hours after calculation, etc. (thanks Guntram Trebs)
|
488 |
+
- nusoapclient: support user-settable cURL options (thanks Ciprian Popovici)
|
489 |
+
- nusoapclient: call SOAP 1.2 binding operations if no SOAP 1.1 present (there is no reason to believe this will always work!)
|
490 |
+
- nusoapclient: improve doc accuracy and consistency (thanks Martin K?gler)
|
491 |
+
- soap_server: don't try to use eval to call function when any parameter is an object
|
492 |
+
- soap_server: don't print return value within debug string; returned objects would need __toString in PHP 5.2
|
493 |
+
- soap_server: use URL scheme for WSDL access as the scheme in SOAPAction
|
494 |
+
- soap_server: strip port number from server name (some FastCGI implementations include port in server name)
|
495 |
+
- soap_transport_http: support user-settable cURL options (thanks Ciprian Popovici)
|
496 |
+
- soap_transport_http: use cURL for NTLM authentication
|
497 |
+
- soap_transport_http: make digest authentication work for GET as well as POST
|
498 |
+
- soap_transport_http: improve doc accuracy and consistency (thanks Martin K?gler)
|
499 |
+
- soapval: remove __toString
|
500 |
+
- wsdl: set operation style if necessary, but do not override one already provided (thanks Raffaele Capobianco)
|
501 |
+
- wsdl: check SOAP 1.2 binding operations if no SOAP 1.1 present
|
502 |
+
- wsdl: improve doc accuracy and consistency (thanks Martin K?gler)
|
503 |
+
- xmlschema: fix simpleType serialization
|
504 |
+
- xmlschema: improve doc accuracy and consistency (thanks Martin K?gler)
|
505 |
+
|
506 |
+
2007-04-09, version 0.7.2
|
507 |
+
- nusoapclient: set decode_utf8 when creating a proxy (thanks Dmitri Dmitrienko)
|
508 |
+
- nusoapclient: rename class to nusoap_client
|
509 |
+
- soap_fault: also provide a class named nusoap_fault
|
510 |
+
- soap_parser: also provide a class named nusoap_parser
|
511 |
+
- soap_server: also provide a class named nusoap_server
|
512 |
+
- soap_transport_http: skip HTTP responses 301 and 401 when using cURL
|
513 |
+
- soap_transport_http: don't force HTTP Connection header when using cURL
|
514 |
+
- soap_transport_http: don't set HTTP Host and Content-Length headers when using cURL
|
515 |
+
- soap_transport_http: support CURLOPT_SSLCERTPASSWD (thanks David Blanco)
|
516 |
+
- wsdl: support user-settable cURL options (thanks Ciprian Popovici)
|
517 |
+
- wsdl: serialize parameters for non-SOAP 1.1 binding operations (there is no reason to believe this will always work!)
|
518 |
+
- xmlschema: also provide a class named nusoap_xmlschema
|
519 |
+
- nusoapclientmime: rename class to nusoap_client_mime
|
520 |
+
- nusoapservermime: rename class to nusoap_server_mime
|
521 |
+
|
522 |
+
2007-04-11, version 0.7.2
|
523 |
+
- nusoap_client: enable cURL usage to be forced (thanks Giunta Gaetano)
|
524 |
+
- soap_transport_http: enable cURL proxy usage (thanks Giunta Gaetano)
|
525 |
+
- soap_transport_http: enable cURL usage to be forced (thanks Giunta Gaetano)
|
526 |
+
- soap_transport_http: use cURL's HTTP authentication options for basic, digest
|
527 |
+
- wsdl: enable cURL usage to be forced (thanks Giunta Gaetano)
|
528 |
+
|
529 |
+
2007-04-12, version 0.7.2
|
530 |
+
- nusoap_client: add debug
|
531 |
+
- nusoap_xmlschema: don't add elements of complexTypes to elements array (thanks Heiko Hund)
|
532 |
+
- soap_transport_http: set cURL connection timeout if supported
|
533 |
+
- soap_transport_http: add debug when setting cURL option
|
534 |
+
- soap_transport_http: fix digest authentication broken in previous revision
|
535 |
+
- wsdl: add debug
|
536 |
+
- wsdlcache: address some issues with non-existing cache-files and PHP Warnings which came in such cases (thanks Ingo Fischer)
|
537 |
+
- wsdlcache: change class name to nusoap_wsdlcache
|
538 |
+
|
539 |
+
2007-04-13, version 0.7.2
|
540 |
+
- wsdl: wrap parameters if unwrapped values are supplied and WSDL specifies Microsoft-style wrapping
|
541 |
+
|
542 |
+
2007-04-16, version 0.7.2
|
543 |
+
- nusoap_base: avoid warning in getDebugAsXMLComment
|
544 |
+
- nusoap_client: small debug change
|
545 |
+
- nusoap_client_mime: set responseData when the root part is found
|
546 |
+
|
547 |
+
2007-04-17, version 0.7.2
|
548 |
+
- soap_transport_http: improve detection of undefined cURL options (thanks Ingo Fischer)
|
549 |
+
|
550 |
+
2007-05-28, version 0.7.2
|
551 |
+
- soap_transport_http: support digest authentication opaque feature (cf. RFC 2617) (thanks Daniel Lacroix)
|
552 |
+
- soap_transport_http: check safe_mode and open_basedir before setting CURLOPT_FOLLOWLOCATION
|
553 |
+
- soap_transport_http: skip "HTTP/1.0 200 Connection established" header when cURL returns it (thanks Raimund Jacob)
|
554 |
+
- nusoap_client: improve handling when getProxy is called and WSDL is not being used
|
555 |
+
- nusoap_base: add comments about which specifications are used/implemented by NuSOAP
|
556 |
+
- nusoap_xmlschema: create names for unnamed types that are unique by scope within XML Schema
|
557 |
+
|
558 |
+
2007-06-11, version 0.7.2
|
559 |
+
- wsdl: wrap return value if unwrapped value is supplied and WSDL specifies Microsoft-style wrapping
|
560 |
+
|
561 |
+
2007-06-22, version 0.7.2
|
562 |
+
- nusoap_xmlschema: fix serialization of simpleType restriction (thanks Rizwan Tejpar)
|
563 |
+
|
564 |
+
2007-07-30, version 0.7.2
|
565 |
+
- nusoap_server: Per http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735, rpc/literal accessor elements should not be in a namespace (thanks Kostas Kalevras)
|
566 |
+
- nusoap_client: Per http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735, rpc/literal accessor elements should not be in a namespace (thanks Kostas Kalevras)
|
567 |
+
|
568 |
+
2007-10-21, version 0.7.2
|
569 |
+
- nusoap_server: Per http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735, rpc/literal accessor elements should not be in a namespace (thanks Kostas Kalevras)
|
570 |
+
- nusoap_client: Per http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735, rpc/literal accessor elements should not be in a namespace (thanks Kostas Kalevras)
|
571 |
+
|
572 |
+
2007-10-26, version 0.7.2
|
573 |
+
- nusoap_server: Fix munging of _SERVER variables that start with HTTP_ (thanks Thomas Wieczorek)
|
574 |
+
|
575 |
+
2007-10-30, version 0.7.2
|
576 |
+
- nusoap_xmlschema: Serialize values for elementFormDefault, attributeFormDefault
|
577 |
+
- wsdl: Improve consistency between doc/lit schema auto-wrapping and client's parsed schema
|
578 |
+
- nusoap_server: Correct bug that placed encodingType in Envelope for doc/lit
|
579 |
+
- nusoap_server: Specify elementFormDefault for schema within doc/lit wsdl
|
580 |
+
|
581 |
+
2007-10-31, version 0.7.2
|
582 |
+
- wsdl: Fix typo in parametersMatchWrapped (thanks Sam Stepanyan)
|
583 |
+
- soap_transport_http: Fix three typos in setProxy (thanks Sam Stepanyan)
|
584 |
+
- nusoap_xmlschema: Fix typo in serializeTypeDef (thanks Sam Stepanyan)
|
585 |
+
|
586 |
+
2007-11-06, version 1.0rc1
|
587 |
+
- wsdl: Improve handling of return values from doc/lit methods
|
588 |
+
- nusoap_server: Handle case when method is not in a namespace
|
589 |
+
|
590 |
+
2007-11-27, version 1.0rc1
|
591 |
+
- nusoap_server: always try to invoke service for a POST
|
592 |
+
- nusoap_server: only return Location: for WSDL at http://...
|
593 |
+
- nusoap_base: change some syntax associated with globalDebugLevel
|
594 |
+
|
595 |
+
2008-01-08, version 1.0rc1
|
596 |
+
- nusoap_server: fix a typo where = was used instead of == (thanks J. (Johan) Bosma)
|
597 |
+
|
598 |
+
2008-01-10, version 1.0rc1
|
599 |
+
- nusoap_client: handle case where request or response has no content-type header (thanks Ingo Fischer)
|
600 |
+
- nusoap_server: handle case where request or response has no content-type header (thanks Ingo Fischer)
|
601 |
+
- wsdl: change CSS for .title in webDescription (thanks Marcus Uy)
|
602 |
+
|
603 |
+
2008-01-25, version 1.0rc1
|
604 |
+
- nusoap_xmlschema: when an element is of a complexType that is an extension, copy extensionBase from the type
|
605 |
+
- nusoap_xmlschema: do not apply elementFormDefault to globally defined elements
|
606 |
+
|
607 |
+
2008-02-11, version 1.0rc1
|
608 |
+
- wsdl: internally set form of wrapped parameter elements to unqualified (so server handles correctly)
|
609 |
+
|
610 |
+
2008-03-03, version 1.0.rc1
|
611 |
+
- nusoap_xmlschema: fix extension when base type has no explicit prefix
|
612 |
+
- nusoap_xmlschema: support XML Schema include
|
613 |
+
- wsdl: improve support for sequence by serializing inherited attributes and elements first
|
614 |
+
|
615 |
+
2008-03-04, version 1.0.rc1
|
616 |
+
- wsdl: allow WSDL port name to be specified in getOperations
|
617 |
+
- nusoap_client: allow WSDL port name to be specified in ctor
|
618 |
+
|
619 |
+
2008-03-06, version 1.0rc1
|
620 |
+
- wsdl: fix some port name variable references
|
621 |
+
- nusoap_base: change comments regarding preferred mode of support
|
622 |
+
- wsdl2nusoap: initial revision
|
623 |
+
|
624 |
+
2008-03-14, version 1.0rc1
|
625 |
+
- nusoap_base: fix timezone offset in timestamp_to_iso8601 (thanks Mario Trojan)
|
626 |
+
|
627 |
+
2008-03-27, version 1.0rc1
|
628 |
+
- nusoap_server: fix bug setting encodingStyle in serialize_return (thanks Luca Gobbo)
|
629 |
+
|
630 |
+
2008-05-15, version 1.0rc1
|
631 |
+
- nusoap_parser: handle case where Header or Body tags are used within SOAP messages (thanks Sergey Zhuravlev)
|
632 |
+
|
633 |
+
2008-08-26, version 1.0rc1
|
634 |
+
- wsdl: serialize simpleContent for complexType
|
635 |
+
- wsdl: avoid serializing complexType elements with no value and minOccurs = 0 regardless of nillability
|
636 |
+
|
637 |
+
2010-04-26, version 0.9.5
|
638 |
+
- nusoap_xmlschema: replace regex function calls (ereg, eregi, split) with PCRE calls (preg_match, preg_split) (thanks Pier-Luc Duchaine)
|
639 |
+
- wsdl: replace regex function calls (ereg, eregi, split) with PCRE calls (preg_match, preg_split) (thanks Pier-Luc Duchaine)
|
640 |
+
- soap_transport_http: replace regex function calls (ereg, eregi, split) with PCRE calls (preg_match, preg_split) (thanks Pier-Luc Duchaine)
|
641 |
+
- soap_transport_http: remove call to deprecated function set_magic_quotes_runtime
|
642 |
+
- nusoap_server: replace regex function calls (ereg, eregi, split) with PCRE calls (preg_match, preg_split) (thanks Pier-Luc Duchaine)
|
643 |
+
- nusoap_server: check that value is an object before calling get_class (thanks Pier-Luc Duchaine)
|
644 |
+
- nusoap_parser: replace regex function calls (ereg, eregi, split) with PCRE calls (preg_match, preg_split) (thanks Pier-Luc Duchaine)
|
645 |
+
- nusoap_client: replace regex function calls (ereg, eregi, split) with PCRE calls (preg_match, preg_split) (thanks Pier-Luc Duchaine)
|
646 |
+
- nusoap_client: do not assign the return value of new by reference (it is deprecated) (thanks Pier-Luc Duchaine)
|
647 |
+
- nusoap_base: replace regex function calls (ereg, eregi, split) with PCRE calls (preg_match, preg_split) (thanks Pier-Luc Duchaine)
|
648 |
+
- nusoapmime: do not assign the return value of new by reference (it is deprecated)
|
app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.nusoap_base.php
ADDED
@@ -0,0 +1,996 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
$Id: class.nusoap_base.php,v 1.56 2010/04/26 20:15:08 snichol Exp $
|
5 |
+
|
6 |
+
NuSOAP - Web Services Toolkit for PHP
|
7 |
+
|
8 |
+
Copyright (c) 2002 NuSphere Corporation
|
9 |
+
|
10 |
+
This library is free software; you can redistribute it and/or
|
11 |
+
modify it under the terms of the GNU Lesser General Public
|
12 |
+
License as published by the Free Software Foundation; either
|
13 |
+
version 2.1 of the License, or (at your option) any later version.
|
14 |
+
|
15 |
+
This library is distributed in the hope that it will be useful,
|
16 |
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
17 |
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
18 |
+
Lesser General Public License for more details.
|
19 |
+
|
20 |
+
You should have received a copy of the GNU Lesser General Public
|
21 |
+
License along with this library; if not, write to the Free Software
|
22 |
+
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
23 |
+
|
24 |
+
The NuSOAP project home is:
|
25 |
+
http://sourceforge.net/projects/nusoap/
|
26 |
+
|
27 |
+
The primary support for NuSOAP is the Help forum on the project home page.
|
28 |
+
|
29 |
+
If you have any questions or comments, please email:
|
30 |
+
|
31 |
+
Dietrich Ayala
|
32 |
+
dietrich@ganx4.com
|
33 |
+
http://dietrich.ganx4.com/nusoap
|
34 |
+
|
35 |
+
NuSphere Corporation
|
36 |
+
http://www.nusphere.com
|
37 |
+
|
38 |
+
*/
|
39 |
+
|
40 |
+
/*
|
41 |
+
* Some of the standards implmented in whole or part by NuSOAP:
|
42 |
+
*
|
43 |
+
* SOAP 1.1 (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/)
|
44 |
+
* WSDL 1.1 (http://www.w3.org/TR/2001/NOTE-wsdl-20010315)
|
45 |
+
* SOAP Messages With Attachments (http://www.w3.org/TR/SOAP-attachments)
|
46 |
+
* XML 1.0 (http://www.w3.org/TR/2006/REC-xml-20060816/)
|
47 |
+
* Namespaces in XML 1.0 (http://www.w3.org/TR/2006/REC-xml-names-20060816/)
|
48 |
+
* XML Schema 1.0 (http://www.w3.org/TR/xmlschema-0/)
|
49 |
+
* RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies
|
50 |
+
* RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1
|
51 |
+
* RFC 2617 HTTP Authentication: Basic and Digest Access Authentication
|
52 |
+
*/
|
53 |
+
|
54 |
+
/* load classes
|
55 |
+
|
56 |
+
// necessary classes
|
57 |
+
require_once('class.soapclient.php');
|
58 |
+
require_once('class.soap_val.php');
|
59 |
+
require_once('class.soap_parser.php');
|
60 |
+
require_once('class.soap_fault.php');
|
61 |
+
|
62 |
+
// transport classes
|
63 |
+
require_once('class.soap_transport_http.php');
|
64 |
+
|
65 |
+
// optional add-on classes
|
66 |
+
require_once('class.xmlschema.php');
|
67 |
+
require_once('class.wsdl.php');
|
68 |
+
|
69 |
+
// server class
|
70 |
+
require_once('class.soap_server.php');*/
|
71 |
+
|
72 |
+
// class variable emulation
|
73 |
+
// cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
|
74 |
+
$GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = 9;
|
75 |
+
|
76 |
+
/**
|
77 |
+
*
|
78 |
+
* nusoap_base
|
79 |
+
*
|
80 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
81 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
82 |
+
* @version $Id: class.nusoap_base.php,v 1.56 2010/04/26 20:15:08 snichol Exp $
|
83 |
+
* @access public
|
84 |
+
*/
|
85 |
+
class nusoap_base {
|
86 |
+
/**
|
87 |
+
* Identification for HTTP headers.
|
88 |
+
*
|
89 |
+
* @var string
|
90 |
+
* @access private
|
91 |
+
*/
|
92 |
+
var $title = 'NuSOAP';
|
93 |
+
/**
|
94 |
+
* Version for HTTP headers.
|
95 |
+
*
|
96 |
+
* @var string
|
97 |
+
* @access private
|
98 |
+
*/
|
99 |
+
var $version = '0.9.5';
|
100 |
+
/**
|
101 |
+
* CVS revision for HTTP headers.
|
102 |
+
*
|
103 |
+
* @var string
|
104 |
+
* @access private
|
105 |
+
*/
|
106 |
+
var $revision = '$Revision: 1.56 $';
|
107 |
+
/**
|
108 |
+
* Current error string (manipulated by getError/setError)
|
109 |
+
*
|
110 |
+
* @var string
|
111 |
+
* @access private
|
112 |
+
*/
|
113 |
+
var $error_str = '';
|
114 |
+
/**
|
115 |
+
* Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment)
|
116 |
+
*
|
117 |
+
* @var string
|
118 |
+
* @access private
|
119 |
+
*/
|
120 |
+
var $debug_str = '';
|
121 |
+
/**
|
122 |
+
* toggles automatic encoding of special characters as entities
|
123 |
+
* (should always be true, I think)
|
124 |
+
*
|
125 |
+
* @var boolean
|
126 |
+
* @access private
|
127 |
+
*/
|
128 |
+
var $charencoding = true;
|
129 |
+
/**
|
130 |
+
* the debug level for this instance
|
131 |
+
*
|
132 |
+
* @var integer
|
133 |
+
* @access private
|
134 |
+
*/
|
135 |
+
var $debugLevel;
|
136 |
+
|
137 |
+
/**
|
138 |
+
* set schema version
|
139 |
+
*
|
140 |
+
* @var string
|
141 |
+
* @access public
|
142 |
+
*/
|
143 |
+
var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
|
144 |
+
|
145 |
+
/**
|
146 |
+
* charset encoding for outgoing messages
|
147 |
+
*
|
148 |
+
* @var string
|
149 |
+
* @access public
|
150 |
+
*/
|
151 |
+
var $soap_defencoding = 'ISO-8859-1';
|
152 |
+
//var $soap_defencoding = 'UTF-8';
|
153 |
+
|
154 |
+
/**
|
155 |
+
* namespaces in an array of prefix => uri
|
156 |
+
*
|
157 |
+
* this is "seeded" by a set of constants, but it may be altered by code
|
158 |
+
*
|
159 |
+
* @var array
|
160 |
+
* @access public
|
161 |
+
*/
|
162 |
+
var $namespaces = array(
|
163 |
+
'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
|
164 |
+
'xsd' => 'http://www.w3.org/2001/XMLSchema',
|
165 |
+
'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
|
166 |
+
'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
|
167 |
+
);
|
168 |
+
|
169 |
+
/**
|
170 |
+
* namespaces used in the current context, e.g. during serialization
|
171 |
+
*
|
172 |
+
* @var array
|
173 |
+
* @access private
|
174 |
+
*/
|
175 |
+
var $usedNamespaces = array();
|
176 |
+
|
177 |
+
/**
|
178 |
+
* XML Schema types in an array of uri => (array of xml type => php type)
|
179 |
+
* is this legacy yet?
|
180 |
+
* no, this is used by the nusoap_xmlschema class to verify type => namespace mappings.
|
181 |
+
* @var array
|
182 |
+
* @access public
|
183 |
+
*/
|
184 |
+
var $typemap = array(
|
185 |
+
'http://www.w3.org/2001/XMLSchema' => array(
|
186 |
+
'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
|
187 |
+
'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
|
188 |
+
'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
|
189 |
+
// abstract "any" types
|
190 |
+
'anyType'=>'string','anySimpleType'=>'string',
|
191 |
+
// derived datatypes
|
192 |
+
'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
|
193 |
+
'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
|
194 |
+
'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
|
195 |
+
'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
|
196 |
+
'http://www.w3.org/2000/10/XMLSchema' => array(
|
197 |
+
'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
|
198 |
+
'float'=>'double','dateTime'=>'string',
|
199 |
+
'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
|
200 |
+
'http://www.w3.org/1999/XMLSchema' => array(
|
201 |
+
'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
|
202 |
+
'float'=>'double','dateTime'=>'string',
|
203 |
+
'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
|
204 |
+
'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
|
205 |
+
'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),
|
206 |
+
'http://xml.apache.org/xml-soap' => array('Map')
|
207 |
+
);
|
208 |
+
|
209 |
+
/**
|
210 |
+
* XML entities to convert
|
211 |
+
*
|
212 |
+
* @var array
|
213 |
+
* @access public
|
214 |
+
* @deprecated
|
215 |
+
* @see expandEntities
|
216 |
+
*/
|
217 |
+
var $xmlEntities = array('quot' => '"','amp' => '&',
|
218 |
+
'lt' => '<','gt' => '>','apos' => "'");
|
219 |
+
|
220 |
+
/**
|
221 |
+
* constructor
|
222 |
+
*
|
223 |
+
* @access public
|
224 |
+
*/
|
225 |
+
function nusoap_base() {
|
226 |
+
$this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
|
227 |
+
}
|
228 |
+
|
229 |
+
/**
|
230 |
+
* gets the global debug level, which applies to future instances
|
231 |
+
*
|
232 |
+
* @return integer Debug level 0-9, where 0 turns off
|
233 |
+
* @access public
|
234 |
+
*/
|
235 |
+
function getGlobalDebugLevel() {
|
236 |
+
return $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
|
237 |
+
}
|
238 |
+
|
239 |
+
/**
|
240 |
+
* sets the global debug level, which applies to future instances
|
241 |
+
*
|
242 |
+
* @param int $level Debug level 0-9, where 0 turns off
|
243 |
+
* @access public
|
244 |
+
*/
|
245 |
+
function setGlobalDebugLevel($level) {
|
246 |
+
$GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = $level;
|
247 |
+
}
|
248 |
+
|
249 |
+
/**
|
250 |
+
* gets the debug level for this instance
|
251 |
+
*
|
252 |
+
* @return int Debug level 0-9, where 0 turns off
|
253 |
+
* @access public
|
254 |
+
*/
|
255 |
+
function getDebugLevel() {
|
256 |
+
return $this->debugLevel;
|
257 |
+
}
|
258 |
+
|
259 |
+
/**
|
260 |
+
* sets the debug level for this instance
|
261 |
+
*
|
262 |
+
* @param int $level Debug level 0-9, where 0 turns off
|
263 |
+
* @access public
|
264 |
+
*/
|
265 |
+
function setDebugLevel($level) {
|
266 |
+
$this->debugLevel = $level;
|
267 |
+
}
|
268 |
+
|
269 |
+
/**
|
270 |
+
* adds debug data to the instance debug string with formatting
|
271 |
+
*
|
272 |
+
* @param string $string debug data
|
273 |
+
* @access private
|
274 |
+
*/
|
275 |
+
function debug($string){
|
276 |
+
if ($this->debugLevel > 0) {
|
277 |
+
$this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n");
|
278 |
+
}
|
279 |
+
}
|
280 |
+
|
281 |
+
/**
|
282 |
+
* adds debug data to the instance debug string without formatting
|
283 |
+
*
|
284 |
+
* @param string $string debug data
|
285 |
+
* @access public
|
286 |
+
*/
|
287 |
+
function appendDebug($string){
|
288 |
+
if ($this->debugLevel > 0) {
|
289 |
+
// it would be nice to use a memory stream here to use
|
290 |
+
// memory more efficiently
|
291 |
+
$this->debug_str .= $string;
|
292 |
+
}
|
293 |
+
}
|
294 |
+
|
295 |
+
/**
|
296 |
+
* clears the current debug data for this instance
|
297 |
+
*
|
298 |
+
* @access public
|
299 |
+
*/
|
300 |
+
function clearDebug() {
|
301 |
+
// it would be nice to use a memory stream here to use
|
302 |
+
// memory more efficiently
|
303 |
+
$this->debug_str = '';
|
304 |
+
}
|
305 |
+
|
306 |
+
/**
|
307 |
+
* gets the current debug data for this instance
|
308 |
+
*
|
309 |
+
* @return debug data
|
310 |
+
* @access public
|
311 |
+
*/
|
312 |
+
function &getDebug() {
|
313 |
+
// it would be nice to use a memory stream here to use
|
314 |
+
// memory more efficiently
|
315 |
+
return $this->debug_str;
|
316 |
+
}
|
317 |
+
|
318 |
+
/**
|
319 |
+
* gets the current debug data for this instance as an XML comment
|
320 |
+
* this may change the contents of the debug data
|
321 |
+
*
|
322 |
+
* @return debug data as an XML comment
|
323 |
+
* @access public
|
324 |
+
*/
|
325 |
+
function &getDebugAsXMLComment() {
|
326 |
+
// it would be nice to use a memory stream here to use
|
327 |
+
// memory more efficiently
|
328 |
+
while (strpos($this->debug_str, '--')) {
|
329 |
+
$this->debug_str = str_replace('--', '- -', $this->debug_str);
|
330 |
+
}
|
331 |
+
$ret = "<!--\n" . $this->debug_str . "\n-->";
|
332 |
+
return $ret;
|
333 |
+
}
|
334 |
+
|
335 |
+
/**
|
336 |
+
* expands entities, e.g. changes '<' to '<'.
|
337 |
+
*
|
338 |
+
* @param string $val The string in which to expand entities.
|
339 |
+
* @access private
|
340 |
+
*/
|
341 |
+
function expandEntities($val) {
|
342 |
+
if ($this->charencoding) {
|
343 |
+
$val = str_replace('&', '&', $val);
|
344 |
+
$val = str_replace("'", ''', $val);
|
345 |
+
$val = str_replace('"', '"', $val);
|
346 |
+
$val = str_replace('<', '<', $val);
|
347 |
+
$val = str_replace('>', '>', $val);
|
348 |
+
}
|
349 |
+
return $val;
|
350 |
+
}
|
351 |
+
|
352 |
+
/**
|
353 |
+
* returns error string if present
|
354 |
+
*
|
355 |
+
* @return mixed error string or false
|
356 |
+
* @access public
|
357 |
+
*/
|
358 |
+
function getError(){
|
359 |
+
if($this->error_str != ''){
|
360 |
+
return $this->error_str;
|
361 |
+
}
|
362 |
+
return false;
|
363 |
+
}
|
364 |
+
|
365 |
+
/**
|
366 |
+
* sets error string
|
367 |
+
*
|
368 |
+
* @return boolean $string error string
|
369 |
+
* @access private
|
370 |
+
*/
|
371 |
+
function setError($str){
|
372 |
+
$this->error_str = $str;
|
373 |
+
}
|
374 |
+
|
375 |
+
/**
|
376 |
+
* detect if array is a simple array or a struct (associative array)
|
377 |
+
*
|
378 |
+
* @param mixed $val The PHP array
|
379 |
+
* @return string (arraySimple|arrayStruct)
|
380 |
+
* @access private
|
381 |
+
*/
|
382 |
+
function isArraySimpleOrStruct($val) {
|
383 |
+
$keyList = array_keys($val);
|
384 |
+
foreach ($keyList as $keyListValue) {
|
385 |
+
if (!is_int($keyListValue)) {
|
386 |
+
return 'arrayStruct';
|
387 |
+
}
|
388 |
+
}
|
389 |
+
return 'arraySimple';
|
390 |
+
}
|
391 |
+
|
392 |
+
/**
|
393 |
+
* serializes PHP values in accordance w/ section 5. Type information is
|
394 |
+
* not serialized if $use == 'literal'.
|
395 |
+
*
|
396 |
+
* @param mixed $val The value to serialize
|
397 |
+
* @param string $name The name (local part) of the XML element
|
398 |
+
* @param string $type The XML schema type (local part) for the element
|
399 |
+
* @param string $name_ns The namespace for the name of the XML element
|
400 |
+
* @param string $type_ns The namespace for the type of the element
|
401 |
+
* @param array $attributes The attributes to serialize as name=>value pairs
|
402 |
+
* @param string $use The WSDL "use" (encoded|literal)
|
403 |
+
* @param boolean $soapval Whether this is called from soapval.
|
404 |
+
* @return string The serialized element, possibly with child elements
|
405 |
+
* @access public
|
406 |
+
*/
|
407 |
+
function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded',$soapval=false) {
|
408 |
+
$this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval");
|
409 |
+
$this->appendDebug('value=' . $this->varDump($val));
|
410 |
+
$this->appendDebug('attributes=' . $this->varDump($attributes));
|
411 |
+
|
412 |
+
if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) {
|
413 |
+
$this->debug("serialize_val: serialize soapval");
|
414 |
+
$xml = $val->serialize($use);
|
415 |
+
$this->appendDebug($val->getDebug());
|
416 |
+
$val->clearDebug();
|
417 |
+
$this->debug("serialize_val of soapval returning $xml");
|
418 |
+
return $xml;
|
419 |
+
}
|
420 |
+
// force valid name if necessary
|
421 |
+
if (is_numeric($name)) {
|
422 |
+
$name = '__numeric_' . $name;
|
423 |
+
} elseif (! $name) {
|
424 |
+
$name = 'noname';
|
425 |
+
}
|
426 |
+
// if name has ns, add ns prefix to name
|
427 |
+
$xmlns = '';
|
428 |
+
if($name_ns){
|
429 |
+
$prefix = 'nu'.rand(1000,9999);
|
430 |
+
$name = $prefix.':'.$name;
|
431 |
+
$xmlns .= " xmlns:$prefix=\"$name_ns\"";
|
432 |
+
}
|
433 |
+
// if type is prefixed, create type prefix
|
434 |
+
if($type_ns != '' && $type_ns == $this->namespaces['xsd']){
|
435 |
+
// need to fix this. shouldn't default to xsd if no ns specified
|
436 |
+
// w/o checking against typemap
|
437 |
+
$type_prefix = 'xsd';
|
438 |
+
} elseif($type_ns){
|
439 |
+
$type_prefix = 'ns'.rand(1000,9999);
|
440 |
+
$xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
|
441 |
+
}
|
442 |
+
// serialize attributes if present
|
443 |
+
$atts = '';
|
444 |
+
if($attributes){
|
445 |
+
foreach($attributes as $k => $v){
|
446 |
+
$atts .= " $k=\"".$this->expandEntities($v).'"';
|
447 |
+
}
|
448 |
+
}
|
449 |
+
// serialize null value
|
450 |
+
if (is_null($val)) {
|
451 |
+
$this->debug("serialize_val: serialize null");
|
452 |
+
if ($use == 'literal') {
|
453 |
+
// TODO: depends on minOccurs
|
454 |
+
$xml = "<$name$xmlns$atts/>";
|
455 |
+
$this->debug("serialize_val returning $xml");
|
456 |
+
return $xml;
|
457 |
+
} else {
|
458 |
+
if (isset($type) && isset($type_prefix)) {
|
459 |
+
$type_str = " xsi:type=\"$type_prefix:$type\"";
|
460 |
+
} else {
|
461 |
+
$type_str = '';
|
462 |
+
}
|
463 |
+
$xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>";
|
464 |
+
$this->debug("serialize_val returning $xml");
|
465 |
+
return $xml;
|
466 |
+
}
|
467 |
+
}
|
468 |
+
// serialize if an xsd built-in primitive type
|
469 |
+
if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){
|
470 |
+
$this->debug("serialize_val: serialize xsd built-in primitive type");
|
471 |
+
if (is_bool($val)) {
|
472 |
+
if ($type == 'boolean') {
|
473 |
+
$val = $val ? 'true' : 'false';
|
474 |
+
} elseif (! $val) {
|
475 |
+
$val = 0;
|
476 |
+
}
|
477 |
+
} else if (is_string($val)) {
|
478 |
+
$val = $this->expandEntities($val);
|
479 |
+
}
|
480 |
+
if ($use == 'literal') {
|
481 |
+
$xml = "<$name$xmlns$atts>$val</$name>";
|
482 |
+
$this->debug("serialize_val returning $xml");
|
483 |
+
return $xml;
|
484 |
+
} else {
|
485 |
+
$xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>";
|
486 |
+
$this->debug("serialize_val returning $xml");
|
487 |
+
return $xml;
|
488 |
+
}
|
489 |
+
}
|
490 |
+
// detect type and serialize
|
491 |
+
$xml = '';
|
492 |
+
switch(true) {
|
493 |
+
case (is_bool($val) || $type == 'boolean'):
|
494 |
+
$this->debug("serialize_val: serialize boolean");
|
495 |
+
if ($type == 'boolean') {
|
496 |
+
$val = $val ? 'true' : 'false';
|
497 |
+
} elseif (! $val) {
|
498 |
+
$val = 0;
|
499 |
+
}
|
500 |
+
if ($use == 'literal') {
|
501 |
+
$xml .= "<$name$xmlns$atts>$val</$name>";
|
502 |
+
} else {
|
503 |
+
$xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
|
504 |
+
}
|
505 |
+
break;
|
506 |
+
case (is_int($val) || is_long($val) || $type == 'int'):
|
507 |
+
$this->debug("serialize_val: serialize int");
|
508 |
+
if ($use == 'literal') {
|
509 |
+
$xml .= "<$name$xmlns$atts>$val</$name>";
|
510 |
+
} else {
|
511 |
+
$xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
|
512 |
+
}
|
513 |
+
break;
|
514 |
+
case (is_float($val)|| is_double($val) || $type == 'float'):
|
515 |
+
$this->debug("serialize_val: serialize float");
|
516 |
+
if ($use == 'literal') {
|
517 |
+
$xml .= "<$name$xmlns$atts>$val</$name>";
|
518 |
+
} else {
|
519 |
+
$xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
|
520 |
+
}
|
521 |
+
break;
|
522 |
+
case (is_string($val) || $type == 'string'):
|
523 |
+
$this->debug("serialize_val: serialize string");
|
524 |
+
$val = $this->expandEntities($val);
|
525 |
+
if ($use == 'literal') {
|
526 |
+
$xml .= "<$name$xmlns$atts>$val</$name>";
|
527 |
+
} else {
|
528 |
+
$xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
|
529 |
+
}
|
530 |
+
break;
|
531 |
+
case is_object($val):
|
532 |
+
$this->debug("serialize_val: serialize object");
|
533 |
+
if (get_class($val) == 'soapval') {
|
534 |
+
$this->debug("serialize_val: serialize soapval object");
|
535 |
+
$pXml = $val->serialize($use);
|
536 |
+
$this->appendDebug($val->getDebug());
|
537 |
+
$val->clearDebug();
|
538 |
+
} else {
|
539 |
+
if (! $name) {
|
540 |
+
$name = get_class($val);
|
541 |
+
$this->debug("In serialize_val, used class name $name as element name");
|
542 |
+
} else {
|
543 |
+
$this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
|
544 |
+
}
|
545 |
+
foreach(get_object_vars($val) as $k => $v){
|
546 |
+
$pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use);
|
547 |
+
}
|
548 |
+
}
|
549 |
+
if(isset($type) && isset($type_prefix)){
|
550 |
+
$type_str = " xsi:type=\"$type_prefix:$type\"";
|
551 |
+
} else {
|
552 |
+
$type_str = '';
|
553 |
+
}
|
554 |
+
if ($use == 'literal') {
|
555 |
+
$xml .= "<$name$xmlns$atts>$pXml</$name>";
|
556 |
+
} else {
|
557 |
+
$xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";
|
558 |
+
}
|
559 |
+
break;
|
560 |
+
break;
|
561 |
+
case (is_array($val) || $type):
|
562 |
+
// detect if struct or array
|
563 |
+
$valueType = $this->isArraySimpleOrStruct($val);
|
564 |
+
if($valueType=='arraySimple' || preg_match('/^ArrayOf/',$type)){
|
565 |
+
$this->debug("serialize_val: serialize array");
|
566 |
+
$i = 0;
|
567 |
+
if(is_array($val) && count($val)> 0){
|
568 |
+
foreach($val as $v){
|
569 |
+
if(is_object($v) && get_class($v) == 'soapval'){
|
570 |
+
$tt_ns = $v->type_ns;
|
571 |
+
$tt = $v->type;
|
572 |
+
} elseif (is_array($v)) {
|
573 |
+
$tt = $this->isArraySimpleOrStruct($v);
|
574 |
+
} else {
|
575 |
+
$tt = gettype($v);
|
576 |
+
}
|
577 |
+
$array_types[$tt] = 1;
|
578 |
+
// TODO: for literal, the name should be $name
|
579 |
+
$xml .= $this->serialize_val($v,'item',false,false,false,false,$use);
|
580 |
+
++$i;
|
581 |
+
}
|
582 |
+
if(count($array_types) > 1){
|
583 |
+
$array_typename = 'xsd:anyType';
|
584 |
+
} elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
|
585 |
+
if ($tt == 'integer') {
|
586 |
+
$tt = 'int';
|
587 |
+
}
|
588 |
+
$array_typename = 'xsd:'.$tt;
|
589 |
+
} elseif(isset($tt) && $tt == 'arraySimple'){
|
590 |
+
$array_typename = 'SOAP-ENC:Array';
|
591 |
+
} elseif(isset($tt) && $tt == 'arrayStruct'){
|
592 |
+
$array_typename = 'unnamed_struct_use_soapval';
|
593 |
+
} else {
|
594 |
+
// if type is prefixed, create type prefix
|
595 |
+
if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){
|
596 |
+
$array_typename = 'xsd:' . $tt;
|
597 |
+
} elseif ($tt_ns) {
|
598 |
+
$tt_prefix = 'ns' . rand(1000, 9999);
|
599 |
+
$array_typename = "$tt_prefix:$tt";
|
600 |
+
$xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
|
601 |
+
} else {
|
602 |
+
$array_typename = $tt;
|
603 |
+
}
|
604 |
+
}
|
605 |
+
$array_type = $i;
|
606 |
+
if ($use == 'literal') {
|
607 |
+
$type_str = '';
|
608 |
+
} else if (isset($type) && isset($type_prefix)) {
|
609 |
+
$type_str = " xsi:type=\"$type_prefix:$type\"";
|
610 |
+
} else {
|
611 |
+
$type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"";
|
612 |
+
}
|
613 |
+
// empty array
|
614 |
+
} else {
|
615 |
+
if ($use == 'literal') {
|
616 |
+
$type_str = '';
|
617 |
+
} else if (isset($type) && isset($type_prefix)) {
|
618 |
+
$type_str = " xsi:type=\"$type_prefix:$type\"";
|
619 |
+
} else {
|
620 |
+
$type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
|
621 |
+
}
|
622 |
+
}
|
623 |
+
// TODO: for array in literal, there is no wrapper here
|
624 |
+
$xml = "<$name$xmlns$type_str$atts>".$xml."</$name>";
|
625 |
+
} else {
|
626 |
+
// got a struct
|
627 |
+
$this->debug("serialize_val: serialize struct");
|
628 |
+
if(isset($type) && isset($type_prefix)){
|
629 |
+
$type_str = " xsi:type=\"$type_prefix:$type\"";
|
630 |
+
} else {
|
631 |
+
$type_str = '';
|
632 |
+
}
|
633 |
+
if ($use == 'literal') {
|
634 |
+
$xml .= "<$name$xmlns$atts>";
|
635 |
+
} else {
|
636 |
+
$xml .= "<$name$xmlns$type_str$atts>";
|
637 |
+
}
|
638 |
+
foreach($val as $k => $v){
|
639 |
+
// Apache Map
|
640 |
+
if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
|
641 |
+
$xml .= '<item>';
|
642 |
+
$xml .= $this->serialize_val($k,'key',false,false,false,false,$use);
|
643 |
+
$xml .= $this->serialize_val($v,'value',false,false,false,false,$use);
|
644 |
+
$xml .= '</item>';
|
645 |
+
} else {
|
646 |
+
$xml .= $this->serialize_val($v,$k,false,false,false,false,$use);
|
647 |
+
}
|
648 |
+
}
|
649 |
+
$xml .= "</$name>";
|
650 |
+
}
|
651 |
+
break;
|
652 |
+
default:
|
653 |
+
$this->debug("serialize_val: serialize unknown");
|
654 |
+
$xml .= 'not detected, got '.gettype($val).' for '.$val;
|
655 |
+
break;
|
656 |
+
}
|
657 |
+
$this->debug("serialize_val returning $xml");
|
658 |
+
return $xml;
|
659 |
+
}
|
660 |
+
|
661 |
+
/**
|
662 |
+
* serializes a message
|
663 |
+
*
|
664 |
+
* @param string $body the XML of the SOAP body
|
665 |
+
* @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
|
666 |
+
* @param array $namespaces optional the namespaces used in generating the body and headers
|
667 |
+
* @param string $style optional (rpc|document)
|
668 |
+
* @param string $use optional (encoded|literal)
|
669 |
+
* @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
|
670 |
+
* @return string the message
|
671 |
+
* @access public
|
672 |
+
*/
|
673 |
+
function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded',$encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'){
|
674 |
+
// TODO: add an option to automatically run utf8_encode on $body and $headers
|
675 |
+
// if $this->soap_defencoding is UTF-8. Not doing this automatically allows
|
676 |
+
// one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
|
677 |
+
|
678 |
+
$this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");
|
679 |
+
$this->debug("headers:");
|
680 |
+
$this->appendDebug($this->varDump($headers));
|
681 |
+
$this->debug("namespaces:");
|
682 |
+
$this->appendDebug($this->varDump($namespaces));
|
683 |
+
|
684 |
+
// serialize namespaces
|
685 |
+
$ns_string = '';
|
686 |
+
foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
|
687 |
+
$ns_string .= " xmlns:$k=\"$v\"";
|
688 |
+
}
|
689 |
+
if($encodingStyle) {
|
690 |
+
$ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
|
691 |
+
}
|
692 |
+
|
693 |
+
// serialize headers
|
694 |
+
if($headers){
|
695 |
+
if (is_array($headers)) {
|
696 |
+
$xml = '';
|
697 |
+
foreach ($headers as $k => $v) {
|
698 |
+
if (is_object($v) && get_class($v) == 'soapval') {
|
699 |
+
$xml .= $this->serialize_val($v, false, false, false, false, false, $use);
|
700 |
+
} else {
|
701 |
+
$xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
|
702 |
+
}
|
703 |
+
}
|
704 |
+
$headers = $xml;
|
705 |
+
$this->debug("In serializeEnvelope, serialized array of headers to $headers");
|
706 |
+
}
|
707 |
+
$headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
|
708 |
+
}
|
709 |
+
// serialize envelope
|
710 |
+
return
|
711 |
+
'<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
|
712 |
+
'<SOAP-ENV:Envelope'.$ns_string.">".
|
713 |
+
$headers.
|
714 |
+
"<SOAP-ENV:Body>".
|
715 |
+
$body.
|
716 |
+
"</SOAP-ENV:Body>".
|
717 |
+
"</SOAP-ENV:Envelope>";
|
718 |
+
}
|
719 |
+
|
720 |
+
/**
|
721 |
+
* formats a string to be inserted into an HTML stream
|
722 |
+
*
|
723 |
+
* @param string $str The string to format
|
724 |
+
* @return string The formatted string
|
725 |
+
* @access public
|
726 |
+
* @deprecated
|
727 |
+
*/
|
728 |
+
function formatDump($str){
|
729 |
+
$str = htmlspecialchars($str);
|
730 |
+
return nl2br($str);
|
731 |
+
}
|
732 |
+
|
733 |
+
/**
|
734 |
+
* contracts (changes namespace to prefix) a qualified name
|
735 |
+
*
|
736 |
+
* @param string $qname qname
|
737 |
+
* @return string contracted qname
|
738 |
+
* @access private
|
739 |
+
*/
|
740 |
+
function contractQname($qname){
|
741 |
+
// get element namespace
|
742 |
+
//$this->xdebug("Contract $qname");
|
743 |
+
if (strrpos($qname, ':')) {
|
744 |
+
// get unqualified name
|
745 |
+
$name = substr($qname, strrpos($qname, ':') + 1);
|
746 |
+
// get ns
|
747 |
+
$ns = substr($qname, 0, strrpos($qname, ':'));
|
748 |
+
$p = $this->getPrefixFromNamespace($ns);
|
749 |
+
if ($p) {
|
750 |
+
return $p . ':' . $name;
|
751 |
+
}
|
752 |
+
return $qname;
|
753 |
+
} else {
|
754 |
+
return $qname;
|
755 |
+
}
|
756 |
+
}
|
757 |
+
|
758 |
+
/**
|
759 |
+
* expands (changes prefix to namespace) a qualified name
|
760 |
+
*
|
761 |
+
* @param string $qname qname
|
762 |
+
* @return string expanded qname
|
763 |
+
* @access private
|
764 |
+
*/
|
765 |
+
function expandQname($qname){
|
766 |
+
// get element prefix
|
767 |
+
if(strpos($qname,':') && !preg_match('/^http:\/\//',$qname)){
|
768 |
+
// get unqualified name
|
769 |
+
$name = substr(strstr($qname,':'),1);
|
770 |
+
// get ns prefix
|
771 |
+
$prefix = substr($qname,0,strpos($qname,':'));
|
772 |
+
if(isset($this->namespaces[$prefix])){
|
773 |
+
return $this->namespaces[$prefix].':'.$name;
|
774 |
+
} else {
|
775 |
+
return $qname;
|
776 |
+
}
|
777 |
+
} else {
|
778 |
+
return $qname;
|
779 |
+
}
|
780 |
+
}
|
781 |
+
|
782 |
+
/**
|
783 |
+
* returns the local part of a prefixed string
|
784 |
+
* returns the original string, if not prefixed
|
785 |
+
*
|
786 |
+
* @param string $str The prefixed string
|
787 |
+
* @return string The local part
|
788 |
+
* @access public
|
789 |
+
*/
|
790 |
+
function getLocalPart($str){
|
791 |
+
if($sstr = strrchr($str,':')){
|
792 |
+
// get unqualified name
|
793 |
+
return substr( $sstr, 1 );
|
794 |
+
} else {
|
795 |
+
return $str;
|
796 |
+
}
|
797 |
+
}
|
798 |
+
|
799 |
+
/**
|
800 |
+
* returns the prefix part of a prefixed string
|
801 |
+
* returns false, if not prefixed
|
802 |
+
*
|
803 |
+
* @param string $str The prefixed string
|
804 |
+
* @return mixed The prefix or false if there is no prefix
|
805 |
+
* @access public
|
806 |
+
*/
|
807 |
+
function getPrefix($str){
|
808 |
+
if($pos = strrpos($str,':')){
|
809 |
+
// get prefix
|
810 |
+
return substr($str,0,$pos);
|
811 |
+
}
|
812 |
+
return false;
|
813 |
+
}
|
814 |
+
|
815 |
+
/**
|
816 |
+
* pass it a prefix, it returns a namespace
|
817 |
+
*
|
818 |
+
* @param string $prefix The prefix
|
819 |
+
* @return mixed The namespace, false if no namespace has the specified prefix
|
820 |
+
* @access public
|
821 |
+
*/
|
822 |
+
function getNamespaceFromPrefix($prefix){
|
823 |
+
if (isset($this->namespaces[$prefix])) {
|
824 |
+
return $this->namespaces[$prefix];
|
825 |
+
}
|
826 |
+
//$this->setError("No namespace registered for prefix '$prefix'");
|
827 |
+
return false;
|
828 |
+
}
|
829 |
+
|
830 |
+
/**
|
831 |
+
* returns the prefix for a given namespace (or prefix)
|
832 |
+
* or false if no prefixes registered for the given namespace
|
833 |
+
*
|
834 |
+
* @param string $ns The namespace
|
835 |
+
* @return mixed The prefix, false if the namespace has no prefixes
|
836 |
+
* @access public
|
837 |
+
*/
|
838 |
+
function getPrefixFromNamespace($ns) {
|
839 |
+
foreach ($this->namespaces as $p => $n) {
|
840 |
+
if ($ns == $n || $ns == $p) {
|
841 |
+
$this->usedNamespaces[$p] = $n;
|
842 |
+
return $p;
|
843 |
+
}
|
844 |
+
}
|
845 |
+
return false;
|
846 |
+
}
|
847 |
+
|
848 |
+
/**
|
849 |
+
* returns the time in ODBC canonical form with microseconds
|
850 |
+
*
|
851 |
+
* @return string The time in ODBC canonical form with microseconds
|
852 |
+
* @access public
|
853 |
+
*/
|
854 |
+
function getmicrotime() {
|
855 |
+
if (function_exists('gettimeofday')) {
|
856 |
+
$tod = gettimeofday();
|
857 |
+
$sec = $tod['sec'];
|
858 |
+
$usec = $tod['usec'];
|
859 |
+
} else {
|
860 |
+
$sec = time();
|
861 |
+
$usec = 0;
|
862 |
+
}
|
863 |
+
return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
|
864 |
+
}
|
865 |
+
|
866 |
+
/**
|
867 |
+
* Returns a string with the output of var_dump
|
868 |
+
*
|
869 |
+
* @param mixed $data The variable to var_dump
|
870 |
+
* @return string The output of var_dump
|
871 |
+
* @access public
|
872 |
+
*/
|
873 |
+
function varDump($data) {
|
874 |
+
ob_start();
|
875 |
+
var_dump($data);
|
876 |
+
$ret_val = ob_get_contents();
|
877 |
+
ob_end_clean();
|
878 |
+
return $ret_val;
|
879 |
+
}
|
880 |
+
|
881 |
+
/**
|
882 |
+
* represents the object as a string
|
883 |
+
*
|
884 |
+
* @return string
|
885 |
+
* @access public
|
886 |
+
*/
|
887 |
+
function __toString() {
|
888 |
+
return $this->varDump($this);
|
889 |
+
}
|
890 |
+
}
|
891 |
+
|
892 |
+
// XML Schema Datatype Helper Functions
|
893 |
+
|
894 |
+
//xsd:dateTime helpers
|
895 |
+
|
896 |
+
/**
|
897 |
+
* convert unix timestamp to ISO 8601 compliant date string
|
898 |
+
*
|
899 |
+
* @param int $timestamp Unix time stamp
|
900 |
+
* @param boolean $utc Whether the time stamp is UTC or local
|
901 |
+
* @return mixed ISO 8601 date string or false
|
902 |
+
* @access public
|
903 |
+
*/
|
904 |
+
function timestamp_to_iso8601($timestamp,$utc=true){
|
905 |
+
$datestr = date('Y-m-d\TH:i:sO',$timestamp);
|
906 |
+
$pos = strrpos($datestr, "+");
|
907 |
+
if ($pos === FALSE) {
|
908 |
+
$pos = strrpos($datestr, "-");
|
909 |
+
}
|
910 |
+
if ($pos !== FALSE) {
|
911 |
+
if (strlen($datestr) == $pos + 5) {
|
912 |
+
$datestr = substr($datestr, 0, $pos + 3) . ':' . substr($datestr, -2);
|
913 |
+
}
|
914 |
+
}
|
915 |
+
if($utc){
|
916 |
+
$pattern = '/'.
|
917 |
+
'([0-9]{4})-'. // centuries & years CCYY-
|
918 |
+
'([0-9]{2})-'. // months MM-
|
919 |
+
'([0-9]{2})'. // days DD
|
920 |
+
'T'. // separator T
|
921 |
+
'([0-9]{2}):'. // hours hh:
|
922 |
+
'([0-9]{2}):'. // minutes mm:
|
923 |
+
'([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
|
924 |
+
'(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
|
925 |
+
'/';
|
926 |
+
|
927 |
+
if(preg_match($pattern,$datestr,$regs)){
|
928 |
+
return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
|
929 |
+
}
|
930 |
+
return false;
|
931 |
+
} else {
|
932 |
+
return $datestr;
|
933 |
+
}
|
934 |
+
}
|
935 |
+
|
936 |
+
/**
|
937 |
+
* convert ISO 8601 compliant date string to unix timestamp
|
938 |
+
*
|
939 |
+
* @param string $datestr ISO 8601 compliant date string
|
940 |
+
* @return mixed Unix timestamp (int) or false
|
941 |
+
* @access public
|
942 |
+
*/
|
943 |
+
function iso8601_to_timestamp($datestr){
|
944 |
+
$pattern = '/'.
|
945 |
+
'([0-9]{4})-'. // centuries & years CCYY-
|
946 |
+
'([0-9]{2})-'. // months MM-
|
947 |
+
'([0-9]{2})'. // days DD
|
948 |
+
'T'. // separator T
|
949 |
+
'([0-9]{2}):'. // hours hh:
|
950 |
+
'([0-9]{2}):'. // minutes mm:
|
951 |
+
'([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
|
952 |
+
'(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
|
953 |
+
'/';
|
954 |
+
if(preg_match($pattern,$datestr,$regs)){
|
955 |
+
// not utc
|
956 |
+
if($regs[8] != 'Z'){
|
957 |
+
$op = substr($regs[8],0,1);
|
958 |
+
$h = substr($regs[8],1,2);
|
959 |
+
$m = substr($regs[8],strlen($regs[8])-2,2);
|
960 |
+
if($op == '-'){
|
961 |
+
$regs[4] = $regs[4] + $h;
|
962 |
+
$regs[5] = $regs[5] + $m;
|
963 |
+
} elseif($op == '+'){
|
964 |
+
$regs[4] = $regs[4] - $h;
|
965 |
+
$regs[5] = $regs[5] - $m;
|
966 |
+
}
|
967 |
+
}
|
968 |
+
return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
|
969 |
+
// return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
|
970 |
+
} else {
|
971 |
+
return false;
|
972 |
+
}
|
973 |
+
}
|
974 |
+
|
975 |
+
/**
|
976 |
+
* sleeps some number of microseconds
|
977 |
+
*
|
978 |
+
* @param string $usec the number of microseconds to sleep
|
979 |
+
* @access public
|
980 |
+
* @deprecated
|
981 |
+
*/
|
982 |
+
function usleepWindows($usec)
|
983 |
+
{
|
984 |
+
$start = gettimeofday();
|
985 |
+
|
986 |
+
do
|
987 |
+
{
|
988 |
+
$stop = gettimeofday();
|
989 |
+
$timePassed = 1000000 * ($stop['sec'] - $start['sec'])
|
990 |
+
+ $stop['usec'] - $start['usec'];
|
991 |
+
}
|
992 |
+
while ($timePassed < $usec);
|
993 |
+
}
|
994 |
+
|
995 |
+
|
996 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.soap_fault.php
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
|
4 |
+
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Contains information for a SOAP fault.
|
8 |
+
* Mainly used for returning faults from deployed functions
|
9 |
+
* in a server instance.
|
10 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
11 |
+
* @version $Id: class.soap_fault.php,v 1.14 2007/04/11 15:49:47 snichol Exp $
|
12 |
+
* @access public
|
13 |
+
*/
|
14 |
+
class nusoap_fault extends nusoap_base {
|
15 |
+
/**
|
16 |
+
* The fault code (client|server)
|
17 |
+
* @var string
|
18 |
+
* @access private
|
19 |
+
*/
|
20 |
+
var $faultcode;
|
21 |
+
/**
|
22 |
+
* The fault actor
|
23 |
+
* @var string
|
24 |
+
* @access private
|
25 |
+
*/
|
26 |
+
var $faultactor;
|
27 |
+
/**
|
28 |
+
* The fault string, a description of the fault
|
29 |
+
* @var string
|
30 |
+
* @access private
|
31 |
+
*/
|
32 |
+
var $faultstring;
|
33 |
+
/**
|
34 |
+
* The fault detail, typically a string or array of string
|
35 |
+
* @var mixed
|
36 |
+
* @access private
|
37 |
+
*/
|
38 |
+
var $faultdetail;
|
39 |
+
|
40 |
+
/**
|
41 |
+
* constructor
|
42 |
+
*
|
43 |
+
* @param string $faultcode (SOAP-ENV:Client | SOAP-ENV:Server)
|
44 |
+
* @param string $faultactor only used when msg routed between multiple actors
|
45 |
+
* @param string $faultstring human readable error message
|
46 |
+
* @param mixed $faultdetail detail, typically a string or array of string
|
47 |
+
*/
|
48 |
+
function nusoap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){
|
49 |
+
parent::nusoap_base();
|
50 |
+
$this->faultcode = $faultcode;
|
51 |
+
$this->faultactor = $faultactor;
|
52 |
+
$this->faultstring = $faultstring;
|
53 |
+
$this->faultdetail = $faultdetail;
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* serialize a fault
|
58 |
+
*
|
59 |
+
* @return string The serialization of the fault instance.
|
60 |
+
* @access public
|
61 |
+
*/
|
62 |
+
function serialize(){
|
63 |
+
$ns_string = '';
|
64 |
+
foreach($this->namespaces as $k => $v){
|
65 |
+
$ns_string .= "\n xmlns:$k=\"$v\"";
|
66 |
+
}
|
67 |
+
$return_msg =
|
68 |
+
'<?xml version="1.0" encoding="'.$this->soap_defencoding.'"?>'.
|
69 |
+
'<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.">\n".
|
70 |
+
'<SOAP-ENV:Body>'.
|
71 |
+
'<SOAP-ENV:Fault>'.
|
72 |
+
$this->serialize_val($this->faultcode, 'faultcode').
|
73 |
+
$this->serialize_val($this->faultactor, 'faultactor').
|
74 |
+
$this->serialize_val($this->faultstring, 'faultstring').
|
75 |
+
$this->serialize_val($this->faultdetail, 'detail').
|
76 |
+
'</SOAP-ENV:Fault>'.
|
77 |
+
'</SOAP-ENV:Body>'.
|
78 |
+
'</SOAP-ENV:Envelope>';
|
79 |
+
return $return_msg;
|
80 |
+
}
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Backward compatibility
|
85 |
+
*/
|
86 |
+
class soap_fault extends nusoap_fault {
|
87 |
+
}
|
88 |
+
|
89 |
+
|
90 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.soap_parser.php
ADDED
@@ -0,0 +1,643 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
|
4 |
+
|
5 |
+
|
6 |
+
/**
|
7 |
+
*
|
8 |
+
* nusoap_parser class parses SOAP XML messages into native PHP values
|
9 |
+
*
|
10 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
11 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
12 |
+
* @version $Id: class.soap_parser.php,v 1.42 2010/04/26 20:15:08 snichol Exp $
|
13 |
+
* @access public
|
14 |
+
*/
|
15 |
+
class nusoap_parser extends nusoap_base {
|
16 |
+
|
17 |
+
var $xml = '';
|
18 |
+
var $xml_encoding = '';
|
19 |
+
var $method = '';
|
20 |
+
var $root_struct = '';
|
21 |
+
var $root_struct_name = '';
|
22 |
+
var $root_struct_namespace = '';
|
23 |
+
var $root_header = '';
|
24 |
+
var $document = ''; // incoming SOAP body (text)
|
25 |
+
// determines where in the message we are (envelope,header,body,method)
|
26 |
+
var $status = '';
|
27 |
+
var $position = 0;
|
28 |
+
var $depth = 0;
|
29 |
+
var $default_namespace = '';
|
30 |
+
var $namespaces = array();
|
31 |
+
var $message = array();
|
32 |
+
var $parent = '';
|
33 |
+
var $fault = false;
|
34 |
+
var $fault_code = '';
|
35 |
+
var $fault_str = '';
|
36 |
+
var $fault_detail = '';
|
37 |
+
var $depth_array = array();
|
38 |
+
var $debug_flag = true;
|
39 |
+
var $soapresponse = NULL; // parsed SOAP Body
|
40 |
+
var $soapheader = NULL; // parsed SOAP Header
|
41 |
+
var $responseHeaders = ''; // incoming SOAP headers (text)
|
42 |
+
var $body_position = 0;
|
43 |
+
// for multiref parsing:
|
44 |
+
// array of id => pos
|
45 |
+
var $ids = array();
|
46 |
+
// array of id => hrefs => pos
|
47 |
+
var $multirefs = array();
|
48 |
+
// toggle for auto-decoding element content
|
49 |
+
var $decode_utf8 = true;
|
50 |
+
|
51 |
+
/**
|
52 |
+
* constructor that actually does the parsing
|
53 |
+
*
|
54 |
+
* @param string $xml SOAP message
|
55 |
+
* @param string $encoding character encoding scheme of message
|
56 |
+
* @param string $method method for which XML is parsed (unused?)
|
57 |
+
* @param string $decode_utf8 whether to decode UTF-8 to ISO-8859-1
|
58 |
+
* @access public
|
59 |
+
*/
|
60 |
+
function nusoap_parser($xml,$encoding='UTF-8',$method='',$decode_utf8=true){
|
61 |
+
parent::nusoap_base();
|
62 |
+
$this->xml = $xml;
|
63 |
+
$this->xml_encoding = $encoding;
|
64 |
+
$this->method = $method;
|
65 |
+
$this->decode_utf8 = $decode_utf8;
|
66 |
+
|
67 |
+
// Check whether content has been read.
|
68 |
+
if(!empty($xml)){
|
69 |
+
// Check XML encoding
|
70 |
+
$pos_xml = strpos($xml, '<?xml');
|
71 |
+
if ($pos_xml !== FALSE) {
|
72 |
+
$xml_decl = substr($xml, $pos_xml, strpos($xml, '?>', $pos_xml + 2) - $pos_xml + 1);
|
73 |
+
if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
|
74 |
+
$xml_encoding = $res[1];
|
75 |
+
if (strtoupper($xml_encoding) != $encoding) {
|
76 |
+
$err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";
|
77 |
+
$this->debug($err);
|
78 |
+
if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') {
|
79 |
+
$this->setError($err);
|
80 |
+
return;
|
81 |
+
}
|
82 |
+
// when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed
|
83 |
+
} else {
|
84 |
+
$this->debug('Charset from HTTP Content-Type matches encoding from XML declaration');
|
85 |
+
}
|
86 |
+
} else {
|
87 |
+
$this->debug('No encoding specified in XML declaration');
|
88 |
+
}
|
89 |
+
} else {
|
90 |
+
$this->debug('No XML declaration');
|
91 |
+
}
|
92 |
+
$this->debug('Entering nusoap_parser(), length='.strlen($xml).', encoding='.$encoding);
|
93 |
+
// Create an XML parser - why not xml_parser_create_ns?
|
94 |
+
$this->parser = xml_parser_create($this->xml_encoding);
|
95 |
+
// Set the options for parsing the XML data.
|
96 |
+
//xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
|
97 |
+
xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
|
98 |
+
xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
|
99 |
+
// Set the object for the parser.
|
100 |
+
xml_set_object($this->parser, $this);
|
101 |
+
// Set the element handlers for the parser.
|
102 |
+
xml_set_element_handler($this->parser, 'start_element','end_element');
|
103 |
+
xml_set_character_data_handler($this->parser,'character_data');
|
104 |
+
|
105 |
+
// Parse the XML file.
|
106 |
+
if(!xml_parse($this->parser,$xml,true)){
|
107 |
+
// Display an error message.
|
108 |
+
$err = sprintf('XML error parsing SOAP payload on line %d: %s',
|
109 |
+
xml_get_current_line_number($this->parser),
|
110 |
+
xml_error_string(xml_get_error_code($this->parser)));
|
111 |
+
$this->debug($err);
|
112 |
+
$this->debug("XML payload:\n" . $xml);
|
113 |
+
$this->setError($err);
|
114 |
+
} else {
|
115 |
+
$this->debug('in nusoap_parser ctor, message:');
|
116 |
+
$this->appendDebug($this->varDump($this->message));
|
117 |
+
$this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name);
|
118 |
+
// get final value
|
119 |
+
$this->soapresponse = $this->message[$this->root_struct]['result'];
|
120 |
+
// get header value
|
121 |
+
if($this->root_header != '' && isset($this->message[$this->root_header]['result'])){
|
122 |
+
$this->soapheader = $this->message[$this->root_header]['result'];
|
123 |
+
}
|
124 |
+
// resolve hrefs/ids
|
125 |
+
if(sizeof($this->multirefs) > 0){
|
126 |
+
foreach($this->multirefs as $id => $hrefs){
|
127 |
+
$this->debug('resolving multirefs for id: '.$id);
|
128 |
+
$idVal = $this->buildVal($this->ids[$id]);
|
129 |
+
if (is_array($idVal) && isset($idVal['!id'])) {
|
130 |
+
unset($idVal['!id']);
|
131 |
+
}
|
132 |
+
foreach($hrefs as $refPos => $ref){
|
133 |
+
$this->debug('resolving href at pos '.$refPos);
|
134 |
+
$this->multirefs[$id][$refPos] = $idVal;
|
135 |
+
}
|
136 |
+
}
|
137 |
+
}
|
138 |
+
}
|
139 |
+
xml_parser_free($this->parser);
|
140 |
+
} else {
|
141 |
+
$this->debug('xml was empty, didn\'t parse!');
|
142 |
+
$this->setError('xml was empty, didn\'t parse!');
|
143 |
+
}
|
144 |
+
}
|
145 |
+
|
146 |
+
/**
|
147 |
+
* start-element handler
|
148 |
+
*
|
149 |
+
* @param resource $parser XML parser object
|
150 |
+
* @param string $name element name
|
151 |
+
* @param array $attrs associative array of attributes
|
152 |
+
* @access private
|
153 |
+
*/
|
154 |
+
function start_element($parser, $name, $attrs) {
|
155 |
+
// position in a total number of elements, starting from 0
|
156 |
+
// update class level pos
|
157 |
+
$pos = $this->position++;
|
158 |
+
// and set mine
|
159 |
+
$this->message[$pos] = array('pos' => $pos,'children'=>'','cdata'=>'');
|
160 |
+
// depth = how many levels removed from root?
|
161 |
+
// set mine as current global depth and increment global depth value
|
162 |
+
$this->message[$pos]['depth'] = $this->depth++;
|
163 |
+
|
164 |
+
// else add self as child to whoever the current parent is
|
165 |
+
if($pos != 0){
|
166 |
+
$this->message[$this->parent]['children'] .= '|'.$pos;
|
167 |
+
}
|
168 |
+
// set my parent
|
169 |
+
$this->message[$pos]['parent'] = $this->parent;
|
170 |
+
// set self as current parent
|
171 |
+
$this->parent = $pos;
|
172 |
+
// set self as current value for this depth
|
173 |
+
$this->depth_array[$this->depth] = $pos;
|
174 |
+
// get element prefix
|
175 |
+
if(strpos($name,':')){
|
176 |
+
// get ns prefix
|
177 |
+
$prefix = substr($name,0,strpos($name,':'));
|
178 |
+
// get unqualified name
|
179 |
+
$name = substr(strstr($name,':'),1);
|
180 |
+
}
|
181 |
+
// set status
|
182 |
+
if ($name == 'Envelope' && $this->status == '') {
|
183 |
+
$this->status = 'envelope';
|
184 |
+
} elseif ($name == 'Header' && $this->status == 'envelope') {
|
185 |
+
$this->root_header = $pos;
|
186 |
+
$this->status = 'header';
|
187 |
+
} elseif ($name == 'Body' && $this->status == 'envelope'){
|
188 |
+
$this->status = 'body';
|
189 |
+
$this->body_position = $pos;
|
190 |
+
// set method
|
191 |
+
} elseif($this->status == 'body' && $pos == ($this->body_position+1)) {
|
192 |
+
$this->status = 'method';
|
193 |
+
$this->root_struct_name = $name;
|
194 |
+
$this->root_struct = $pos;
|
195 |
+
$this->message[$pos]['type'] = 'struct';
|
196 |
+
$this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
|
197 |
+
}
|
198 |
+
// set my status
|
199 |
+
$this->message[$pos]['status'] = $this->status;
|
200 |
+
// set name
|
201 |
+
$this->message[$pos]['name'] = htmlspecialchars($name);
|
202 |
+
// set attrs
|
203 |
+
$this->message[$pos]['attrs'] = $attrs;
|
204 |
+
|
205 |
+
// loop through atts, logging ns and type declarations
|
206 |
+
$attstr = '';
|
207 |
+
foreach($attrs as $key => $value){
|
208 |
+
$key_prefix = $this->getPrefix($key);
|
209 |
+
$key_localpart = $this->getLocalPart($key);
|
210 |
+
// if ns declarations, add to class level array of valid namespaces
|
211 |
+
if($key_prefix == 'xmlns'){
|
212 |
+
if(preg_match('/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/',$value)){
|
213 |
+
$this->XMLSchemaVersion = $value;
|
214 |
+
$this->namespaces['xsd'] = $this->XMLSchemaVersion;
|
215 |
+
$this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance';
|
216 |
+
}
|
217 |
+
$this->namespaces[$key_localpart] = $value;
|
218 |
+
// set method namespace
|
219 |
+
if($name == $this->root_struct_name){
|
220 |
+
$this->methodNamespace = $value;
|
221 |
+
}
|
222 |
+
// if it's a type declaration, set type
|
223 |
+
} elseif($key_localpart == 'type'){
|
224 |
+
if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') {
|
225 |
+
// do nothing: already processed arrayType
|
226 |
+
} else {
|
227 |
+
$value_prefix = $this->getPrefix($value);
|
228 |
+
$value_localpart = $this->getLocalPart($value);
|
229 |
+
$this->message[$pos]['type'] = $value_localpart;
|
230 |
+
$this->message[$pos]['typePrefix'] = $value_prefix;
|
231 |
+
if(isset($this->namespaces[$value_prefix])){
|
232 |
+
$this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
|
233 |
+
} else if(isset($attrs['xmlns:'.$value_prefix])) {
|
234 |
+
$this->message[$pos]['type_namespace'] = $attrs['xmlns:'.$value_prefix];
|
235 |
+
}
|
236 |
+
// should do something here with the namespace of specified type?
|
237 |
+
}
|
238 |
+
} elseif($key_localpart == 'arrayType'){
|
239 |
+
$this->message[$pos]['type'] = 'array';
|
240 |
+
/* do arrayType ereg here
|
241 |
+
[1] arrayTypeValue ::= atype asize
|
242 |
+
[2] atype ::= QName rank*
|
243 |
+
[3] rank ::= '[' (',')* ']'
|
244 |
+
[4] asize ::= '[' length~ ']'
|
245 |
+
[5] length ::= nextDimension* Digit+
|
246 |
+
[6] nextDimension ::= Digit+ ','
|
247 |
+
*/
|
248 |
+
$expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/';
|
249 |
+
if(preg_match($expr,$value,$regs)){
|
250 |
+
$this->message[$pos]['typePrefix'] = $regs[1];
|
251 |
+
$this->message[$pos]['arrayTypePrefix'] = $regs[1];
|
252 |
+
if (isset($this->namespaces[$regs[1]])) {
|
253 |
+
$this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];
|
254 |
+
} else if (isset($attrs['xmlns:'.$regs[1]])) {
|
255 |
+
$this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:'.$regs[1]];
|
256 |
+
}
|
257 |
+
$this->message[$pos]['arrayType'] = $regs[2];
|
258 |
+
$this->message[$pos]['arraySize'] = $regs[3];
|
259 |
+
$this->message[$pos]['arrayCols'] = $regs[4];
|
260 |
+
}
|
261 |
+
// specifies nil value (or not)
|
262 |
+
} elseif ($key_localpart == 'nil'){
|
263 |
+
$this->message[$pos]['nil'] = ($value == 'true' || $value == '1');
|
264 |
+
// some other attribute
|
265 |
+
} elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') {
|
266 |
+
$this->message[$pos]['xattrs']['!' . $key] = $value;
|
267 |
+
}
|
268 |
+
|
269 |
+
if ($key == 'xmlns') {
|
270 |
+
$this->default_namespace = $value;
|
271 |
+
}
|
272 |
+
// log id
|
273 |
+
if($key == 'id'){
|
274 |
+
$this->ids[$value] = $pos;
|
275 |
+
}
|
276 |
+
// root
|
277 |
+
if($key_localpart == 'root' && $value == 1){
|
278 |
+
$this->status = 'method';
|
279 |
+
$this->root_struct_name = $name;
|
280 |
+
$this->root_struct = $pos;
|
281 |
+
$this->debug("found root struct $this->root_struct_name, pos $pos");
|
282 |
+
}
|
283 |
+
// for doclit
|
284 |
+
$attstr .= " $key=\"$value\"";
|
285 |
+
}
|
286 |
+
// get namespace - must be done after namespace atts are processed
|
287 |
+
if(isset($prefix)){
|
288 |
+
$this->message[$pos]['namespace'] = $this->namespaces[$prefix];
|
289 |
+
$this->default_namespace = $this->namespaces[$prefix];
|
290 |
+
} else {
|
291 |
+
$this->message[$pos]['namespace'] = $this->default_namespace;
|
292 |
+
}
|
293 |
+
if($this->status == 'header'){
|
294 |
+
if ($this->root_header != $pos) {
|
295 |
+
$this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
|
296 |
+
}
|
297 |
+
} elseif($this->root_struct_name != ''){
|
298 |
+
$this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
|
299 |
+
}
|
300 |
+
}
|
301 |
+
|
302 |
+
/**
|
303 |
+
* end-element handler
|
304 |
+
*
|
305 |
+
* @param resource $parser XML parser object
|
306 |
+
* @param string $name element name
|
307 |
+
* @access private
|
308 |
+
*/
|
309 |
+
function end_element($parser, $name) {
|
310 |
+
// position of current element is equal to the last value left in depth_array for my depth
|
311 |
+
$pos = $this->depth_array[$this->depth--];
|
312 |
+
|
313 |
+
// get element prefix
|
314 |
+
if(strpos($name,':')){
|
315 |
+
// get ns prefix
|
316 |
+
$prefix = substr($name,0,strpos($name,':'));
|
317 |
+
// get unqualified name
|
318 |
+
$name = substr(strstr($name,':'),1);
|
319 |
+
}
|
320 |
+
|
321 |
+
// build to native type
|
322 |
+
if(isset($this->body_position) && $pos > $this->body_position){
|
323 |
+
// deal w/ multirefs
|
324 |
+
if(isset($this->message[$pos]['attrs']['href'])){
|
325 |
+
// get id
|
326 |
+
$id = substr($this->message[$pos]['attrs']['href'],1);
|
327 |
+
// add placeholder to href array
|
328 |
+
$this->multirefs[$id][$pos] = 'placeholder';
|
329 |
+
// add set a reference to it as the result value
|
330 |
+
$this->message[$pos]['result'] =& $this->multirefs[$id][$pos];
|
331 |
+
// build complexType values
|
332 |
+
} elseif($this->message[$pos]['children'] != ''){
|
333 |
+
// if result has already been generated (struct/array)
|
334 |
+
if(!isset($this->message[$pos]['result'])){
|
335 |
+
$this->message[$pos]['result'] = $this->buildVal($pos);
|
336 |
+
}
|
337 |
+
// build complexType values of attributes and possibly simpleContent
|
338 |
+
} elseif (isset($this->message[$pos]['xattrs'])) {
|
339 |
+
if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
|
340 |
+
$this->message[$pos]['xattrs']['!'] = null;
|
341 |
+
} elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
|
342 |
+
if (isset($this->message[$pos]['type'])) {
|
343 |
+
$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'] : '');
|
344 |
+
} else {
|
345 |
+
$parent = $this->message[$pos]['parent'];
|
346 |
+
if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
|
347 |
+
$this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
|
348 |
+
} else {
|
349 |
+
$this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];
|
350 |
+
}
|
351 |
+
}
|
352 |
+
}
|
353 |
+
$this->message[$pos]['result'] = $this->message[$pos]['xattrs'];
|
354 |
+
// set value of simpleType (or nil complexType)
|
355 |
+
} else {
|
356 |
+
//$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
|
357 |
+
if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
|
358 |
+
$this->message[$pos]['xattrs']['!'] = null;
|
359 |
+
} elseif (isset($this->message[$pos]['type'])) {
|
360 |
+
$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'] : '');
|
361 |
+
} else {
|
362 |
+
$parent = $this->message[$pos]['parent'];
|
363 |
+
if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
|
364 |
+
$this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
|
365 |
+
} else {
|
366 |
+
$this->message[$pos]['result'] = $this->message[$pos]['cdata'];
|
367 |
+
}
|
368 |
+
}
|
369 |
+
|
370 |
+
/* add value to parent's result, if parent is struct/array
|
371 |
+
$parent = $this->message[$pos]['parent'];
|
372 |
+
if($this->message[$parent]['type'] != 'map'){
|
373 |
+
if(strtolower($this->message[$parent]['type']) == 'array'){
|
374 |
+
$this->message[$parent]['result'][] = $this->message[$pos]['result'];
|
375 |
+
} else {
|
376 |
+
$this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];
|
377 |
+
}
|
378 |
+
}
|
379 |
+
*/
|
380 |
+
}
|
381 |
+
}
|
382 |
+
|
383 |
+
// for doclit
|
384 |
+
if($this->status == 'header'){
|
385 |
+
if ($this->root_header != $pos) {
|
386 |
+
$this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
|
387 |
+
}
|
388 |
+
} elseif($pos >= $this->root_struct){
|
389 |
+
$this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
|
390 |
+
}
|
391 |
+
// switch status
|
392 |
+
if ($pos == $this->root_struct){
|
393 |
+
$this->status = 'body';
|
394 |
+
$this->root_struct_namespace = $this->message[$pos]['namespace'];
|
395 |
+
} elseif ($pos == $this->root_header) {
|
396 |
+
$this->status = 'envelope';
|
397 |
+
} elseif ($name == 'Body' && $this->status == 'body') {
|
398 |
+
$this->status = 'envelope';
|
399 |
+
} elseif ($name == 'Header' && $this->status == 'header') { // will never happen
|
400 |
+
$this->status = 'envelope';
|
401 |
+
} elseif ($name == 'Envelope' && $this->status == 'envelope') {
|
402 |
+
$this->status = '';
|
403 |
+
}
|
404 |
+
// set parent back to my parent
|
405 |
+
$this->parent = $this->message[$pos]['parent'];
|
406 |
+
}
|
407 |
+
|
408 |
+
/**
|
409 |
+
* element content handler
|
410 |
+
*
|
411 |
+
* @param resource $parser XML parser object
|
412 |
+
* @param string $data element content
|
413 |
+
* @access private
|
414 |
+
*/
|
415 |
+
function character_data($parser, $data){
|
416 |
+
$pos = $this->depth_array[$this->depth];
|
417 |
+
if ($this->xml_encoding=='UTF-8'){
|
418 |
+
// TODO: add an option to disable this for folks who want
|
419 |
+
// raw UTF-8 that, e.g., might not map to iso-8859-1
|
420 |
+
// TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
|
421 |
+
if($this->decode_utf8){
|
422 |
+
$data = utf8_decode($data);
|
423 |
+
}
|
424 |
+
}
|
425 |
+
$this->message[$pos]['cdata'] .= $data;
|
426 |
+
// for doclit
|
427 |
+
if($this->status == 'header'){
|
428 |
+
$this->responseHeaders .= $data;
|
429 |
+
} else {
|
430 |
+
$this->document .= $data;
|
431 |
+
}
|
432 |
+
}
|
433 |
+
|
434 |
+
/**
|
435 |
+
* get the parsed message (SOAP Body)
|
436 |
+
*
|
437 |
+
* @return mixed
|
438 |
+
* @access public
|
439 |
+
* @deprecated use get_soapbody instead
|
440 |
+
*/
|
441 |
+
function get_response(){
|
442 |
+
return $this->soapresponse;
|
443 |
+
}
|
444 |
+
|
445 |
+
/**
|
446 |
+
* get the parsed SOAP Body (NULL if there was none)
|
447 |
+
*
|
448 |
+
* @return mixed
|
449 |
+
* @access public
|
450 |
+
*/
|
451 |
+
function get_soapbody(){
|
452 |
+
return $this->soapresponse;
|
453 |
+
}
|
454 |
+
|
455 |
+
/**
|
456 |
+
* get the parsed SOAP Header (NULL if there was none)
|
457 |
+
*
|
458 |
+
* @return mixed
|
459 |
+
* @access public
|
460 |
+
*/
|
461 |
+
function get_soapheader(){
|
462 |
+
return $this->soapheader;
|
463 |
+
}
|
464 |
+
|
465 |
+
/**
|
466 |
+
* get the unparsed SOAP Header
|
467 |
+
*
|
468 |
+
* @return string XML or empty if no Header
|
469 |
+
* @access public
|
470 |
+
*/
|
471 |
+
function getHeaders(){
|
472 |
+
return $this->responseHeaders;
|
473 |
+
}
|
474 |
+
|
475 |
+
/**
|
476 |
+
* decodes simple types into PHP variables
|
477 |
+
*
|
478 |
+
* @param string $value value to decode
|
479 |
+
* @param string $type XML type to decode
|
480 |
+
* @param string $typens XML type namespace to decode
|
481 |
+
* @return mixed PHP value
|
482 |
+
* @access private
|
483 |
+
*/
|
484 |
+
function decodeSimple($value, $type, $typens) {
|
485 |
+
// TODO: use the namespace!
|
486 |
+
if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {
|
487 |
+
return (string) $value;
|
488 |
+
}
|
489 |
+
if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {
|
490 |
+
return (int) $value;
|
491 |
+
}
|
492 |
+
if ($type == 'float' || $type == 'double' || $type == 'decimal') {
|
493 |
+
return (double) $value;
|
494 |
+
}
|
495 |
+
if ($type == 'boolean') {
|
496 |
+
if (strtolower($value) == 'false' || strtolower($value) == 'f') {
|
497 |
+
return false;
|
498 |
+
}
|
499 |
+
return (boolean) $value;
|
500 |
+
}
|
501 |
+
if ($type == 'base64' || $type == 'base64Binary') {
|
502 |
+
$this->debug('Decode base64 value');
|
503 |
+
return base64_decode($value);
|
504 |
+
}
|
505 |
+
// obscure numeric types
|
506 |
+
if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
|
507 |
+
|| $type == 'nonNegativeInteger' || $type == 'positiveInteger'
|
508 |
+
|| $type == 'unsignedInt'
|
509 |
+
|| $type == 'unsignedShort' || $type == 'unsignedByte') {
|
510 |
+
return (int) $value;
|
511 |
+
}
|
512 |
+
// bogus: parser treats array with no elements as a simple type
|
513 |
+
if ($type == 'array') {
|
514 |
+
return array();
|
515 |
+
}
|
516 |
+
// everything else
|
517 |
+
return (string) $value;
|
518 |
+
}
|
519 |
+
|
520 |
+
/**
|
521 |
+
* builds response structures for compound values (arrays/structs)
|
522 |
+
* and scalars
|
523 |
+
*
|
524 |
+
* @param integer $pos position in node tree
|
525 |
+
* @return mixed PHP value
|
526 |
+
* @access private
|
527 |
+
*/
|
528 |
+
function buildVal($pos){
|
529 |
+
if(!isset($this->message[$pos]['type'])){
|
530 |
+
$this->message[$pos]['type'] = '';
|
531 |
+
}
|
532 |
+
$this->debug('in buildVal() for '.$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]['type']);
|
533 |
+
// if there are children...
|
534 |
+
if($this->message[$pos]['children'] != ''){
|
535 |
+
$this->debug('in buildVal, there are children');
|
536 |
+
$children = explode('|',$this->message[$pos]['children']);
|
537 |
+
array_shift($children); // knock off empty
|
538 |
+
// md array
|
539 |
+
if(isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != ''){
|
540 |
+
$r=0; // rowcount
|
541 |
+
$c=0; // colcount
|
542 |
+
foreach($children as $child_pos){
|
543 |
+
$this->debug("in buildVal, got an MD array element: $r, $c");
|
544 |
+
$params[$r][] = $this->message[$child_pos]['result'];
|
545 |
+
$c++;
|
546 |
+
if($c == $this->message[$pos]['arrayCols']){
|
547 |
+
$c = 0;
|
548 |
+
$r++;
|
549 |
+
}
|
550 |
+
}
|
551 |
+
// array
|
552 |
+
} elseif($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array'){
|
553 |
+
$this->debug('in buildVal, adding array '.$this->message[$pos]['name']);
|
554 |
+
foreach($children as $child_pos){
|
555 |
+
$params[] = &$this->message[$child_pos]['result'];
|
556 |
+
}
|
557 |
+
// apache Map type: java hashtable
|
558 |
+
} elseif($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap'){
|
559 |
+
$this->debug('in buildVal, Java Map '.$this->message[$pos]['name']);
|
560 |
+
foreach($children as $child_pos){
|
561 |
+
$kv = explode("|",$this->message[$child_pos]['children']);
|
562 |
+
$params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];
|
563 |
+
}
|
564 |
+
// generic compound type
|
565 |
+
//} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
|
566 |
+
} else {
|
567 |
+
// Apache Vector type: treat as an array
|
568 |
+
$this->debug('in buildVal, adding Java Vector or generic compound type '.$this->message[$pos]['name']);
|
569 |
+
if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
|
570 |
+
$notstruct = 1;
|
571 |
+
} else {
|
572 |
+
$notstruct = 0;
|
573 |
+
}
|
574 |
+
//
|
575 |
+
foreach($children as $child_pos){
|
576 |
+
if($notstruct){
|
577 |
+
$params[] = &$this->message[$child_pos]['result'];
|
578 |
+
} else {
|
579 |
+
if (isset($params[$this->message[$child_pos]['name']])) {
|
580 |
+
// de-serialize repeated element name into an array
|
581 |
+
if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) {
|
582 |
+
$params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]);
|
583 |
+
}
|
584 |
+
$params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result'];
|
585 |
+
} else {
|
586 |
+
$params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];
|
587 |
+
}
|
588 |
+
}
|
589 |
+
}
|
590 |
+
}
|
591 |
+
if (isset($this->message[$pos]['xattrs'])) {
|
592 |
+
$this->debug('in buildVal, handling attributes');
|
593 |
+
foreach ($this->message[$pos]['xattrs'] as $n => $v) {
|
594 |
+
$params[$n] = $v;
|
595 |
+
}
|
596 |
+
}
|
597 |
+
// handle simpleContent
|
598 |
+
if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
|
599 |
+
$this->debug('in buildVal, handling simpleContent');
|
600 |
+
if (isset($this->message[$pos]['type'])) {
|
601 |
+
$params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
|
602 |
+
} else {
|
603 |
+
$parent = $this->message[$pos]['parent'];
|
604 |
+
if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
|
605 |
+
$params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
|
606 |
+
} else {
|
607 |
+
$params['!'] = $this->message[$pos]['cdata'];
|
608 |
+
}
|
609 |
+
}
|
610 |
+
}
|
611 |
+
$ret = is_array($params) ? $params : array();
|
612 |
+
$this->debug('in buildVal, return:');
|
613 |
+
$this->appendDebug($this->varDump($ret));
|
614 |
+
return $ret;
|
615 |
+
} else {
|
616 |
+
$this->debug('in buildVal, no children, building scalar');
|
617 |
+
$cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : '';
|
618 |
+
if (isset($this->message[$pos]['type'])) {
|
619 |
+
$ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
|
620 |
+
$this->debug("in buildVal, return: $ret");
|
621 |
+
return $ret;
|
622 |
+
}
|
623 |
+
$parent = $this->message[$pos]['parent'];
|
624 |
+
if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
|
625 |
+
$ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
|
626 |
+
$this->debug("in buildVal, return: $ret");
|
627 |
+
return $ret;
|
628 |
+
}
|
629 |
+
$ret = $this->message[$pos]['cdata'];
|
630 |
+
$this->debug("in buildVal, return: $ret");
|
631 |
+
return $ret;
|
632 |
+
}
|
633 |
+
}
|
634 |
+
}
|
635 |
+
|
636 |
+
/**
|
637 |
+
* Backward compatibility
|
638 |
+
*/
|
639 |
+
class soap_parser extends nusoap_parser {
|
640 |
+
}
|
641 |
+
|
642 |
+
|
643 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.soap_server.php
ADDED
@@ -0,0 +1,1127 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
|
4 |
+
|
5 |
+
|
6 |
+
/**
|
7 |
+
*
|
8 |
+
* nusoap_server allows the user to create a SOAP server
|
9 |
+
* that is capable of receiving messages and returning responses
|
10 |
+
*
|
11 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
12 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
13 |
+
* @version $Id: class.soap_server.php,v 1.63 2010/04/26 20:15:08 snichol Exp $
|
14 |
+
* @access public
|
15 |
+
*/
|
16 |
+
class nusoap_server extends nusoap_base {
|
17 |
+
/**
|
18 |
+
* HTTP headers of request
|
19 |
+
* @var array
|
20 |
+
* @access private
|
21 |
+
*/
|
22 |
+
var $headers = array();
|
23 |
+
/**
|
24 |
+
* HTTP request
|
25 |
+
* @var string
|
26 |
+
* @access private
|
27 |
+
*/
|
28 |
+
var $request = '';
|
29 |
+
/**
|
30 |
+
* SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text)
|
31 |
+
* @var string
|
32 |
+
* @access public
|
33 |
+
*/
|
34 |
+
var $requestHeaders = '';
|
35 |
+
/**
|
36 |
+
* SOAP Headers from request (parsed)
|
37 |
+
* @var mixed
|
38 |
+
* @access public
|
39 |
+
*/
|
40 |
+
var $requestHeader = NULL;
|
41 |
+
/**
|
42 |
+
* SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text)
|
43 |
+
* @var string
|
44 |
+
* @access public
|
45 |
+
*/
|
46 |
+
var $document = '';
|
47 |
+
/**
|
48 |
+
* SOAP payload for request (text)
|
49 |
+
* @var string
|
50 |
+
* @access public
|
51 |
+
*/
|
52 |
+
var $requestSOAP = '';
|
53 |
+
/**
|
54 |
+
* requested method namespace URI
|
55 |
+
* @var string
|
56 |
+
* @access private
|
57 |
+
*/
|
58 |
+
var $methodURI = '';
|
59 |
+
/**
|
60 |
+
* name of method requested
|
61 |
+
* @var string
|
62 |
+
* @access private
|
63 |
+
*/
|
64 |
+
var $methodname = '';
|
65 |
+
/**
|
66 |
+
* method parameters from request
|
67 |
+
* @var array
|
68 |
+
* @access private
|
69 |
+
*/
|
70 |
+
var $methodparams = array();
|
71 |
+
/**
|
72 |
+
* SOAP Action from request
|
73 |
+
* @var string
|
74 |
+
* @access private
|
75 |
+
*/
|
76 |
+
var $SOAPAction = '';
|
77 |
+
/**
|
78 |
+
* character set encoding of incoming (request) messages
|
79 |
+
* @var string
|
80 |
+
* @access public
|
81 |
+
*/
|
82 |
+
var $xml_encoding = '';
|
83 |
+
/**
|
84 |
+
* toggles whether the parser decodes element content w/ utf8_decode()
|
85 |
+
* @var boolean
|
86 |
+
* @access public
|
87 |
+
*/
|
88 |
+
var $decode_utf8 = true;
|
89 |
+
|
90 |
+
/**
|
91 |
+
* HTTP headers of response
|
92 |
+
* @var array
|
93 |
+
* @access public
|
94 |
+
*/
|
95 |
+
var $outgoing_headers = array();
|
96 |
+
/**
|
97 |
+
* HTTP response
|
98 |
+
* @var string
|
99 |
+
* @access private
|
100 |
+
*/
|
101 |
+
var $response = '';
|
102 |
+
/**
|
103 |
+
* SOAP headers for response (text or array of soapval or associative array)
|
104 |
+
* @var mixed
|
105 |
+
* @access public
|
106 |
+
*/
|
107 |
+
var $responseHeaders = '';
|
108 |
+
/**
|
109 |
+
* SOAP payload for response (text)
|
110 |
+
* @var string
|
111 |
+
* @access private
|
112 |
+
*/
|
113 |
+
var $responseSOAP = '';
|
114 |
+
/**
|
115 |
+
* method return value to place in response
|
116 |
+
* @var mixed
|
117 |
+
* @access private
|
118 |
+
*/
|
119 |
+
var $methodreturn = false;
|
120 |
+
/**
|
121 |
+
* whether $methodreturn is a string of literal XML
|
122 |
+
* @var boolean
|
123 |
+
* @access public
|
124 |
+
*/
|
125 |
+
var $methodreturnisliteralxml = false;
|
126 |
+
/**
|
127 |
+
* SOAP fault for response (or false)
|
128 |
+
* @var mixed
|
129 |
+
* @access private
|
130 |
+
*/
|
131 |
+
var $fault = false;
|
132 |
+
/**
|
133 |
+
* text indication of result (for debugging)
|
134 |
+
* @var string
|
135 |
+
* @access private
|
136 |
+
*/
|
137 |
+
var $result = 'successful';
|
138 |
+
|
139 |
+
/**
|
140 |
+
* assoc array of operations => opData; operations are added by the register()
|
141 |
+
* method or by parsing an external WSDL definition
|
142 |
+
* @var array
|
143 |
+
* @access private
|
144 |
+
*/
|
145 |
+
var $operations = array();
|
146 |
+
/**
|
147 |
+
* wsdl instance (if one)
|
148 |
+
* @var mixed
|
149 |
+
* @access private
|
150 |
+
*/
|
151 |
+
var $wsdl = false;
|
152 |
+
/**
|
153 |
+
* URL for WSDL (if one)
|
154 |
+
* @var mixed
|
155 |
+
* @access private
|
156 |
+
*/
|
157 |
+
var $externalWSDLURL = false;
|
158 |
+
/**
|
159 |
+
* whether to append debug to response as XML comment
|
160 |
+
* @var boolean
|
161 |
+
* @access public
|
162 |
+
*/
|
163 |
+
var $debug_flag = false;
|
164 |
+
|
165 |
+
|
166 |
+
/**
|
167 |
+
* constructor
|
168 |
+
* the optional parameter is a path to a WSDL file that you'd like to bind the server instance to.
|
169 |
+
*
|
170 |
+
* @param mixed $wsdl file path or URL (string), or wsdl instance (object)
|
171 |
+
* @access public
|
172 |
+
*/
|
173 |
+
function nusoap_server($wsdl=false){
|
174 |
+
parent::nusoap_base();
|
175 |
+
// turn on debugging?
|
176 |
+
global $debug;
|
177 |
+
global $HTTP_SERVER_VARS;
|
178 |
+
|
179 |
+
if (isset($_SERVER)) {
|
180 |
+
$this->debug("_SERVER is defined:");
|
181 |
+
$this->appendDebug($this->varDump($_SERVER));
|
182 |
+
} elseif (isset($HTTP_SERVER_VARS)) {
|
183 |
+
$this->debug("HTTP_SERVER_VARS is defined:");
|
184 |
+
$this->appendDebug($this->varDump($HTTP_SERVER_VARS));
|
185 |
+
} else {
|
186 |
+
$this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
|
187 |
+
}
|
188 |
+
|
189 |
+
if (isset($debug)) {
|
190 |
+
$this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
|
191 |
+
$this->debug_flag = $debug;
|
192 |
+
} elseif (isset($_SERVER['QUERY_STRING'])) {
|
193 |
+
$qs = explode('&', $_SERVER['QUERY_STRING']);
|
194 |
+
foreach ($qs as $v) {
|
195 |
+
if (substr($v, 0, 6) == 'debug=') {
|
196 |
+
$this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
|
197 |
+
$this->debug_flag = substr($v, 6);
|
198 |
+
}
|
199 |
+
}
|
200 |
+
} elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
|
201 |
+
$qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
|
202 |
+
foreach ($qs as $v) {
|
203 |
+
if (substr($v, 0, 6) == 'debug=') {
|
204 |
+
$this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
|
205 |
+
$this->debug_flag = substr($v, 6);
|
206 |
+
}
|
207 |
+
}
|
208 |
+
}
|
209 |
+
|
210 |
+
// wsdl
|
211 |
+
if($wsdl){
|
212 |
+
$this->debug("In nusoap_server, WSDL is specified");
|
213 |
+
if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
|
214 |
+
$this->wsdl = $wsdl;
|
215 |
+
$this->externalWSDLURL = $this->wsdl->wsdl;
|
216 |
+
$this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
|
217 |
+
} else {
|
218 |
+
$this->debug('Create wsdl from ' . $wsdl);
|
219 |
+
$this->wsdl = new wsdl($wsdl);
|
220 |
+
$this->externalWSDLURL = $wsdl;
|
221 |
+
}
|
222 |
+
$this->appendDebug($this->wsdl->getDebug());
|
223 |
+
$this->wsdl->clearDebug();
|
224 |
+
if($err = $this->wsdl->getError()){
|
225 |
+
die('WSDL ERROR: '.$err);
|
226 |
+
}
|
227 |
+
}
|
228 |
+
}
|
229 |
+
|
230 |
+
/**
|
231 |
+
* processes request and returns response
|
232 |
+
*
|
233 |
+
* @param string $data usually is the value of $HTTP_RAW_POST_DATA
|
234 |
+
* @access public
|
235 |
+
*/
|
236 |
+
function service($data){
|
237 |
+
global $HTTP_SERVER_VARS;
|
238 |
+
|
239 |
+
if (isset($_SERVER['REQUEST_METHOD'])) {
|
240 |
+
$rm = $_SERVER['REQUEST_METHOD'];
|
241 |
+
} elseif (isset($HTTP_SERVER_VARS['REQUEST_METHOD'])) {
|
242 |
+
$rm = $HTTP_SERVER_VARS['REQUEST_METHOD'];
|
243 |
+
} else {
|
244 |
+
$rm = '';
|
245 |
+
}
|
246 |
+
|
247 |
+
if (isset($_SERVER['QUERY_STRING'])) {
|
248 |
+
$qs = $_SERVER['QUERY_STRING'];
|
249 |
+
} elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
|
250 |
+
$qs = $HTTP_SERVER_VARS['QUERY_STRING'];
|
251 |
+
} else {
|
252 |
+
$qs = '';
|
253 |
+
}
|
254 |
+
$this->debug("In service, request method=$rm query string=$qs strlen(\$data)=" . strlen($data));
|
255 |
+
|
256 |
+
if ($rm == 'POST') {
|
257 |
+
$this->debug("In service, invoke the request");
|
258 |
+
$this->parse_request($data);
|
259 |
+
if (! $this->fault) {
|
260 |
+
$this->invoke_method();
|
261 |
+
}
|
262 |
+
if (! $this->fault) {
|
263 |
+
$this->serialize_return();
|
264 |
+
}
|
265 |
+
$this->send_response();
|
266 |
+
} elseif (preg_match('/wsdl/', $qs) ){
|
267 |
+
$this->debug("In service, this is a request for WSDL");
|
268 |
+
if ($this->externalWSDLURL){
|
269 |
+
if (strpos($this->externalWSDLURL, "http://") !== false) { // assume URL
|
270 |
+
$this->debug("In service, re-direct for WSDL");
|
271 |
+
header('Location: '.$this->externalWSDLURL);
|
272 |
+
} else { // assume file
|
273 |
+
$this->debug("In service, use file passthru for WSDL");
|
274 |
+
header("Content-Type: text/xml\r\n");
|
275 |
+
$pos = strpos($this->externalWSDLURL, "file://");
|
276 |
+
if ($pos === false) {
|
277 |
+
$filename = $this->externalWSDLURL;
|
278 |
+
} else {
|
279 |
+
$filename = substr($this->externalWSDLURL, $pos + 7);
|
280 |
+
}
|
281 |
+
$fp = fopen($this->externalWSDLURL, 'r');
|
282 |
+
fpassthru($fp);
|
283 |
+
}
|
284 |
+
} elseif ($this->wsdl) {
|
285 |
+
$this->debug("In service, serialize WSDL");
|
286 |
+
header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
|
287 |
+
print $this->wsdl->serialize($this->debug_flag);
|
288 |
+
if ($this->debug_flag) {
|
289 |
+
$this->debug('wsdl:');
|
290 |
+
$this->appendDebug($this->varDump($this->wsdl));
|
291 |
+
print $this->getDebugAsXMLComment();
|
292 |
+
}
|
293 |
+
} else {
|
294 |
+
$this->debug("In service, there is no WSDL");
|
295 |
+
header("Content-Type: text/html; charset=ISO-8859-1\r\n");
|
296 |
+
print "This service does not provide WSDL";
|
297 |
+
}
|
298 |
+
} elseif ($this->wsdl) {
|
299 |
+
$this->debug("In service, return Web description");
|
300 |
+
print $this->wsdl->webDescription();
|
301 |
+
} else {
|
302 |
+
$this->debug("In service, no Web description");
|
303 |
+
header("Content-Type: text/html; charset=ISO-8859-1\r\n");
|
304 |
+
print "This service does not provide a Web description";
|
305 |
+
}
|
306 |
+
}
|
307 |
+
|
308 |
+
/**
|
309 |
+
* parses HTTP request headers.
|
310 |
+
*
|
311 |
+
* The following fields are set by this function (when successful)
|
312 |
+
*
|
313 |
+
* headers
|
314 |
+
* request
|
315 |
+
* xml_encoding
|
316 |
+
* SOAPAction
|
317 |
+
*
|
318 |
+
* @access private
|
319 |
+
*/
|
320 |
+
function parse_http_headers() {
|
321 |
+
global $HTTP_SERVER_VARS;
|
322 |
+
|
323 |
+
$this->request = '';
|
324 |
+
$this->SOAPAction = '';
|
325 |
+
if(function_exists('getallheaders')){
|
326 |
+
$this->debug("In parse_http_headers, use getallheaders");
|
327 |
+
$headers = getallheaders();
|
328 |
+
foreach($headers as $k=>$v){
|
329 |
+
$k = strtolower($k);
|
330 |
+
$this->headers[$k] = $v;
|
331 |
+
$this->request .= "$k: $v\r\n";
|
332 |
+
$this->debug("$k: $v");
|
333 |
+
}
|
334 |
+
// get SOAPAction header
|
335 |
+
if(isset($this->headers['soapaction'])){
|
336 |
+
$this->SOAPAction = str_replace('"','',$this->headers['soapaction']);
|
337 |
+
}
|
338 |
+
// get the character encoding of the incoming request
|
339 |
+
if(isset($this->headers['content-type']) && strpos($this->headers['content-type'],'=')){
|
340 |
+
$enc = str_replace('"','',substr(strstr($this->headers["content-type"],'='),1));
|
341 |
+
if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
|
342 |
+
$this->xml_encoding = strtoupper($enc);
|
343 |
+
} else {
|
344 |
+
$this->xml_encoding = 'US-ASCII';
|
345 |
+
}
|
346 |
+
} else {
|
347 |
+
// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
|
348 |
+
$this->xml_encoding = 'ISO-8859-1';
|
349 |
+
}
|
350 |
+
} elseif(isset($_SERVER) && is_array($_SERVER)){
|
351 |
+
$this->debug("In parse_http_headers, use _SERVER");
|
352 |
+
foreach ($_SERVER as $k => $v) {
|
353 |
+
if (substr($k, 0, 5) == 'HTTP_') {
|
354 |
+
$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
|
355 |
+
} else {
|
356 |
+
$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
|
357 |
+
}
|
358 |
+
if ($k == 'soapaction') {
|
359 |
+
// get SOAPAction header
|
360 |
+
$k = 'SOAPAction';
|
361 |
+
$v = str_replace('"', '', $v);
|
362 |
+
$v = str_replace('\\', '', $v);
|
363 |
+
$this->SOAPAction = $v;
|
364 |
+
} else if ($k == 'content-type') {
|
365 |
+
// get the character encoding of the incoming request
|
366 |
+
if (strpos($v, '=')) {
|
367 |
+
$enc = substr(strstr($v, '='), 1);
|
368 |
+
$enc = str_replace('"', '', $enc);
|
369 |
+
$enc = str_replace('\\', '', $enc);
|
370 |
+
if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
|
371 |
+
$this->xml_encoding = strtoupper($enc);
|
372 |
+
} else {
|
373 |
+
$this->xml_encoding = 'US-ASCII';
|
374 |
+
}
|
375 |
+
} else {
|
376 |
+
// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
|
377 |
+
$this->xml_encoding = 'ISO-8859-1';
|
378 |
+
}
|
379 |
+
}
|
380 |
+
$this->headers[$k] = $v;
|
381 |
+
$this->request .= "$k: $v\r\n";
|
382 |
+
$this->debug("$k: $v");
|
383 |
+
}
|
384 |
+
} elseif (is_array($HTTP_SERVER_VARS)) {
|
385 |
+
$this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
|
386 |
+
foreach ($HTTP_SERVER_VARS as $k => $v) {
|
387 |
+
if (substr($k, 0, 5) == 'HTTP_') {
|
388 |
+
$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); $k = strtolower(substr($k, 5));
|
389 |
+
} else {
|
390 |
+
$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); $k = strtolower($k);
|
391 |
+
}
|
392 |
+
if ($k == 'soapaction') {
|
393 |
+
// get SOAPAction header
|
394 |
+
$k = 'SOAPAction';
|
395 |
+
$v = str_replace('"', '', $v);
|
396 |
+
$v = str_replace('\\', '', $v);
|
397 |
+
$this->SOAPAction = $v;
|
398 |
+
} else if ($k == 'content-type') {
|
399 |
+
// get the character encoding of the incoming request
|
400 |
+
if (strpos($v, '=')) {
|
401 |
+
$enc = substr(strstr($v, '='), 1);
|
402 |
+
$enc = str_replace('"', '', $enc);
|
403 |
+
$enc = str_replace('\\', '', $enc);
|
404 |
+
if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
|
405 |
+
$this->xml_encoding = strtoupper($enc);
|
406 |
+
} else {
|
407 |
+
$this->xml_encoding = 'US-ASCII';
|
408 |
+
}
|
409 |
+
} else {
|
410 |
+
// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
|
411 |
+
$this->xml_encoding = 'ISO-8859-1';
|
412 |
+
}
|
413 |
+
}
|
414 |
+
$this->headers[$k] = $v;
|
415 |
+
$this->request .= "$k: $v\r\n";
|
416 |
+
$this->debug("$k: $v");
|
417 |
+
}
|
418 |
+
} else {
|
419 |
+
$this->debug("In parse_http_headers, HTTP headers not accessible");
|
420 |
+
$this->setError("HTTP headers not accessible");
|
421 |
+
}
|
422 |
+
}
|
423 |
+
|
424 |
+
/**
|
425 |
+
* parses a request
|
426 |
+
*
|
427 |
+
* The following fields are set by this function (when successful)
|
428 |
+
*
|
429 |
+
* headers
|
430 |
+
* request
|
431 |
+
* xml_encoding
|
432 |
+
* SOAPAction
|
433 |
+
* request
|
434 |
+
* requestSOAP
|
435 |
+
* methodURI
|
436 |
+
* methodname
|
437 |
+
* methodparams
|
438 |
+
* requestHeaders
|
439 |
+
* document
|
440 |
+
*
|
441 |
+
* This sets the fault field on error
|
442 |
+
*
|
443 |
+
* @param string $data XML string
|
444 |
+
* @access private
|
445 |
+
*/
|
446 |
+
function parse_request($data='') {
|
447 |
+
$this->debug('entering parse_request()');
|
448 |
+
$this->parse_http_headers();
|
449 |
+
$this->debug('got character encoding: '.$this->xml_encoding);
|
450 |
+
// uncompress if necessary
|
451 |
+
if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
|
452 |
+
$this->debug('got content encoding: ' . $this->headers['content-encoding']);
|
453 |
+
if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
|
454 |
+
// if decoding works, use it. else assume data wasn't gzencoded
|
455 |
+
if (function_exists('gzuncompress')) {
|
456 |
+
if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
|
457 |
+
$data = $degzdata;
|
458 |
+
} elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
|
459 |
+
$data = $degzdata;
|
460 |
+
} else {
|
461 |
+
$this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
|
462 |
+
return;
|
463 |
+
}
|
464 |
+
} else {
|
465 |
+
$this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
|
466 |
+
return;
|
467 |
+
}
|
468 |
+
}
|
469 |
+
}
|
470 |
+
$this->request .= "\r\n".$data;
|
471 |
+
$data = $this->parseRequest($this->headers, $data);
|
472 |
+
$this->requestSOAP = $data;
|
473 |
+
$this->debug('leaving parse_request');
|
474 |
+
}
|
475 |
+
|
476 |
+
/**
|
477 |
+
* invokes a PHP function for the requested SOAP method
|
478 |
+
*
|
479 |
+
* The following fields are set by this function (when successful)
|
480 |
+
*
|
481 |
+
* methodreturn
|
482 |
+
*
|
483 |
+
* Note that the PHP function that is called may also set the following
|
484 |
+
* fields to affect the response sent to the client
|
485 |
+
*
|
486 |
+
* responseHeaders
|
487 |
+
* outgoing_headers
|
488 |
+
*
|
489 |
+
* This sets the fault field on error
|
490 |
+
*
|
491 |
+
* @access private
|
492 |
+
*/
|
493 |
+
function invoke_method() {
|
494 |
+
$this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
|
495 |
+
|
496 |
+
//
|
497 |
+
// if you are debugging in this area of the code, your service uses a class to implement methods,
|
498 |
+
// you use SOAP RPC, and the client is .NET, please be aware of the following...
|
499 |
+
// when the .NET wsdl.exe utility generates a proxy, it will remove the '.' or '..' from the
|
500 |
+
// method name. that is fine for naming the .NET methods. it is not fine for properly constructing
|
501 |
+
// the XML request and reading the XML response. you need to add the RequestElementName and
|
502 |
+
// ResponseElementName to the System.Web.Services.Protocols.SoapRpcMethodAttribute that wsdl.exe
|
503 |
+
// generates for the method. these parameters are used to specify the correct XML element names
|
504 |
+
// for .NET to use, i.e. the names with the '.' in them.
|
505 |
+
//
|
506 |
+
$orig_methodname = $this->methodname;
|
507 |
+
if ($this->wsdl) {
|
508 |
+
if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
|
509 |
+
$this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
|
510 |
+
$this->appendDebug('opData=' . $this->varDump($this->opData));
|
511 |
+
} elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
|
512 |
+
// Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
|
513 |
+
$this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
|
514 |
+
$this->appendDebug('opData=' . $this->varDump($this->opData));
|
515 |
+
$this->methodname = $this->opData['name'];
|
516 |
+
} else {
|
517 |
+
$this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
|
518 |
+
$this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
|
519 |
+
return;
|
520 |
+
}
|
521 |
+
} else {
|
522 |
+
$this->debug('in invoke_method, no WSDL to validate method');
|
523 |
+
}
|
524 |
+
|
525 |
+
// if a . is present in $this->methodname, we see if there is a class in scope,
|
526 |
+
// which could be referred to. We will also distinguish between two deliminators,
|
527 |
+
// to allow methods to be called a the class or an instance
|
528 |
+
if (strpos($this->methodname, '..') > 0) {
|
529 |
+
$delim = '..';
|
530 |
+
} else if (strpos($this->methodname, '.') > 0) {
|
531 |
+
$delim = '.';
|
532 |
+
} else {
|
533 |
+
$delim = '';
|
534 |
+
}
|
535 |
+
$this->debug("in invoke_method, delim=$delim");
|
536 |
+
|
537 |
+
$class = '';
|
538 |
+
$method = '';
|
539 |
+
if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1) {
|
540 |
+
$try_class = substr($this->methodname, 0, strpos($this->methodname, $delim));
|
541 |
+
if (class_exists($try_class)) {
|
542 |
+
// get the class and method name
|
543 |
+
$class = $try_class;
|
544 |
+
$method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
|
545 |
+
$this->debug("in invoke_method, class=$class method=$method delim=$delim");
|
546 |
+
} else {
|
547 |
+
$this->debug("in invoke_method, class=$try_class not found");
|
548 |
+
}
|
549 |
+
} else {
|
550 |
+
$try_class = '';
|
551 |
+
$this->debug("in invoke_method, no class to try");
|
552 |
+
}
|
553 |
+
|
554 |
+
// does method exist?
|
555 |
+
if ($class == '') {
|
556 |
+
if (!function_exists($this->methodname)) {
|
557 |
+
$this->debug("in invoke_method, function '$this->methodname' not found!");
|
558 |
+
$this->result = 'fault: method not found';
|
559 |
+
$this->fault('SOAP-ENV:Client',"method '$this->methodname'('$orig_methodname') not defined in service('$try_class' '$delim')");
|
560 |
+
return;
|
561 |
+
}
|
562 |
+
} else {
|
563 |
+
$method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
|
564 |
+
if (!in_array($method_to_compare, get_class_methods($class))) {
|
565 |
+
$this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
|
566 |
+
$this->result = 'fault: method not found';
|
567 |
+
$this->fault('SOAP-ENV:Client',"method '$this->methodname'/'$method_to_compare'('$orig_methodname') not defined in service/'$class'('$try_class' '$delim')");
|
568 |
+
return;
|
569 |
+
}
|
570 |
+
}
|
571 |
+
|
572 |
+
// evaluate message, getting back parameters
|
573 |
+
// verify that request parameters match the method's signature
|
574 |
+
if(! $this->verify_method($this->methodname,$this->methodparams)){
|
575 |
+
// debug
|
576 |
+
$this->debug('ERROR: request not verified against method signature');
|
577 |
+
$this->result = 'fault: request failed validation against method signature';
|
578 |
+
// return fault
|
579 |
+
$this->fault('SOAP-ENV:Client',"Operation '$this->methodname' not defined in service.");
|
580 |
+
return;
|
581 |
+
}
|
582 |
+
|
583 |
+
// if there are parameters to pass
|
584 |
+
$this->debug('in invoke_method, params:');
|
585 |
+
$this->appendDebug($this->varDump($this->methodparams));
|
586 |
+
$this->debug("in invoke_method, calling '$this->methodname'");
|
587 |
+
if (!function_exists('call_user_func_array')) {
|
588 |
+
if ($class == '') {
|
589 |
+
$this->debug('in invoke_method, calling function using eval()');
|
590 |
+
$funcCall = "\$this->methodreturn = $this->methodname(";
|
591 |
+
} else {
|
592 |
+
if ($delim == '..') {
|
593 |
+
$this->debug('in invoke_method, calling class method using eval()');
|
594 |
+
$funcCall = "\$this->methodreturn = ".$class."::".$method."(";
|
595 |
+
} else {
|
596 |
+
$this->debug('in invoke_method, calling instance method using eval()');
|
597 |
+
// generate unique instance name
|
598 |
+
$instname = "\$inst_".time();
|
599 |
+
$funcCall = $instname." = new ".$class."(); ";
|
600 |
+
$funcCall .= "\$this->methodreturn = ".$instname."->".$method."(";
|
601 |
+
}
|
602 |
+
}
|
603 |
+
if ($this->methodparams) {
|
604 |
+
foreach ($this->methodparams as $param) {
|
605 |
+
if (is_array($param) || is_object($param)) {
|
606 |
+
$this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
|
607 |
+
return;
|
608 |
+
}
|
609 |
+
$funcCall .= "\"$param\",";
|
610 |
+
}
|
611 |
+
$funcCall = substr($funcCall, 0, -1);
|
612 |
+
}
|
613 |
+
$funcCall .= ');';
|
614 |
+
$this->debug('in invoke_method, function call: '.$funcCall);
|
615 |
+
@eval($funcCall);
|
616 |
+
} else {
|
617 |
+
if ($class == '') {
|
618 |
+
$this->debug('in invoke_method, calling function using call_user_func_array()');
|
619 |
+
$call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array()
|
620 |
+
} elseif ($delim == '..') {
|
621 |
+
$this->debug('in invoke_method, calling class method using call_user_func_array()');
|
622 |
+
$call_arg = array ($class, $method);
|
623 |
+
} else {
|
624 |
+
$this->debug('in invoke_method, calling instance method using call_user_func_array()');
|
625 |
+
$instance = new $class ();
|
626 |
+
$call_arg = array(&$instance, $method);
|
627 |
+
}
|
628 |
+
if (is_array($this->methodparams)) {
|
629 |
+
$this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
|
630 |
+
} else {
|
631 |
+
$this->methodreturn = call_user_func_array($call_arg, array());
|
632 |
+
}
|
633 |
+
}
|
634 |
+
$this->debug('in invoke_method, methodreturn:');
|
635 |
+
$this->appendDebug($this->varDump($this->methodreturn));
|
636 |
+
$this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn));
|
637 |
+
}
|
638 |
+
|
639 |
+
/**
|
640 |
+
* serializes the return value from a PHP function into a full SOAP Envelope
|
641 |
+
*
|
642 |
+
* The following fields are set by this function (when successful)
|
643 |
+
*
|
644 |
+
* responseSOAP
|
645 |
+
*
|
646 |
+
* This sets the fault field on error
|
647 |
+
*
|
648 |
+
* @access private
|
649 |
+
*/
|
650 |
+
function serialize_return() {
|
651 |
+
$this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
|
652 |
+
// if fault
|
653 |
+
if (isset($this->methodreturn) && is_object($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) {
|
654 |
+
$this->debug('got a fault object from method');
|
655 |
+
$this->fault = $this->methodreturn;
|
656 |
+
return;
|
657 |
+
} elseif ($this->methodreturnisliteralxml) {
|
658 |
+
$return_val = $this->methodreturn;
|
659 |
+
// returned value(s)
|
660 |
+
} else {
|
661 |
+
$this->debug('got a(n) '.gettype($this->methodreturn).' from method');
|
662 |
+
$this->debug('serializing return value');
|
663 |
+
if($this->wsdl){
|
664 |
+
if (sizeof($this->opData['output']['parts']) > 1) {
|
665 |
+
$this->debug('more than one output part, so use the method return unchanged');
|
666 |
+
$opParams = $this->methodreturn;
|
667 |
+
} elseif (sizeof($this->opData['output']['parts']) == 1) {
|
668 |
+
$this->debug('exactly one output part, so wrap the method return in a simple array');
|
669 |
+
// TODO: verify that it is not already wrapped!
|
670 |
+
//foreach ($this->opData['output']['parts'] as $name => $type) {
|
671 |
+
// $this->debug('wrap in element named ' . $name);
|
672 |
+
//}
|
673 |
+
$opParams = array($this->methodreturn);
|
674 |
+
}
|
675 |
+
$return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams);
|
676 |
+
$this->appendDebug($this->wsdl->getDebug());
|
677 |
+
$this->wsdl->clearDebug();
|
678 |
+
if($errstr = $this->wsdl->getError()){
|
679 |
+
$this->debug('got wsdl error: '.$errstr);
|
680 |
+
$this->fault('SOAP-ENV:Server', 'unable to serialize result');
|
681 |
+
return;
|
682 |
+
}
|
683 |
+
} else {
|
684 |
+
if (isset($this->methodreturn)) {
|
685 |
+
$return_val = $this->serialize_val($this->methodreturn, 'return');
|
686 |
+
} else {
|
687 |
+
$return_val = '';
|
688 |
+
$this->debug('in absence of WSDL, assume void return for backward compatibility');
|
689 |
+
}
|
690 |
+
}
|
691 |
+
}
|
692 |
+
$this->debug('return value:');
|
693 |
+
$this->appendDebug($this->varDump($return_val));
|
694 |
+
|
695 |
+
$this->debug('serializing response');
|
696 |
+
if ($this->wsdl) {
|
697 |
+
$this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
|
698 |
+
if ($this->opData['style'] == 'rpc') {
|
699 |
+
$this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
|
700 |
+
if ($this->opData['output']['use'] == 'literal') {
|
701 |
+
// 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
|
702 |
+
if ($this->methodURI) {
|
703 |
+
$payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
|
704 |
+
} else {
|
705 |
+
$payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
|
706 |
+
}
|
707 |
+
} else {
|
708 |
+
if ($this->methodURI) {
|
709 |
+
$payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
|
710 |
+
} else {
|
711 |
+
$payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
|
712 |
+
}
|
713 |
+
}
|
714 |
+
} else {
|
715 |
+
$this->debug('style is not rpc for serialization: assume document');
|
716 |
+
$payload = $return_val;
|
717 |
+
}
|
718 |
+
} else {
|
719 |
+
$this->debug('do not have WSDL for serialization: assume rpc/encoded');
|
720 |
+
$payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
|
721 |
+
}
|
722 |
+
$this->result = 'successful';
|
723 |
+
if($this->wsdl){
|
724 |
+
//if($this->debug_flag){
|
725 |
+
$this->appendDebug($this->wsdl->getDebug());
|
726 |
+
// }
|
727 |
+
if (isset($this->opData['output']['encodingStyle'])) {
|
728 |
+
$encodingStyle = $this->opData['output']['encodingStyle'];
|
729 |
+
} else {
|
730 |
+
$encodingStyle = '';
|
731 |
+
}
|
732 |
+
// Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
|
733 |
+
$this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$this->opData['output']['use'],$encodingStyle);
|
734 |
+
} else {
|
735 |
+
$this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders);
|
736 |
+
}
|
737 |
+
$this->debug("Leaving serialize_return");
|
738 |
+
}
|
739 |
+
|
740 |
+
/**
|
741 |
+
* sends an HTTP response
|
742 |
+
*
|
743 |
+
* The following fields are set by this function (when successful)
|
744 |
+
*
|
745 |
+
* outgoing_headers
|
746 |
+
* response
|
747 |
+
*
|
748 |
+
* @access private
|
749 |
+
*/
|
750 |
+
function send_response() {
|
751 |
+
$this->debug('Enter send_response');
|
752 |
+
if ($this->fault) {
|
753 |
+
$payload = $this->fault->serialize();
|
754 |
+
$this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
|
755 |
+
$this->outgoing_headers[] = "Status: 500 Internal Server Error";
|
756 |
+
} else {
|
757 |
+
$payload = $this->responseSOAP;
|
758 |
+
// Some combinations of PHP+Web server allow the Status
|
759 |
+
// to come through as a header. Since OK is the default
|
760 |
+
// just do nothing.
|
761 |
+
// $this->outgoing_headers[] = "HTTP/1.0 200 OK";
|
762 |
+
// $this->outgoing_headers[] = "Status: 200 OK";
|
763 |
+
}
|
764 |
+
// add debug data if in debug mode
|
765 |
+
if(isset($this->debug_flag) && $this->debug_flag){
|
766 |
+
$payload .= $this->getDebugAsXMLComment();
|
767 |
+
}
|
768 |
+
$this->outgoing_headers[] = "Server: $this->title Server v$this->version";
|
769 |
+
preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
|
770 |
+
$this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")";
|
771 |
+
// Let the Web server decide about this
|
772 |
+
//$this->outgoing_headers[] = "Connection: Close\r\n";
|
773 |
+
$payload = $this->getHTTPBody($payload);
|
774 |
+
$type = $this->getHTTPContentType();
|
775 |
+
$charset = $this->getHTTPContentTypeCharset();
|
776 |
+
$this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
|
777 |
+
//begin code to compress payload - by John
|
778 |
+
// NOTE: there is no way to know whether the Web server will also compress
|
779 |
+
// this data.
|
780 |
+
if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {
|
781 |
+
if (strstr($this->headers['accept-encoding'], 'gzip')) {
|
782 |
+
if (function_exists('gzencode')) {
|
783 |
+
if (isset($this->debug_flag) && $this->debug_flag) {
|
784 |
+
$payload .= "<!-- Content being gzipped -->";
|
785 |
+
}
|
786 |
+
$this->outgoing_headers[] = "Content-Encoding: gzip";
|
787 |
+
$payload = gzencode($payload);
|
788 |
+
} else {
|
789 |
+
if (isset($this->debug_flag) && $this->debug_flag) {
|
790 |
+
$payload .= "<!-- Content will not be gzipped: no gzencode -->";
|
791 |
+
}
|
792 |
+
}
|
793 |
+
} elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
|
794 |
+
// Note: MSIE requires gzdeflate output (no Zlib header and checksum),
|
795 |
+
// instead of gzcompress output,
|
796 |
+
// which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
|
797 |
+
if (function_exists('gzdeflate')) {
|
798 |
+
if (isset($this->debug_flag) && $this->debug_flag) {
|
799 |
+
$payload .= "<!-- Content being deflated -->";
|
800 |
+
}
|
801 |
+
$this->outgoing_headers[] = "Content-Encoding: deflate";
|
802 |
+
$payload = gzdeflate($payload);
|
803 |
+
} else {
|
804 |
+
if (isset($this->debug_flag) && $this->debug_flag) {
|
805 |
+
$payload .= "<!-- Content will not be deflated: no gzcompress -->";
|
806 |
+
}
|
807 |
+
}
|
808 |
+
}
|
809 |
+
}
|
810 |
+
//end code
|
811 |
+
$this->outgoing_headers[] = "Content-Length: ".strlen($payload);
|
812 |
+
reset($this->outgoing_headers);
|
813 |
+
foreach($this->outgoing_headers as $hdr){
|
814 |
+
header($hdr, false);
|
815 |
+
}
|
816 |
+
print $payload;
|
817 |
+
$this->response = join("\r\n",$this->outgoing_headers)."\r\n\r\n".$payload;
|
818 |
+
}
|
819 |
+
|
820 |
+
/**
|
821 |
+
* takes the value that was created by parsing the request
|
822 |
+
* and compares to the method's signature, if available.
|
823 |
+
*
|
824 |
+
* @param string $operation The operation to be invoked
|
825 |
+
* @param array $request The array of parameter values
|
826 |
+
* @return boolean Whether the operation was found
|
827 |
+
* @access private
|
828 |
+
*/
|
829 |
+
function verify_method($operation,$request){
|
830 |
+
if(isset($this->wsdl) && is_object($this->wsdl)){
|
831 |
+
if($this->wsdl->getOperationData($operation)){
|
832 |
+
return true;
|
833 |
+
}
|
834 |
+
} elseif(isset($this->operations[$operation])){
|
835 |
+
return true;
|
836 |
+
}
|
837 |
+
return false;
|
838 |
+
}
|
839 |
+
|
840 |
+
/**
|
841 |
+
* processes SOAP message received from client
|
842 |
+
*
|
843 |
+
* @param array $headers The HTTP headers
|
844 |
+
* @param string $data unprocessed request data from client
|
845 |
+
* @return mixed value of the message, decoded into a PHP type
|
846 |
+
* @access private
|
847 |
+
*/
|
848 |
+
function parseRequest($headers, $data) {
|
849 |
+
$this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' headers:');
|
850 |
+
$this->appendDebug($this->varDump($headers));
|
851 |
+
if (!isset($headers['content-type'])) {
|
852 |
+
$this->setError('Request not of type text/xml (no content-type header)');
|
853 |
+
return false;
|
854 |
+
}
|
855 |
+
if (!strstr($headers['content-type'], 'text/xml')) {
|
856 |
+
$this->setError('Request not of type text/xml');
|
857 |
+
return false;
|
858 |
+
}
|
859 |
+
if (strpos($headers['content-type'], '=')) {
|
860 |
+
$enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
|
861 |
+
$this->debug('Got response encoding: ' . $enc);
|
862 |
+
if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
|
863 |
+
$this->xml_encoding = strtoupper($enc);
|
864 |
+
} else {
|
865 |
+
$this->xml_encoding = 'US-ASCII';
|
866 |
+
}
|
867 |
+
} else {
|
868 |
+
// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
|
869 |
+
$this->xml_encoding = 'ISO-8859-1';
|
870 |
+
}
|
871 |
+
$this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
|
872 |
+
// parse response, get soap parser obj
|
873 |
+
$parser = new nusoap_parser($data,$this->xml_encoding,'',$this->decode_utf8);
|
874 |
+
// parser debug
|
875 |
+
$this->debug("parser debug: \n".$parser->getDebug());
|
876 |
+
// if fault occurred during message parsing
|
877 |
+
if($err = $parser->getError()){
|
878 |
+
$this->result = 'fault: error in msg parsing: '.$err;
|
879 |
+
$this->fault('SOAP-ENV:Client',"error in msg parsing:\n".$err);
|
880 |
+
// else successfully parsed request into soapval object
|
881 |
+
} else {
|
882 |
+
// get/set methodname
|
883 |
+
$this->methodURI = $parser->root_struct_namespace;
|
884 |
+
$this->methodname = $parser->root_struct_name;
|
885 |
+
$this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI);
|
886 |
+
$this->debug('calling parser->get_soapbody()');
|
887 |
+
$this->methodparams = $parser->get_soapbody();
|
888 |
+
// get SOAP headers
|
889 |
+
$this->requestHeaders = $parser->getHeaders();
|
890 |
+
// get SOAP Header
|
891 |
+
$this->requestHeader = $parser->get_soapheader();
|
892 |
+
// add document for doclit support
|
893 |
+
$this->document = $parser->document;
|
894 |
+
}
|
895 |
+
}
|
896 |
+
|
897 |
+
/**
|
898 |
+
* gets the HTTP body for the current response.
|
899 |
+
*
|
900 |
+
* @param string $soapmsg The SOAP payload
|
901 |
+
* @return string The HTTP body, which includes the SOAP payload
|
902 |
+
* @access private
|
903 |
+
*/
|
904 |
+
function getHTTPBody($soapmsg) {
|
905 |
+
return $soapmsg;
|
906 |
+
}
|
907 |
+
|
908 |
+
/**
|
909 |
+
* gets the HTTP content type for the current response.
|
910 |
+
*
|
911 |
+
* Note: getHTTPBody must be called before this.
|
912 |
+
*
|
913 |
+
* @return string the HTTP content type for the current response.
|
914 |
+
* @access private
|
915 |
+
*/
|
916 |
+
function getHTTPContentType() {
|
917 |
+
return 'text/xml';
|
918 |
+
}
|
919 |
+
|
920 |
+
/**
|
921 |
+
* gets the HTTP content type charset for the current response.
|
922 |
+
* returns false for non-text content types.
|
923 |
+
*
|
924 |
+
* Note: getHTTPBody must be called before this.
|
925 |
+
*
|
926 |
+
* @return string the HTTP content type charset for the current response.
|
927 |
+
* @access private
|
928 |
+
*/
|
929 |
+
function getHTTPContentTypeCharset() {
|
930 |
+
return $this->soap_defencoding;
|
931 |
+
}
|
932 |
+
|
933 |
+
/**
|
934 |
+
* add a method to the dispatch map (this has been replaced by the register method)
|
935 |
+
*
|
936 |
+
* @param string $methodname
|
937 |
+
* @param string $in array of input values
|
938 |
+
* @param string $out array of output values
|
939 |
+
* @access public
|
940 |
+
* @deprecated
|
941 |
+
*/
|
942 |
+
function add_to_map($methodname,$in,$out){
|
943 |
+
$this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
|
944 |
+
}
|
945 |
+
|
946 |
+
/**
|
947 |
+
* register a service function with the server
|
948 |
+
*
|
949 |
+
* @param string $name the name of the PHP function, class.method or class..method
|
950 |
+
* @param array $in assoc array of input values: key = param name, value = param type
|
951 |
+
* @param array $out assoc array of output values: key = param name, value = param type
|
952 |
+
* @param mixed $namespace the element namespace for the method or false
|
953 |
+
* @param mixed $soapaction the soapaction for the method or false
|
954 |
+
* @param mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically
|
955 |
+
* @param mixed $use optional (encoded|literal) or false
|
956 |
+
* @param string $documentation optional Description to include in WSDL
|
957 |
+
* @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
|
958 |
+
* @access public
|
959 |
+
*/
|
960 |
+
function register($name,$in=array(),$out=array(),$namespace=false,$soapaction=false,$style=false,$use=false,$documentation='',$encodingStyle=''){
|
961 |
+
global $HTTP_SERVER_VARS;
|
962 |
+
|
963 |
+
if($this->externalWSDLURL){
|
964 |
+
die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
|
965 |
+
}
|
966 |
+
if (! $name) {
|
967 |
+
die('You must specify a name when you register an operation');
|
968 |
+
}
|
969 |
+
if (!is_array($in)) {
|
970 |
+
die('You must provide an array for operation inputs');
|
971 |
+
}
|
972 |
+
if (!is_array($out)) {
|
973 |
+
die('You must provide an array for operation outputs');
|
974 |
+
}
|
975 |
+
if(false == $namespace) {
|
976 |
+
}
|
977 |
+
if(false == $soapaction) {
|
978 |
+
if (isset($_SERVER)) {
|
979 |
+
$SERVER_NAME = $_SERVER['SERVER_NAME'];
|
980 |
+
$SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
|
981 |
+
$HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
|
982 |
+
} elseif (isset($HTTP_SERVER_VARS)) {
|
983 |
+
$SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
|
984 |
+
$SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
|
985 |
+
$HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
|
986 |
+
} else {
|
987 |
+
$this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
|
988 |
+
}
|
989 |
+
if ($HTTPS == '1' || $HTTPS == 'on') {
|
990 |
+
$SCHEME = 'https';
|
991 |
+
} else {
|
992 |
+
$SCHEME = 'http';
|
993 |
+
}
|
994 |
+
$soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
|
995 |
+
}
|
996 |
+
if(false == $style) {
|
997 |
+
$style = "rpc";
|
998 |
+
}
|
999 |
+
if(false == $use) {
|
1000 |
+
$use = "encoded";
|
1001 |
+
}
|
1002 |
+
if ($use == 'encoded' && $encodingStyle == '') {
|
1003 |
+
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
|
1004 |
+
}
|
1005 |
+
|
1006 |
+
$this->operations[$name] = array(
|
1007 |
+
'name' => $name,
|
1008 |
+
'in' => $in,
|
1009 |
+
'out' => $out,
|
1010 |
+
'namespace' => $namespace,
|
1011 |
+
'soapaction' => $soapaction,
|
1012 |
+
'style' => $style);
|
1013 |
+
if($this->wsdl){
|
1014 |
+
$this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use,$documentation,$encodingStyle);
|
1015 |
+
}
|
1016 |
+
return true;
|
1017 |
+
}
|
1018 |
+
|
1019 |
+
/**
|
1020 |
+
* Specify a fault to be returned to the client.
|
1021 |
+
* This also acts as a flag to the server that a fault has occured.
|
1022 |
+
*
|
1023 |
+
* @param string $faultcode
|
1024 |
+
* @param string $faultstring
|
1025 |
+
* @param string $faultactor
|
1026 |
+
* @param string $faultdetail
|
1027 |
+
* @access public
|
1028 |
+
*/
|
1029 |
+
function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){
|
1030 |
+
if ($faultdetail == '' && $this->debug_flag) {
|
1031 |
+
$faultdetail = $this->getDebug();
|
1032 |
+
}
|
1033 |
+
$this->fault = new nusoap_fault($faultcode,$faultactor,$faultstring,$faultdetail);
|
1034 |
+
$this->fault->soap_defencoding = $this->soap_defencoding;
|
1035 |
+
}
|
1036 |
+
|
1037 |
+
/**
|
1038 |
+
* Sets up wsdl object.
|
1039 |
+
* Acts as a flag to enable internal WSDL generation
|
1040 |
+
*
|
1041 |
+
* @param string $serviceName, name of the service
|
1042 |
+
* @param mixed $namespace optional 'tns' service namespace or false
|
1043 |
+
* @param mixed $endpoint optional URL of service endpoint or false
|
1044 |
+
* @param string $style optional (rpc|document) WSDL style (also specified by operation)
|
1045 |
+
* @param string $transport optional SOAP transport
|
1046 |
+
* @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false
|
1047 |
+
*/
|
1048 |
+
function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
|
1049 |
+
{
|
1050 |
+
global $HTTP_SERVER_VARS;
|
1051 |
+
|
1052 |
+
if (isset($_SERVER)) {
|
1053 |
+
$SERVER_NAME = $_SERVER['SERVER_NAME'];
|
1054 |
+
$SERVER_PORT = $_SERVER['SERVER_PORT'];
|
1055 |
+
$SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
|
1056 |
+
$HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
|
1057 |
+
} elseif (isset($HTTP_SERVER_VARS)) {
|
1058 |
+
$SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
|
1059 |
+
$SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
|
1060 |
+
$SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
|
1061 |
+
$HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
|
1062 |
+
} else {
|
1063 |
+
$this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
|
1064 |
+
}
|
1065 |
+
// If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)
|
1066 |
+
$colon = strpos($SERVER_NAME,":");
|
1067 |
+
if ($colon) {
|
1068 |
+
$SERVER_NAME = substr($SERVER_NAME, 0, $colon);
|
1069 |
+
}
|
1070 |
+
if ($SERVER_PORT == 80) {
|
1071 |
+
$SERVER_PORT = '';
|
1072 |
+
} else {
|
1073 |
+
$SERVER_PORT = ':' . $SERVER_PORT;
|
1074 |
+
}
|
1075 |
+
if(false == $namespace) {
|
1076 |
+
$namespace = "http://$SERVER_NAME/soap/$serviceName";
|
1077 |
+
}
|
1078 |
+
|
1079 |
+
if(false == $endpoint) {
|
1080 |
+
if ($HTTPS == '1' || $HTTPS == 'on') {
|
1081 |
+
$SCHEME = 'https';
|
1082 |
+
} else {
|
1083 |
+
$SCHEME = 'http';
|
1084 |
+
}
|
1085 |
+
$endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
|
1086 |
+
}
|
1087 |
+
|
1088 |
+
if(false == $schemaTargetNamespace) {
|
1089 |
+
$schemaTargetNamespace = $namespace;
|
1090 |
+
}
|
1091 |
+
|
1092 |
+
$this->wsdl = new wsdl;
|
1093 |
+
$this->wsdl->serviceName = $serviceName;
|
1094 |
+
$this->wsdl->endpoint = $endpoint;
|
1095 |
+
$this->wsdl->namespaces['tns'] = $namespace;
|
1096 |
+
$this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
|
1097 |
+
$this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
|
1098 |
+
if ($schemaTargetNamespace != $namespace) {
|
1099 |
+
$this->wsdl->namespaces['types'] = $schemaTargetNamespace;
|
1100 |
+
}
|
1101 |
+
$this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces);
|
1102 |
+
if ($style == 'document') {
|
1103 |
+
$this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified';
|
1104 |
+
}
|
1105 |
+
$this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
|
1106 |
+
$this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
|
1107 |
+
$this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
|
1108 |
+
$this->wsdl->bindings[$serviceName.'Binding'] = array(
|
1109 |
+
'name'=>$serviceName.'Binding',
|
1110 |
+
'style'=>$style,
|
1111 |
+
'transport'=>$transport,
|
1112 |
+
'portType'=>$serviceName.'PortType');
|
1113 |
+
$this->wsdl->ports[$serviceName.'Port'] = array(
|
1114 |
+
'binding'=>$serviceName.'Binding',
|
1115 |
+
'location'=>$endpoint,
|
1116 |
+
'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/');
|
1117 |
+
}
|
1118 |
+
}
|
1119 |
+
|
1120 |
+
/**
|
1121 |
+
* Backward compatibility
|
1122 |
+
*/
|
1123 |
+
class soap_server extends nusoap_server {
|
1124 |
+
}
|
1125 |
+
|
1126 |
+
|
1127 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.soap_transport_http.php
ADDED
@@ -0,0 +1,1307 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
|
4 |
+
|
5 |
+
|
6 |
+
/**
|
7 |
+
* transport class for sending/receiving data via HTTP and HTTPS
|
8 |
+
* NOTE: PHP must be compiled with the CURL extension for HTTPS support
|
9 |
+
*
|
10 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
11 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
12 |
+
* @version $Id: class.soap_transport_http.php,v 1.68 2010/04/26 20:15:08 snichol Exp $
|
13 |
+
* @access public
|
14 |
+
*/
|
15 |
+
class soap_transport_http extends nusoap_base {
|
16 |
+
|
17 |
+
var $url = '';
|
18 |
+
var $uri = '';
|
19 |
+
var $digest_uri = '';
|
20 |
+
var $scheme = '';
|
21 |
+
var $host = '';
|
22 |
+
var $port = '';
|
23 |
+
var $path = '';
|
24 |
+
var $request_method = 'POST';
|
25 |
+
var $protocol_version = '1.0';
|
26 |
+
var $encoding = '';
|
27 |
+
var $outgoing_headers = array();
|
28 |
+
var $incoming_headers = array();
|
29 |
+
var $incoming_cookies = array();
|
30 |
+
var $outgoing_payload = '';
|
31 |
+
var $incoming_payload = '';
|
32 |
+
var $response_status_line; // HTTP response status line
|
33 |
+
var $useSOAPAction = true;
|
34 |
+
var $persistentConnection = false;
|
35 |
+
var $ch = false; // cURL handle
|
36 |
+
var $ch_options = array(); // cURL custom options
|
37 |
+
var $use_curl = false; // force cURL use
|
38 |
+
var $proxy = null; // proxy information (associative array)
|
39 |
+
var $username = '';
|
40 |
+
var $password = '';
|
41 |
+
var $authtype = '';
|
42 |
+
var $digestRequest = array();
|
43 |
+
var $certRequest = array(); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional)
|
44 |
+
// cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'
|
45 |
+
// sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
|
46 |
+
// sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'
|
47 |
+
// passphrase: SSL key password/passphrase
|
48 |
+
// certpassword: SSL certificate password
|
49 |
+
// verifypeer: default is 1
|
50 |
+
// verifyhost: default is 1
|
51 |
+
|
52 |
+
/**
|
53 |
+
* constructor
|
54 |
+
*
|
55 |
+
* @param string $url The URL to which to connect
|
56 |
+
* @param array $curl_options User-specified cURL options
|
57 |
+
* @param boolean $use_curl Whether to try to force cURL use
|
58 |
+
* @access public
|
59 |
+
*/
|
60 |
+
function soap_transport_http($url, $curl_options = NULL, $use_curl = false){
|
61 |
+
parent::nusoap_base();
|
62 |
+
$this->debug("ctor url=$url use_curl=$use_curl curl_options:");
|
63 |
+
$this->appendDebug($this->varDump($curl_options));
|
64 |
+
$this->setURL($url);
|
65 |
+
if (is_array($curl_options)) {
|
66 |
+
$this->ch_options = $curl_options;
|
67 |
+
}
|
68 |
+
$this->use_curl = $use_curl;
|
69 |
+
preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
|
70 |
+
$this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')');
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* sets a cURL option
|
75 |
+
*
|
76 |
+
* @param mixed $option The cURL option (always integer?)
|
77 |
+
* @param mixed $value The cURL option value
|
78 |
+
* @access private
|
79 |
+
*/
|
80 |
+
function setCurlOption($option, $value) {
|
81 |
+
$this->debug("setCurlOption option=$option, value=");
|
82 |
+
$this->appendDebug($this->varDump($value));
|
83 |
+
curl_setopt($this->ch, $option, $value);
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* sets an HTTP header
|
88 |
+
*
|
89 |
+
* @param string $name The name of the header
|
90 |
+
* @param string $value The value of the header
|
91 |
+
* @access private
|
92 |
+
*/
|
93 |
+
function setHeader($name, $value) {
|
94 |
+
$this->outgoing_headers[$name] = $value;
|
95 |
+
$this->debug("set header $name: $value");
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* unsets an HTTP header
|
100 |
+
*
|
101 |
+
* @param string $name The name of the header
|
102 |
+
* @access private
|
103 |
+
*/
|
104 |
+
function unsetHeader($name) {
|
105 |
+
if (isset($this->outgoing_headers[$name])) {
|
106 |
+
$this->debug("unset header $name");
|
107 |
+
unset($this->outgoing_headers[$name]);
|
108 |
+
}
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* sets the URL to which to connect
|
113 |
+
*
|
114 |
+
* @param string $url The URL to which to connect
|
115 |
+
* @access private
|
116 |
+
*/
|
117 |
+
function setURL($url) {
|
118 |
+
$this->url = $url;
|
119 |
+
|
120 |
+
$u = parse_url($url);
|
121 |
+
foreach($u as $k => $v){
|
122 |
+
$this->debug("parsed URL $k = $v");
|
123 |
+
$this->$k = $v;
|
124 |
+
}
|
125 |
+
|
126 |
+
// add any GET params to path
|
127 |
+
if(isset($u['query']) && $u['query'] != ''){
|
128 |
+
$this->path .= '?' . $u['query'];
|
129 |
+
}
|
130 |
+
|
131 |
+
// set default port
|
132 |
+
if(!isset($u['port'])){
|
133 |
+
if($u['scheme'] == 'https'){
|
134 |
+
$this->port = 443;
|
135 |
+
} else {
|
136 |
+
$this->port = 80;
|
137 |
+
}
|
138 |
+
}
|
139 |
+
|
140 |
+
$this->uri = $this->path;
|
141 |
+
$this->digest_uri = $this->uri;
|
142 |
+
|
143 |
+
// build headers
|
144 |
+
if (!isset($u['port'])) {
|
145 |
+
$this->setHeader('Host', $this->host);
|
146 |
+
} else {
|
147 |
+
$this->setHeader('Host', $this->host.':'.$this->port);
|
148 |
+
}
|
149 |
+
|
150 |
+
if (isset($u['user']) && $u['user'] != '') {
|
151 |
+
$this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : '');
|
152 |
+
}
|
153 |
+
}
|
154 |
+
|
155 |
+
/**
|
156 |
+
* gets the I/O method to use
|
157 |
+
*
|
158 |
+
* @return string I/O method to use (socket|curl|unknown)
|
159 |
+
* @access private
|
160 |
+
*/
|
161 |
+
function io_method() {
|
162 |
+
if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm'))
|
163 |
+
return 'curl';
|
164 |
+
if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm'))
|
165 |
+
return 'socket';
|
166 |
+
return 'unknown';
|
167 |
+
}
|
168 |
+
|
169 |
+
/**
|
170 |
+
* establish an HTTP connection
|
171 |
+
*
|
172 |
+
* @param integer $timeout set connection timeout in seconds
|
173 |
+
* @param integer $response_timeout set response timeout in seconds
|
174 |
+
* @return boolean true if connected, false if not
|
175 |
+
* @access private
|
176 |
+
*/
|
177 |
+
function connect($connection_timeout=0,$response_timeout=30){
|
178 |
+
// For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like
|
179 |
+
// "regular" socket.
|
180 |
+
// TODO: disabled for now because OpenSSL must be *compiled* in (not just
|
181 |
+
// loaded), and until PHP5 stream_get_wrappers is not available.
|
182 |
+
// if ($this->scheme == 'https') {
|
183 |
+
// if (version_compare(phpversion(), '4.3.0') >= 0) {
|
184 |
+
// if (extension_loaded('openssl')) {
|
185 |
+
// $this->scheme = 'ssl';
|
186 |
+
// $this->debug('Using SSL over OpenSSL');
|
187 |
+
// }
|
188 |
+
// }
|
189 |
+
// }
|
190 |
+
$this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
|
191 |
+
if ($this->io_method() == 'socket') {
|
192 |
+
if (!is_array($this->proxy)) {
|
193 |
+
$host = $this->host;
|
194 |
+
$port = $this->port;
|
195 |
+
} else {
|
196 |
+
$host = $this->proxy['host'];
|
197 |
+
$port = $this->proxy['port'];
|
198 |
+
}
|
199 |
+
|
200 |
+
// use persistent connection
|
201 |
+
if($this->persistentConnection && isset($this->fp) && is_resource($this->fp)){
|
202 |
+
if (!feof($this->fp)) {
|
203 |
+
$this->debug('Re-use persistent connection');
|
204 |
+
return true;
|
205 |
+
}
|
206 |
+
fclose($this->fp);
|
207 |
+
$this->debug('Closed persistent connection at EOF');
|
208 |
+
}
|
209 |
+
|
210 |
+
// munge host if using OpenSSL
|
211 |
+
if ($this->scheme == 'ssl') {
|
212 |
+
$host = 'ssl://' . $host;
|
213 |
+
}
|
214 |
+
$this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);
|
215 |
+
|
216 |
+
// open socket
|
217 |
+
if($connection_timeout > 0){
|
218 |
+
$this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str, $connection_timeout);
|
219 |
+
} else {
|
220 |
+
$this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str);
|
221 |
+
}
|
222 |
+
|
223 |
+
// test pointer
|
224 |
+
if(!$this->fp) {
|
225 |
+
$msg = 'Couldn\'t open socket connection to server ' . $this->url;
|
226 |
+
if ($this->errno) {
|
227 |
+
$msg .= ', Error ('.$this->errno.'): '.$this->error_str;
|
228 |
+
} else {
|
229 |
+
$msg .= ' prior to connect(). This is often a problem looking up the host name.';
|
230 |
+
}
|
231 |
+
$this->debug($msg);
|
232 |
+
$this->setError($msg);
|
233 |
+
return false;
|
234 |
+
}
|
235 |
+
|
236 |
+
// set response timeout
|
237 |
+
$this->debug('set response timeout to ' . $response_timeout);
|
238 |
+
socket_set_timeout( $this->fp, $response_timeout);
|
239 |
+
|
240 |
+
$this->debug('socket connected');
|
241 |
+
return true;
|
242 |
+
} else if ($this->io_method() == 'curl') {
|
243 |
+
if (!extension_loaded('curl')) {
|
244 |
+
// $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
|
245 |
+
$this->setError('The PHP cURL Extension is required for HTTPS or NLTM. You will need to re-build or update your PHP to include cURL or change php.ini to load the PHP cURL extension.');
|
246 |
+
return false;
|
247 |
+
}
|
248 |
+
// Avoid warnings when PHP does not have these options
|
249 |
+
if (defined('CURLOPT_CONNECTIONTIMEOUT'))
|
250 |
+
$CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT;
|
251 |
+
else
|
252 |
+
$CURLOPT_CONNECTIONTIMEOUT = 78;
|
253 |
+
if (defined('CURLOPT_HTTPAUTH'))
|
254 |
+
$CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH;
|
255 |
+
else
|
256 |
+
$CURLOPT_HTTPAUTH = 107;
|
257 |
+
if (defined('CURLOPT_PROXYAUTH'))
|
258 |
+
$CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH;
|
259 |
+
else
|
260 |
+
$CURLOPT_PROXYAUTH = 111;
|
261 |
+
if (defined('CURLAUTH_BASIC'))
|
262 |
+
$CURLAUTH_BASIC = CURLAUTH_BASIC;
|
263 |
+
else
|
264 |
+
$CURLAUTH_BASIC = 1;
|
265 |
+
if (defined('CURLAUTH_DIGEST'))
|
266 |
+
$CURLAUTH_DIGEST = CURLAUTH_DIGEST;
|
267 |
+
else
|
268 |
+
$CURLAUTH_DIGEST = 2;
|
269 |
+
if (defined('CURLAUTH_NTLM'))
|
270 |
+
$CURLAUTH_NTLM = CURLAUTH_NTLM;
|
271 |
+
else
|
272 |
+
$CURLAUTH_NTLM = 8;
|
273 |
+
|
274 |
+
$this->debug('connect using cURL');
|
275 |
+
// init CURL
|
276 |
+
$this->ch = curl_init();
|
277 |
+
// set url
|
278 |
+
$hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host";
|
279 |
+
// add path
|
280 |
+
$hostURL .= $this->path;
|
281 |
+
$this->setCurlOption(CURLOPT_URL, $hostURL);
|
282 |
+
// follow location headers (re-directs)
|
283 |
+
if (ini_get('safe_mode') || ini_get('open_basedir')) {
|
284 |
+
$this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION');
|
285 |
+
$this->debug('safe_mode = ');
|
286 |
+
$this->appendDebug($this->varDump(ini_get('safe_mode')));
|
287 |
+
$this->debug('open_basedir = ');
|
288 |
+
$this->appendDebug($this->varDump(ini_get('open_basedir')));
|
289 |
+
} else {
|
290 |
+
$this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1);
|
291 |
+
}
|
292 |
+
// ask for headers in the response output
|
293 |
+
$this->setCurlOption(CURLOPT_HEADER, 1);
|
294 |
+
// ask for the response output as the return value
|
295 |
+
$this->setCurlOption(CURLOPT_RETURNTRANSFER, 1);
|
296 |
+
// encode
|
297 |
+
// We manage this ourselves through headers and encoding
|
298 |
+
// if(function_exists('gzuncompress')){
|
299 |
+
// $this->setCurlOption(CURLOPT_ENCODING, 'deflate');
|
300 |
+
// }
|
301 |
+
// persistent connection
|
302 |
+
if ($this->persistentConnection) {
|
303 |
+
// I believe the following comment is now bogus, having applied to
|
304 |
+
// the code when it used CURLOPT_CUSTOMREQUEST to send the request.
|
305 |
+
// The way we send data, we cannot use persistent connections, since
|
306 |
+
// there will be some "junk" at the end of our request.
|
307 |
+
//$this->setCurlOption(CURL_HTTP_VERSION_1_1, true);
|
308 |
+
$this->persistentConnection = false;
|
309 |
+
$this->setHeader('Connection', 'close');
|
310 |
+
}
|
311 |
+
// set timeouts
|
312 |
+
if ($connection_timeout != 0) {
|
313 |
+
$this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);
|
314 |
+
}
|
315 |
+
if ($response_timeout != 0) {
|
316 |
+
$this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout);
|
317 |
+
}
|
318 |
+
|
319 |
+
if ($this->scheme == 'https') {
|
320 |
+
$this->debug('set cURL SSL verify options');
|
321 |
+
// recent versions of cURL turn on peer/host checking by default,
|
322 |
+
// while PHP binaries are not compiled with a default location for the
|
323 |
+
// CA cert bundle, so disable peer/host checking.
|
324 |
+
//$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');
|
325 |
+
$this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0);
|
326 |
+
$this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0);
|
327 |
+
|
328 |
+
// support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)
|
329 |
+
if ($this->authtype == 'certificate') {
|
330 |
+
$this->debug('set cURL certificate options');
|
331 |
+
if (isset($this->certRequest['cainfofile'])) {
|
332 |
+
$this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']);
|
333 |
+
}
|
334 |
+
if (isset($this->certRequest['verifypeer'])) {
|
335 |
+
$this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);
|
336 |
+
} else {
|
337 |
+
$this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1);
|
338 |
+
}
|
339 |
+
if (isset($this->certRequest['verifyhost'])) {
|
340 |
+
$this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);
|
341 |
+
} else {
|
342 |
+
$this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1);
|
343 |
+
}
|
344 |
+
if (isset($this->certRequest['sslcertfile'])) {
|
345 |
+
$this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);
|
346 |
+
}
|
347 |
+
if (isset($this->certRequest['sslkeyfile'])) {
|
348 |
+
$this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);
|
349 |
+
}
|
350 |
+
if (isset($this->certRequest['passphrase'])) {
|
351 |
+
$this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']);
|
352 |
+
}
|
353 |
+
if (isset($this->certRequest['certpassword'])) {
|
354 |
+
$this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']);
|
355 |
+
}
|
356 |
+
}
|
357 |
+
}
|
358 |
+
if ($this->authtype && ($this->authtype != 'certificate')) {
|
359 |
+
if ($this->username) {
|
360 |
+
$this->debug('set cURL username/password');
|
361 |
+
$this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password");
|
362 |
+
}
|
363 |
+
if ($this->authtype == 'basic') {
|
364 |
+
$this->debug('set cURL for Basic authentication');
|
365 |
+
$this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC);
|
366 |
+
}
|
367 |
+
if ($this->authtype == 'digest') {
|
368 |
+
$this->debug('set cURL for digest authentication');
|
369 |
+
$this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST);
|
370 |
+
}
|
371 |
+
if ($this->authtype == 'ntlm') {
|
372 |
+
$this->debug('set cURL for NTLM authentication');
|
373 |
+
$this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM);
|
374 |
+
}
|
375 |
+
}
|
376 |
+
if (is_array($this->proxy)) {
|
377 |
+
$this->debug('set cURL proxy options');
|
378 |
+
if ($this->proxy['port'] != '') {
|
379 |
+
$this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'].':'.$this->proxy['port']);
|
380 |
+
} else {
|
381 |
+
$this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']);
|
382 |
+
}
|
383 |
+
if ($this->proxy['username'] || $this->proxy['password']) {
|
384 |
+
$this->debug('set cURL proxy authentication options');
|
385 |
+
$this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'].':'.$this->proxy['password']);
|
386 |
+
if ($this->proxy['authtype'] == 'basic') {
|
387 |
+
$this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC);
|
388 |
+
}
|
389 |
+
if ($this->proxy['authtype'] == 'ntlm') {
|
390 |
+
$this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM);
|
391 |
+
}
|
392 |
+
}
|
393 |
+
}
|
394 |
+
$this->debug('cURL connection set up');
|
395 |
+
return true;
|
396 |
+
} else {
|
397 |
+
$this->setError('Unknown scheme ' . $this->scheme);
|
398 |
+
$this->debug('Unknown scheme ' . $this->scheme);
|
399 |
+
return false;
|
400 |
+
}
|
401 |
+
}
|
402 |
+
|
403 |
+
/**
|
404 |
+
* sends the SOAP request and gets the SOAP response via HTTP[S]
|
405 |
+
*
|
406 |
+
* @param string $data message data
|
407 |
+
* @param integer $timeout set connection timeout in seconds
|
408 |
+
* @param integer $response_timeout set response timeout in seconds
|
409 |
+
* @param array $cookies cookies to send
|
410 |
+
* @return string data
|
411 |
+
* @access public
|
412 |
+
*/
|
413 |
+
function send($data, $timeout=0, $response_timeout=30, $cookies=NULL) {
|
414 |
+
|
415 |
+
$this->debug('entered send() with data of length: '.strlen($data));
|
416 |
+
|
417 |
+
$this->tryagain = true;
|
418 |
+
$tries = 0;
|
419 |
+
while ($this->tryagain) {
|
420 |
+
$this->tryagain = false;
|
421 |
+
if ($tries++ < 2) {
|
422 |
+
// make connnection
|
423 |
+
if (!$this->connect($timeout, $response_timeout)){
|
424 |
+
return false;
|
425 |
+
}
|
426 |
+
|
427 |
+
// send request
|
428 |
+
if (!$this->sendRequest($data, $cookies)){
|
429 |
+
return false;
|
430 |
+
}
|
431 |
+
|
432 |
+
// get response
|
433 |
+
$respdata = $this->getResponse();
|
434 |
+
} else {
|
435 |
+
$this->setError("Too many tries to get an OK response ($this->response_status_line)");
|
436 |
+
}
|
437 |
+
}
|
438 |
+
$this->debug('end of send()');
|
439 |
+
return $respdata;
|
440 |
+
}
|
441 |
+
|
442 |
+
|
443 |
+
/**
|
444 |
+
* sends the SOAP request and gets the SOAP response via HTTPS using CURL
|
445 |
+
*
|
446 |
+
* @param string $data message data
|
447 |
+
* @param integer $timeout set connection timeout in seconds
|
448 |
+
* @param integer $response_timeout set response timeout in seconds
|
449 |
+
* @param array $cookies cookies to send
|
450 |
+
* @return string data
|
451 |
+
* @access public
|
452 |
+
* @deprecated
|
453 |
+
*/
|
454 |
+
function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies) {
|
455 |
+
return $this->send($data, $timeout, $response_timeout, $cookies);
|
456 |
+
}
|
457 |
+
|
458 |
+
/**
|
459 |
+
* if authenticating, set user credentials here
|
460 |
+
*
|
461 |
+
* @param string $username
|
462 |
+
* @param string $password
|
463 |
+
* @param string $authtype (basic|digest|certificate|ntlm)
|
464 |
+
* @param array $digestRequest (keys must be nonce, nc, realm, qop)
|
465 |
+
* @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
|
466 |
+
* @access public
|
467 |
+
*/
|
468 |
+
function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array()) {
|
469 |
+
$this->debug("setCredentials username=$username authtype=$authtype digestRequest=");
|
470 |
+
$this->appendDebug($this->varDump($digestRequest));
|
471 |
+
$this->debug("certRequest=");
|
472 |
+
$this->appendDebug($this->varDump($certRequest));
|
473 |
+
// cf. RFC 2617
|
474 |
+
if ($authtype == 'basic') {
|
475 |
+
$this->setHeader('Authorization', 'Basic '.base64_encode(str_replace(':','',$username).':'.$password));
|
476 |
+
} elseif ($authtype == 'digest') {
|
477 |
+
if (isset($digestRequest['nonce'])) {
|
478 |
+
$digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
|
479 |
+
|
480 |
+
// calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)
|
481 |
+
|
482 |
+
// A1 = unq(username-value) ":" unq(realm-value) ":" passwd
|
483 |
+
$A1 = $username. ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password;
|
484 |
+
|
485 |
+
// H(A1) = MD5(A1)
|
486 |
+
$HA1 = md5($A1);
|
487 |
+
|
488 |
+
// A2 = Method ":" digest-uri-value
|
489 |
+
$A2 = $this->request_method . ':' . $this->digest_uri;
|
490 |
+
|
491 |
+
// H(A2)
|
492 |
+
$HA2 = md5($A2);
|
493 |
+
|
494 |
+
// KD(secret, data) = H(concat(secret, ":", data))
|
495 |
+
// if qop == auth:
|
496 |
+
// request-digest = <"> < KD ( H(A1), unq(nonce-value)
|
497 |
+
// ":" nc-value
|
498 |
+
// ":" unq(cnonce-value)
|
499 |
+
// ":" unq(qop-value)
|
500 |
+
// ":" H(A2)
|
501 |
+
// ) <">
|
502 |
+
// if qop is missing,
|
503 |
+
// request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
|
504 |
+
|
505 |
+
$unhashedDigest = '';
|
506 |
+
$nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';
|
507 |
+
$cnonce = $nonce;
|
508 |
+
if ($digestRequest['qop'] != '') {
|
509 |
+
$unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
|
510 |
+
} else {
|
511 |
+
$unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
|
512 |
+
}
|
513 |
+
|
514 |
+
$hashedDigest = md5($unhashedDigest);
|
515 |
+
|
516 |
+
$opaque = '';
|
517 |
+
if (isset($digestRequest['opaque'])) {
|
518 |
+
$opaque = ', opaque="' . $digestRequest['opaque'] . '"';
|
519 |
+
}
|
520 |
+
|
521 |
+
$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 . '"');
|
522 |
+
}
|
523 |
+
} elseif ($authtype == 'certificate') {
|
524 |
+
$this->certRequest = $certRequest;
|
525 |
+
$this->debug('Authorization header not set for certificate');
|
526 |
+
} elseif ($authtype == 'ntlm') {
|
527 |
+
// do nothing
|
528 |
+
$this->debug('Authorization header not set for ntlm');
|
529 |
+
}
|
530 |
+
$this->username = $username;
|
531 |
+
$this->password = $password;
|
532 |
+
$this->authtype = $authtype;
|
533 |
+
$this->digestRequest = $digestRequest;
|
534 |
+
}
|
535 |
+
|
536 |
+
/**
|
537 |
+
* set the soapaction value
|
538 |
+
*
|
539 |
+
* @param string $soapaction
|
540 |
+
* @access public
|
541 |
+
*/
|
542 |
+
function setSOAPAction($soapaction) {
|
543 |
+
$this->setHeader('SOAPAction', '"' . $soapaction . '"');
|
544 |
+
}
|
545 |
+
|
546 |
+
/**
|
547 |
+
* use http encoding
|
548 |
+
*
|
549 |
+
* @param string $enc encoding style. supported values: gzip, deflate, or both
|
550 |
+
* @access public
|
551 |
+
*/
|
552 |
+
function setEncoding($enc='gzip, deflate') {
|
553 |
+
if (function_exists('gzdeflate')) {
|
554 |
+
$this->protocol_version = '1.1';
|
555 |
+
$this->setHeader('Accept-Encoding', $enc);
|
556 |
+
if (!isset($this->outgoing_headers['Connection'])) {
|
557 |
+
$this->setHeader('Connection', 'close');
|
558 |
+
$this->persistentConnection = false;
|
559 |
+
}
|
560 |
+
// deprecated as of PHP 5.3.0
|
561 |
+
//set_magic_quotes_runtime(0);
|
562 |
+
$this->encoding = $enc;
|
563 |
+
}
|
564 |
+
}
|
565 |
+
|
566 |
+
/**
|
567 |
+
* set proxy info here
|
568 |
+
*
|
569 |
+
* @param string $proxyhost use an empty string to remove proxy
|
570 |
+
* @param string $proxyport
|
571 |
+
* @param string $proxyusername
|
572 |
+
* @param string $proxypassword
|
573 |
+
* @param string $proxyauthtype (basic|ntlm)
|
574 |
+
* @access public
|
575 |
+
*/
|
576 |
+
function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic') {
|
577 |
+
if ($proxyhost) {
|
578 |
+
$this->proxy = array(
|
579 |
+
'host' => $proxyhost,
|
580 |
+
'port' => $proxyport,
|
581 |
+
'username' => $proxyusername,
|
582 |
+
'password' => $proxypassword,
|
583 |
+
'authtype' => $proxyauthtype
|
584 |
+
);
|
585 |
+
if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') {
|
586 |
+
$this->setHeader('Proxy-Authorization', ' Basic '.base64_encode($proxyusername.':'.$proxypassword));
|
587 |
+
}
|
588 |
+
} else {
|
589 |
+
$this->debug('remove proxy');
|
590 |
+
$proxy = null;
|
591 |
+
unsetHeader('Proxy-Authorization');
|
592 |
+
}
|
593 |
+
}
|
594 |
+
|
595 |
+
|
596 |
+
/**
|
597 |
+
* Test if the given string starts with a header that is to be skipped.
|
598 |
+
* Skippable headers result from chunked transfer and proxy requests.
|
599 |
+
*
|
600 |
+
* @param string $data The string to check.
|
601 |
+
* @returns boolean Whether a skippable header was found.
|
602 |
+
* @access private
|
603 |
+
*/
|
604 |
+
function isSkippableCurlHeader(&$data) {
|
605 |
+
$skipHeaders = array( 'HTTP/1.1 100',
|
606 |
+
'HTTP/1.0 301',
|
607 |
+
'HTTP/1.1 301',
|
608 |
+
'HTTP/1.0 302',
|
609 |
+
'HTTP/1.1 302',
|
610 |
+
'HTTP/1.0 401',
|
611 |
+
'HTTP/1.1 401',
|
612 |
+
'HTTP/1.0 200 Connection established');
|
613 |
+
foreach ($skipHeaders as $hd) {
|
614 |
+
$prefix = substr($data, 0, strlen($hd));
|
615 |
+
if ($prefix == $hd) return true;
|
616 |
+
}
|
617 |
+
|
618 |
+
return false;
|
619 |
+
}
|
620 |
+
|
621 |
+
/**
|
622 |
+
* decode a string that is encoded w/ "chunked' transfer encoding
|
623 |
+
* as defined in RFC2068 19.4.6
|
624 |
+
*
|
625 |
+
* @param string $buffer
|
626 |
+
* @param string $lb
|
627 |
+
* @returns string
|
628 |
+
* @access public
|
629 |
+
* @deprecated
|
630 |
+
*/
|
631 |
+
function decodeChunked($buffer, $lb){
|
632 |
+
// length := 0
|
633 |
+
$length = 0;
|
634 |
+
$new = '';
|
635 |
+
|
636 |
+
// read chunk-size, chunk-extension (if any) and CRLF
|
637 |
+
// get the position of the linebreak
|
638 |
+
$chunkend = strpos($buffer, $lb);
|
639 |
+
if ($chunkend == FALSE) {
|
640 |
+
$this->debug('no linebreak found in decodeChunked');
|
641 |
+
return $new;
|
642 |
+
}
|
643 |
+
$temp = substr($buffer,0,$chunkend);
|
644 |
+
$chunk_size = hexdec( trim($temp) );
|
645 |
+
$chunkstart = $chunkend + strlen($lb);
|
646 |
+
// while (chunk-size > 0) {
|
647 |
+
while ($chunk_size > 0) {
|
648 |
+
$this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
|
649 |
+
$chunkend = strpos( $buffer, $lb, $chunkstart + $chunk_size);
|
650 |
+
|
651 |
+
// Just in case we got a broken connection
|
652 |
+
if ($chunkend == FALSE) {
|
653 |
+
$chunk = substr($buffer,$chunkstart);
|
654 |
+
// append chunk-data to entity-body
|
655 |
+
$new .= $chunk;
|
656 |
+
$length += strlen($chunk);
|
657 |
+
break;
|
658 |
+
}
|
659 |
+
|
660 |
+
// read chunk-data and CRLF
|
661 |
+
$chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart);
|
662 |
+
// append chunk-data to entity-body
|
663 |
+
$new .= $chunk;
|
664 |
+
// length := length + chunk-size
|
665 |
+
$length += strlen($chunk);
|
666 |
+
// read chunk-size and CRLF
|
667 |
+
$chunkstart = $chunkend + strlen($lb);
|
668 |
+
|
669 |
+
$chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
|
670 |
+
if ($chunkend == FALSE) {
|
671 |
+
break; //Just in case we got a broken connection
|
672 |
+
}
|
673 |
+
$temp = substr($buffer,$chunkstart,$chunkend-$chunkstart);
|
674 |
+
$chunk_size = hexdec( trim($temp) );
|
675 |
+
$chunkstart = $chunkend;
|
676 |
+
}
|
677 |
+
return $new;
|
678 |
+
}
|
679 |
+
|
680 |
+
/**
|
681 |
+
* Writes the payload, including HTTP headers, to $this->outgoing_payload.
|
682 |
+
*
|
683 |
+
* @param string $data HTTP body
|
684 |
+
* @param string $cookie_str data for HTTP Cookie header
|
685 |
+
* @return void
|
686 |
+
* @access private
|
687 |
+
*/
|
688 |
+
function buildPayload($data, $cookie_str = '') {
|
689 |
+
// Note: for cURL connections, $this->outgoing_payload is ignored,
|
690 |
+
// as is the Content-Length header, but these are still created as
|
691 |
+
// debugging guides.
|
692 |
+
|
693 |
+
// add content-length header
|
694 |
+
if ($this->request_method != 'GET') {
|
695 |
+
$this->setHeader('Content-Length', strlen($data));
|
696 |
+
}
|
697 |
+
|
698 |
+
// start building outgoing payload:
|
699 |
+
if ($this->proxy) {
|
700 |
+
$uri = $this->url;
|
701 |
+
} else {
|
702 |
+
$uri = $this->uri;
|
703 |
+
}
|
704 |
+
$req = "$this->request_method $uri HTTP/$this->protocol_version";
|
705 |
+
$this->debug("HTTP request: $req");
|
706 |
+
$this->outgoing_payload = "$req\r\n";
|
707 |
+
|
708 |
+
// loop thru headers, serializing
|
709 |
+
foreach($this->outgoing_headers as $k => $v){
|
710 |
+
$hdr = $k.': '.$v;
|
711 |
+
$this->debug("HTTP header: $hdr");
|
712 |
+
$this->outgoing_payload .= "$hdr\r\n";
|
713 |
+
}
|
714 |
+
|
715 |
+
// add any cookies
|
716 |
+
if ($cookie_str != '') {
|
717 |
+
$hdr = 'Cookie: '.$cookie_str;
|
718 |
+
$this->debug("HTTP header: $hdr");
|
719 |
+
$this->outgoing_payload .= "$hdr\r\n";
|
720 |
+
}
|
721 |
+
|
722 |
+
// header/body separator
|
723 |
+
$this->outgoing_payload .= "\r\n";
|
724 |
+
|
725 |
+
// add data
|
726 |
+
$this->outgoing_payload .= $data;
|
727 |
+
}
|
728 |
+
|
729 |
+
/**
|
730 |
+
* sends the SOAP request via HTTP[S]
|
731 |
+
*
|
732 |
+
* @param string $data message data
|
733 |
+
* @param array $cookies cookies to send
|
734 |
+
* @return boolean true if OK, false if problem
|
735 |
+
* @access private
|
736 |
+
*/
|
737 |
+
function sendRequest($data, $cookies = NULL) {
|
738 |
+
// build cookie string
|
739 |
+
$cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));
|
740 |
+
|
741 |
+
// build payload
|
742 |
+
$this->buildPayload($data, $cookie_str);
|
743 |
+
|
744 |
+
if ($this->io_method() == 'socket') {
|
745 |
+
// send payload
|
746 |
+
if(!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
|
747 |
+
$this->setError('couldn\'t write message data to socket');
|
748 |
+
$this->debug('couldn\'t write message data to socket');
|
749 |
+
return false;
|
750 |
+
}
|
751 |
+
$this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
|
752 |
+
return true;
|
753 |
+
} else if ($this->io_method() == 'curl') {
|
754 |
+
// set payload
|
755 |
+
// cURL does say this should only be the verb, and in fact it
|
756 |
+
// turns out that the URI and HTTP version are appended to this, which
|
757 |
+
// some servers refuse to work with (so we no longer use this method!)
|
758 |
+
//$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
|
759 |
+
$curl_headers = array();
|
760 |
+
foreach($this->outgoing_headers as $k => $v){
|
761 |
+
if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') {
|
762 |
+
$this->debug("Skip cURL header $k: $v");
|
763 |
+
} else {
|
764 |
+
$curl_headers[] = "$k: $v";
|
765 |
+
}
|
766 |
+
}
|
767 |
+
if ($cookie_str != '') {
|
768 |
+
$curl_headers[] = 'Cookie: ' . $cookie_str;
|
769 |
+
}
|
770 |
+
$this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers);
|
771 |
+
$this->debug('set cURL HTTP headers');
|
772 |
+
if ($this->request_method == "POST") {
|
773 |
+
$this->setCurlOption(CURLOPT_POST, 1);
|
774 |
+
$this->setCurlOption(CURLOPT_POSTFIELDS, $data);
|
775 |
+
$this->debug('set cURL POST data');
|
776 |
+
} else {
|
777 |
+
}
|
778 |
+
// insert custom user-set cURL options
|
779 |
+
foreach ($this->ch_options as $key => $val) {
|
780 |
+
$this->setCurlOption($key, $val);
|
781 |
+
}
|
782 |
+
|
783 |
+
$this->debug('set cURL payload');
|
784 |
+
return true;
|
785 |
+
}
|
786 |
+
}
|
787 |
+
|
788 |
+
/**
|
789 |
+
* gets the SOAP response via HTTP[S]
|
790 |
+
*
|
791 |
+
* @return string the response (also sets member variables like incoming_payload)
|
792 |
+
* @access private
|
793 |
+
*/
|
794 |
+
function getResponse(){
|
795 |
+
$this->incoming_payload = '';
|
796 |
+
|
797 |
+
if ($this->io_method() == 'socket') {
|
798 |
+
// loop until headers have been retrieved
|
799 |
+
$data = '';
|
800 |
+
while (!isset($lb)){
|
801 |
+
|
802 |
+
// We might EOF during header read.
|
803 |
+
if(feof($this->fp)) {
|
804 |
+
$this->incoming_payload = $data;
|
805 |
+
$this->debug('found no headers before EOF after length ' . strlen($data));
|
806 |
+
$this->debug("received before EOF:\n" . $data);
|
807 |
+
$this->setError('server failed to send headers');
|
808 |
+
return false;
|
809 |
+
}
|
810 |
+
|
811 |
+
$tmp = fgets($this->fp, 256);
|
812 |
+
$tmplen = strlen($tmp);
|
813 |
+
$this->debug("read line of $tmplen bytes: " . trim($tmp));
|
814 |
+
|
815 |
+
if ($tmplen == 0) {
|
816 |
+
$this->incoming_payload = $data;
|
817 |
+
$this->debug('socket read of headers timed out after length ' . strlen($data));
|
818 |
+
$this->debug("read before timeout: " . $data);
|
819 |
+
$this->setError('socket read of headers timed out');
|
820 |
+
return false;
|
821 |
+
}
|
822 |
+
|
823 |
+
$data .= $tmp;
|
824 |
+
$pos = strpos($data,"\r\n\r\n");
|
825 |
+
if($pos > 1){
|
826 |
+
$lb = "\r\n";
|
827 |
+
} else {
|
828 |
+
$pos = strpos($data,"\n\n");
|
829 |
+
if($pos > 1){
|
830 |
+
$lb = "\n";
|
831 |
+
}
|
832 |
+
}
|
833 |
+
// remove 100 headers
|
834 |
+
if (isset($lb) && preg_match('/^HTTP\/1.1 100/',$data)) {
|
835 |
+
unset($lb);
|
836 |
+
$data = '';
|
837 |
+
}//
|
838 |
+
}
|
839 |
+
// store header data
|
840 |
+
$this->incoming_payload .= $data;
|
841 |
+
$this->debug('found end of headers after length ' . strlen($data));
|
842 |
+
// process headers
|
843 |
+
$header_data = trim(substr($data,0,$pos));
|
844 |
+
$header_array = explode($lb,$header_data);
|
845 |
+
$this->incoming_headers = array();
|
846 |
+
$this->incoming_cookies = array();
|
847 |
+
foreach($header_array as $header_line){
|
848 |
+
$arr = explode(':',$header_line, 2);
|
849 |
+
if(count($arr) > 1){
|
850 |
+
$header_name = strtolower(trim($arr[0]));
|
851 |
+
$this->incoming_headers[$header_name] = trim($arr[1]);
|
852 |
+
if ($header_name == 'set-cookie') {
|
853 |
+
// TODO: allow multiple cookies from parseCookie
|
854 |
+
$cookie = $this->parseCookie(trim($arr[1]));
|
855 |
+
if ($cookie) {
|
856 |
+
$this->incoming_cookies[] = $cookie;
|
857 |
+
$this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
|
858 |
+
} else {
|
859 |
+
$this->debug('did not find cookie in ' . trim($arr[1]));
|
860 |
+
}
|
861 |
+
}
|
862 |
+
} else if (isset($header_name)) {
|
863 |
+
// append continuation line to previous header
|
864 |
+
$this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
|
865 |
+
}
|
866 |
+
}
|
867 |
+
|
868 |
+
// loop until msg has been received
|
869 |
+
if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') {
|
870 |
+
$content_length = 2147483647; // ignore any content-length header
|
871 |
+
$chunked = true;
|
872 |
+
$this->debug("want to read chunked content");
|
873 |
+
} elseif (isset($this->incoming_headers['content-length'])) {
|
874 |
+
$content_length = $this->incoming_headers['content-length'];
|
875 |
+
$chunked = false;
|
876 |
+
$this->debug("want to read content of length $content_length");
|
877 |
+
} else {
|
878 |
+
$content_length = 2147483647;
|
879 |
+
$chunked = false;
|
880 |
+
$this->debug("want to read content to EOF");
|
881 |
+
}
|
882 |
+
$data = '';
|
883 |
+
do {
|
884 |
+
if ($chunked) {
|
885 |
+
$tmp = fgets($this->fp, 256);
|
886 |
+
$tmplen = strlen($tmp);
|
887 |
+
$this->debug("read chunk line of $tmplen bytes");
|
888 |
+
if ($tmplen == 0) {
|
889 |
+
$this->incoming_payload = $data;
|
890 |
+
$this->debug('socket read of chunk length timed out after length ' . strlen($data));
|
891 |
+
$this->debug("read before timeout:\n" . $data);
|
892 |
+
$this->setError('socket read of chunk length timed out');
|
893 |
+
return false;
|
894 |
+
}
|
895 |
+
$content_length = hexdec(trim($tmp));
|
896 |
+
$this->debug("chunk length $content_length");
|
897 |
+
}
|
898 |
+
$strlen = 0;
|
899 |
+
while (($strlen < $content_length) && (!feof($this->fp))) {
|
900 |
+
$readlen = min(8192, $content_length - $strlen);
|
901 |
+
$tmp = fread($this->fp, $readlen);
|
902 |
+
$tmplen = strlen($tmp);
|
903 |
+
$this->debug("read buffer of $tmplen bytes");
|
904 |
+
if (($tmplen == 0) && (!feof($this->fp))) {
|
905 |
+
$this->incoming_payload = $data;
|
906 |
+
$this->debug('socket read of body timed out after length ' . strlen($data));
|
907 |
+
$this->debug("read before timeout:\n" . $data);
|
908 |
+
$this->setError('socket read of body timed out');
|
909 |
+
return false;
|
910 |
+
}
|
911 |
+
$strlen += $tmplen;
|
912 |
+
$data .= $tmp;
|
913 |
+
}
|
914 |
+
if ($chunked && ($content_length > 0)) {
|
915 |
+
$tmp = fgets($this->fp, 256);
|
916 |
+
$tmplen = strlen($tmp);
|
917 |
+
$this->debug("read chunk terminator of $tmplen bytes");
|
918 |
+
if ($tmplen == 0) {
|
919 |
+
$this->incoming_payload = $data;
|
920 |
+
$this->debug('socket read of chunk terminator timed out after length ' . strlen($data));
|
921 |
+
$this->debug("read before timeout:\n" . $data);
|
922 |
+
$this->setError('socket read of chunk terminator timed out');
|
923 |
+
return false;
|
924 |
+
}
|
925 |
+
}
|
926 |
+
} while ($chunked && ($content_length > 0) && (!feof($this->fp)));
|
927 |
+
if (feof($this->fp)) {
|
928 |
+
$this->debug('read to EOF');
|
929 |
+
}
|
930 |
+
$this->debug('read body of length ' . strlen($data));
|
931 |
+
$this->incoming_payload .= $data;
|
932 |
+
$this->debug('received a total of '.strlen($this->incoming_payload).' bytes of data from server');
|
933 |
+
|
934 |
+
// close filepointer
|
935 |
+
if(
|
936 |
+
(isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') ||
|
937 |
+
(! $this->persistentConnection) || feof($this->fp)){
|
938 |
+
fclose($this->fp);
|
939 |
+
$this->fp = false;
|
940 |
+
$this->debug('closed socket');
|
941 |
+
}
|
942 |
+
|
943 |
+
// connection was closed unexpectedly
|
944 |
+
if($this->incoming_payload == ''){
|
945 |
+
$this->setError('no response from server');
|
946 |
+
return false;
|
947 |
+
}
|
948 |
+
|
949 |
+
// decode transfer-encoding
|
950 |
+
// if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){
|
951 |
+
// if(!$data = $this->decodeChunked($data, $lb)){
|
952 |
+
// $this->setError('Decoding of chunked data failed');
|
953 |
+
// return false;
|
954 |
+
// }
|
955 |
+
//print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";
|
956 |
+
// set decoded payload
|
957 |
+
// $this->incoming_payload = $header_data.$lb.$lb.$data;
|
958 |
+
// }
|
959 |
+
|
960 |
+
} else if ($this->io_method() == 'curl') {
|
961 |
+
// send and receive
|
962 |
+
$this->debug('send and receive with cURL');
|
963 |
+
$this->incoming_payload = curl_exec($this->ch);
|
964 |
+
$data = $this->incoming_payload;
|
965 |
+
|
966 |
+
$cErr = curl_error($this->ch);
|
967 |
+
if ($cErr != '') {
|
968 |
+
$err = 'cURL ERROR: '.curl_errno($this->ch).': '.$cErr.'<br>';
|
969 |
+
// TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE
|
970 |
+
foreach(curl_getinfo($this->ch) as $k => $v){
|
971 |
+
$err .= "$k: $v<br>";
|
972 |
+
}
|
973 |
+
$this->debug($err);
|
974 |
+
$this->setError($err);
|
975 |
+
curl_close($this->ch);
|
976 |
+
return false;
|
977 |
+
} else {
|
978 |
+
//echo '<pre>';
|
979 |
+
//var_dump(curl_getinfo($this->ch));
|
980 |
+
//echo '</pre>';
|
981 |
+
}
|
982 |
+
// close curl
|
983 |
+
$this->debug('No cURL error, closing cURL');
|
984 |
+
curl_close($this->ch);
|
985 |
+
|
986 |
+
// try removing skippable headers
|
987 |
+
$savedata = $data;
|
988 |
+
while ($this->isSkippableCurlHeader($data)) {
|
989 |
+
$this->debug("Found HTTP header to skip");
|
990 |
+
if ($pos = strpos($data,"\r\n\r\n")) {
|
991 |
+
$data = ltrim(substr($data,$pos));
|
992 |
+
} elseif($pos = strpos($data,"\n\n") ) {
|
993 |
+
$data = ltrim(substr($data,$pos));
|
994 |
+
}
|
995 |
+
}
|
996 |
+
|
997 |
+
if ($data == '') {
|
998 |
+
// have nothing left; just remove 100 header(s)
|
999 |
+
$data = $savedata;
|
1000 |
+
while (preg_match('/^HTTP\/1.1 100/',$data)) {
|
1001 |
+
if ($pos = strpos($data,"\r\n\r\n")) {
|
1002 |
+
$data = ltrim(substr($data,$pos));
|
1003 |
+
} elseif($pos = strpos($data,"\n\n") ) {
|
1004 |
+
$data = ltrim(substr($data,$pos));
|
1005 |
+
}
|
1006 |
+
}
|
1007 |
+
}
|
1008 |
+
|
1009 |
+
// separate content from HTTP headers
|
1010 |
+
if ($pos = strpos($data,"\r\n\r\n")) {
|
1011 |
+
$lb = "\r\n";
|
1012 |
+
} elseif( $pos = strpos($data,"\n\n")) {
|
1013 |
+
$lb = "\n";
|
1014 |
+
} else {
|
1015 |
+
$this->debug('no proper separation of headers and document');
|
1016 |
+
$this->setError('no proper separation of headers and document');
|
1017 |
+
return false;
|
1018 |
+
}
|
1019 |
+
$header_data = trim(substr($data,0,$pos));
|
1020 |
+
$header_array = explode($lb,$header_data);
|
1021 |
+
$data = ltrim(substr($data,$pos));
|
1022 |
+
$this->debug('found proper separation of headers and document');
|
1023 |
+
$this->debug('cleaned data, stringlen: '.strlen($data));
|
1024 |
+
// clean headers
|
1025 |
+
foreach ($header_array as $header_line) {
|
1026 |
+
$arr = explode(':',$header_line,2);
|
1027 |
+
if(count($arr) > 1){
|
1028 |
+
$header_name = strtolower(trim($arr[0]));
|
1029 |
+
$this->incoming_headers[$header_name] = trim($arr[1]);
|
1030 |
+
if ($header_name == 'set-cookie') {
|
1031 |
+
// TODO: allow multiple cookies from parseCookie
|
1032 |
+
$cookie = $this->parseCookie(trim($arr[1]));
|
1033 |
+
if ($cookie) {
|
1034 |
+
$this->incoming_cookies[] = $cookie;
|
1035 |
+
$this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
|
1036 |
+
} else {
|
1037 |
+
$this->debug('did not find cookie in ' . trim($arr[1]));
|
1038 |
+
}
|
1039 |
+
}
|
1040 |
+
} else if (isset($header_name)) {
|
1041 |
+
// append continuation line to previous header
|
1042 |
+
$this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
|
1043 |
+
}
|
1044 |
+
}
|
1045 |
+
}
|
1046 |
+
|
1047 |
+
$this->response_status_line = $header_array[0];
|
1048 |
+
$arr = explode(' ', $this->response_status_line, 3);
|
1049 |
+
$http_version = $arr[0];
|
1050 |
+
$http_status = intval($arr[1]);
|
1051 |
+
$http_reason = count($arr) > 2 ? $arr[2] : '';
|
1052 |
+
|
1053 |
+
// see if we need to resend the request with http digest authentication
|
1054 |
+
if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) {
|
1055 |
+
$this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']);
|
1056 |
+
$this->setURL($this->incoming_headers['location']);
|
1057 |
+
$this->tryagain = true;
|
1058 |
+
return false;
|
1059 |
+
}
|
1060 |
+
|
1061 |
+
// see if we need to resend the request with http digest authentication
|
1062 |
+
if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) {
|
1063 |
+
$this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']);
|
1064 |
+
if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) {
|
1065 |
+
$this->debug('Server wants digest authentication');
|
1066 |
+
// remove "Digest " from our elements
|
1067 |
+
$digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);
|
1068 |
+
|
1069 |
+
// parse elements into array
|
1070 |
+
$digestElements = explode(',', $digestString);
|
1071 |
+
foreach ($digestElements as $val) {
|
1072 |
+
$tempElement = explode('=', trim($val), 2);
|
1073 |
+
$digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);
|
1074 |
+
}
|
1075 |
+
|
1076 |
+
// should have (at least) qop, realm, nonce
|
1077 |
+
if (isset($digestRequest['nonce'])) {
|
1078 |
+
$this->setCredentials($this->username, $this->password, 'digest', $digestRequest);
|
1079 |
+
$this->tryagain = true;
|
1080 |
+
return false;
|
1081 |
+
}
|
1082 |
+
}
|
1083 |
+
$this->debug('HTTP authentication failed');
|
1084 |
+
$this->setError('HTTP authentication failed');
|
1085 |
+
return false;
|
1086 |
+
}
|
1087 |
+
|
1088 |
+
if (
|
1089 |
+
($http_status >= 300 && $http_status <= 307) ||
|
1090 |
+
($http_status >= 400 && $http_status <= 417) ||
|
1091 |
+
($http_status >= 501 && $http_status <= 505)
|
1092 |
+
) {
|
1093 |
+
$this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");
|
1094 |
+
return false;
|
1095 |
+
}
|
1096 |
+
|
1097 |
+
// decode content-encoding
|
1098 |
+
if(isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != ''){
|
1099 |
+
if(strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip'){
|
1100 |
+
// if decoding works, use it. else assume data wasn't gzencoded
|
1101 |
+
if(function_exists('gzinflate')){
|
1102 |
+
//$timer->setMarker('starting decoding of gzip/deflated content');
|
1103 |
+
// IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress)
|
1104 |
+
// this means there are no Zlib headers, although there should be
|
1105 |
+
$this->debug('The gzinflate function exists');
|
1106 |
+
$datalen = strlen($data);
|
1107 |
+
if ($this->incoming_headers['content-encoding'] == 'deflate') {
|
1108 |
+
if ($degzdata = @gzinflate($data)) {
|
1109 |
+
$data = $degzdata;
|
1110 |
+
$this->debug('The payload has been inflated to ' . strlen($data) . ' bytes');
|
1111 |
+
if (strlen($data) < $datalen) {
|
1112 |
+
// test for the case that the payload has been compressed twice
|
1113 |
+
$this->debug('The inflated payload is smaller than the gzipped one; try again');
|
1114 |
+
if ($degzdata = @gzinflate($data)) {
|
1115 |
+
$data = $degzdata;
|
1116 |
+
$this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes');
|
1117 |
+
}
|
1118 |
+
}
|
1119 |
+
} else {
|
1120 |
+
$this->debug('Error using gzinflate to inflate the payload');
|
1121 |
+
$this->setError('Error using gzinflate to inflate the payload');
|
1122 |
+
}
|
1123 |
+
} elseif ($this->incoming_headers['content-encoding'] == 'gzip') {
|
1124 |
+
if ($degzdata = @gzinflate(substr($data, 10))) { // do our best
|
1125 |
+
$data = $degzdata;
|
1126 |
+
$this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes');
|
1127 |
+
if (strlen($data) < $datalen) {
|
1128 |
+
// test for the case that the payload has been compressed twice
|
1129 |
+
$this->debug('The un-gzipped payload is smaller than the gzipped one; try again');
|
1130 |
+
if ($degzdata = @gzinflate(substr($data, 10))) {
|
1131 |
+
$data = $degzdata;
|
1132 |
+
$this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes');
|
1133 |
+
}
|
1134 |
+
}
|
1135 |
+
} else {
|
1136 |
+
$this->debug('Error using gzinflate to un-gzip the payload');
|
1137 |
+
$this->setError('Error using gzinflate to un-gzip the payload');
|
1138 |
+
}
|
1139 |
+
}
|
1140 |
+
//$timer->setMarker('finished decoding of gzip/deflated content');
|
1141 |
+
//print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";
|
1142 |
+
// set decoded payload
|
1143 |
+
$this->incoming_payload = $header_data.$lb.$lb.$data;
|
1144 |
+
} else {
|
1145 |
+
$this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
|
1146 |
+
$this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
|
1147 |
+
}
|
1148 |
+
} else {
|
1149 |
+
$this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
|
1150 |
+
$this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
|
1151 |
+
}
|
1152 |
+
} else {
|
1153 |
+
$this->debug('No Content-Encoding header');
|
1154 |
+
}
|
1155 |
+
|
1156 |
+
if(strlen($data) == 0){
|
1157 |
+
$this->debug('no data after headers!');
|
1158 |
+
$this->setError('no data present after HTTP headers');
|
1159 |
+
return false;
|
1160 |
+
}
|
1161 |
+
|
1162 |
+
return $data;
|
1163 |
+
}
|
1164 |
+
|
1165 |
+
/**
|
1166 |
+
* sets the content-type for the SOAP message to be sent
|
1167 |
+
*
|
1168 |
+
* @param string $type the content type, MIME style
|
1169 |
+
* @param mixed $charset character set used for encoding (or false)
|
1170 |
+
* @access public
|
1171 |
+
*/
|
1172 |
+
function setContentType($type, $charset = false) {
|
1173 |
+
$this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
|
1174 |
+
}
|
1175 |
+
|
1176 |
+
/**
|
1177 |
+
* specifies that an HTTP persistent connection should be used
|
1178 |
+
*
|
1179 |
+
* @return boolean whether the request was honored by this method.
|
1180 |
+
* @access public
|
1181 |
+
*/
|
1182 |
+
function usePersistentConnection(){
|
1183 |
+
if (isset($this->outgoing_headers['Accept-Encoding'])) {
|
1184 |
+
return false;
|
1185 |
+
}
|
1186 |
+
$this->protocol_version = '1.1';
|
1187 |
+
$this->persistentConnection = true;
|
1188 |
+
$this->setHeader('Connection', 'Keep-Alive');
|
1189 |
+
return true;
|
1190 |
+
}
|
1191 |
+
|
1192 |
+
/**
|
1193 |
+
* parse an incoming Cookie into it's parts
|
1194 |
+
*
|
1195 |
+
* @param string $cookie_str content of cookie
|
1196 |
+
* @return array with data of that cookie
|
1197 |
+
* @access private
|
1198 |
+
*/
|
1199 |
+
/*
|
1200 |
+
* TODO: allow a Set-Cookie string to be parsed into multiple cookies
|
1201 |
+
*/
|
1202 |
+
function parseCookie($cookie_str) {
|
1203 |
+
$cookie_str = str_replace('; ', ';', $cookie_str) . ';';
|
1204 |
+
$data = preg_split('/;/', $cookie_str);
|
1205 |
+
$value_str = $data[0];
|
1206 |
+
|
1207 |
+
$cookie_param = 'domain=';
|
1208 |
+
$start = strpos($cookie_str, $cookie_param);
|
1209 |
+
if ($start > 0) {
|
1210 |
+
$domain = substr($cookie_str, $start + strlen($cookie_param));
|
1211 |
+
$domain = substr($domain, 0, strpos($domain, ';'));
|
1212 |
+
} else {
|
1213 |
+
$domain = '';
|
1214 |
+
}
|
1215 |
+
|
1216 |
+
$cookie_param = 'expires=';
|
1217 |
+
$start = strpos($cookie_str, $cookie_param);
|
1218 |
+
if ($start > 0) {
|
1219 |
+
$expires = substr($cookie_str, $start + strlen($cookie_param));
|
1220 |
+
$expires = substr($expires, 0, strpos($expires, ';'));
|
1221 |
+
} else {
|
1222 |
+
$expires = '';
|
1223 |
+
}
|
1224 |
+
|
1225 |
+
$cookie_param = 'path=';
|
1226 |
+
$start = strpos($cookie_str, $cookie_param);
|
1227 |
+
if ( $start > 0 ) {
|
1228 |
+
$path = substr($cookie_str, $start + strlen($cookie_param));
|
1229 |
+
$path = substr($path, 0, strpos($path, ';'));
|
1230 |
+
} else {
|
1231 |
+
$path = '/';
|
1232 |
+
}
|
1233 |
+
|
1234 |
+
$cookie_param = ';secure;';
|
1235 |
+
if (strpos($cookie_str, $cookie_param) !== FALSE) {
|
1236 |
+
$secure = true;
|
1237 |
+
} else {
|
1238 |
+
$secure = false;
|
1239 |
+
}
|
1240 |
+
|
1241 |
+
$sep_pos = strpos($value_str, '=');
|
1242 |
+
|
1243 |
+
if ($sep_pos) {
|
1244 |
+
$name = substr($value_str, 0, $sep_pos);
|
1245 |
+
$value = substr($value_str, $sep_pos + 1);
|
1246 |
+
$cookie= array( 'name' => $name,
|
1247 |
+
'value' => $value,
|
1248 |
+
'domain' => $domain,
|
1249 |
+
'path' => $path,
|
1250 |
+
'expires' => $expires,
|
1251 |
+
'secure' => $secure
|
1252 |
+
);
|
1253 |
+
return $cookie;
|
1254 |
+
}
|
1255 |
+
return false;
|
1256 |
+
}
|
1257 |
+
|
1258 |
+
/**
|
1259 |
+
* sort out cookies for the current request
|
1260 |
+
*
|
1261 |
+
* @param array $cookies array with all cookies
|
1262 |
+
* @param boolean $secure is the send-content secure or not?
|
1263 |
+
* @return string for Cookie-HTTP-Header
|
1264 |
+
* @access private
|
1265 |
+
*/
|
1266 |
+
function getCookiesForRequest($cookies, $secure=false) {
|
1267 |
+
$cookie_str = '';
|
1268 |
+
if ((! is_null($cookies)) && (is_array($cookies))) {
|
1269 |
+
foreach ($cookies as $cookie) {
|
1270 |
+
if (! is_array($cookie)) {
|
1271 |
+
continue;
|
1272 |
+
}
|
1273 |
+
$this->debug("check cookie for validity: ".$cookie['name'].'='.$cookie['value']);
|
1274 |
+
if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
|
1275 |
+
if (strtotime($cookie['expires']) <= time()) {
|
1276 |
+
$this->debug('cookie has expired');
|
1277 |
+
continue;
|
1278 |
+
}
|
1279 |
+
}
|
1280 |
+
if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) {
|
1281 |
+
$domain = preg_quote($cookie['domain']);
|
1282 |
+
if (! preg_match("'.*$domain$'i", $this->host)) {
|
1283 |
+
$this->debug('cookie has different domain');
|
1284 |
+
continue;
|
1285 |
+
}
|
1286 |
+
}
|
1287 |
+
if ((isset($cookie['path'])) && (! empty($cookie['path']))) {
|
1288 |
+
$path = preg_quote($cookie['path']);
|
1289 |
+
if (! preg_match("'^$path.*'i", $this->path)) {
|
1290 |
+
$this->debug('cookie is for a different path');
|
1291 |
+
continue;
|
1292 |
+
}
|
1293 |
+
}
|
1294 |
+
if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) {
|
1295 |
+
$this->debug('cookie is secure, transport is not');
|
1296 |
+
continue;
|
1297 |
+
}
|
1298 |
+
$cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';
|
1299 |
+
$this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']);
|
1300 |
+
}
|
1301 |
+
}
|
1302 |
+
return $cookie_str;
|
1303 |
+
}
|
1304 |
+
}
|
1305 |
+
|
1306 |
+
|
1307 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.soap_val.php
ADDED
@@ -0,0 +1,107 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
|
4 |
+
|
5 |
+
|
6 |
+
/**
|
7 |
+
* For creating serializable abstractions of native PHP types. This class
|
8 |
+
* allows element name/namespace, XSD type, and XML attributes to be
|
9 |
+
* associated with a value. This is extremely useful when WSDL is not
|
10 |
+
* used, but is also useful when WSDL is used with polymorphic types, including
|
11 |
+
* xsd:anyType and user-defined types.
|
12 |
+
*
|
13 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
14 |
+
* @version $Id: class.soap_val.php,v 1.11 2007/04/06 13:56:32 snichol Exp $
|
15 |
+
* @access public
|
16 |
+
*/
|
17 |
+
class soapval extends nusoap_base {
|
18 |
+
/**
|
19 |
+
* The XML element name
|
20 |
+
*
|
21 |
+
* @var string
|
22 |
+
* @access private
|
23 |
+
*/
|
24 |
+
var $name;
|
25 |
+
/**
|
26 |
+
* The XML type name (string or false)
|
27 |
+
*
|
28 |
+
* @var mixed
|
29 |
+
* @access private
|
30 |
+
*/
|
31 |
+
var $type;
|
32 |
+
/**
|
33 |
+
* The PHP value
|
34 |
+
*
|
35 |
+
* @var mixed
|
36 |
+
* @access private
|
37 |
+
*/
|
38 |
+
var $value;
|
39 |
+
/**
|
40 |
+
* The XML element namespace (string or false)
|
41 |
+
*
|
42 |
+
* @var mixed
|
43 |
+
* @access private
|
44 |
+
*/
|
45 |
+
var $element_ns;
|
46 |
+
/**
|
47 |
+
* The XML type namespace (string or false)
|
48 |
+
*
|
49 |
+
* @var mixed
|
50 |
+
* @access private
|
51 |
+
*/
|
52 |
+
var $type_ns;
|
53 |
+
/**
|
54 |
+
* The XML element attributes (array or false)
|
55 |
+
*
|
56 |
+
* @var mixed
|
57 |
+
* @access private
|
58 |
+
*/
|
59 |
+
var $attributes;
|
60 |
+
|
61 |
+
/**
|
62 |
+
* constructor
|
63 |
+
*
|
64 |
+
* @param string $name optional name
|
65 |
+
* @param mixed $type optional type name
|
66 |
+
* @param mixed $value optional value
|
67 |
+
* @param mixed $element_ns optional namespace of value
|
68 |
+
* @param mixed $type_ns optional namespace of type
|
69 |
+
* @param mixed $attributes associative array of attributes to add to element serialization
|
70 |
+
* @access public
|
71 |
+
*/
|
72 |
+
function soapval($name='soapval',$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false) {
|
73 |
+
parent::nusoap_base();
|
74 |
+
$this->name = $name;
|
75 |
+
$this->type = $type;
|
76 |
+
$this->value = $value;
|
77 |
+
$this->element_ns = $element_ns;
|
78 |
+
$this->type_ns = $type_ns;
|
79 |
+
$this->attributes = $attributes;
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* return serialized value
|
84 |
+
*
|
85 |
+
* @param string $use The WSDL use value (encoded|literal)
|
86 |
+
* @return string XML data
|
87 |
+
* @access public
|
88 |
+
*/
|
89 |
+
function serialize($use='encoded') {
|
90 |
+
return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true);
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* decodes a soapval object into a PHP native type
|
95 |
+
*
|
96 |
+
* @return mixed
|
97 |
+
* @access public
|
98 |
+
*/
|
99 |
+
function decode(){
|
100 |
+
return $this->value;
|
101 |
+
}
|
102 |
+
}
|
103 |
+
|
104 |
+
|
105 |
+
|
106 |
+
|
107 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.soapclient.php
ADDED
@@ -0,0 +1,991 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
|
4 |
+
|
5 |
+
|
6 |
+
/**
|
7 |
+
*
|
8 |
+
* [nu]soapclient higher level class for easy usage.
|
9 |
+
*
|
10 |
+
* usage:
|
11 |
+
*
|
12 |
+
* // instantiate client with server info
|
13 |
+
* $soapclient = new nusoap_client( string path [ ,mixed wsdl] );
|
14 |
+
*
|
15 |
+
* // call method, get results
|
16 |
+
* echo $soapclient->call( string methodname [ ,array parameters] );
|
17 |
+
*
|
18 |
+
* // bye bye client
|
19 |
+
* unset($soapclient);
|
20 |
+
*
|
21 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
22 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
23 |
+
* @version $Id: class.soapclient.php,v 1.69 2010/04/26 20:15:08 snichol Exp $
|
24 |
+
* @access public
|
25 |
+
*/
|
26 |
+
class nusoap_client extends nusoap_base {
|
27 |
+
|
28 |
+
var $username = ''; // Username for HTTP authentication
|
29 |
+
var $password = ''; // Password for HTTP authentication
|
30 |
+
var $authtype = ''; // Type of HTTP authentication
|
31 |
+
var $certRequest = array(); // Certificate for HTTP SSL authentication
|
32 |
+
var $requestHeaders = false; // SOAP headers in request (text)
|
33 |
+
var $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (text)
|
34 |
+
var $responseHeader = NULL; // SOAP Header from response (parsed)
|
35 |
+
var $document = ''; // SOAP body response portion (incomplete namespace resolution) (text)
|
36 |
+
var $endpoint;
|
37 |
+
var $forceEndpoint = ''; // overrides WSDL endpoint
|
38 |
+
var $proxyhost = '';
|
39 |
+
var $proxyport = '';
|
40 |
+
var $proxyusername = '';
|
41 |
+
var $proxypassword = '';
|
42 |
+
var $portName = ''; // port name to use in WSDL
|
43 |
+
var $xml_encoding = ''; // character set encoding of incoming (response) messages
|
44 |
+
var $http_encoding = false;
|
45 |
+
var $timeout = 0; // HTTP connection timeout
|
46 |
+
var $response_timeout = 30; // HTTP response timeout
|
47 |
+
var $endpointType = ''; // soap|wsdl, empty for WSDL initialization error
|
48 |
+
var $persistentConnection = false;
|
49 |
+
var $defaultRpcParams = false; // This is no longer used
|
50 |
+
var $request = ''; // HTTP request
|
51 |
+
var $response = ''; // HTTP response
|
52 |
+
var $responseData = ''; // SOAP payload of response
|
53 |
+
var $cookies = array(); // Cookies from response or for request
|
54 |
+
var $decode_utf8 = true; // toggles whether the parser decodes element content w/ utf8_decode()
|
55 |
+
var $operations = array(); // WSDL operations, empty for WSDL initialization error
|
56 |
+
var $curl_options = array(); // User-specified cURL options
|
57 |
+
var $bindingType = ''; // WSDL operation binding type
|
58 |
+
var $use_curl = false; // whether to always try to use cURL
|
59 |
+
|
60 |
+
/*
|
61 |
+
* fault related variables
|
62 |
+
*/
|
63 |
+
/**
|
64 |
+
* @var fault
|
65 |
+
* @access public
|
66 |
+
*/
|
67 |
+
var $fault;
|
68 |
+
/**
|
69 |
+
* @var faultcode
|
70 |
+
* @access public
|
71 |
+
*/
|
72 |
+
var $faultcode;
|
73 |
+
/**
|
74 |
+
* @var faultstring
|
75 |
+
* @access public
|
76 |
+
*/
|
77 |
+
var $faultstring;
|
78 |
+
/**
|
79 |
+
* @var faultdetail
|
80 |
+
* @access public
|
81 |
+
*/
|
82 |
+
var $faultdetail;
|
83 |
+
|
84 |
+
/**
|
85 |
+
* constructor
|
86 |
+
*
|
87 |
+
* @param mixed $endpoint SOAP server or WSDL URL (string), or wsdl instance (object)
|
88 |
+
* @param mixed $wsdl optional, set to 'wsdl' or true if using WSDL
|
89 |
+
* @param string $proxyhost optional
|
90 |
+
* @param string $proxyport optional
|
91 |
+
* @param string $proxyusername optional
|
92 |
+
* @param string $proxypassword optional
|
93 |
+
* @param integer $timeout set the connection timeout
|
94 |
+
* @param integer $response_timeout set the response timeout
|
95 |
+
* @param string $portName optional portName in WSDL document
|
96 |
+
* @access public
|
97 |
+
*/
|
98 |
+
function nusoap_client($endpoint,$wsdl = false,$proxyhost = false,$proxyport = false,$proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30, $portName = ''){
|
99 |
+
parent::nusoap_base();
|
100 |
+
$this->endpoint = $endpoint;
|
101 |
+
$this->proxyhost = $proxyhost;
|
102 |
+
$this->proxyport = $proxyport;
|
103 |
+
$this->proxyusername = $proxyusername;
|
104 |
+
$this->proxypassword = $proxypassword;
|
105 |
+
$this->timeout = $timeout;
|
106 |
+
$this->response_timeout = $response_timeout;
|
107 |
+
$this->portName = $portName;
|
108 |
+
|
109 |
+
$this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
|
110 |
+
$this->appendDebug('endpoint=' . $this->varDump($endpoint));
|
111 |
+
|
112 |
+
// make values
|
113 |
+
if($wsdl){
|
114 |
+
if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) {
|
115 |
+
$this->wsdl = $endpoint;
|
116 |
+
$this->endpoint = $this->wsdl->wsdl;
|
117 |
+
$this->wsdlFile = $this->endpoint;
|
118 |
+
$this->debug('existing wsdl instance created from ' . $this->endpoint);
|
119 |
+
$this->checkWSDL();
|
120 |
+
} else {
|
121 |
+
$this->wsdlFile = $this->endpoint;
|
122 |
+
$this->wsdl = null;
|
123 |
+
$this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint);
|
124 |
+
}
|
125 |
+
$this->endpointType = 'wsdl';
|
126 |
+
} else {
|
127 |
+
$this->debug("instantiate SOAP with endpoint at $endpoint");
|
128 |
+
$this->endpointType = 'soap';
|
129 |
+
}
|
130 |
+
}
|
131 |
+
|
132 |
+
/**
|
133 |
+
* calls method, returns PHP native type
|
134 |
+
*
|
135 |
+
* @param string $operation SOAP server URL or path
|
136 |
+
* @param mixed $params An array, associative or simple, of the parameters
|
137 |
+
* for the method call, or a string that is the XML
|
138 |
+
* for the call. For rpc style, this call will
|
139 |
+
* wrap the XML in a tag named after the method, as
|
140 |
+
* well as the SOAP Envelope and Body. For document
|
141 |
+
* style, this will only wrap with the Envelope and Body.
|
142 |
+
* IMPORTANT: when using an array with document style,
|
143 |
+
* in which case there
|
144 |
+
* is really one parameter, the root of the fragment
|
145 |
+
* used in the call, which encloses what programmers
|
146 |
+
* normally think of parameters. A parameter array
|
147 |
+
* *must* include the wrapper.
|
148 |
+
* @param string $namespace optional method namespace (WSDL can override)
|
149 |
+
* @param string $soapAction optional SOAPAction value (WSDL can override)
|
150 |
+
* @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
|
151 |
+
* @param boolean $rpcParams optional (no longer used)
|
152 |
+
* @param string $style optional (rpc|document) the style to use when serializing parameters (WSDL can override)
|
153 |
+
* @param string $use optional (encoded|literal) the use when serializing parameters (WSDL can override)
|
154 |
+
* @return mixed response from SOAP call, normally an associative array mirroring the structure of the XML response, false for certain fatal errors
|
155 |
+
* @access public
|
156 |
+
*/
|
157 |
+
function call($operation,$params=array(),$namespace='http://tempuri.org',$soapAction='',$headers=false,$rpcParams=null,$style='rpc',$use='encoded'){
|
158 |
+
$this->operation = $operation;
|
159 |
+
$this->fault = false;
|
160 |
+
$this->setError('');
|
161 |
+
$this->request = '';
|
162 |
+
$this->response = '';
|
163 |
+
$this->responseData = '';
|
164 |
+
$this->faultstring = '';
|
165 |
+
$this->faultcode = '';
|
166 |
+
$this->opData = array();
|
167 |
+
|
168 |
+
$this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType");
|
169 |
+
$this->appendDebug('params=' . $this->varDump($params));
|
170 |
+
$this->appendDebug('headers=' . $this->varDump($headers));
|
171 |
+
if ($headers) {
|
172 |
+
$this->requestHeaders = $headers;
|
173 |
+
}
|
174 |
+
if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
|
175 |
+
$this->loadWSDL();
|
176 |
+
if ($this->getError())
|
177 |
+
return false;
|
178 |
+
}
|
179 |
+
// serialize parameters
|
180 |
+
if($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)){
|
181 |
+
// use WSDL for operation
|
182 |
+
$this->opData = $opData;
|
183 |
+
$this->debug("found operation");
|
184 |
+
$this->appendDebug('opData=' . $this->varDump($opData));
|
185 |
+
if (isset($opData['soapAction'])) {
|
186 |
+
$soapAction = $opData['soapAction'];
|
187 |
+
}
|
188 |
+
if (! $this->forceEndpoint) {
|
189 |
+
$this->endpoint = $opData['endpoint'];
|
190 |
+
} else {
|
191 |
+
$this->endpoint = $this->forceEndpoint;
|
192 |
+
}
|
193 |
+
$namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] : $namespace;
|
194 |
+
$style = $opData['style'];
|
195 |
+
$use = $opData['input']['use'];
|
196 |
+
// add ns to ns array
|
197 |
+
if($namespace != '' && !isset($this->wsdl->namespaces[$namespace])){
|
198 |
+
$nsPrefix = 'ns' . rand(1000, 9999);
|
199 |
+
$this->wsdl->namespaces[$nsPrefix] = $namespace;
|
200 |
+
}
|
201 |
+
$nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);
|
202 |
+
// serialize payload
|
203 |
+
if (is_string($params)) {
|
204 |
+
$this->debug("serializing param string for WSDL operation $operation");
|
205 |
+
$payload = $params;
|
206 |
+
} elseif (is_array($params)) {
|
207 |
+
$this->debug("serializing param array for WSDL operation $operation");
|
208 |
+
$payload = $this->wsdl->serializeRPCParameters($operation,'input',$params,$this->bindingType);
|
209 |
+
} else {
|
210 |
+
$this->debug('params must be array or string');
|
211 |
+
$this->setError('params must be array or string');
|
212 |
+
return false;
|
213 |
+
}
|
214 |
+
$usedNamespaces = $this->wsdl->usedNamespaces;
|
215 |
+
if (isset($opData['input']['encodingStyle'])) {
|
216 |
+
$encodingStyle = $opData['input']['encodingStyle'];
|
217 |
+
} else {
|
218 |
+
$encodingStyle = '';
|
219 |
+
}
|
220 |
+
$this->appendDebug($this->wsdl->getDebug());
|
221 |
+
$this->wsdl->clearDebug();
|
222 |
+
if ($errstr = $this->wsdl->getError()) {
|
223 |
+
$this->debug('got wsdl error: '.$errstr);
|
224 |
+
$this->setError('wsdl error: '.$errstr);
|
225 |
+
return false;
|
226 |
+
}
|
227 |
+
} elseif($this->endpointType == 'wsdl') {
|
228 |
+
// operation not in WSDL
|
229 |
+
$this->appendDebug($this->wsdl->getDebug());
|
230 |
+
$this->wsdl->clearDebug();
|
231 |
+
$this->setError('operation '.$operation.' not present in WSDL.');
|
232 |
+
$this->debug("operation '$operation' not present in WSDL.");
|
233 |
+
return false;
|
234 |
+
} else {
|
235 |
+
// no WSDL
|
236 |
+
//$this->namespaces['ns1'] = $namespace;
|
237 |
+
$nsPrefix = 'ns' . rand(1000, 9999);
|
238 |
+
// serialize
|
239 |
+
$payload = '';
|
240 |
+
if (is_string($params)) {
|
241 |
+
$this->debug("serializing param string for operation $operation");
|
242 |
+
$payload = $params;
|
243 |
+
} elseif (is_array($params)) {
|
244 |
+
$this->debug("serializing param array for operation $operation");
|
245 |
+
foreach($params as $k => $v){
|
246 |
+
$payload .= $this->serialize_val($v,$k,false,false,false,false,$use);
|
247 |
+
}
|
248 |
+
} else {
|
249 |
+
$this->debug('params must be array or string');
|
250 |
+
$this->setError('params must be array or string');
|
251 |
+
return false;
|
252 |
+
}
|
253 |
+
$usedNamespaces = array();
|
254 |
+
if ($use == 'encoded') {
|
255 |
+
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
|
256 |
+
} else {
|
257 |
+
$encodingStyle = '';
|
258 |
+
}
|
259 |
+
}
|
260 |
+
// wrap RPC calls with method element
|
261 |
+
if ($style == 'rpc') {
|
262 |
+
if ($use == 'literal') {
|
263 |
+
$this->debug("wrapping RPC request with literal method element");
|
264 |
+
if ($namespace) {
|
265 |
+
// 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
|
266 |
+
$payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
|
267 |
+
$payload .
|
268 |
+
"</$nsPrefix:$operation>";
|
269 |
+
} else {
|
270 |
+
$payload = "<$operation>" . $payload . "</$operation>";
|
271 |
+
}
|
272 |
+
} else {
|
273 |
+
$this->debug("wrapping RPC request with encoded method element");
|
274 |
+
if ($namespace) {
|
275 |
+
$payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
|
276 |
+
$payload .
|
277 |
+
"</$nsPrefix:$operation>";
|
278 |
+
} else {
|
279 |
+
$payload = "<$operation>" .
|
280 |
+
$payload .
|
281 |
+
"</$operation>";
|
282 |
+
}
|
283 |
+
}
|
284 |
+
}
|
285 |
+
// serialize envelope
|
286 |
+
$soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders,$usedNamespaces,$style,$use,$encodingStyle);
|
287 |
+
$this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
|
288 |
+
$this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
|
289 |
+
// send
|
290 |
+
$return = $this->send($this->getHTTPBody($soapmsg),$soapAction,$this->timeout,$this->response_timeout);
|
291 |
+
if($errstr = $this->getError()){
|
292 |
+
$this->debug('Error: '.$errstr);
|
293 |
+
return false;
|
294 |
+
} else {
|
295 |
+
$this->return = $return;
|
296 |
+
$this->debug('sent message successfully and got a(n) '.gettype($return));
|
297 |
+
$this->appendDebug('return=' . $this->varDump($return));
|
298 |
+
|
299 |
+
// fault?
|
300 |
+
if(is_array($return) && isset($return['faultcode'])){
|
301 |
+
$this->debug('got fault');
|
302 |
+
$this->setError($return['faultcode'].': '.$return['faultstring']);
|
303 |
+
$this->fault = true;
|
304 |
+
foreach($return as $k => $v){
|
305 |
+
$this->$k = $v;
|
306 |
+
$this->debug("$k = $v<br>");
|
307 |
+
}
|
308 |
+
return $return;
|
309 |
+
} elseif ($style == 'document') {
|
310 |
+
// NOTE: if the response is defined to have multiple parts (i.e. unwrapped),
|
311 |
+
// we are only going to return the first part here...sorry about that
|
312 |
+
return $return;
|
313 |
+
} else {
|
314 |
+
// array of return values
|
315 |
+
if(is_array($return)){
|
316 |
+
// multiple 'out' parameters, which we return wrapped up
|
317 |
+
// in the array
|
318 |
+
if(sizeof($return) > 1){
|
319 |
+
return $return;
|
320 |
+
}
|
321 |
+
// single 'out' parameter (normally the return value)
|
322 |
+
$return = array_shift($return);
|
323 |
+
$this->debug('return shifted value: ');
|
324 |
+
$this->appendDebug($this->varDump($return));
|
325 |
+
return $return;
|
326 |
+
// nothing returned (ie, echoVoid)
|
327 |
+
} else {
|
328 |
+
return "";
|
329 |
+
}
|
330 |
+
}
|
331 |
+
}
|
332 |
+
}
|
333 |
+
|
334 |
+
/**
|
335 |
+
* check WSDL passed as an instance or pulled from an endpoint
|
336 |
+
*
|
337 |
+
* @access private
|
338 |
+
*/
|
339 |
+
function checkWSDL() {
|
340 |
+
$this->appendDebug($this->wsdl->getDebug());
|
341 |
+
$this->wsdl->clearDebug();
|
342 |
+
$this->debug('checkWSDL');
|
343 |
+
// catch errors
|
344 |
+
if ($errstr = $this->wsdl->getError()) {
|
345 |
+
$this->appendDebug($this->wsdl->getDebug());
|
346 |
+
$this->wsdl->clearDebug();
|
347 |
+
$this->debug('got wsdl error: '.$errstr);
|
348 |
+
$this->setError('wsdl error: '.$errstr);
|
349 |
+
} elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap')) {
|
350 |
+
$this->appendDebug($this->wsdl->getDebug());
|
351 |
+
$this->wsdl->clearDebug();
|
352 |
+
$this->bindingType = 'soap';
|
353 |
+
$this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
|
354 |
+
} elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap12')) {
|
355 |
+
$this->appendDebug($this->wsdl->getDebug());
|
356 |
+
$this->wsdl->clearDebug();
|
357 |
+
$this->bindingType = 'soap12';
|
358 |
+
$this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
|
359 |
+
$this->debug('**************** WARNING: SOAP 1.2 BINDING *****************');
|
360 |
+
} else {
|
361 |
+
$this->appendDebug($this->wsdl->getDebug());
|
362 |
+
$this->wsdl->clearDebug();
|
363 |
+
$this->debug('getOperations returned false');
|
364 |
+
$this->setError('no operations defined in the WSDL document!');
|
365 |
+
}
|
366 |
+
}
|
367 |
+
|
368 |
+
/**
|
369 |
+
* instantiate wsdl object and parse wsdl file
|
370 |
+
*
|
371 |
+
* @access public
|
372 |
+
*/
|
373 |
+
function loadWSDL() {
|
374 |
+
$this->debug('instantiating wsdl class with doc: '.$this->wsdlFile);
|
375 |
+
$this->wsdl = new wsdl('',$this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeout,$this->response_timeout,$this->curl_options,$this->use_curl);
|
376 |
+
$this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest);
|
377 |
+
$this->wsdl->fetchWSDL($this->wsdlFile);
|
378 |
+
$this->checkWSDL();
|
379 |
+
}
|
380 |
+
|
381 |
+
/**
|
382 |
+
* get available data pertaining to an operation
|
383 |
+
*
|
384 |
+
* @param string $operation operation name
|
385 |
+
* @return array array of data pertaining to the operation
|
386 |
+
* @access public
|
387 |
+
*/
|
388 |
+
function getOperationData($operation){
|
389 |
+
if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
|
390 |
+
$this->loadWSDL();
|
391 |
+
if ($this->getError())
|
392 |
+
return false;
|
393 |
+
}
|
394 |
+
if(isset($this->operations[$operation])){
|
395 |
+
return $this->operations[$operation];
|
396 |
+
}
|
397 |
+
$this->debug("No data for operation: $operation");
|
398 |
+
}
|
399 |
+
|
400 |
+
/**
|
401 |
+
* send the SOAP message
|
402 |
+
*
|
403 |
+
* Note: if the operation has multiple return values
|
404 |
+
* the return value of this method will be an array
|
405 |
+
* of those values.
|
406 |
+
*
|
407 |
+
* @param string $msg a SOAPx4 soapmsg object
|
408 |
+
* @param string $soapaction SOAPAction value
|
409 |
+
* @param integer $timeout set connection timeout in seconds
|
410 |
+
* @param integer $response_timeout set response timeout in seconds
|
411 |
+
* @return mixed native PHP types.
|
412 |
+
* @access private
|
413 |
+
*/
|
414 |
+
function send($msg, $soapaction = '', $timeout=0, $response_timeout=30) {
|
415 |
+
$this->checkCookies();
|
416 |
+
// detect transport
|
417 |
+
switch(true){
|
418 |
+
// http(s)
|
419 |
+
case preg_match('/^http/',$this->endpoint):
|
420 |
+
$this->debug('transporting via HTTP');
|
421 |
+
if($this->persistentConnection == true && is_object($this->persistentConnection)){
|
422 |
+
$http =& $this->persistentConnection;
|
423 |
+
} else {
|
424 |
+
$http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl);
|
425 |
+
if ($this->persistentConnection) {
|
426 |
+
$http->usePersistentConnection();
|
427 |
+
}
|
428 |
+
}
|
429 |
+
$http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset());
|
430 |
+
$http->setSOAPAction($soapaction);
|
431 |
+
if($this->proxyhost && $this->proxyport){
|
432 |
+
$http->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
|
433 |
+
}
|
434 |
+
if($this->authtype != '') {
|
435 |
+
$http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
|
436 |
+
}
|
437 |
+
if($this->http_encoding != ''){
|
438 |
+
$http->setEncoding($this->http_encoding);
|
439 |
+
}
|
440 |
+
$this->debug('sending message, length='.strlen($msg));
|
441 |
+
if(preg_match('/^http:/',$this->endpoint)){
|
442 |
+
//if(strpos($this->endpoint,'http:')){
|
443 |
+
$this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies);
|
444 |
+
} elseif(preg_match('/^https/',$this->endpoint)){
|
445 |
+
//} elseif(strpos($this->endpoint,'https:')){
|
446 |
+
//if(phpversion() == '4.3.0-dev'){
|
447 |
+
//$response = $http->send($msg,$timeout,$response_timeout);
|
448 |
+
//$this->request = $http->outgoing_payload;
|
449 |
+
//$this->response = $http->incoming_payload;
|
450 |
+
//} else
|
451 |
+
$this->responseData = $http->sendHTTPS($msg,$timeout,$response_timeout,$this->cookies);
|
452 |
+
} else {
|
453 |
+
$this->setError('no http/s in endpoint url');
|
454 |
+
}
|
455 |
+
$this->request = $http->outgoing_payload;
|
456 |
+
$this->response = $http->incoming_payload;
|
457 |
+
$this->appendDebug($http->getDebug());
|
458 |
+
$this->UpdateCookies($http->incoming_cookies);
|
459 |
+
|
460 |
+
// save transport object if using persistent connections
|
461 |
+
if ($this->persistentConnection) {
|
462 |
+
$http->clearDebug();
|
463 |
+
if (!is_object($this->persistentConnection)) {
|
464 |
+
$this->persistentConnection = $http;
|
465 |
+
}
|
466 |
+
}
|
467 |
+
|
468 |
+
if($err = $http->getError()){
|
469 |
+
$this->setError('HTTP Error: '.$err);
|
470 |
+
return false;
|
471 |
+
} elseif($this->getError()){
|
472 |
+
return false;
|
473 |
+
} else {
|
474 |
+
$this->debug('got response, length='. strlen($this->responseData).' type='.$http->incoming_headers['content-type']);
|
475 |
+
return $this->parseResponse($http->incoming_headers, $this->responseData);
|
476 |
+
}
|
477 |
+
break;
|
478 |
+
default:
|
479 |
+
$this->setError('no transport found, or selected transport is not yet supported!');
|
480 |
+
return false;
|
481 |
+
break;
|
482 |
+
}
|
483 |
+
}
|
484 |
+
|
485 |
+
/**
|
486 |
+
* processes SOAP message returned from server
|
487 |
+
*
|
488 |
+
* @param array $headers The HTTP headers
|
489 |
+
* @param string $data unprocessed response data from server
|
490 |
+
* @return mixed value of the message, decoded into a PHP type
|
491 |
+
* @access private
|
492 |
+
*/
|
493 |
+
function parseResponse($headers, $data) {
|
494 |
+
$this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:');
|
495 |
+
$this->appendDebug($this->varDump($headers));
|
496 |
+
if (!isset($headers['content-type'])) {
|
497 |
+
$this->setError('Response not of type text/xml (no content-type header)');
|
498 |
+
return false;
|
499 |
+
}
|
500 |
+
if (!strstr($headers['content-type'], 'text/xml')) {
|
501 |
+
$this->setError('Response not of type text/xml: ' . $headers['content-type']);
|
502 |
+
return false;
|
503 |
+
}
|
504 |
+
if (strpos($headers['content-type'], '=')) {
|
505 |
+
$enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
|
506 |
+
$this->debug('Got response encoding: ' . $enc);
|
507 |
+
if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
|
508 |
+
$this->xml_encoding = strtoupper($enc);
|
509 |
+
} else {
|
510 |
+
$this->xml_encoding = 'US-ASCII';
|
511 |
+
}
|
512 |
+
} else {
|
513 |
+
// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
|
514 |
+
$this->xml_encoding = 'ISO-8859-1';
|
515 |
+
}
|
516 |
+
$this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
|
517 |
+
$parser = new nusoap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8);
|
518 |
+
// add parser debug data to our debug
|
519 |
+
$this->appendDebug($parser->getDebug());
|
520 |
+
// if parse errors
|
521 |
+
if($errstr = $parser->getError()){
|
522 |
+
$this->setError( $errstr);
|
523 |
+
// destroy the parser object
|
524 |
+
unset($parser);
|
525 |
+
return false;
|
526 |
+
} else {
|
527 |
+
// get SOAP headers
|
528 |
+
$this->responseHeaders = $parser->getHeaders();
|
529 |
+
// get SOAP headers
|
530 |
+
$this->responseHeader = $parser->get_soapheader();
|
531 |
+
// get decoded message
|
532 |
+
$return = $parser->get_soapbody();
|
533 |
+
// add document for doclit support
|
534 |
+
$this->document = $parser->document;
|
535 |
+
// destroy the parser object
|
536 |
+
unset($parser);
|
537 |
+
// return decode message
|
538 |
+
return $return;
|
539 |
+
}
|
540 |
+
}
|
541 |
+
|
542 |
+
/**
|
543 |
+
* sets user-specified cURL options
|
544 |
+
*
|
545 |
+
* @param mixed $option The cURL option (always integer?)
|
546 |
+
* @param mixed $value The cURL option value
|
547 |
+
* @access public
|
548 |
+
*/
|
549 |
+
function setCurlOption($option, $value) {
|
550 |
+
$this->debug("setCurlOption option=$option, value=");
|
551 |
+
$this->appendDebug($this->varDump($value));
|
552 |
+
$this->curl_options[$option] = $value;
|
553 |
+
}
|
554 |
+
|
555 |
+
/**
|
556 |
+
* sets the SOAP endpoint, which can override WSDL
|
557 |
+
*
|
558 |
+
* @param string $endpoint The endpoint URL to use, or empty string or false to prevent override
|
559 |
+
* @access public
|
560 |
+
*/
|
561 |
+
function setEndpoint($endpoint) {
|
562 |
+
$this->debug("setEndpoint(\"$endpoint\")");
|
563 |
+
$this->forceEndpoint = $endpoint;
|
564 |
+
}
|
565 |
+
|
566 |
+
/**
|
567 |
+
* set the SOAP headers
|
568 |
+
*
|
569 |
+
* @param mixed $headers String of XML with SOAP header content, or array of soapval objects for SOAP headers
|
570 |
+
* @access public
|
571 |
+
*/
|
572 |
+
function setHeaders($headers){
|
573 |
+
$this->debug("setHeaders headers=");
|
574 |
+
$this->appendDebug($this->varDump($headers));
|
575 |
+
$this->requestHeaders = $headers;
|
576 |
+
}
|
577 |
+
|
578 |
+
/**
|
579 |
+
* get the SOAP response headers (namespace resolution incomplete)
|
580 |
+
*
|
581 |
+
* @return string
|
582 |
+
* @access public
|
583 |
+
*/
|
584 |
+
function getHeaders(){
|
585 |
+
return $this->responseHeaders;
|
586 |
+
}
|
587 |
+
|
588 |
+
/**
|
589 |
+
* get the SOAP response Header (parsed)
|
590 |
+
*
|
591 |
+
* @return mixed
|
592 |
+
* @access public
|
593 |
+
*/
|
594 |
+
function getHeader(){
|
595 |
+
return $this->responseHeader;
|
596 |
+
}
|
597 |
+
|
598 |
+
/**
|
599 |
+
* set proxy info here
|
600 |
+
*
|
601 |
+
* @param string $proxyhost
|
602 |
+
* @param string $proxyport
|
603 |
+
* @param string $proxyusername
|
604 |
+
* @param string $proxypassword
|
605 |
+
* @access public
|
606 |
+
*/
|
607 |
+
function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') {
|
608 |
+
$this->proxyhost = $proxyhost;
|
609 |
+
$this->proxyport = $proxyport;
|
610 |
+
$this->proxyusername = $proxyusername;
|
611 |
+
$this->proxypassword = $proxypassword;
|
612 |
+
}
|
613 |
+
|
614 |
+
/**
|
615 |
+
* if authenticating, set user credentials here
|
616 |
+
*
|
617 |
+
* @param string $username
|
618 |
+
* @param string $password
|
619 |
+
* @param string $authtype (basic|digest|certificate|ntlm)
|
620 |
+
* @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
|
621 |
+
* @access public
|
622 |
+
*/
|
623 |
+
function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
|
624 |
+
$this->debug("setCredentials username=$username authtype=$authtype certRequest=");
|
625 |
+
$this->appendDebug($this->varDump($certRequest));
|
626 |
+
$this->username = $username;
|
627 |
+
$this->password = $password;
|
628 |
+
$this->authtype = $authtype;
|
629 |
+
$this->certRequest = $certRequest;
|
630 |
+
}
|
631 |
+
|
632 |
+
/**
|
633 |
+
* use HTTP encoding
|
634 |
+
*
|
635 |
+
* @param string $enc HTTP encoding
|
636 |
+
* @access public
|
637 |
+
*/
|
638 |
+
function setHTTPEncoding($enc='gzip, deflate'){
|
639 |
+
$this->debug("setHTTPEncoding(\"$enc\")");
|
640 |
+
$this->http_encoding = $enc;
|
641 |
+
}
|
642 |
+
|
643 |
+
/**
|
644 |
+
* Set whether to try to use cURL connections if possible
|
645 |
+
*
|
646 |
+
* @param boolean $use Whether to try to use cURL
|
647 |
+
* @access public
|
648 |
+
*/
|
649 |
+
function setUseCURL($use) {
|
650 |
+
$this->debug("setUseCURL($use)");
|
651 |
+
$this->use_curl = $use;
|
652 |
+
}
|
653 |
+
|
654 |
+
/**
|
655 |
+
* use HTTP persistent connections if possible
|
656 |
+
*
|
657 |
+
* @access public
|
658 |
+
*/
|
659 |
+
function useHTTPPersistentConnection(){
|
660 |
+
$this->debug("useHTTPPersistentConnection");
|
661 |
+
$this->persistentConnection = true;
|
662 |
+
}
|
663 |
+
|
664 |
+
/**
|
665 |
+
* gets the default RPC parameter setting.
|
666 |
+
* If true, default is that call params are like RPC even for document style.
|
667 |
+
* Each call() can override this value.
|
668 |
+
*
|
669 |
+
* This is no longer used.
|
670 |
+
*
|
671 |
+
* @return boolean
|
672 |
+
* @access public
|
673 |
+
* @deprecated
|
674 |
+
*/
|
675 |
+
function getDefaultRpcParams() {
|
676 |
+
return $this->defaultRpcParams;
|
677 |
+
}
|
678 |
+
|
679 |
+
/**
|
680 |
+
* sets the default RPC parameter setting.
|
681 |
+
* If true, default is that call params are like RPC even for document style
|
682 |
+
* Each call() can override this value.
|
683 |
+
*
|
684 |
+
* This is no longer used.
|
685 |
+
*
|
686 |
+
* @param boolean $rpcParams
|
687 |
+
* @access public
|
688 |
+
* @deprecated
|
689 |
+
*/
|
690 |
+
function setDefaultRpcParams($rpcParams) {
|
691 |
+
$this->defaultRpcParams = $rpcParams;
|
692 |
+
}
|
693 |
+
|
694 |
+
/**
|
695 |
+
* dynamically creates an instance of a proxy class,
|
696 |
+
* allowing user to directly call methods from wsdl
|
697 |
+
*
|
698 |
+
* @return object soap_proxy object
|
699 |
+
* @access public
|
700 |
+
*/
|
701 |
+
function getProxy() {
|
702 |
+
$r = rand();
|
703 |
+
$evalStr = $this->_getProxyClassCode($r);
|
704 |
+
//$this->debug("proxy class: $evalStr");
|
705 |
+
if ($this->getError()) {
|
706 |
+
$this->debug("Error from _getProxyClassCode, so return NULL");
|
707 |
+
return null;
|
708 |
+
}
|
709 |
+
// eval the class
|
710 |
+
eval($evalStr);
|
711 |
+
// instantiate proxy object
|
712 |
+
eval("\$proxy = new nusoap_proxy_$r('');");
|
713 |
+
// transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
|
714 |
+
$proxy->endpointType = 'wsdl';
|
715 |
+
$proxy->wsdlFile = $this->wsdlFile;
|
716 |
+
$proxy->wsdl = $this->wsdl;
|
717 |
+
$proxy->operations = $this->operations;
|
718 |
+
$proxy->defaultRpcParams = $this->defaultRpcParams;
|
719 |
+
// transfer other state
|
720 |
+
$proxy->soap_defencoding = $this->soap_defencoding;
|
721 |
+
$proxy->username = $this->username;
|
722 |
+
$proxy->password = $this->password;
|
723 |
+
$proxy->authtype = $this->authtype;
|
724 |
+
$proxy->certRequest = $this->certRequest;
|
725 |
+
$proxy->requestHeaders = $this->requestHeaders;
|
726 |
+
$proxy->endpoint = $this->endpoint;
|
727 |
+
$proxy->forceEndpoint = $this->forceEndpoint;
|
728 |
+
$proxy->proxyhost = $this->proxyhost;
|
729 |
+
$proxy->proxyport = $this->proxyport;
|
730 |
+
$proxy->proxyusername = $this->proxyusername;
|
731 |
+
$proxy->proxypassword = $this->proxypassword;
|
732 |
+
$proxy->http_encoding = $this->http_encoding;
|
733 |
+
$proxy->timeout = $this->timeout;
|
734 |
+
$proxy->response_timeout = $this->response_timeout;
|
735 |
+
$proxy->persistentConnection = &$this->persistentConnection;
|
736 |
+
$proxy->decode_utf8 = $this->decode_utf8;
|
737 |
+
$proxy->curl_options = $this->curl_options;
|
738 |
+
$proxy->bindingType = $this->bindingType;
|
739 |
+
$proxy->use_curl = $this->use_curl;
|
740 |
+
return $proxy;
|
741 |
+
}
|
742 |
+
|
743 |
+
/**
|
744 |
+
* dynamically creates proxy class code
|
745 |
+
*
|
746 |
+
* @return string PHP/NuSOAP code for the proxy class
|
747 |
+
* @access private
|
748 |
+
*/
|
749 |
+
function _getProxyClassCode($r) {
|
750 |
+
$this->debug("in getProxy endpointType=$this->endpointType");
|
751 |
+
$this->appendDebug("wsdl=" . $this->varDump($this->wsdl));
|
752 |
+
if ($this->endpointType != 'wsdl') {
|
753 |
+
$evalStr = 'A proxy can only be created for a WSDL client';
|
754 |
+
$this->setError($evalStr);
|
755 |
+
$evalStr = "echo \"$evalStr\";";
|
756 |
+
return $evalStr;
|
757 |
+
}
|
758 |
+
if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
|
759 |
+
$this->loadWSDL();
|
760 |
+
if ($this->getError()) {
|
761 |
+
return "echo \"" . $this->getError() . "\";";
|
762 |
+
}
|
763 |
+
}
|
764 |
+
$evalStr = '';
|
765 |
+
foreach ($this->operations as $operation => $opData) {
|
766 |
+
if ($operation != '') {
|
767 |
+
// create param string and param comment string
|
768 |
+
if (sizeof($opData['input']['parts']) > 0) {
|
769 |
+
$paramStr = '';
|
770 |
+
$paramArrayStr = '';
|
771 |
+
$paramCommentStr = '';
|
772 |
+
foreach ($opData['input']['parts'] as $name => $type) {
|
773 |
+
$paramStr .= "\$$name, ";
|
774 |
+
$paramArrayStr .= "'$name' => \$$name, ";
|
775 |
+
$paramCommentStr .= "$type \$$name, ";
|
776 |
+
}
|
777 |
+
$paramStr = substr($paramStr, 0, strlen($paramStr)-2);
|
778 |
+
$paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr)-2);
|
779 |
+
$paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2);
|
780 |
+
} else {
|
781 |
+
$paramStr = '';
|
782 |
+
$paramArrayStr = '';
|
783 |
+
$paramCommentStr = 'void';
|
784 |
+
}
|
785 |
+
$opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
|
786 |
+
$evalStr .= "// $paramCommentStr
|
787 |
+
function " . str_replace('.', '__', $operation) . "($paramStr) {
|
788 |
+
\$params = array($paramArrayStr);
|
789 |
+
return \$this->call('$operation', \$params, '".$opData['namespace']."', '".(isset($opData['soapAction']) ? $opData['soapAction'] : '')."');
|
790 |
+
}
|
791 |
+
";
|
792 |
+
unset($paramStr);
|
793 |
+
unset($paramCommentStr);
|
794 |
+
}
|
795 |
+
}
|
796 |
+
$evalStr = 'class nusoap_proxy_'.$r.' extends nusoap_client {
|
797 |
+
'.$evalStr.'
|
798 |
+
}';
|
799 |
+
return $evalStr;
|
800 |
+
}
|
801 |
+
|
802 |
+
/**
|
803 |
+
* dynamically creates proxy class code
|
804 |
+
*
|
805 |
+
* @return string PHP/NuSOAP code for the proxy class
|
806 |
+
* @access public
|
807 |
+
*/
|
808 |
+
function getProxyClassCode() {
|
809 |
+
$r = rand();
|
810 |
+
return $this->_getProxyClassCode($r);
|
811 |
+
}
|
812 |
+
|
813 |
+
/**
|
814 |
+
* gets the HTTP body for the current request.
|
815 |
+
*
|
816 |
+
* @param string $soapmsg The SOAP payload
|
817 |
+
* @return string The HTTP body, which includes the SOAP payload
|
818 |
+
* @access private
|
819 |
+
*/
|
820 |
+
function getHTTPBody($soapmsg) {
|
821 |
+
return $soapmsg;
|
822 |
+
}
|
823 |
+
|
824 |
+
/**
|
825 |
+
* gets the HTTP content type for the current request.
|
826 |
+
*
|
827 |
+
* Note: getHTTPBody must be called before this.
|
828 |
+
*
|
829 |
+
* @return string the HTTP content type for the current request.
|
830 |
+
* @access private
|
831 |
+
*/
|
832 |
+
function getHTTPContentType() {
|
833 |
+
return 'text/xml';
|
834 |
+
}
|
835 |
+
|
836 |
+
/**
|
837 |
+
* gets the HTTP content type charset for the current request.
|
838 |
+
* returns false for non-text content types.
|
839 |
+
*
|
840 |
+
* Note: getHTTPBody must be called before this.
|
841 |
+
*
|
842 |
+
* @return string the HTTP content type charset for the current request.
|
843 |
+
* @access private
|
844 |
+
*/
|
845 |
+
function getHTTPContentTypeCharset() {
|
846 |
+
return $this->soap_defencoding;
|
847 |
+
}
|
848 |
+
|
849 |
+
/*
|
850 |
+
* whether or not parser should decode utf8 element content
|
851 |
+
*
|
852 |
+
* @return always returns true
|
853 |
+
* @access public
|
854 |
+
*/
|
855 |
+
function decodeUTF8($bool){
|
856 |
+
$this->decode_utf8 = $bool;
|
857 |
+
return true;
|
858 |
+
}
|
859 |
+
|
860 |
+
/**
|
861 |
+
* adds a new Cookie into $this->cookies array
|
862 |
+
*
|
863 |
+
* @param string $name Cookie Name
|
864 |
+
* @param string $value Cookie Value
|
865 |
+
* @return boolean if cookie-set was successful returns true, else false
|
866 |
+
* @access public
|
867 |
+
*/
|
868 |
+
function setCookie($name, $value) {
|
869 |
+
if (strlen($name) == 0) {
|
870 |
+
return false;
|
871 |
+
}
|
872 |
+
$this->cookies[] = array('name' => $name, 'value' => $value);
|
873 |
+
return true;
|
874 |
+
}
|
875 |
+
|
876 |
+
/**
|
877 |
+
* gets all Cookies
|
878 |
+
*
|
879 |
+
* @return array with all internal cookies
|
880 |
+
* @access public
|
881 |
+
*/
|
882 |
+
function getCookies() {
|
883 |
+
return $this->cookies;
|
884 |
+
}
|
885 |
+
|
886 |
+
/**
|
887 |
+
* checks all Cookies and delete those which are expired
|
888 |
+
*
|
889 |
+
* @return boolean always return true
|
890 |
+
* @access private
|
891 |
+
*/
|
892 |
+
function checkCookies() {
|
893 |
+
if (sizeof($this->cookies) == 0) {
|
894 |
+
return true;
|
895 |
+
}
|
896 |
+
$this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies');
|
897 |
+
$curr_cookies = $this->cookies;
|
898 |
+
$this->cookies = array();
|
899 |
+
foreach ($curr_cookies as $cookie) {
|
900 |
+
if (! is_array($cookie)) {
|
901 |
+
$this->debug('Remove cookie that is not an array');
|
902 |
+
continue;
|
903 |
+
}
|
904 |
+
if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
|
905 |
+
if (strtotime($cookie['expires']) > time()) {
|
906 |
+
$this->cookies[] = $cookie;
|
907 |
+
} else {
|
908 |
+
$this->debug('Remove expired cookie ' . $cookie['name']);
|
909 |
+
}
|
910 |
+
} else {
|
911 |
+
$this->cookies[] = $cookie;
|
912 |
+
}
|
913 |
+
}
|
914 |
+
$this->debug('checkCookie: '.sizeof($this->cookies).' cookies left in array');
|
915 |
+
return true;
|
916 |
+
}
|
917 |
+
|
918 |
+
/**
|
919 |
+
* updates the current cookies with a new set
|
920 |
+
*
|
921 |
+
* @param array $cookies new cookies with which to update current ones
|
922 |
+
* @return boolean always return true
|
923 |
+
* @access private
|
924 |
+
*/
|
925 |
+
function UpdateCookies($cookies) {
|
926 |
+
if (sizeof($this->cookies) == 0) {
|
927 |
+
// no existing cookies: take whatever is new
|
928 |
+
if (sizeof($cookies) > 0) {
|
929 |
+
$this->debug('Setting new cookie(s)');
|
930 |
+
$this->cookies = $cookies;
|
931 |
+
}
|
932 |
+
return true;
|
933 |
+
}
|
934 |
+
if (sizeof($cookies) == 0) {
|
935 |
+
// no new cookies: keep what we've got
|
936 |
+
return true;
|
937 |
+
}
|
938 |
+
// merge
|
939 |
+
foreach ($cookies as $newCookie) {
|
940 |
+
if (!is_array($newCookie)) {
|
941 |
+
continue;
|
942 |
+
}
|
943 |
+
if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) {
|
944 |
+
continue;
|
945 |
+
}
|
946 |
+
$newName = $newCookie['name'];
|
947 |
+
|
948 |
+
$found = false;
|
949 |
+
for ($i = 0; $i < count($this->cookies); $i++) {
|
950 |
+
$cookie = $this->cookies[$i];
|
951 |
+
if (!is_array($cookie)) {
|
952 |
+
continue;
|
953 |
+
}
|
954 |
+
if (!isset($cookie['name'])) {
|
955 |
+
continue;
|
956 |
+
}
|
957 |
+
if ($newName != $cookie['name']) {
|
958 |
+
continue;
|
959 |
+
}
|
960 |
+
$newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN';
|
961 |
+
$domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN';
|
962 |
+
if ($newDomain != $domain) {
|
963 |
+
continue;
|
964 |
+
}
|
965 |
+
$newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH';
|
966 |
+
$path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH';
|
967 |
+
if ($newPath != $path) {
|
968 |
+
continue;
|
969 |
+
}
|
970 |
+
$this->cookies[$i] = $newCookie;
|
971 |
+
$found = true;
|
972 |
+
$this->debug('Update cookie ' . $newName . '=' . $newCookie['value']);
|
973 |
+
break;
|
974 |
+
}
|
975 |
+
if (! $found) {
|
976 |
+
$this->debug('Add cookie ' . $newName . '=' . $newCookie['value']);
|
977 |
+
$this->cookies[] = $newCookie;
|
978 |
+
}
|
979 |
+
}
|
980 |
+
return true;
|
981 |
+
}
|
982 |
+
}
|
983 |
+
|
984 |
+
if (!extension_loaded('soap')) {
|
985 |
+
/**
|
986 |
+
* For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded.
|
987 |
+
*/
|
988 |
+
class soapclient extends nusoap_client {
|
989 |
+
}
|
990 |
+
}
|
991 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.wsdl.php
ADDED
@@ -0,0 +1,1938 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
|
4 |
+
|
5 |
+
|
6 |
+
/**
|
7 |
+
* parses a WSDL file, allows access to it's data, other utility methods.
|
8 |
+
* also builds WSDL structures programmatically.
|
9 |
+
*
|
10 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
11 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
12 |
+
* @version $Id: class.wsdl.php,v 1.76 2010/04/26 20:15:08 snichol Exp $
|
13 |
+
* @access public
|
14 |
+
*/
|
15 |
+
class wsdl extends nusoap_base {
|
16 |
+
// URL or filename of the root of this WSDL
|
17 |
+
var $wsdl;
|
18 |
+
// define internal arrays of bindings, ports, operations, messages, etc.
|
19 |
+
var $schemas = array();
|
20 |
+
var $currentSchema;
|
21 |
+
var $message = array();
|
22 |
+
var $complexTypes = array();
|
23 |
+
var $messages = array();
|
24 |
+
var $currentMessage;
|
25 |
+
var $currentOperation;
|
26 |
+
var $portTypes = array();
|
27 |
+
var $currentPortType;
|
28 |
+
var $bindings = array();
|
29 |
+
var $currentBinding;
|
30 |
+
var $ports = array();
|
31 |
+
var $currentPort;
|
32 |
+
var $opData = array();
|
33 |
+
var $status = '';
|
34 |
+
var $documentation = false;
|
35 |
+
var $endpoint = '';
|
36 |
+
// array of wsdl docs to import
|
37 |
+
var $import = array();
|
38 |
+
// parser vars
|
39 |
+
var $parser;
|
40 |
+
var $position = 0;
|
41 |
+
var $depth = 0;
|
42 |
+
var $depth_array = array();
|
43 |
+
// for getting wsdl
|
44 |
+
var $proxyhost = '';
|
45 |
+
var $proxyport = '';
|
46 |
+
var $proxyusername = '';
|
47 |
+
var $proxypassword = '';
|
48 |
+
var $timeout = 0;
|
49 |
+
var $response_timeout = 30;
|
50 |
+
var $curl_options = array(); // User-specified cURL options
|
51 |
+
var $use_curl = false; // whether to always try to use cURL
|
52 |
+
// for HTTP authentication
|
53 |
+
var $username = ''; // Username for HTTP authentication
|
54 |
+
var $password = ''; // Password for HTTP authentication
|
55 |
+
var $authtype = ''; // Type of HTTP authentication
|
56 |
+
var $certRequest = array(); // Certificate for HTTP SSL authentication
|
57 |
+
|
58 |
+
/**
|
59 |
+
* constructor
|
60 |
+
*
|
61 |
+
* @param string $wsdl WSDL document URL
|
62 |
+
* @param string $proxyhost
|
63 |
+
* @param string $proxyport
|
64 |
+
* @param string $proxyusername
|
65 |
+
* @param string $proxypassword
|
66 |
+
* @param integer $timeout set the connection timeout
|
67 |
+
* @param integer $response_timeout set the response timeout
|
68 |
+
* @param array $curl_options user-specified cURL options
|
69 |
+
* @param boolean $use_curl try to use cURL
|
70 |
+
* @access public
|
71 |
+
*/
|
72 |
+
function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30,$curl_options=null,$use_curl=false){
|
73 |
+
parent::nusoap_base();
|
74 |
+
$this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
|
75 |
+
$this->proxyhost = $proxyhost;
|
76 |
+
$this->proxyport = $proxyport;
|
77 |
+
$this->proxyusername = $proxyusername;
|
78 |
+
$this->proxypassword = $proxypassword;
|
79 |
+
$this->timeout = $timeout;
|
80 |
+
$this->response_timeout = $response_timeout;
|
81 |
+
if (is_array($curl_options))
|
82 |
+
$this->curl_options = $curl_options;
|
83 |
+
$this->use_curl = $use_curl;
|
84 |
+
$this->fetchWSDL($wsdl);
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* fetches the WSDL document and parses it
|
89 |
+
*
|
90 |
+
* @access public
|
91 |
+
*/
|
92 |
+
function fetchWSDL($wsdl) {
|
93 |
+
$this->debug("parse and process WSDL path=$wsdl");
|
94 |
+
$this->wsdl = $wsdl;
|
95 |
+
// parse wsdl file
|
96 |
+
if ($this->wsdl != "") {
|
97 |
+
$this->parseWSDL($this->wsdl);
|
98 |
+
}
|
99 |
+
// imports
|
100 |
+
// TODO: handle imports more properly, grabbing them in-line and nesting them
|
101 |
+
$imported_urls = array();
|
102 |
+
$imported = 1;
|
103 |
+
while ($imported > 0) {
|
104 |
+
$imported = 0;
|
105 |
+
// Schema imports
|
106 |
+
foreach ($this->schemas as $ns => $list) {
|
107 |
+
foreach ($list as $xs) {
|
108 |
+
$wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
|
109 |
+
foreach ($xs->imports as $ns2 => $list2) {
|
110 |
+
for ($ii = 0; $ii < count($list2); $ii++) {
|
111 |
+
if (! $list2[$ii]['loaded']) {
|
112 |
+
$this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
|
113 |
+
$url = $list2[$ii]['location'];
|
114 |
+
if ($url != '') {
|
115 |
+
$urlparts = parse_url($url);
|
116 |
+
if (!isset($urlparts['host'])) {
|
117 |
+
$url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') .
|
118 |
+
substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
|
119 |
+
}
|
120 |
+
if (! in_array($url, $imported_urls)) {
|
121 |
+
$this->parseWSDL($url);
|
122 |
+
$imported++;
|
123 |
+
$imported_urls[] = $url;
|
124 |
+
}
|
125 |
+
} else {
|
126 |
+
$this->debug("Unexpected scenario: empty URL for unloaded import");
|
127 |
+
}
|
128 |
+
}
|
129 |
+
}
|
130 |
+
}
|
131 |
+
}
|
132 |
+
}
|
133 |
+
// WSDL imports
|
134 |
+
$wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
|
135 |
+
foreach ($this->import as $ns => $list) {
|
136 |
+
for ($ii = 0; $ii < count($list); $ii++) {
|
137 |
+
if (! $list[$ii]['loaded']) {
|
138 |
+
$this->import[$ns][$ii]['loaded'] = true;
|
139 |
+
$url = $list[$ii]['location'];
|
140 |
+
if ($url != '') {
|
141 |
+
$urlparts = parse_url($url);
|
142 |
+
if (!isset($urlparts['host'])) {
|
143 |
+
$url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
|
144 |
+
substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
|
145 |
+
}
|
146 |
+
if (! in_array($url, $imported_urls)) {
|
147 |
+
$this->parseWSDL($url);
|
148 |
+
$imported++;
|
149 |
+
$imported_urls[] = $url;
|
150 |
+
}
|
151 |
+
} else {
|
152 |
+
$this->debug("Unexpected scenario: empty URL for unloaded import");
|
153 |
+
}
|
154 |
+
}
|
155 |
+
}
|
156 |
+
}
|
157 |
+
}
|
158 |
+
// add new data to operation data
|
159 |
+
foreach($this->bindings as $binding => $bindingData) {
|
160 |
+
if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
|
161 |
+
foreach($bindingData['operations'] as $operation => $data) {
|
162 |
+
$this->debug('post-parse data gathering for ' . $operation);
|
163 |
+
$this->bindings[$binding]['operations'][$operation]['input'] =
|
164 |
+
isset($this->bindings[$binding]['operations'][$operation]['input']) ?
|
165 |
+
array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
|
166 |
+
$this->portTypes[ $bindingData['portType'] ][$operation]['input'];
|
167 |
+
$this->bindings[$binding]['operations'][$operation]['output'] =
|
168 |
+
isset($this->bindings[$binding]['operations'][$operation]['output']) ?
|
169 |
+
array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
|
170 |
+
$this->portTypes[ $bindingData['portType'] ][$operation]['output'];
|
171 |
+
if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])){
|
172 |
+
$this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
|
173 |
+
}
|
174 |
+
if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])){
|
175 |
+
$this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
|
176 |
+
}
|
177 |
+
// Set operation style if necessary, but do not override one already provided
|
178 |
+
if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) {
|
179 |
+
$this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
|
180 |
+
}
|
181 |
+
$this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
|
182 |
+
$this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
|
183 |
+
$this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
|
184 |
+
}
|
185 |
+
}
|
186 |
+
}
|
187 |
+
}
|
188 |
+
|
189 |
+
/**
|
190 |
+
* parses the wsdl document
|
191 |
+
*
|
192 |
+
* @param string $wsdl path or URL
|
193 |
+
* @access private
|
194 |
+
*/
|
195 |
+
function parseWSDL($wsdl = '') {
|
196 |
+
$this->debug("parse WSDL at path=$wsdl");
|
197 |
+
|
198 |
+
if ($wsdl == '') {
|
199 |
+
$this->debug('no wsdl passed to parseWSDL()!!');
|
200 |
+
$this->setError('no wsdl passed to parseWSDL()!!');
|
201 |
+
return false;
|
202 |
+
}
|
203 |
+
|
204 |
+
// parse $wsdl for url format
|
205 |
+
$wsdl_props = parse_url($wsdl);
|
206 |
+
|
207 |
+
if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
|
208 |
+
$this->debug('getting WSDL http(s) URL ' . $wsdl);
|
209 |
+
// get wsdl
|
210 |
+
$tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl);
|
211 |
+
$tr->request_method = 'GET';
|
212 |
+
$tr->useSOAPAction = false;
|
213 |
+
if($this->proxyhost && $this->proxyport){
|
214 |
+
$tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
|
215 |
+
}
|
216 |
+
if ($this->authtype != '') {
|
217 |
+
$tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
|
218 |
+
}
|
219 |
+
$tr->setEncoding('gzip, deflate');
|
220 |
+
$wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
|
221 |
+
//$this->debug("WSDL request\n" . $tr->outgoing_payload);
|
222 |
+
//$this->debug("WSDL response\n" . $tr->incoming_payload);
|
223 |
+
$this->appendDebug($tr->getDebug());
|
224 |
+
// catch errors
|
225 |
+
if($err = $tr->getError() ){
|
226 |
+
$errstr = 'Getting ' . $wsdl . ' - HTTP ERROR: '.$err;
|
227 |
+
$this->debug($errstr);
|
228 |
+
$this->setError($errstr);
|
229 |
+
unset($tr);
|
230 |
+
return false;
|
231 |
+
}
|
232 |
+
unset($tr);
|
233 |
+
$this->debug("got WSDL URL");
|
234 |
+
} else {
|
235 |
+
// $wsdl is not http(s), so treat it as a file URL or plain file path
|
236 |
+
if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
|
237 |
+
$path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
|
238 |
+
} else {
|
239 |
+
$path = $wsdl;
|
240 |
+
}
|
241 |
+
$this->debug('getting WSDL file ' . $path);
|
242 |
+
if ($fp = @fopen($path, 'r')) {
|
243 |
+
$wsdl_string = '';
|
244 |
+
while ($data = fread($fp, 32768)) {
|
245 |
+
$wsdl_string .= $data;
|
246 |
+
}
|
247 |
+
fclose($fp);
|
248 |
+
} else {
|
249 |
+
$errstr = "Bad path to WSDL file $path";
|
250 |
+
$this->debug($errstr);
|
251 |
+
$this->setError($errstr);
|
252 |
+
return false;
|
253 |
+
}
|
254 |
+
}
|
255 |
+
$this->debug('Parse WSDL');
|
256 |
+
// end new code added
|
257 |
+
// Create an XML parser.
|
258 |
+
$this->parser = xml_parser_create();
|
259 |
+
// Set the options for parsing the XML data.
|
260 |
+
// xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
|
261 |
+
xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
|
262 |
+
// Set the object for the parser.
|
263 |
+
xml_set_object($this->parser, $this);
|
264 |
+
// Set the element handlers for the parser.
|
265 |
+
xml_set_element_handler($this->parser, 'start_element', 'end_element');
|
266 |
+
xml_set_character_data_handler($this->parser, 'character_data');
|
267 |
+
// Parse the XML file.
|
268 |
+
if (!xml_parse($this->parser, $wsdl_string, true)) {
|
269 |
+
// Display an error message.
|
270 |
+
$errstr = sprintf(
|
271 |
+
'XML error parsing WSDL from %s on line %d: %s',
|
272 |
+
$wsdl,
|
273 |
+
xml_get_current_line_number($this->parser),
|
274 |
+
xml_error_string(xml_get_error_code($this->parser))
|
275 |
+
);
|
276 |
+
$this->debug($errstr);
|
277 |
+
$this->debug("XML payload:\n" . $wsdl_string);
|
278 |
+
$this->setError($errstr);
|
279 |
+
return false;
|
280 |
+
}
|
281 |
+
// free the parser
|
282 |
+
xml_parser_free($this->parser);
|
283 |
+
$this->debug('Parsing WSDL done');
|
284 |
+
// catch wsdl parse errors
|
285 |
+
if($this->getError()){
|
286 |
+
return false;
|
287 |
+
}
|
288 |
+
return true;
|
289 |
+
}
|
290 |
+
|
291 |
+
/**
|
292 |
+
* start-element handler
|
293 |
+
*
|
294 |
+
* @param string $parser XML parser object
|
295 |
+
* @param string $name element name
|
296 |
+
* @param string $attrs associative array of attributes
|
297 |
+
* @access private
|
298 |
+
*/
|
299 |
+
function start_element($parser, $name, $attrs)
|
300 |
+
{
|
301 |
+
if ($this->status == 'schema') {
|
302 |
+
$this->currentSchema->schemaStartElement($parser, $name, $attrs);
|
303 |
+
$this->appendDebug($this->currentSchema->getDebug());
|
304 |
+
$this->currentSchema->clearDebug();
|
305 |
+
} elseif (preg_match('/schema$/', $name)) {
|
306 |
+
$this->debug('Parsing WSDL schema');
|
307 |
+
// $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
|
308 |
+
$this->status = 'schema';
|
309 |
+
$this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
|
310 |
+
$this->currentSchema->schemaStartElement($parser, $name, $attrs);
|
311 |
+
$this->appendDebug($this->currentSchema->getDebug());
|
312 |
+
$this->currentSchema->clearDebug();
|
313 |
+
} else {
|
314 |
+
// position in the total number of elements, starting from 0
|
315 |
+
$pos = $this->position++;
|
316 |
+
$depth = $this->depth++;
|
317 |
+
// set self as current value for this depth
|
318 |
+
$this->depth_array[$depth] = $pos;
|
319 |
+
$this->message[$pos] = array('cdata' => '');
|
320 |
+
// process attributes
|
321 |
+
if (count($attrs) > 0) {
|
322 |
+
// register namespace declarations
|
323 |
+
foreach($attrs as $k => $v) {
|
324 |
+
if (preg_match('/^xmlns/',$k)) {
|
325 |
+
if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
|
326 |
+
$this->namespaces[$ns_prefix] = $v;
|
327 |
+
} else {
|
328 |
+
$this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
|
329 |
+
}
|
330 |
+
if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
|
331 |
+
$this->XMLSchemaVersion = $v;
|
332 |
+
$this->namespaces['xsi'] = $v . '-instance';
|
333 |
+
}
|
334 |
+
}
|
335 |
+
}
|
336 |
+
// expand each attribute prefix to its namespace
|
337 |
+
foreach($attrs as $k => $v) {
|
338 |
+
$k = strpos($k, ':') ? $this->expandQname($k) : $k;
|
339 |
+
if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
|
340 |
+
$v = strpos($v, ':') ? $this->expandQname($v) : $v;
|
341 |
+
}
|
342 |
+
$eAttrs[$k] = $v;
|
343 |
+
}
|
344 |
+
$attrs = $eAttrs;
|
345 |
+
} else {
|
346 |
+
$attrs = array();
|
347 |
+
}
|
348 |
+
// get element prefix, namespace and name
|
349 |
+
if (preg_match('/:/', $name)) {
|
350 |
+
// get ns prefix
|
351 |
+
$prefix = substr($name, 0, strpos($name, ':'));
|
352 |
+
// get ns
|
353 |
+
$namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : '';
|
354 |
+
// get unqualified name
|
355 |
+
$name = substr(strstr($name, ':'), 1);
|
356 |
+
}
|
357 |
+
// process attributes, expanding any prefixes to namespaces
|
358 |
+
// find status, register data
|
359 |
+
switch ($this->status) {
|
360 |
+
case 'message':
|
361 |
+
if ($name == 'part') {
|
362 |
+
if (isset($attrs['type'])) {
|
363 |
+
$this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs));
|
364 |
+
$this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
|
365 |
+
}
|
366 |
+
if (isset($attrs['element'])) {
|
367 |
+
$this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));
|
368 |
+
$this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';
|
369 |
+
}
|
370 |
+
}
|
371 |
+
break;
|
372 |
+
case 'portType':
|
373 |
+
switch ($name) {
|
374 |
+
case 'operation':
|
375 |
+
$this->currentPortOperation = $attrs['name'];
|
376 |
+
$this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
|
377 |
+
if (isset($attrs['parameterOrder'])) {
|
378 |
+
$this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
|
379 |
+
}
|
380 |
+
break;
|
381 |
+
case 'documentation':
|
382 |
+
$this->documentation = true;
|
383 |
+
break;
|
384 |
+
// merge input/output data
|
385 |
+
default:
|
386 |
+
$m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
|
387 |
+
$this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
|
388 |
+
break;
|
389 |
+
}
|
390 |
+
break;
|
391 |
+
case 'binding':
|
392 |
+
switch ($name) {
|
393 |
+
case 'binding':
|
394 |
+
// get ns prefix
|
395 |
+
if (isset($attrs['style'])) {
|
396 |
+
$this->bindings[$this->currentBinding]['prefix'] = $prefix;
|
397 |
+
}
|
398 |
+
$this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
|
399 |
+
break;
|
400 |
+
case 'header':
|
401 |
+
$this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
|
402 |
+
break;
|
403 |
+
case 'operation':
|
404 |
+
if (isset($attrs['soapAction'])) {
|
405 |
+
$this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
|
406 |
+
}
|
407 |
+
if (isset($attrs['style'])) {
|
408 |
+
$this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
|
409 |
+
}
|
410 |
+
if (isset($attrs['name'])) {
|
411 |
+
$this->currentOperation = $attrs['name'];
|
412 |
+
$this->debug("current binding operation: $this->currentOperation");
|
413 |
+
$this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
|
414 |
+
$this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
|
415 |
+
$this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
|
416 |
+
}
|
417 |
+
break;
|
418 |
+
case 'input':
|
419 |
+
$this->opStatus = 'input';
|
420 |
+
break;
|
421 |
+
case 'output':
|
422 |
+
$this->opStatus = 'output';
|
423 |
+
break;
|
424 |
+
case 'body':
|
425 |
+
if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
|
426 |
+
$this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
|
427 |
+
} else {
|
428 |
+
$this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
|
429 |
+
}
|
430 |
+
break;
|
431 |
+
}
|
432 |
+
break;
|
433 |
+
case 'service':
|
434 |
+
switch ($name) {
|
435 |
+
case 'port':
|
436 |
+
$this->currentPort = $attrs['name'];
|
437 |
+
$this->debug('current port: ' . $this->currentPort);
|
438 |
+
$this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
|
439 |
+
|
440 |
+
break;
|
441 |
+
case 'address':
|
442 |
+
$this->ports[$this->currentPort]['location'] = $attrs['location'];
|
443 |
+
$this->ports[$this->currentPort]['bindingType'] = $namespace;
|
444 |
+
$this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;
|
445 |
+
$this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
|
446 |
+
break;
|
447 |
+
}
|
448 |
+
break;
|
449 |
+
}
|
450 |
+
// set status
|
451 |
+
switch ($name) {
|
452 |
+
case 'import':
|
453 |
+
if (isset($attrs['location'])) {
|
454 |
+
$this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
|
455 |
+
$this->debug('parsing import ' . $attrs['namespace']. ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]).')');
|
456 |
+
} else {
|
457 |
+
$this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
|
458 |
+
if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
|
459 |
+
$this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
|
460 |
+
}
|
461 |
+
$this->debug('parsing import ' . $attrs['namespace']. ' - [no location] (' . count($this->import[$attrs['namespace']]).')');
|
462 |
+
}
|
463 |
+
break;
|
464 |
+
//wait for schema
|
465 |
+
//case 'types':
|
466 |
+
// $this->status = 'schema';
|
467 |
+
// break;
|
468 |
+
case 'message':
|
469 |
+
$this->status = 'message';
|
470 |
+
$this->messages[$attrs['name']] = array();
|
471 |
+
$this->currentMessage = $attrs['name'];
|
472 |
+
break;
|
473 |
+
case 'portType':
|
474 |
+
$this->status = 'portType';
|
475 |
+
$this->portTypes[$attrs['name']] = array();
|
476 |
+
$this->currentPortType = $attrs['name'];
|
477 |
+
break;
|
478 |
+
case "binding":
|
479 |
+
if (isset($attrs['name'])) {
|
480 |
+
// get binding name
|
481 |
+
if (strpos($attrs['name'], ':')) {
|
482 |
+
$this->currentBinding = $this->getLocalPart($attrs['name']);
|
483 |
+
} else {
|
484 |
+
$this->currentBinding = $attrs['name'];
|
485 |
+
}
|
486 |
+
$this->status = 'binding';
|
487 |
+
$this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
|
488 |
+
$this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
|
489 |
+
}
|
490 |
+
break;
|
491 |
+
case 'service':
|
492 |
+
$this->serviceName = $attrs['name'];
|
493 |
+
$this->status = 'service';
|
494 |
+
$this->debug('current service: ' . $this->serviceName);
|
495 |
+
break;
|
496 |
+
case 'definitions':
|
497 |
+
foreach ($attrs as $name => $value) {
|
498 |
+
$this->wsdl_info[$name] = $value;
|
499 |
+
}
|
500 |
+
break;
|
501 |
+
}
|
502 |
+
}
|
503 |
+
}
|
504 |
+
|
505 |
+
/**
|
506 |
+
* end-element handler
|
507 |
+
*
|
508 |
+
* @param string $parser XML parser object
|
509 |
+
* @param string $name element name
|
510 |
+
* @access private
|
511 |
+
*/
|
512 |
+
function end_element($parser, $name){
|
513 |
+
// unset schema status
|
514 |
+
if (/*preg_match('/types$/', $name) ||*/ preg_match('/schema$/', $name)) {
|
515 |
+
$this->status = "";
|
516 |
+
$this->appendDebug($this->currentSchema->getDebug());
|
517 |
+
$this->currentSchema->clearDebug();
|
518 |
+
$this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
|
519 |
+
$this->debug('Parsing WSDL schema done');
|
520 |
+
}
|
521 |
+
if ($this->status == 'schema') {
|
522 |
+
$this->currentSchema->schemaEndElement($parser, $name);
|
523 |
+
} else {
|
524 |
+
// bring depth down a notch
|
525 |
+
$this->depth--;
|
526 |
+
}
|
527 |
+
// end documentation
|
528 |
+
if ($this->documentation) {
|
529 |
+
//TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
|
530 |
+
//$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
|
531 |
+
$this->documentation = false;
|
532 |
+
}
|
533 |
+
}
|
534 |
+
|
535 |
+
/**
|
536 |
+
* element content handler
|
537 |
+
*
|
538 |
+
* @param string $parser XML parser object
|
539 |
+
* @param string $data element content
|
540 |
+
* @access private
|
541 |
+
*/
|
542 |
+
function character_data($parser, $data)
|
543 |
+
{
|
544 |
+
$pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
|
545 |
+
if (isset($this->message[$pos]['cdata'])) {
|
546 |
+
$this->message[$pos]['cdata'] .= $data;
|
547 |
+
}
|
548 |
+
if ($this->documentation) {
|
549 |
+
$this->documentation .= $data;
|
550 |
+
}
|
551 |
+
}
|
552 |
+
|
553 |
+
/**
|
554 |
+
* if authenticating, set user credentials here
|
555 |
+
*
|
556 |
+
* @param string $username
|
557 |
+
* @param string $password
|
558 |
+
* @param string $authtype (basic|digest|certificate|ntlm)
|
559 |
+
* @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
|
560 |
+
* @access public
|
561 |
+
*/
|
562 |
+
function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
|
563 |
+
$this->debug("setCredentials username=$username authtype=$authtype certRequest=");
|
564 |
+
$this->appendDebug($this->varDump($certRequest));
|
565 |
+
$this->username = $username;
|
566 |
+
$this->password = $password;
|
567 |
+
$this->authtype = $authtype;
|
568 |
+
$this->certRequest = $certRequest;
|
569 |
+
}
|
570 |
+
|
571 |
+
function getBindingData($binding)
|
572 |
+
{
|
573 |
+
if (is_array($this->bindings[$binding])) {
|
574 |
+
return $this->bindings[$binding];
|
575 |
+
}
|
576 |
+
}
|
577 |
+
|
578 |
+
/**
|
579 |
+
* returns an assoc array of operation names => operation data
|
580 |
+
*
|
581 |
+
* @param string $portName WSDL port name
|
582 |
+
* @param string $bindingType eg: soap, smtp, dime (only soap and soap12 are currently supported)
|
583 |
+
* @return array
|
584 |
+
* @access public
|
585 |
+
*/
|
586 |
+
function getOperations($portName = '', $bindingType = 'soap') {
|
587 |
+
$ops = array();
|
588 |
+
if ($bindingType == 'soap') {
|
589 |
+
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
|
590 |
+
} elseif ($bindingType == 'soap12') {
|
591 |
+
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
|
592 |
+
} else {
|
593 |
+
$this->debug("getOperations bindingType $bindingType may not be supported");
|
594 |
+
}
|
595 |
+
$this->debug("getOperations for port '$portName' bindingType $bindingType");
|
596 |
+
// loop thru ports
|
597 |
+
foreach($this->ports as $port => $portData) {
|
598 |
+
$this->debug("getOperations checking port $port bindingType " . $portData['bindingType']);
|
599 |
+
if ($portName == '' || $port == $portName) {
|
600 |
+
// binding type of port matches parameter
|
601 |
+
if ($portData['bindingType'] == $bindingType) {
|
602 |
+
$this->debug("getOperations found port $port bindingType $bindingType");
|
603 |
+
//$this->debug("port data: " . $this->varDump($portData));
|
604 |
+
//$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
|
605 |
+
// merge bindings
|
606 |
+
if (isset($this->bindings[ $portData['binding'] ]['operations'])) {
|
607 |
+
$ops = array_merge ($ops, $this->bindings[ $portData['binding'] ]['operations']);
|
608 |
+
}
|
609 |
+
}
|
610 |
+
}
|
611 |
+
}
|
612 |
+
if (count($ops) == 0) {
|
613 |
+
$this->debug("getOperations found no operations for port '$portName' bindingType $bindingType");
|
614 |
+
}
|
615 |
+
return $ops;
|
616 |
+
}
|
617 |
+
|
618 |
+
/**
|
619 |
+
* returns an associative array of data necessary for calling an operation
|
620 |
+
*
|
621 |
+
* @param string $operation name of operation
|
622 |
+
* @param string $bindingType type of binding eg: soap, soap12
|
623 |
+
* @return array
|
624 |
+
* @access public
|
625 |
+
*/
|
626 |
+
function getOperationData($operation, $bindingType = 'soap')
|
627 |
+
{
|
628 |
+
if ($bindingType == 'soap') {
|
629 |
+
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
|
630 |
+
} elseif ($bindingType == 'soap12') {
|
631 |
+
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
|
632 |
+
}
|
633 |
+
// loop thru ports
|
634 |
+
foreach($this->ports as $port => $portData) {
|
635 |
+
// binding type of port matches parameter
|
636 |
+
if ($portData['bindingType'] == $bindingType) {
|
637 |
+
// get binding
|
638 |
+
//foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
|
639 |
+
foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {
|
640 |
+
// note that we could/should also check the namespace here
|
641 |
+
if ($operation == $bOperation) {
|
642 |
+
$opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];
|
643 |
+
return $opData;
|
644 |
+
}
|
645 |
+
}
|
646 |
+
}
|
647 |
+
}
|
648 |
+
}
|
649 |
+
|
650 |
+
/**
|
651 |
+
* returns an associative array of data necessary for calling an operation
|
652 |
+
*
|
653 |
+
* @param string $soapAction soapAction for operation
|
654 |
+
* @param string $bindingType type of binding eg: soap, soap12
|
655 |
+
* @return array
|
656 |
+
* @access public
|
657 |
+
*/
|
658 |
+
function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') {
|
659 |
+
if ($bindingType == 'soap') {
|
660 |
+
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
|
661 |
+
} elseif ($bindingType == 'soap12') {
|
662 |
+
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
|
663 |
+
}
|
664 |
+
// loop thru ports
|
665 |
+
foreach($this->ports as $port => $portData) {
|
666 |
+
// binding type of port matches parameter
|
667 |
+
if ($portData['bindingType'] == $bindingType) {
|
668 |
+
// loop through operations for the binding
|
669 |
+
foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
|
670 |
+
if ($opData['soapAction'] == $soapAction) {
|
671 |
+
return $opData;
|
672 |
+
}
|
673 |
+
}
|
674 |
+
}
|
675 |
+
}
|
676 |
+
}
|
677 |
+
|
678 |
+
/**
|
679 |
+
* returns an array of information about a given type
|
680 |
+
* returns false if no type exists by the given name
|
681 |
+
*
|
682 |
+
* typeDef = array(
|
683 |
+
* 'elements' => array(), // refs to elements array
|
684 |
+
* 'restrictionBase' => '',
|
685 |
+
* 'phpType' => '',
|
686 |
+
* 'order' => '(sequence|all)',
|
687 |
+
* 'attrs' => array() // refs to attributes array
|
688 |
+
* )
|
689 |
+
*
|
690 |
+
* @param string $type the type
|
691 |
+
* @param string $ns namespace (not prefix) of the type
|
692 |
+
* @return mixed
|
693 |
+
* @access public
|
694 |
+
* @see nusoap_xmlschema
|
695 |
+
*/
|
696 |
+
function getTypeDef($type, $ns) {
|
697 |
+
$this->debug("in getTypeDef: type=$type, ns=$ns");
|
698 |
+
if ((! $ns) && isset($this->namespaces['tns'])) {
|
699 |
+
$ns = $this->namespaces['tns'];
|
700 |
+
$this->debug("in getTypeDef: type namespace forced to $ns");
|
701 |
+
}
|
702 |
+
if (!isset($this->schemas[$ns])) {
|
703 |
+
foreach ($this->schemas as $ns0 => $schema0) {
|
704 |
+
if (strcasecmp($ns, $ns0) == 0) {
|
705 |
+
$this->debug("in getTypeDef: replacing schema namespace $ns with $ns0");
|
706 |
+
$ns = $ns0;
|
707 |
+
break;
|
708 |
+
}
|
709 |
+
}
|
710 |
+
}
|
711 |
+
if (isset($this->schemas[$ns])) {
|
712 |
+
$this->debug("in getTypeDef: have schema for namespace $ns");
|
713 |
+
for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
|
714 |
+
$xs = &$this->schemas[$ns][$i];
|
715 |
+
$t = $xs->getTypeDef($type);
|
716 |
+
$this->appendDebug($xs->getDebug());
|
717 |
+
$xs->clearDebug();
|
718 |
+
if ($t) {
|
719 |
+
$this->debug("in getTypeDef: found type $type");
|
720 |
+
if (!isset($t['phpType'])) {
|
721 |
+
// get info for type to tack onto the element
|
722 |
+
$uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
|
723 |
+
$ns = substr($t['type'], 0, strrpos($t['type'], ':'));
|
724 |
+
$etype = $this->getTypeDef($uqType, $ns);
|
725 |
+
if ($etype) {
|
726 |
+
$this->debug("found type for [element] $type:");
|
727 |
+
$this->debug($this->varDump($etype));
|
728 |
+
if (isset($etype['phpType'])) {
|
729 |
+
$t['phpType'] = $etype['phpType'];
|
730 |
+
}
|
731 |
+
if (isset($etype['elements'])) {
|
732 |
+
$t['elements'] = $etype['elements'];
|
733 |
+
}
|
734 |
+
if (isset($etype['attrs'])) {
|
735 |
+
$t['attrs'] = $etype['attrs'];
|
736 |
+
}
|
737 |
+
} else {
|
738 |
+
$this->debug("did not find type for [element] $type");
|
739 |
+
}
|
740 |
+
}
|
741 |
+
return $t;
|
742 |
+
}
|
743 |
+
}
|
744 |
+
$this->debug("in getTypeDef: did not find type $type");
|
745 |
+
} else {
|
746 |
+
$this->debug("in getTypeDef: do not have schema for namespace $ns");
|
747 |
+
}
|
748 |
+
return false;
|
749 |
+
}
|
750 |
+
|
751 |
+
/**
|
752 |
+
* prints html description of services
|
753 |
+
*
|
754 |
+
* @access private
|
755 |
+
*/
|
756 |
+
function webDescription(){
|
757 |
+
global $HTTP_SERVER_VARS;
|
758 |
+
|
759 |
+
if (isset($_SERVER)) {
|
760 |
+
$PHP_SELF = $_SERVER['PHP_SELF'];
|
761 |
+
} elseif (isset($HTTP_SERVER_VARS)) {
|
762 |
+
$PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
|
763 |
+
} else {
|
764 |
+
$this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
|
765 |
+
}
|
766 |
+
|
767 |
+
$b = '
|
768 |
+
<html><head><title>NuSOAP: '.$this->serviceName.'</title>
|
769 |
+
<style type="text/css">
|
770 |
+
body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
|
771 |
+
p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
|
772 |
+
pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
|
773 |
+
ul { margin-top: 10px; margin-left: 20px; }
|
774 |
+
li { list-style-type: none; margin-top: 10px; color: #000000; }
|
775 |
+
.content{
|
776 |
+
margin-left: 0px; padding-bottom: 2em; }
|
777 |
+
.nav {
|
778 |
+
padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
|
779 |
+
margin-top: 10px; margin-left: 0px; color: #000000;
|
780 |
+
background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
|
781 |
+
.title {
|
782 |
+
font-family: arial; font-size: 26px; color: #ffffff;
|
783 |
+
background-color: #999999; width: 100%;
|
784 |
+
margin-left: 0px; margin-right: 0px;
|
785 |
+
padding-top: 10px; padding-bottom: 10px;}
|
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'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 .= " $captain:<br>";
|
861 |
+
//if(is_array($tenille)){
|
862 |
+
foreach($tenille as $joanie => $chachi){
|
863 |
+
$b .= " $joanie: $chachi<br>";
|
864 |
+
}
|
865 |
+
//}
|
866 |
+
} else {
|
867 |
+
$b .= " $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 |
+
foreach ($typeDef['elements'] as $name => $attrs) {
|
1075 |
+
if (isset($parameters[$name])) {
|
1076 |
+
$this->debug("in parametersMatchWrapped: have parameter named $name");
|
1077 |
+
$matches++;
|
1078 |
+
} else {
|
1079 |
+
$this->debug("in parametersMatchWrapped: do not have parameter named $name");
|
1080 |
+
}
|
1081 |
+
$elements++;
|
1082 |
+
}
|
1083 |
+
|
1084 |
+
$this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names");
|
1085 |
+
if ($matches == 0) {
|
1086 |
+
return false;
|
1087 |
+
}
|
1088 |
+
return true;
|
1089 |
+
}
|
1090 |
+
|
1091 |
+
// since there are no elements for the type, if the user passed no
|
1092 |
+
// parameters, the parameters match wrapped.
|
1093 |
+
$this->debug("in parametersMatchWrapped: no elements type $ns:$uqType");
|
1094 |
+
return count($parameters) == 0;
|
1095 |
+
}
|
1096 |
+
|
1097 |
+
/**
|
1098 |
+
* serialize PHP values according to a WSDL message definition
|
1099 |
+
* contrary to the method name, this is not limited to RPC
|
1100 |
+
*
|
1101 |
+
* TODO
|
1102 |
+
* - multi-ref serialization
|
1103 |
+
* - validate PHP values against type definitions, return errors if invalid
|
1104 |
+
*
|
1105 |
+
* @param string $operation operation name
|
1106 |
+
* @param string $direction (input|output)
|
1107 |
+
* @param mixed $parameters parameter value(s)
|
1108 |
+
* @param string $bindingType (soap|soap12)
|
1109 |
+
* @return mixed parameters serialized as XML or false on error (e.g. operation not found)
|
1110 |
+
* @access public
|
1111 |
+
*/
|
1112 |
+
function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap') {
|
1113 |
+
$this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");
|
1114 |
+
$this->appendDebug('parameters=' . $this->varDump($parameters));
|
1115 |
+
|
1116 |
+
if ($direction != 'input' && $direction != 'output') {
|
1117 |
+
$this->debug('The value of the \$direction argument needs to be either "input" or "output"');
|
1118 |
+
$this->setError('The value of the \$direction argument needs to be either "input" or "output"');
|
1119 |
+
return false;
|
1120 |
+
}
|
1121 |
+
if (!$opData = $this->getOperationData($operation, $bindingType)) {
|
1122 |
+
$this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
|
1123 |
+
$this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
|
1124 |
+
return false;
|
1125 |
+
}
|
1126 |
+
$this->debug('in serializeRPCParameters: opData:');
|
1127 |
+
$this->appendDebug($this->varDump($opData));
|
1128 |
+
|
1129 |
+
// Get encoding style for output and set to current
|
1130 |
+
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
|
1131 |
+
if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
|
1132 |
+
$encodingStyle = $opData['output']['encodingStyle'];
|
1133 |
+
$enc_style = $encodingStyle;
|
1134 |
+
}
|
1135 |
+
|
1136 |
+
// set input params
|
1137 |
+
$xml = '';
|
1138 |
+
if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
|
1139 |
+
$parts = &$opData[$direction]['parts'];
|
1140 |
+
$part_count = sizeof($parts);
|
1141 |
+
$style = $opData['style'];
|
1142 |
+
$use = $opData[$direction]['use'];
|
1143 |
+
$this->debug("have $part_count part(s) to serialize using $style/$use");
|
1144 |
+
if (is_array($parameters)) {
|
1145 |
+
$parametersArrayType = $this->isArraySimpleOrStruct($parameters);
|
1146 |
+
$parameter_count = count($parameters);
|
1147 |
+
$this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize");
|
1148 |
+
// check for Microsoft-style wrapped parameters
|
1149 |
+
if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) {
|
1150 |
+
$this->debug('check whether the caller has wrapped the parameters');
|
1151 |
+
if ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1) {
|
1152 |
+
// TODO: consider checking here for double-wrapping, when
|
1153 |
+
// service function wraps, then NuSOAP wraps again
|
1154 |
+
$this->debug("change simple array to associative with 'parameters' element");
|
1155 |
+
$parameters['parameters'] = $parameters[0];
|
1156 |
+
unset($parameters[0]);
|
1157 |
+
}
|
1158 |
+
if (($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) {
|
1159 |
+
$this->debug('check whether caller\'s parameters match the wrapped ones');
|
1160 |
+
if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) {
|
1161 |
+
$this->debug('wrap the parameters for the caller');
|
1162 |
+
$parameters = array('parameters' => $parameters);
|
1163 |
+
$parameter_count = 1;
|
1164 |
+
}
|
1165 |
+
}
|
1166 |
+
}
|
1167 |
+
foreach ($parts as $name => $type) {
|
1168 |
+
$this->debug("serializing part $name of type $type");
|
1169 |
+
// Track encoding style
|
1170 |
+
if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
|
1171 |
+
$encodingStyle = $opData[$direction]['encodingStyle'];
|
1172 |
+
$enc_style = $encodingStyle;
|
1173 |
+
} else {
|
1174 |
+
$enc_style = false;
|
1175 |
+
}
|
1176 |
+
// NOTE: add error handling here
|
1177 |
+
// if serializeType returns false, then catch global error and fault
|
1178 |
+
if ($parametersArrayType == 'arraySimple') {
|
1179 |
+
$p = array_shift($parameters);
|
1180 |
+
$this->debug('calling serializeType w/indexed param');
|
1181 |
+
$xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
|
1182 |
+
} elseif (isset($parameters[$name])) {
|
1183 |
+
$this->debug('calling serializeType w/named param');
|
1184 |
+
$xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
|
1185 |
+
} else {
|
1186 |
+
// TODO: only send nillable
|
1187 |
+
$this->debug('calling serializeType w/null param');
|
1188 |
+
$xml .= $this->serializeType($name, $type, null, $use, $enc_style);
|
1189 |
+
}
|
1190 |
+
}
|
1191 |
+
} else {
|
1192 |
+
$this->debug('no parameters passed.');
|
1193 |
+
}
|
1194 |
+
}
|
1195 |
+
$this->debug("serializeRPCParameters returning: $xml");
|
1196 |
+
return $xml;
|
1197 |
+
}
|
1198 |
+
|
1199 |
+
/**
|
1200 |
+
* serialize a PHP value according to a WSDL message definition
|
1201 |
+
*
|
1202 |
+
* TODO
|
1203 |
+
* - multi-ref serialization
|
1204 |
+
* - validate PHP values against type definitions, return errors if invalid
|
1205 |
+
*
|
1206 |
+
* @param string $operation operation name
|
1207 |
+
* @param string $direction (input|output)
|
1208 |
+
* @param mixed $parameters parameter value(s)
|
1209 |
+
* @return mixed parameters serialized as XML or false on error (e.g. operation not found)
|
1210 |
+
* @access public
|
1211 |
+
* @deprecated
|
1212 |
+
*/
|
1213 |
+
function serializeParameters($operation, $direction, $parameters)
|
1214 |
+
{
|
1215 |
+
$this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
|
1216 |
+
$this->appendDebug('parameters=' . $this->varDump($parameters));
|
1217 |
+
|
1218 |
+
if ($direction != 'input' && $direction != 'output') {
|
1219 |
+
$this->debug('The value of the \$direction argument needs to be either "input" or "output"');
|
1220 |
+
$this->setError('The value of the \$direction argument needs to be either "input" or "output"');
|
1221 |
+
return false;
|
1222 |
+
}
|
1223 |
+
if (!$opData = $this->getOperationData($operation)) {
|
1224 |
+
$this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
|
1225 |
+
$this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
|
1226 |
+
return false;
|
1227 |
+
}
|
1228 |
+
$this->debug('opData:');
|
1229 |
+
$this->appendDebug($this->varDump($opData));
|
1230 |
+
|
1231 |
+
// Get encoding style for output and set to current
|
1232 |
+
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
|
1233 |
+
if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
|
1234 |
+
$encodingStyle = $opData['output']['encodingStyle'];
|
1235 |
+
$enc_style = $encodingStyle;
|
1236 |
+
}
|
1237 |
+
|
1238 |
+
// set input params
|
1239 |
+
$xml = '';
|
1240 |
+
if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
|
1241 |
+
|
1242 |
+
$use = $opData[$direction]['use'];
|
1243 |
+
$this->debug("use=$use");
|
1244 |
+
$this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
|
1245 |
+
if (is_array($parameters)) {
|
1246 |
+
$parametersArrayType = $this->isArraySimpleOrStruct($parameters);
|
1247 |
+
$this->debug('have ' . $parametersArrayType . ' parameters');
|
1248 |
+
foreach($opData[$direction]['parts'] as $name => $type) {
|
1249 |
+
$this->debug('serializing part "'.$name.'" of type "'.$type.'"');
|
1250 |
+
// Track encoding style
|
1251 |
+
if(isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
|
1252 |
+
$encodingStyle = $opData[$direction]['encodingStyle'];
|
1253 |
+
$enc_style = $encodingStyle;
|
1254 |
+
} else {
|
1255 |
+
$enc_style = false;
|
1256 |
+
}
|
1257 |
+
// NOTE: add error handling here
|
1258 |
+
// if serializeType returns false, then catch global error and fault
|
1259 |
+
if ($parametersArrayType == 'arraySimple') {
|
1260 |
+
$p = array_shift($parameters);
|
1261 |
+
$this->debug('calling serializeType w/indexed param');
|
1262 |
+
$xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
|
1263 |
+
} elseif (isset($parameters[$name])) {
|
1264 |
+
$this->debug('calling serializeType w/named param');
|
1265 |
+
$xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
|
1266 |
+
} else {
|
1267 |
+
// TODO: only send nillable
|
1268 |
+
$this->debug('calling serializeType w/null param');
|
1269 |
+
$xml .= $this->serializeType($name, $type, null, $use, $enc_style);
|
1270 |
+
}
|
1271 |
+
}
|
1272 |
+
} else {
|
1273 |
+
$this->debug('no parameters passed.');
|
1274 |
+
}
|
1275 |
+
}
|
1276 |
+
$this->debug("serializeParameters returning: $xml");
|
1277 |
+
return $xml;
|
1278 |
+
}
|
1279 |
+
|
1280 |
+
/**
|
1281 |
+
* serializes a PHP value according a given type definition
|
1282 |
+
*
|
1283 |
+
* @param string $name name of value (part or element)
|
1284 |
+
* @param string $type XML schema type of value (type or element)
|
1285 |
+
* @param mixed $value a native PHP value (parameter value)
|
1286 |
+
* @param string $use use for part (encoded|literal)
|
1287 |
+
* @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
|
1288 |
+
* @param boolean $unqualified a kludge for what should be XML namespace form handling
|
1289 |
+
* @return string value serialized as an XML string
|
1290 |
+
* @access private
|
1291 |
+
*/
|
1292 |
+
function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
|
1293 |
+
{
|
1294 |
+
$this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));
|
1295 |
+
$this->appendDebug("value=" . $this->varDump($value));
|
1296 |
+
if($use == 'encoded' && $encodingStyle) {
|
1297 |
+
$encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
|
1298 |
+
}
|
1299 |
+
|
1300 |
+
// if a soapval has been supplied, let its type override the WSDL
|
1301 |
+
if (is_object($value) && get_class($value) == 'soapval') {
|
1302 |
+
if ($value->type_ns) {
|
1303 |
+
$type = $value->type_ns . ':' . $value->type;
|
1304 |
+
$forceType = true;
|
1305 |
+
$this->debug("in serializeType: soapval overrides type to $type");
|
1306 |
+
} elseif ($value->type) {
|
1307 |
+
$type = $value->type;
|
1308 |
+
$forceType = true;
|
1309 |
+
$this->debug("in serializeType: soapval overrides type to $type");
|
1310 |
+
} else {
|
1311 |
+
$forceType = false;
|
1312 |
+
$this->debug("in serializeType: soapval does not override type");
|
1313 |
+
}
|
1314 |
+
$attrs = $value->attributes;
|
1315 |
+
$value = $value->value;
|
1316 |
+
$this->debug("in serializeType: soapval overrides value to $value");
|
1317 |
+
if ($attrs) {
|
1318 |
+
if (!is_array($value)) {
|
1319 |
+
$value['!'] = $value;
|
1320 |
+
}
|
1321 |
+
foreach ($attrs as $n => $v) {
|
1322 |
+
$value['!' . $n] = $v;
|
1323 |
+
}
|
1324 |
+
$this->debug("in serializeType: soapval provides attributes");
|
1325 |
+
}
|
1326 |
+
} else {
|
1327 |
+
$forceType = false;
|
1328 |
+
}
|
1329 |
+
|
1330 |
+
$xml = '';
|
1331 |
+
if (strpos($type, ':')) {
|
1332 |
+
$uqType = substr($type, strrpos($type, ':') + 1);
|
1333 |
+
$ns = substr($type, 0, strrpos($type, ':'));
|
1334 |
+
$this->debug("in serializeType: got a prefixed type: $uqType, $ns");
|
1335 |
+
if ($this->getNamespaceFromPrefix($ns)) {
|
1336 |
+
$ns = $this->getNamespaceFromPrefix($ns);
|
1337 |
+
$this->debug("in serializeType: expanded prefixed type: $uqType, $ns");
|
1338 |
+
}
|
1339 |
+
|
1340 |
+
if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/'){
|
1341 |
+
$this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
|
1342 |
+
if ($unqualified && $use == 'literal') {
|
1343 |
+
$elementNS = " xmlns=\"\"";
|
1344 |
+
} else {
|
1345 |
+
$elementNS = '';
|
1346 |
+
}
|
1347 |
+
if (is_null($value)) {
|
1348 |
+
if ($use == 'literal') {
|
1349 |
+
// TODO: depends on minOccurs
|
1350 |
+
$xml = "<$name$elementNS/>";
|
1351 |
+
} else {
|
1352 |
+
// TODO: depends on nillable, which should be checked before calling this method
|
1353 |
+
$xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
|
1354 |
+
}
|
1355 |
+
$this->debug("in serializeType: returning: $xml");
|
1356 |
+
return $xml;
|
1357 |
+
}
|
1358 |
+
if ($uqType == 'Array') {
|
1359 |
+
// JBoss/Axis does this sometimes
|
1360 |
+
return $this->serialize_val($value, $name, false, false, false, false, $use);
|
1361 |
+
}
|
1362 |
+
if ($uqType == 'boolean') {
|
1363 |
+
if ((is_string($value) && $value == 'false') || (! $value)) {
|
1364 |
+
$value = 'false';
|
1365 |
+
} else {
|
1366 |
+
$value = 'true';
|
1367 |
+
}
|
1368 |
+
}
|
1369 |
+
if ($uqType == 'string' && gettype($value) == 'string') {
|
1370 |
+
$value = $this->expandEntities($value);
|
1371 |
+
}
|
1372 |
+
if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {
|
1373 |
+
$value = sprintf("%.0lf", $value);
|
1374 |
+
}
|
1375 |
+
// it's a scalar
|
1376 |
+
// TODO: what about null/nil values?
|
1377 |
+
// check type isn't a custom type extending xmlschema namespace
|
1378 |
+
if (!$this->getTypeDef($uqType, $ns)) {
|
1379 |
+
if ($use == 'literal') {
|
1380 |
+
if ($forceType) {
|
1381 |
+
$xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
|
1382 |
+
} else {
|
1383 |
+
$xml = "<$name$elementNS>$value</$name>";
|
1384 |
+
}
|
1385 |
+
} else {
|
1386 |
+
$xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
|
1387 |
+
}
|
1388 |
+
$this->debug("in serializeType: returning: $xml");
|
1389 |
+
return $xml;
|
1390 |
+
}
|
1391 |
+
$this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');
|
1392 |
+
} else if ($ns == 'http://xml.apache.org/xml-soap') {
|
1393 |
+
$this->debug('in serializeType: appears to be Apache SOAP type');
|
1394 |
+
if ($uqType == 'Map') {
|
1395 |
+
$tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
|
1396 |
+
if (! $tt_prefix) {
|
1397 |
+
$this->debug('in serializeType: Add namespace for Apache SOAP type');
|
1398 |
+
$tt_prefix = 'ns' . rand(1000, 9999);
|
1399 |
+
$this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap';
|
1400 |
+
// force this to be added to usedNamespaces
|
1401 |
+
$tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
|
1402 |
+
}
|
1403 |
+
$contents = '';
|
1404 |
+
foreach($value as $k => $v) {
|
1405 |
+
$this->debug("serializing map element: key $k, value $v");
|
1406 |
+
$contents .= '<item>';
|
1407 |
+
$contents .= $this->serialize_val($k,'key',false,false,false,false,$use);
|
1408 |
+
$contents .= $this->serialize_val($v,'value',false,false,false,false,$use);
|
1409 |
+
$contents .= '</item>';
|
1410 |
+
}
|
1411 |
+
if ($use == 'literal') {
|
1412 |
+
if ($forceType) {
|
1413 |
+
$xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
|
1414 |
+
} else {
|
1415 |
+
$xml = "<$name>$contents</$name>";
|
1416 |
+
}
|
1417 |
+
} else {
|
1418 |
+
$xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
|
1419 |
+
}
|
1420 |
+
$this->debug("in serializeType: returning: $xml");
|
1421 |
+
return $xml;
|
1422 |
+
}
|
1423 |
+
$this->debug('in serializeType: Apache SOAP type, but only support Map');
|
1424 |
+
}
|
1425 |
+
} else {
|
1426 |
+
// TODO: should the type be compared to types in XSD, and the namespace
|
1427 |
+
// set to XSD if the type matches?
|
1428 |
+
$this->debug("in serializeType: No namespace for type $type");
|
1429 |
+
$ns = '';
|
1430 |
+
$uqType = $type;
|
1431 |
+
}
|
1432 |
+
if(!$typeDef = $this->getTypeDef($uqType, $ns)){
|
1433 |
+
$this->setError("$type ($uqType) is not a supported type.");
|
1434 |
+
$this->debug("in serializeType: $type ($uqType) is not a supported type.");
|
1435 |
+
return false;
|
1436 |
+
} else {
|
1437 |
+
$this->debug("in serializeType: found typeDef");
|
1438 |
+
$this->appendDebug('typeDef=' . $this->varDump($typeDef));
|
1439 |
+
if (substr($uqType, -1) == '^') {
|
1440 |
+
$uqType = substr($uqType, 0, -1);
|
1441 |
+
}
|
1442 |
+
}
|
1443 |
+
if (!isset($typeDef['phpType'])) {
|
1444 |
+
$this->setError("$type ($uqType) has no phpType.");
|
1445 |
+
$this->debug("in serializeType: $type ($uqType) has no phpType.");
|
1446 |
+
return false;
|
1447 |
+
}
|
1448 |
+
$phpType = $typeDef['phpType'];
|
1449 |
+
$this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') );
|
1450 |
+
// if php type == struct, map value to the <all> element names
|
1451 |
+
if ($phpType == 'struct') {
|
1452 |
+
if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
|
1453 |
+
$elementName = $uqType;
|
1454 |
+
if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
|
1455 |
+
$elementNS = " xmlns=\"$ns\"";
|
1456 |
+
} else {
|
1457 |
+
$elementNS = " xmlns=\"\"";
|
1458 |
+
}
|
1459 |
+
} else {
|
1460 |
+
$elementName = $name;
|
1461 |
+
if ($unqualified) {
|
1462 |
+
$elementNS = " xmlns=\"\"";
|
1463 |
+
} else {
|
1464 |
+
$elementNS = '';
|
1465 |
+
}
|
1466 |
+
}
|
1467 |
+
if (is_null($value)) {
|
1468 |
+
if ($use == 'literal') {
|
1469 |
+
// TODO: depends on minOccurs and nillable
|
1470 |
+
$xml = "<$elementName$elementNS/>";
|
1471 |
+
} else {
|
1472 |
+
$xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
|
1473 |
+
}
|
1474 |
+
$this->debug("in serializeType: returning: $xml");
|
1475 |
+
return $xml;
|
1476 |
+
}
|
1477 |
+
if (is_object($value)) {
|
1478 |
+
$value = get_object_vars($value);
|
1479 |
+
}
|
1480 |
+
if (is_array($value)) {
|
1481 |
+
$elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
|
1482 |
+
if ($use == 'literal') {
|
1483 |
+
if ($forceType) {
|
1484 |
+
$xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
|
1485 |
+
} else {
|
1486 |
+
$xml = "<$elementName$elementNS$elementAttrs>";
|
1487 |
+
}
|
1488 |
+
} else {
|
1489 |
+
$xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
|
1490 |
+
}
|
1491 |
+
|
1492 |
+
if (isset($typeDef['simpleContent']) && $typeDef['simpleContent'] == 'true') {
|
1493 |
+
if (isset($value['!'])) {
|
1494 |
+
$xml .= $value['!'];
|
1495 |
+
$this->debug("in serializeType: serialized simpleContent for type $type");
|
1496 |
+
} else {
|
1497 |
+
$this->debug("in serializeType: no simpleContent to serialize for type $type");
|
1498 |
+
}
|
1499 |
+
} else {
|
1500 |
+
// complexContent
|
1501 |
+
$xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
|
1502 |
+
}
|
1503 |
+
$xml .= "</$elementName>";
|
1504 |
+
} else {
|
1505 |
+
$this->debug("in serializeType: phpType is struct, but value is not an array");
|
1506 |
+
$this->setError("phpType is struct, but value is not an array: see debug output for details");
|
1507 |
+
$xml = '';
|
1508 |
+
}
|
1509 |
+
} elseif ($phpType == 'array') {
|
1510 |
+
if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
|
1511 |
+
$elementNS = " xmlns=\"$ns\"";
|
1512 |
+
} else {
|
1513 |
+
if ($unqualified) {
|
1514 |
+
$elementNS = " xmlns=\"\"";
|
1515 |
+
} else {
|
1516 |
+
$elementNS = '';
|
1517 |
+
}
|
1518 |
+
}
|
1519 |
+
if (is_null($value)) {
|
1520 |
+
if ($use == 'literal') {
|
1521 |
+
// TODO: depends on minOccurs
|
1522 |
+
$xml = "<$name$elementNS/>";
|
1523 |
+
} else {
|
1524 |
+
$xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
|
1525 |
+
$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
|
1526 |
+
":Array\" " .
|
1527 |
+
$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
|
1528 |
+
':arrayType="' .
|
1529 |
+
$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .
|
1530 |
+
':' .
|
1531 |
+
$this->getLocalPart($typeDef['arrayType'])."[0]\"/>";
|
1532 |
+
}
|
1533 |
+
$this->debug("in serializeType: returning: $xml");
|
1534 |
+
return $xml;
|
1535 |
+
}
|
1536 |
+
if (isset($typeDef['multidimensional'])) {
|
1537 |
+
$nv = array();
|
1538 |
+
foreach($value as $v) {
|
1539 |
+
$cols = ',' . sizeof($v);
|
1540 |
+
$nv = array_merge($nv, $v);
|
1541 |
+
}
|
1542 |
+
$value = $nv;
|
1543 |
+
} else {
|
1544 |
+
$cols = '';
|
1545 |
+
}
|
1546 |
+
if (is_array($value) && sizeof($value) >= 1) {
|
1547 |
+
$rows = sizeof($value);
|
1548 |
+
$contents = '';
|
1549 |
+
foreach($value as $k => $v) {
|
1550 |
+
$this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");
|
1551 |
+
//if (strpos($typeDef['arrayType'], ':') ) {
|
1552 |
+
if (!in_array($typeDef['arrayType'],$this->typemap['http://www.w3.org/2001/XMLSchema'])) {
|
1553 |
+
$contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
|
1554 |
+
} else {
|
1555 |
+
$contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
|
1556 |
+
}
|
1557 |
+
}
|
1558 |
+
} else {
|
1559 |
+
$rows = 0;
|
1560 |
+
$contents = null;
|
1561 |
+
}
|
1562 |
+
// TODO: for now, an empty value will be serialized as a zero element
|
1563 |
+
// array. Revisit this when coding the handling of null/nil values.
|
1564 |
+
if ($use == 'literal') {
|
1565 |
+
$xml = "<$name$elementNS>"
|
1566 |
+
.$contents
|
1567 |
+
."</$name>";
|
1568 |
+
} else {
|
1569 |
+
$xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '.
|
1570 |
+
$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
|
1571 |
+
.':arrayType="'
|
1572 |
+
.$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
|
1573 |
+
.":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">"
|
1574 |
+
.$contents
|
1575 |
+
."</$name>";
|
1576 |
+
}
|
1577 |
+
} elseif ($phpType == 'scalar') {
|
1578 |
+
if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
|
1579 |
+
$elementNS = " xmlns=\"$ns\"";
|
1580 |
+
} else {
|
1581 |
+
if ($unqualified) {
|
1582 |
+
$elementNS = " xmlns=\"\"";
|
1583 |
+
} else {
|
1584 |
+
$elementNS = '';
|
1585 |
+
}
|
1586 |
+
}
|
1587 |
+
if ($use == 'literal') {
|
1588 |
+
if ($forceType) {
|
1589 |
+
$xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
|
1590 |
+
} else {
|
1591 |
+
$xml = "<$name$elementNS>$value</$name>";
|
1592 |
+
}
|
1593 |
+
} else {
|
1594 |
+
$xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
|
1595 |
+
}
|
1596 |
+
}
|
1597 |
+
$this->debug("in serializeType: returning: $xml");
|
1598 |
+
return $xml;
|
1599 |
+
}
|
1600 |
+
|
1601 |
+
/**
|
1602 |
+
* serializes the attributes for a complexType
|
1603 |
+
*
|
1604 |
+
* @param array $typeDef our internal representation of an XML schema type (or element)
|
1605 |
+
* @param mixed $value a native PHP value (parameter value)
|
1606 |
+
* @param string $ns the namespace of the type
|
1607 |
+
* @param string $uqType the local part of the type
|
1608 |
+
* @return string value serialized as an XML string
|
1609 |
+
* @access private
|
1610 |
+
*/
|
1611 |
+
function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) {
|
1612 |
+
$this->debug("serializeComplexTypeAttributes for XML Schema type $ns:$uqType");
|
1613 |
+
$xml = '';
|
1614 |
+
if (isset($typeDef['extensionBase'])) {
|
1615 |
+
$nsx = $this->getPrefix($typeDef['extensionBase']);
|
1616 |
+
$uqTypex = $this->getLocalPart($typeDef['extensionBase']);
|
1617 |
+
if ($this->getNamespaceFromPrefix($nsx)) {
|
1618 |
+
$nsx = $this->getNamespaceFromPrefix($nsx);
|
1619 |
+
}
|
1620 |
+
if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) {
|
1621 |
+
$this->debug("serialize attributes for extension base $nsx:$uqTypex");
|
1622 |
+
$xml .= $this->serializeComplexTypeAttributes($typeDefx, $value, $nsx, $uqTypex);
|
1623 |
+
} else {
|
1624 |
+
$this->debug("extension base $nsx:$uqTypex is not a supported type");
|
1625 |
+
}
|
1626 |
+
}
|
1627 |
+
if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
|
1628 |
+
$this->debug("serialize attributes for XML Schema type $ns:$uqType");
|
1629 |
+
if (is_array($value)) {
|
1630 |
+
$xvalue = $value;
|
1631 |
+
} elseif (is_object($value)) {
|
1632 |
+
$xvalue = get_object_vars($value);
|
1633 |
+
} else {
|
1634 |
+
$this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
|
1635 |
+
$xvalue = array();
|
1636 |
+
}
|
1637 |
+
foreach ($typeDef['attrs'] as $aName => $attrs) {
|
1638 |
+
if (isset($xvalue['!' . $aName])) {
|
1639 |
+
$xname = '!' . $aName;
|
1640 |
+
$this->debug("value provided for attribute $aName with key $xname");
|
1641 |
+
} elseif (isset($xvalue[$aName])) {
|
1642 |
+
$xname = $aName;
|
1643 |
+
$this->debug("value provided for attribute $aName with key $xname");
|
1644 |
+
} elseif (isset($attrs['default'])) {
|
1645 |
+
$xname = '!' . $aName;
|
1646 |
+
$xvalue[$xname] = $attrs['default'];
|
1647 |
+
$this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);
|
1648 |
+
} else {
|
1649 |
+
$xname = '';
|
1650 |
+
$this->debug("no value provided for attribute $aName");
|
1651 |
+
}
|
1652 |
+
if ($xname) {
|
1653 |
+
$xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";
|
1654 |
+
}
|
1655 |
+
}
|
1656 |
+
} else {
|
1657 |
+
$this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
|
1658 |
+
}
|
1659 |
+
return $xml;
|
1660 |
+
}
|
1661 |
+
|
1662 |
+
/**
|
1663 |
+
* serializes the elements for a complexType
|
1664 |
+
*
|
1665 |
+
* @param array $typeDef our internal representation of an XML schema type (or element)
|
1666 |
+
* @param mixed $value a native PHP value (parameter value)
|
1667 |
+
* @param string $ns the namespace of the type
|
1668 |
+
* @param string $uqType the local part of the type
|
1669 |
+
* @param string $use use for part (encoded|literal)
|
1670 |
+
* @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
|
1671 |
+
* @return string value serialized as an XML string
|
1672 |
+
* @access private
|
1673 |
+
*/
|
1674 |
+
function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) {
|
1675 |
+
$this->debug("in serializeComplexTypeElements for XML Schema type $ns:$uqType");
|
1676 |
+
$xml = '';
|
1677 |
+
if (isset($typeDef['extensionBase'])) {
|
1678 |
+
$nsx = $this->getPrefix($typeDef['extensionBase']);
|
1679 |
+
$uqTypex = $this->getLocalPart($typeDef['extensionBase']);
|
1680 |
+
if ($this->getNamespaceFromPrefix($nsx)) {
|
1681 |
+
$nsx = $this->getNamespaceFromPrefix($nsx);
|
1682 |
+
}
|
1683 |
+
if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) {
|
1684 |
+
$this->debug("serialize elements for extension base $nsx:$uqTypex");
|
1685 |
+
$xml .= $this->serializeComplexTypeElements($typeDefx, $value, $nsx, $uqTypex, $use, $encodingStyle);
|
1686 |
+
} else {
|
1687 |
+
$this->debug("extension base $nsx:$uqTypex is not a supported type");
|
1688 |
+
}
|
1689 |
+
}
|
1690 |
+
if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
|
1691 |
+
$this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
|
1692 |
+
if (is_array($value)) {
|
1693 |
+
$xvalue = $value;
|
1694 |
+
} elseif (is_object($value)) {
|
1695 |
+
$xvalue = get_object_vars($value);
|
1696 |
+
} else {
|
1697 |
+
$this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
|
1698 |
+
$xvalue = array();
|
1699 |
+
}
|
1700 |
+
// toggle whether all elements are present - ideally should validate against schema
|
1701 |
+
if (count($typeDef['elements']) != count($xvalue)){
|
1702 |
+
$optionals = true;
|
1703 |
+
}
|
1704 |
+
foreach ($typeDef['elements'] as $eName => $attrs) {
|
1705 |
+
if (!isset($xvalue[$eName])) {
|
1706 |
+
if (isset($attrs['default'])) {
|
1707 |
+
$xvalue[$eName] = $attrs['default'];
|
1708 |
+
$this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);
|
1709 |
+
}
|
1710 |
+
}
|
1711 |
+
// if user took advantage of a minOccurs=0, then only serialize named parameters
|
1712 |
+
if (isset($optionals)
|
1713 |
+
&& (!isset($xvalue[$eName]))
|
1714 |
+
&& ( (!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')
|
1715 |
+
){
|
1716 |
+
if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {
|
1717 |
+
$this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
|
1718 |
+
}
|
1719 |
+
// do nothing
|
1720 |
+
$this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");
|
1721 |
+
} else {
|
1722 |
+
// get value
|
1723 |
+
if (isset($xvalue[$eName])) {
|
1724 |
+
$v = $xvalue[$eName];
|
1725 |
+
} else {
|
1726 |
+
$v = null;
|
1727 |
+
}
|
1728 |
+
if (isset($attrs['form'])) {
|
1729 |
+
$unqualified = ($attrs['form'] == 'unqualified');
|
1730 |
+
} else {
|
1731 |
+
$unqualified = false;
|
1732 |
+
}
|
1733 |
+
if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
|
1734 |
+
$vv = $v;
|
1735 |
+
foreach ($vv as $k => $v) {
|
1736 |
+
if (isset($attrs['type']) || isset($attrs['ref'])) {
|
1737 |
+
// serialize schema-defined type
|
1738 |
+
$xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
|
1739 |
+
} else {
|
1740 |
+
// serialize generic type (can this ever really happen?)
|
1741 |
+
$this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
|
1742 |
+
$xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
|
1743 |
+
}
|
1744 |
+
}
|
1745 |
+
} else {
|
1746 |
+
if (is_null($v) && isset($attrs['minOccurs']) && $attrs['minOccurs'] == '0') {
|
1747 |
+
// do nothing
|
1748 |
+
} elseif (is_null($v) && isset($attrs['nillable']) && $attrs['nillable'] == 'true') {
|
1749 |
+
// TODO: serialize a nil correctly, but for now serialize schema-defined type
|
1750 |
+
$xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
|
1751 |
+
} elseif (isset($attrs['type']) || isset($attrs['ref'])) {
|
1752 |
+
// serialize schema-defined type
|
1753 |
+
$xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
|
1754 |
+
} else {
|
1755 |
+
// serialize generic type (can this ever really happen?)
|
1756 |
+
$this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
|
1757 |
+
$xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
|
1758 |
+
}
|
1759 |
+
}
|
1760 |
+
}
|
1761 |
+
}
|
1762 |
+
} else {
|
1763 |
+
$this->debug("no elements to serialize for XML Schema type $ns:$uqType");
|
1764 |
+
}
|
1765 |
+
return $xml;
|
1766 |
+
}
|
1767 |
+
|
1768 |
+
/**
|
1769 |
+
* adds an XML Schema complex type to the WSDL types
|
1770 |
+
*
|
1771 |
+
* @param string $name
|
1772 |
+
* @param string $typeClass (complexType|simpleType|attribute)
|
1773 |
+
* @param string $phpType currently supported are array and struct (php assoc array)
|
1774 |
+
* @param string $compositor (all|sequence|choice)
|
1775 |
+
* @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
|
1776 |
+
* @param array $elements e.g. array ( name => array(name=>'',type=>'') )
|
1777 |
+
* @param array $attrs e.g. array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]'))
|
1778 |
+
* @param string $arrayType as namespace:name (xsd:string)
|
1779 |
+
* @see nusoap_xmlschema
|
1780 |
+
* @access public
|
1781 |
+
*/
|
1782 |
+
function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') {
|
1783 |
+
if (count($elements) > 0) {
|
1784 |
+
$eElements = array();
|
1785 |
+
foreach($elements as $n => $e){
|
1786 |
+
// expand each element
|
1787 |
+
$ee = array();
|
1788 |
+
foreach ($e as $k => $v) {
|
1789 |
+
$k = strpos($k,':') ? $this->expandQname($k) : $k;
|
1790 |
+
$v = strpos($v,':') ? $this->expandQname($v) : $v;
|
1791 |
+
$ee[$k] = $v;
|
1792 |
+
}
|
1793 |
+
$eElements[$n] = $ee;
|
1794 |
+
}
|
1795 |
+
$elements = $eElements;
|
1796 |
+
}
|
1797 |
+
|
1798 |
+
if (count($attrs) > 0) {
|
1799 |
+
foreach($attrs as $n => $a){
|
1800 |
+
// expand each attribute
|
1801 |
+
foreach ($a as $k => $v) {
|
1802 |
+
$k = strpos($k,':') ? $this->expandQname($k) : $k;
|
1803 |
+
$v = strpos($v,':') ? $this->expandQname($v) : $v;
|
1804 |
+
$aa[$k] = $v;
|
1805 |
+
}
|
1806 |
+
$eAttrs[$n] = $aa;
|
1807 |
+
}
|
1808 |
+
$attrs = $eAttrs;
|
1809 |
+
}
|
1810 |
+
|
1811 |
+
$restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
|
1812 |
+
$arrayType = strpos($arrayType,':') ? $this->expandQname($arrayType) : $arrayType;
|
1813 |
+
|
1814 |
+
$typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
|
1815 |
+
$this->schemas[$typens][0]->addComplexType($name,$typeClass,$phpType,$compositor,$restrictionBase,$elements,$attrs,$arrayType);
|
1816 |
+
}
|
1817 |
+
|
1818 |
+
/**
|
1819 |
+
* adds an XML Schema simple type to the WSDL types
|
1820 |
+
*
|
1821 |
+
* @param string $name
|
1822 |
+
* @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
|
1823 |
+
* @param string $typeClass (should always be simpleType)
|
1824 |
+
* @param string $phpType (should always be scalar)
|
1825 |
+
* @param array $enumeration array of values
|
1826 |
+
* @see nusoap_xmlschema
|
1827 |
+
* @access public
|
1828 |
+
*/
|
1829 |
+
function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
|
1830 |
+
$restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
|
1831 |
+
|
1832 |
+
$typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
|
1833 |
+
$this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
|
1834 |
+
}
|
1835 |
+
|
1836 |
+
/**
|
1837 |
+
* adds an element to the WSDL types
|
1838 |
+
*
|
1839 |
+
* @param array $attrs attributes that must include name and type
|
1840 |
+
* @see nusoap_xmlschema
|
1841 |
+
* @access public
|
1842 |
+
*/
|
1843 |
+
function addElement($attrs) {
|
1844 |
+
$typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
|
1845 |
+
$this->schemas[$typens][0]->addElement($attrs);
|
1846 |
+
}
|
1847 |
+
|
1848 |
+
/**
|
1849 |
+
* register an operation with the server
|
1850 |
+
*
|
1851 |
+
* @param string $name operation (method) name
|
1852 |
+
* @param array $in assoc array of input values: key = param name, value = param type
|
1853 |
+
* @param array $out assoc array of output values: key = param name, value = param type
|
1854 |
+
* @param string $namespace optional The namespace for the operation
|
1855 |
+
* @param string $soapaction optional The soapaction for the operation
|
1856 |
+
* @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
|
1857 |
+
* @param string $use (encoded|literal) optional The use for the parameters (cannot mix right now)
|
1858 |
+
* @param string $documentation optional The description to include in the WSDL
|
1859 |
+
* @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
|
1860 |
+
* @access public
|
1861 |
+
*/
|
1862 |
+
function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = ''){
|
1863 |
+
if ($use == 'encoded' && $encodingStyle == '') {
|
1864 |
+
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
|
1865 |
+
}
|
1866 |
+
|
1867 |
+
if ($style == 'document') {
|
1868 |
+
$elements = array();
|
1869 |
+
foreach ($in as $n => $t) {
|
1870 |
+
$elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified');
|
1871 |
+
}
|
1872 |
+
$this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
|
1873 |
+
$this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
|
1874 |
+
$in = array('parameters' => 'tns:' . $name . '^');
|
1875 |
+
|
1876 |
+
$elements = array();
|
1877 |
+
foreach ($out as $n => $t) {
|
1878 |
+
$elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified');
|
1879 |
+
}
|
1880 |
+
$this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
|
1881 |
+
$this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
|
1882 |
+
$out = array('parameters' => 'tns:' . $name . 'Response' . '^');
|
1883 |
+
}
|
1884 |
+
|
1885 |
+
// get binding
|
1886 |
+
$this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =
|
1887 |
+
array(
|
1888 |
+
'name' => $name,
|
1889 |
+
'binding' => $this->serviceName . 'Binding',
|
1890 |
+
'endpoint' => $this->endpoint,
|
1891 |
+
'soapAction' => $soapaction,
|
1892 |
+
'style' => $style,
|
1893 |
+
'input' => array(
|
1894 |
+
'use' => $use,
|
1895 |
+
'namespace' => $namespace,
|
1896 |
+
'encodingStyle' => $encodingStyle,
|
1897 |
+
'message' => $name . 'Request',
|
1898 |
+
'parts' => $in),
|
1899 |
+
'output' => array(
|
1900 |
+
'use' => $use,
|
1901 |
+
'namespace' => $namespace,
|
1902 |
+
'encodingStyle' => $encodingStyle,
|
1903 |
+
'message' => $name . 'Response',
|
1904 |
+
'parts' => $out),
|
1905 |
+
'namespace' => $namespace,
|
1906 |
+
'transport' => 'http://schemas.xmlsoap.org/soap/http',
|
1907 |
+
'documentation' => $documentation);
|
1908 |
+
// add portTypes
|
1909 |
+
// add messages
|
1910 |
+
if($in)
|
1911 |
+
{
|
1912 |
+
foreach($in as $pName => $pType)
|
1913 |
+
{
|
1914 |
+
if(strpos($pType,':')) {
|
1915 |
+
$pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
|
1916 |
+
}
|
1917 |
+
$this->messages[$name.'Request'][$pName] = $pType;
|
1918 |
+
}
|
1919 |
+
} else {
|
1920 |
+
$this->messages[$name.'Request']= '0';
|
1921 |
+
}
|
1922 |
+
if($out)
|
1923 |
+
{
|
1924 |
+
foreach($out as $pName => $pType)
|
1925 |
+
{
|
1926 |
+
if(strpos($pType,':')) {
|
1927 |
+
$pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
|
1928 |
+
}
|
1929 |
+
$this->messages[$name.'Response'][$pName] = $pType;
|
1930 |
+
}
|
1931 |
+
} else {
|
1932 |
+
$this->messages[$name.'Response']= '0';
|
1933 |
+
}
|
1934 |
+
return true;
|
1935 |
+
}
|
1936 |
+
}
|
1937 |
+
|
1938 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.wsdlcache.php
ADDED
@@ -0,0 +1,209 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
The NuSOAP project home is:
|
4 |
+
http://sourceforge.net/projects/nusoap/
|
5 |
+
|
6 |
+
The primary support for NuSOAP is the mailing list:
|
7 |
+
nusoap-general@lists.sourceforge.net
|
8 |
+
*/
|
9 |
+
|
10 |
+
/**
|
11 |
+
* caches instances of the wsdl class
|
12 |
+
*
|
13 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
14 |
+
* @author Ingo Fischer <ingo@apollon.de>
|
15 |
+
* @version $Id: class.wsdlcache.php,v 1.7 2007/04/17 16:34:03 snichol Exp $
|
16 |
+
* @access public
|
17 |
+
*/
|
18 |
+
class nusoap_wsdlcache {
|
19 |
+
/**
|
20 |
+
* @var resource
|
21 |
+
* @access private
|
22 |
+
*/
|
23 |
+
var $fplock;
|
24 |
+
/**
|
25 |
+
* @var integer
|
26 |
+
* @access private
|
27 |
+
*/
|
28 |
+
var $cache_lifetime;
|
29 |
+
/**
|
30 |
+
* @var string
|
31 |
+
* @access private
|
32 |
+
*/
|
33 |
+
var $cache_dir;
|
34 |
+
/**
|
35 |
+
* @var string
|
36 |
+
* @access public
|
37 |
+
*/
|
38 |
+
var $debug_str = '';
|
39 |
+
|
40 |
+
/**
|
41 |
+
* constructor
|
42 |
+
*
|
43 |
+
* @param string $cache_dir directory for cache-files
|
44 |
+
* @param integer $cache_lifetime lifetime for caching-files in seconds or 0 for unlimited
|
45 |
+
* @access public
|
46 |
+
*/
|
47 |
+
function nusoap_wsdlcache($cache_dir='.', $cache_lifetime=0) {
|
48 |
+
$this->fplock = array();
|
49 |
+
$this->cache_dir = $cache_dir != '' ? $cache_dir : '.';
|
50 |
+
$this->cache_lifetime = $cache_lifetime;
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* creates the filename used to cache a wsdl instance
|
55 |
+
*
|
56 |
+
* @param string $wsdl The URL of the wsdl instance
|
57 |
+
* @return string The filename used to cache the instance
|
58 |
+
* @access private
|
59 |
+
*/
|
60 |
+
function createFilename($wsdl) {
|
61 |
+
return $this->cache_dir.'/wsdlcache-' . md5($wsdl);
|
62 |
+
}
|
63 |
+
|
64 |
+
/**
|
65 |
+
* adds debug data to the class level debug string
|
66 |
+
*
|
67 |
+
* @param string $string debug data
|
68 |
+
* @access private
|
69 |
+
*/
|
70 |
+
function debug($string){
|
71 |
+
$this->debug_str .= get_class($this).": $string\n";
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* gets a wsdl instance from the cache
|
76 |
+
*
|
77 |
+
* @param string $wsdl The URL of the wsdl instance
|
78 |
+
* @return object wsdl The cached wsdl instance, null if the instance is not in the cache
|
79 |
+
* @access public
|
80 |
+
*/
|
81 |
+
function get($wsdl) {
|
82 |
+
$filename = $this->createFilename($wsdl);
|
83 |
+
if ($this->obtainMutex($filename, "r")) {
|
84 |
+
// check for expired WSDL that must be removed from the cache
|
85 |
+
if ($this->cache_lifetime > 0) {
|
86 |
+
if (file_exists($filename) && (time() - filemtime($filename) > $this->cache_lifetime)) {
|
87 |
+
unlink($filename);
|
88 |
+
$this->debug("Expired $wsdl ($filename) from cache");
|
89 |
+
$this->releaseMutex($filename);
|
90 |
+
return null;
|
91 |
+
}
|
92 |
+
}
|
93 |
+
// see what there is to return
|
94 |
+
if (!file_exists($filename)) {
|
95 |
+
$this->debug("$wsdl ($filename) not in cache (1)");
|
96 |
+
$this->releaseMutex($filename);
|
97 |
+
return null;
|
98 |
+
}
|
99 |
+
$fp = @fopen($filename, "r");
|
100 |
+
if ($fp) {
|
101 |
+
$s = implode("", @file($filename));
|
102 |
+
fclose($fp);
|
103 |
+
$this->debug("Got $wsdl ($filename) from cache");
|
104 |
+
} else {
|
105 |
+
$s = null;
|
106 |
+
$this->debug("$wsdl ($filename) not in cache (2)");
|
107 |
+
}
|
108 |
+
$this->releaseMutex($filename);
|
109 |
+
return (!is_null($s)) ? unserialize($s) : null;
|
110 |
+
} else {
|
111 |
+
$this->debug("Unable to obtain mutex for $filename in get");
|
112 |
+
}
|
113 |
+
return null;
|
114 |
+
}
|
115 |
+
|
116 |
+
/**
|
117 |
+
* obtains the local mutex
|
118 |
+
*
|
119 |
+
* @param string $filename The Filename of the Cache to lock
|
120 |
+
* @param string $mode The open-mode ("r" or "w") or the file - affects lock-mode
|
121 |
+
* @return boolean Lock successfully obtained ?!
|
122 |
+
* @access private
|
123 |
+
*/
|
124 |
+
function obtainMutex($filename, $mode) {
|
125 |
+
if (isset($this->fplock[md5($filename)])) {
|
126 |
+
$this->debug("Lock for $filename already exists");
|
127 |
+
return false;
|
128 |
+
}
|
129 |
+
$this->fplock[md5($filename)] = fopen($filename.".lock", "w");
|
130 |
+
if ($mode == "r") {
|
131 |
+
return flock($this->fplock[md5($filename)], LOCK_SH);
|
132 |
+
} else {
|
133 |
+
return flock($this->fplock[md5($filename)], LOCK_EX);
|
134 |
+
}
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* adds a wsdl instance to the cache
|
139 |
+
*
|
140 |
+
* @param object wsdl $wsdl_instance The wsdl instance to add
|
141 |
+
* @return boolean WSDL successfully cached
|
142 |
+
* @access public
|
143 |
+
*/
|
144 |
+
function put($wsdl_instance) {
|
145 |
+
$filename = $this->createFilename($wsdl_instance->wsdl);
|
146 |
+
$s = serialize($wsdl_instance);
|
147 |
+
if ($this->obtainMutex($filename, "w")) {
|
148 |
+
$fp = fopen($filename, "w");
|
149 |
+
if (! $fp) {
|
150 |
+
$this->debug("Cannot write $wsdl_instance->wsdl ($filename) in cache");
|
151 |
+
$this->releaseMutex($filename);
|
152 |
+
return false;
|
153 |
+
}
|
154 |
+
fputs($fp, $s);
|
155 |
+
fclose($fp);
|
156 |
+
$this->debug("Put $wsdl_instance->wsdl ($filename) in cache");
|
157 |
+
$this->releaseMutex($filename);
|
158 |
+
return true;
|
159 |
+
} else {
|
160 |
+
$this->debug("Unable to obtain mutex for $filename in put");
|
161 |
+
}
|
162 |
+
return false;
|
163 |
+
}
|
164 |
+
|
165 |
+
/**
|
166 |
+
* releases the local mutex
|
167 |
+
*
|
168 |
+
* @param string $filename The Filename of the Cache to lock
|
169 |
+
* @return boolean Lock successfully released
|
170 |
+
* @access private
|
171 |
+
*/
|
172 |
+
function releaseMutex($filename) {
|
173 |
+
$ret = flock($this->fplock[md5($filename)], LOCK_UN);
|
174 |
+
fclose($this->fplock[md5($filename)]);
|
175 |
+
unset($this->fplock[md5($filename)]);
|
176 |
+
if (! $ret) {
|
177 |
+
$this->debug("Not able to release lock for $filename");
|
178 |
+
}
|
179 |
+
return $ret;
|
180 |
+
}
|
181 |
+
|
182 |
+
/**
|
183 |
+
* removes a wsdl instance from the cache
|
184 |
+
*
|
185 |
+
* @param string $wsdl The URL of the wsdl instance
|
186 |
+
* @return boolean Whether there was an instance to remove
|
187 |
+
* @access public
|
188 |
+
*/
|
189 |
+
function remove($wsdl) {
|
190 |
+
$filename = $this->createFilename($wsdl);
|
191 |
+
if (!file_exists($filename)) {
|
192 |
+
$this->debug("$wsdl ($filename) not in cache to be removed");
|
193 |
+
return false;
|
194 |
+
}
|
195 |
+
// ignore errors obtaining mutex
|
196 |
+
$this->obtainMutex($filename, "w");
|
197 |
+
$ret = unlink($filename);
|
198 |
+
$this->debug("Removed ($ret) $wsdl ($filename) from cache");
|
199 |
+
$this->releaseMutex($filename);
|
200 |
+
return $ret;
|
201 |
+
}
|
202 |
+
}
|
203 |
+
|
204 |
+
/**
|
205 |
+
* For backward compatibility
|
206 |
+
*/
|
207 |
+
class wsdlcache extends nusoap_wsdlcache {
|
208 |
+
}
|
209 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.xmlschema.php
ADDED
@@ -0,0 +1,973 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
|
4 |
+
|
5 |
+
|
6 |
+
/**
|
7 |
+
* parses an XML Schema, allows access to it's data, other utility methods.
|
8 |
+
* imperfect, no validation... yet, but quite functional.
|
9 |
+
*
|
10 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
11 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
12 |
+
* @version $Id: class.xmlschema.php,v 1.53 2010/04/26 20:15:08 snichol Exp $
|
13 |
+
* @access public
|
14 |
+
*/
|
15 |
+
class nusoap_xmlschema extends nusoap_base {
|
16 |
+
|
17 |
+
// files
|
18 |
+
var $schema = '';
|
19 |
+
var $xml = '';
|
20 |
+
// namespaces
|
21 |
+
var $enclosingNamespaces;
|
22 |
+
// schema info
|
23 |
+
var $schemaInfo = array();
|
24 |
+
var $schemaTargetNamespace = '';
|
25 |
+
// types, elements, attributes defined by the schema
|
26 |
+
var $attributes = array();
|
27 |
+
var $complexTypes = array();
|
28 |
+
var $complexTypeStack = array();
|
29 |
+
var $currentComplexType = null;
|
30 |
+
var $elements = array();
|
31 |
+
var $elementStack = array();
|
32 |
+
var $currentElement = null;
|
33 |
+
var $simpleTypes = array();
|
34 |
+
var $simpleTypeStack = array();
|
35 |
+
var $currentSimpleType = null;
|
36 |
+
// imports
|
37 |
+
var $imports = array();
|
38 |
+
// parser vars
|
39 |
+
var $parser;
|
40 |
+
var $position = 0;
|
41 |
+
var $depth = 0;
|
42 |
+
var $depth_array = array();
|
43 |
+
var $message = array();
|
44 |
+
var $defaultNamespace = array();
|
45 |
+
|
46 |
+
/**
|
47 |
+
* constructor
|
48 |
+
*
|
49 |
+
* @param string $schema schema document URI
|
50 |
+
* @param string $xml xml document URI
|
51 |
+
* @param string $namespaces namespaces defined in enclosing XML
|
52 |
+
* @access public
|
53 |
+
*/
|
54 |
+
function nusoap_xmlschema($schema='',$xml='',$namespaces=array()){
|
55 |
+
parent::nusoap_base();
|
56 |
+
$this->debug('nusoap_xmlschema class instantiated, inside constructor');
|
57 |
+
// files
|
58 |
+
$this->schema = $schema;
|
59 |
+
$this->xml = $xml;
|
60 |
+
|
61 |
+
// namespaces
|
62 |
+
$this->enclosingNamespaces = $namespaces;
|
63 |
+
$this->namespaces = array_merge($this->namespaces, $namespaces);
|
64 |
+
|
65 |
+
// parse schema file
|
66 |
+
if($schema != ''){
|
67 |
+
$this->debug('initial schema file: '.$schema);
|
68 |
+
$this->parseFile($schema, 'schema');
|
69 |
+
}
|
70 |
+
|
71 |
+
// parse xml file
|
72 |
+
if($xml != ''){
|
73 |
+
$this->debug('initial xml file: '.$xml);
|
74 |
+
$this->parseFile($xml, 'xml');
|
75 |
+
}
|
76 |
+
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* parse an XML file
|
81 |
+
*
|
82 |
+
* @param string $xml path/URL to XML file
|
83 |
+
* @param string $type (schema | xml)
|
84 |
+
* @return boolean
|
85 |
+
* @access public
|
86 |
+
*/
|
87 |
+
function parseFile($xml,$type){
|
88 |
+
// parse xml file
|
89 |
+
if($xml != ""){
|
90 |
+
$xmlStr = @join("",@file($xml));
|
91 |
+
if($xmlStr == ""){
|
92 |
+
$msg = 'Error reading XML from '.$xml;
|
93 |
+
$this->setError($msg);
|
94 |
+
$this->debug($msg);
|
95 |
+
return false;
|
96 |
+
} else {
|
97 |
+
$this->debug("parsing $xml");
|
98 |
+
$this->parseString($xmlStr,$type);
|
99 |
+
$this->debug("done parsing $xml");
|
100 |
+
return true;
|
101 |
+
}
|
102 |
+
}
|
103 |
+
return false;
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* parse an XML string
|
108 |
+
*
|
109 |
+
* @param string $xml path or URL
|
110 |
+
* @param string $type (schema|xml)
|
111 |
+
* @access private
|
112 |
+
*/
|
113 |
+
function parseString($xml,$type){
|
114 |
+
// parse xml string
|
115 |
+
if($xml != ""){
|
116 |
+
|
117 |
+
// Create an XML parser.
|
118 |
+
$this->parser = xml_parser_create();
|
119 |
+
// Set the options for parsing the XML data.
|
120 |
+
xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
|
121 |
+
|
122 |
+
// Set the object for the parser.
|
123 |
+
xml_set_object($this->parser, $this);
|
124 |
+
|
125 |
+
// Set the element handlers for the parser.
|
126 |
+
if($type == "schema"){
|
127 |
+
xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
|
128 |
+
xml_set_character_data_handler($this->parser,'schemaCharacterData');
|
129 |
+
} elseif($type == "xml"){
|
130 |
+
xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');
|
131 |
+
xml_set_character_data_handler($this->parser,'xmlCharacterData');
|
132 |
+
}
|
133 |
+
|
134 |
+
// Parse the XML file.
|
135 |
+
if(!xml_parse($this->parser,$xml,true)){
|
136 |
+
// Display an error message.
|
137 |
+
$errstr = sprintf('XML error parsing XML schema on line %d: %s',
|
138 |
+
xml_get_current_line_number($this->parser),
|
139 |
+
xml_error_string(xml_get_error_code($this->parser))
|
140 |
+
);
|
141 |
+
$this->debug($errstr);
|
142 |
+
$this->debug("XML payload:\n" . $xml);
|
143 |
+
$this->setError($errstr);
|
144 |
+
}
|
145 |
+
|
146 |
+
xml_parser_free($this->parser);
|
147 |
+
} else{
|
148 |
+
$this->debug('no xml passed to parseString()!!');
|
149 |
+
$this->setError('no xml passed to parseString()!!');
|
150 |
+
}
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* gets a type name for an unnamed type
|
155 |
+
*
|
156 |
+
* @param string Element name
|
157 |
+
* @return string A type name for an unnamed type
|
158 |
+
* @access private
|
159 |
+
*/
|
160 |
+
function CreateTypeName($ename) {
|
161 |
+
$scope = '';
|
162 |
+
for ($i = 0; $i < count($this->complexTypeStack); $i++) {
|
163 |
+
$scope .= $this->complexTypeStack[$i] . '_';
|
164 |
+
}
|
165 |
+
return $scope . $ename . '_ContainedType';
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* start-element handler
|
170 |
+
*
|
171 |
+
* @param string $parser XML parser object
|
172 |
+
* @param string $name element name
|
173 |
+
* @param string $attrs associative array of attributes
|
174 |
+
* @access private
|
175 |
+
*/
|
176 |
+
function schemaStartElement($parser, $name, $attrs) {
|
177 |
+
|
178 |
+
// position in the total number of elements, starting from 0
|
179 |
+
$pos = $this->position++;
|
180 |
+
$depth = $this->depth++;
|
181 |
+
// set self as current value for this depth
|
182 |
+
$this->depth_array[$depth] = $pos;
|
183 |
+
$this->message[$pos] = array('cdata' => '');
|
184 |
+
if ($depth > 0) {
|
185 |
+
$this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
|
186 |
+
} else {
|
187 |
+
$this->defaultNamespace[$pos] = false;
|
188 |
+
}
|
189 |
+
|
190 |
+
// get element prefix
|
191 |
+
if($prefix = $this->getPrefix($name)){
|
192 |
+
// get unqualified name
|
193 |
+
$name = $this->getLocalPart($name);
|
194 |
+
} else {
|
195 |
+
$prefix = '';
|
196 |
+
}
|
197 |
+
|
198 |
+
// loop thru attributes, expanding, and registering namespace declarations
|
199 |
+
if(count($attrs) > 0){
|
200 |
+
foreach($attrs as $k => $v){
|
201 |
+
// if ns declarations, add to class level array of valid namespaces
|
202 |
+
if(preg_match('/^xmlns/',$k)){
|
203 |
+
//$this->xdebug("$k: $v");
|
204 |
+
//$this->xdebug('ns_prefix: '.$this->getPrefix($k));
|
205 |
+
if($ns_prefix = substr(strrchr($k,':'),1)){
|
206 |
+
//$this->xdebug("Add namespace[$ns_prefix] = $v");
|
207 |
+
$this->namespaces[$ns_prefix] = $v;
|
208 |
+
} else {
|
209 |
+
$this->defaultNamespace[$pos] = $v;
|
210 |
+
if (! $this->getPrefixFromNamespace($v)) {
|
211 |
+
$this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
|
212 |
+
}
|
213 |
+
}
|
214 |
+
if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){
|
215 |
+
$this->XMLSchemaVersion = $v;
|
216 |
+
$this->namespaces['xsi'] = $v.'-instance';
|
217 |
+
}
|
218 |
+
}
|
219 |
+
}
|
220 |
+
foreach($attrs as $k => $v){
|
221 |
+
// expand each attribute
|
222 |
+
$k = strpos($k,':') ? $this->expandQname($k) : $k;
|
223 |
+
$v = strpos($v,':') ? $this->expandQname($v) : $v;
|
224 |
+
$eAttrs[$k] = $v;
|
225 |
+
}
|
226 |
+
$attrs = $eAttrs;
|
227 |
+
} else {
|
228 |
+
$attrs = array();
|
229 |
+
}
|
230 |
+
// find status, register data
|
231 |
+
switch($name){
|
232 |
+
case 'all': // (optional) compositor content for a complexType
|
233 |
+
case 'choice':
|
234 |
+
case 'group':
|
235 |
+
case 'sequence':
|
236 |
+
//$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
|
237 |
+
$this->complexTypes[$this->currentComplexType]['compositor'] = $name;
|
238 |
+
//if($name == 'all' || $name == 'sequence'){
|
239 |
+
// $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
|
240 |
+
//}
|
241 |
+
break;
|
242 |
+
case 'attribute': // complexType attribute
|
243 |
+
//$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
|
244 |
+
$this->xdebug("parsing attribute:");
|
245 |
+
$this->appendDebug($this->varDump($attrs));
|
246 |
+
if (!isset($attrs['form'])) {
|
247 |
+
// TODO: handle globals
|
248 |
+
$attrs['form'] = $this->schemaInfo['attributeFormDefault'];
|
249 |
+
}
|
250 |
+
if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
|
251 |
+
$v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
|
252 |
+
if (!strpos($v, ':')) {
|
253 |
+
// no namespace in arrayType attribute value...
|
254 |
+
if ($this->defaultNamespace[$pos]) {
|
255 |
+
// ...so use the default
|
256 |
+
$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
|
257 |
+
}
|
258 |
+
}
|
259 |
+
}
|
260 |
+
if(isset($attrs['name'])){
|
261 |
+
$this->attributes[$attrs['name']] = $attrs;
|
262 |
+
$aname = $attrs['name'];
|
263 |
+
} elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
|
264 |
+
if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
|
265 |
+
$aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
|
266 |
+
} else {
|
267 |
+
$aname = '';
|
268 |
+
}
|
269 |
+
} elseif(isset($attrs['ref'])){
|
270 |
+
$aname = $attrs['ref'];
|
271 |
+
$this->attributes[$attrs['ref']] = $attrs;
|
272 |
+
}
|
273 |
+
|
274 |
+
if($this->currentComplexType){ // This should *always* be
|
275 |
+
$this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
|
276 |
+
}
|
277 |
+
// arrayType attribute
|
278 |
+
if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){
|
279 |
+
$this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
|
280 |
+
$prefix = $this->getPrefix($aname);
|
281 |
+
if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
|
282 |
+
$v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
|
283 |
+
} else {
|
284 |
+
$v = '';
|
285 |
+
}
|
286 |
+
if(strpos($v,'[,]')){
|
287 |
+
$this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
|
288 |
+
}
|
289 |
+
$v = substr($v,0,strpos($v,'[')); // clip the []
|
290 |
+
if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
|
291 |
+
$v = $this->XMLSchemaVersion.':'.$v;
|
292 |
+
}
|
293 |
+
$this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
|
294 |
+
}
|
295 |
+
break;
|
296 |
+
case 'complexContent': // (optional) content for a complexType
|
297 |
+
$this->xdebug("do nothing for element $name");
|
298 |
+
break;
|
299 |
+
case 'complexType':
|
300 |
+
array_push($this->complexTypeStack, $this->currentComplexType);
|
301 |
+
if(isset($attrs['name'])){
|
302 |
+
// TODO: what is the scope of named complexTypes that appear
|
303 |
+
// nested within other c complexTypes?
|
304 |
+
$this->xdebug('processing named complexType '.$attrs['name']);
|
305 |
+
//$this->currentElement = false;
|
306 |
+
$this->currentComplexType = $attrs['name'];
|
307 |
+
$this->complexTypes[$this->currentComplexType] = $attrs;
|
308 |
+
$this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
|
309 |
+
// This is for constructs like
|
310 |
+
// <complexType name="ListOfString" base="soap:Array">
|
311 |
+
// <sequence>
|
312 |
+
// <element name="string" type="xsd:string"
|
313 |
+
// minOccurs="0" maxOccurs="unbounded" />
|
314 |
+
// </sequence>
|
315 |
+
// </complexType>
|
316 |
+
if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
|
317 |
+
$this->xdebug('complexType is unusual array');
|
318 |
+
$this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
|
319 |
+
} else {
|
320 |
+
$this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
|
321 |
+
}
|
322 |
+
} else {
|
323 |
+
$name = $this->CreateTypeName($this->currentElement);
|
324 |
+
$this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
|
325 |
+
$this->currentComplexType = $name;
|
326 |
+
//$this->currentElement = false;
|
327 |
+
$this->complexTypes[$this->currentComplexType] = $attrs;
|
328 |
+
$this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
|
329 |
+
// This is for constructs like
|
330 |
+
// <complexType name="ListOfString" base="soap:Array">
|
331 |
+
// <sequence>
|
332 |
+
// <element name="string" type="xsd:string"
|
333 |
+
// minOccurs="0" maxOccurs="unbounded" />
|
334 |
+
// </sequence>
|
335 |
+
// </complexType>
|
336 |
+
if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
|
337 |
+
$this->xdebug('complexType is unusual array');
|
338 |
+
$this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
|
339 |
+
} else {
|
340 |
+
$this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
|
341 |
+
}
|
342 |
+
}
|
343 |
+
$this->complexTypes[$this->currentComplexType]['simpleContent'] = 'false';
|
344 |
+
break;
|
345 |
+
case 'element':
|
346 |
+
array_push($this->elementStack, $this->currentElement);
|
347 |
+
if (!isset($attrs['form'])) {
|
348 |
+
if ($this->currentComplexType) {
|
349 |
+
$attrs['form'] = $this->schemaInfo['elementFormDefault'];
|
350 |
+
} else {
|
351 |
+
// global
|
352 |
+
$attrs['form'] = 'qualified';
|
353 |
+
}
|
354 |
+
}
|
355 |
+
if(isset($attrs['type'])){
|
356 |
+
$this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']);
|
357 |
+
if (! $this->getPrefix($attrs['type'])) {
|
358 |
+
if ($this->defaultNamespace[$pos]) {
|
359 |
+
$attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
|
360 |
+
$this->xdebug('used default namespace to make type ' . $attrs['type']);
|
361 |
+
}
|
362 |
+
}
|
363 |
+
// This is for constructs like
|
364 |
+
// <complexType name="ListOfString" base="soap:Array">
|
365 |
+
// <sequence>
|
366 |
+
// <element name="string" type="xsd:string"
|
367 |
+
// minOccurs="0" maxOccurs="unbounded" />
|
368 |
+
// </sequence>
|
369 |
+
// </complexType>
|
370 |
+
if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
|
371 |
+
$this->xdebug('arrayType for unusual array is ' . $attrs['type']);
|
372 |
+
$this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
|
373 |
+
}
|
374 |
+
$this->currentElement = $attrs['name'];
|
375 |
+
$ename = $attrs['name'];
|
376 |
+
} elseif(isset($attrs['ref'])){
|
377 |
+
$this->xdebug("processing element as ref to ".$attrs['ref']);
|
378 |
+
$this->currentElement = "ref to ".$attrs['ref'];
|
379 |
+
$ename = $this->getLocalPart($attrs['ref']);
|
380 |
+
} else {
|
381 |
+
$type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
|
382 |
+
$this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
|
383 |
+
$this->currentElement = $attrs['name'];
|
384 |
+
$attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
|
385 |
+
$ename = $attrs['name'];
|
386 |
+
}
|
387 |
+
if (isset($ename) && $this->currentComplexType) {
|
388 |
+
$this->xdebug("add element $ename to complexType $this->currentComplexType");
|
389 |
+
$this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
|
390 |
+
} elseif (!isset($attrs['ref'])) {
|
391 |
+
$this->xdebug("add element $ename to elements array");
|
392 |
+
$this->elements[ $attrs['name'] ] = $attrs;
|
393 |
+
$this->elements[ $attrs['name'] ]['typeClass'] = 'element';
|
394 |
+
}
|
395 |
+
break;
|
396 |
+
case 'enumeration': // restriction value list member
|
397 |
+
$this->xdebug('enumeration ' . $attrs['value']);
|
398 |
+
if ($this->currentSimpleType) {
|
399 |
+
$this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
|
400 |
+
} elseif ($this->currentComplexType) {
|
401 |
+
$this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
|
402 |
+
}
|
403 |
+
break;
|
404 |
+
case 'extension': // simpleContent or complexContent type extension
|
405 |
+
$this->xdebug('extension ' . $attrs['base']);
|
406 |
+
if ($this->currentComplexType) {
|
407 |
+
$ns = $this->getPrefix($attrs['base']);
|
408 |
+
if ($ns == '') {
|
409 |
+
$this->complexTypes[$this->currentComplexType]['extensionBase'] = $this->schemaTargetNamespace . ':' . $attrs['base'];
|
410 |
+
} else {
|
411 |
+
$this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
|
412 |
+
}
|
413 |
+
} else {
|
414 |
+
$this->xdebug('no current complexType to set extensionBase');
|
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 'include':
|
430 |
+
if (isset($attrs['schemaLocation'])) {
|
431 |
+
$this->xdebug('include into namespace ' . $this->schemaTargetNamespace . ' from ' . $attrs['schemaLocation']);
|
432 |
+
$this->imports[$this->schemaTargetNamespace][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
|
433 |
+
} else {
|
434 |
+
$this->xdebug('ignoring invalid XML Schema construct: include without schemaLocation attribute');
|
435 |
+
}
|
436 |
+
break;
|
437 |
+
case 'list': // simpleType value list
|
438 |
+
$this->xdebug("do nothing for element $name");
|
439 |
+
break;
|
440 |
+
case 'restriction': // simpleType, simpleContent or complexContent value restriction
|
441 |
+
$this->xdebug('restriction ' . $attrs['base']);
|
442 |
+
if($this->currentSimpleType){
|
443 |
+
$this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
|
444 |
+
} elseif($this->currentComplexType){
|
445 |
+
$this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
|
446 |
+
if(strstr($attrs['base'],':') == ':Array'){
|
447 |
+
$this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
|
448 |
+
}
|
449 |
+
}
|
450 |
+
break;
|
451 |
+
case 'schema':
|
452 |
+
$this->schemaInfo = $attrs;
|
453 |
+
$this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
|
454 |
+
if (isset($attrs['targetNamespace'])) {
|
455 |
+
$this->schemaTargetNamespace = $attrs['targetNamespace'];
|
456 |
+
}
|
457 |
+
if (!isset($attrs['elementFormDefault'])) {
|
458 |
+
$this->schemaInfo['elementFormDefault'] = 'unqualified';
|
459 |
+
}
|
460 |
+
if (!isset($attrs['attributeFormDefault'])) {
|
461 |
+
$this->schemaInfo['attributeFormDefault'] = 'unqualified';
|
462 |
+
}
|
463 |
+
break;
|
464 |
+
case 'simpleContent': // (optional) content for a complexType
|
465 |
+
if ($this->currentComplexType) { // This should *always* be
|
466 |
+
$this->complexTypes[$this->currentComplexType]['simpleContent'] = 'true';
|
467 |
+
} else {
|
468 |
+
$this->xdebug("do nothing for element $name because there is no current complexType");
|
469 |
+
}
|
470 |
+
break;
|
471 |
+
case 'simpleType':
|
472 |
+
array_push($this->simpleTypeStack, $this->currentSimpleType);
|
473 |
+
if(isset($attrs['name'])){
|
474 |
+
$this->xdebug("processing simpleType for name " . $attrs['name']);
|
475 |
+
$this->currentSimpleType = $attrs['name'];
|
476 |
+
$this->simpleTypes[ $attrs['name'] ] = $attrs;
|
477 |
+
$this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
|
478 |
+
$this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
|
479 |
+
} else {
|
480 |
+
$name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
|
481 |
+
$this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
|
482 |
+
$this->currentSimpleType = $name;
|
483 |
+
//$this->currentElement = false;
|
484 |
+
$this->simpleTypes[$this->currentSimpleType] = $attrs;
|
485 |
+
$this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
|
486 |
+
}
|
487 |
+
break;
|
488 |
+
case 'union': // simpleType type list
|
489 |
+
$this->xdebug("do nothing for element $name");
|
490 |
+
break;
|
491 |
+
default:
|
492 |
+
$this->xdebug("do not have any logic to process element $name");
|
493 |
+
}
|
494 |
+
}
|
495 |
+
|
496 |
+
/**
|
497 |
+
* end-element handler
|
498 |
+
*
|
499 |
+
* @param string $parser XML parser object
|
500 |
+
* @param string $name element name
|
501 |
+
* @access private
|
502 |
+
*/
|
503 |
+
function schemaEndElement($parser, $name) {
|
504 |
+
// bring depth down a notch
|
505 |
+
$this->depth--;
|
506 |
+
// position of current element is equal to the last value left in depth_array for my depth
|
507 |
+
if(isset($this->depth_array[$this->depth])){
|
508 |
+
$pos = $this->depth_array[$this->depth];
|
509 |
+
}
|
510 |
+
// get element prefix
|
511 |
+
if ($prefix = $this->getPrefix($name)){
|
512 |
+
// get unqualified name
|
513 |
+
$name = $this->getLocalPart($name);
|
514 |
+
} else {
|
515 |
+
$prefix = '';
|
516 |
+
}
|
517 |
+
// move on...
|
518 |
+
if($name == 'complexType'){
|
519 |
+
$this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
|
520 |
+
$this->xdebug($this->varDump($this->complexTypes[$this->currentComplexType]));
|
521 |
+
$this->currentComplexType = array_pop($this->complexTypeStack);
|
522 |
+
//$this->currentElement = false;
|
523 |
+
}
|
524 |
+
if($name == 'element'){
|
525 |
+
$this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
|
526 |
+
$this->currentElement = array_pop($this->elementStack);
|
527 |
+
}
|
528 |
+
if($name == 'simpleType'){
|
529 |
+
$this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
|
530 |
+
$this->xdebug($this->varDump($this->simpleTypes[$this->currentSimpleType]));
|
531 |
+
$this->currentSimpleType = array_pop($this->simpleTypeStack);
|
532 |
+
}
|
533 |
+
}
|
534 |
+
|
535 |
+
/**
|
536 |
+
* element content handler
|
537 |
+
*
|
538 |
+
* @param string $parser XML parser object
|
539 |
+
* @param string $data element content
|
540 |
+
* @access private
|
541 |
+
*/
|
542 |
+
function schemaCharacterData($parser, $data){
|
543 |
+
$pos = $this->depth_array[$this->depth - 1];
|
544 |
+
$this->message[$pos]['cdata'] .= $data;
|
545 |
+
}
|
546 |
+
|
547 |
+
/**
|
548 |
+
* serialize the schema
|
549 |
+
*
|
550 |
+
* @access public
|
551 |
+
*/
|
552 |
+
function serializeSchema(){
|
553 |
+
|
554 |
+
$schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
|
555 |
+
$xml = '';
|
556 |
+
// imports
|
557 |
+
if (sizeof($this->imports) > 0) {
|
558 |
+
foreach($this->imports as $ns => $list) {
|
559 |
+
foreach ($list as $ii) {
|
560 |
+
if ($ii['location'] != '') {
|
561 |
+
$xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
|
562 |
+
} else {
|
563 |
+
$xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
|
564 |
+
}
|
565 |
+
}
|
566 |
+
}
|
567 |
+
}
|
568 |
+
// complex types
|
569 |
+
foreach($this->complexTypes as $typeName => $attrs){
|
570 |
+
$contentStr = '';
|
571 |
+
// serialize child elements
|
572 |
+
if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){
|
573 |
+
foreach($attrs['elements'] as $element => $eParts){
|
574 |
+
if(isset($eParts['ref'])){
|
575 |
+
$contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n";
|
576 |
+
} else {
|
577 |
+
$contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
|
578 |
+
foreach ($eParts as $aName => $aValue) {
|
579 |
+
// handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
|
580 |
+
if ($aName != 'name' && $aName != 'type') {
|
581 |
+
$contentStr .= " $aName=\"$aValue\"";
|
582 |
+
}
|
583 |
+
}
|
584 |
+
$contentStr .= "/>\n";
|
585 |
+
}
|
586 |
+
}
|
587 |
+
// compositor wraps elements
|
588 |
+
if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
|
589 |
+
$contentStr = " <$schemaPrefix:$attrs[compositor]>\n".$contentStr." </$schemaPrefix:$attrs[compositor]>\n";
|
590 |
+
}
|
591 |
+
}
|
592 |
+
// attributes
|
593 |
+
if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){
|
594 |
+
foreach($attrs['attrs'] as $attr => $aParts){
|
595 |
+
$contentStr .= " <$schemaPrefix:attribute";
|
596 |
+
foreach ($aParts as $a => $v) {
|
597 |
+
if ($a == 'ref' || $a == 'type') {
|
598 |
+
$contentStr .= " $a=\"".$this->contractQName($v).'"';
|
599 |
+
} elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
|
600 |
+
$this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
|
601 |
+
$contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"';
|
602 |
+
} else {
|
603 |
+
$contentStr .= " $a=\"$v\"";
|
604 |
+
}
|
605 |
+
}
|
606 |
+
$contentStr .= "/>\n";
|
607 |
+
}
|
608 |
+
}
|
609 |
+
// if restriction
|
610 |
+
if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){
|
611 |
+
$contentStr = " <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr." </$schemaPrefix:restriction>\n";
|
612 |
+
// complex or simple content
|
613 |
+
if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){
|
614 |
+
$contentStr = " <$schemaPrefix:complexContent>\n".$contentStr." </$schemaPrefix:complexContent>\n";
|
615 |
+
}
|
616 |
+
}
|
617 |
+
// finalize complex type
|
618 |
+
if($contentStr != ''){
|
619 |
+
$contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n";
|
620 |
+
} else {
|
621 |
+
$contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
|
622 |
+
}
|
623 |
+
$xml .= $contentStr;
|
624 |
+
}
|
625 |
+
// simple types
|
626 |
+
if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){
|
627 |
+
foreach($this->simpleTypes as $typeName => $eParts){
|
628 |
+
$xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\">\n";
|
629 |
+
if (isset($eParts['enumeration'])) {
|
630 |
+
foreach ($eParts['enumeration'] as $e) {
|
631 |
+
$xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n";
|
632 |
+
}
|
633 |
+
}
|
634 |
+
$xml .= " </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
|
635 |
+
}
|
636 |
+
}
|
637 |
+
// elements
|
638 |
+
if(isset($this->elements) && count($this->elements) > 0){
|
639 |
+
foreach($this->elements as $element => $eParts){
|
640 |
+
$xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n";
|
641 |
+
}
|
642 |
+
}
|
643 |
+
// attributes
|
644 |
+
if(isset($this->attributes) && count($this->attributes) > 0){
|
645 |
+
foreach($this->attributes as $attr => $aParts){
|
646 |
+
$xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>";
|
647 |
+
}
|
648 |
+
}
|
649 |
+
// finish 'er up
|
650 |
+
$attr = '';
|
651 |
+
foreach ($this->schemaInfo as $k => $v) {
|
652 |
+
if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {
|
653 |
+
$attr .= " $k=\"$v\"";
|
654 |
+
}
|
655 |
+
}
|
656 |
+
$el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
|
657 |
+
foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
|
658 |
+
$el .= " xmlns:$nsp=\"$ns\"";
|
659 |
+
}
|
660 |
+
$xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
|
661 |
+
return $xml;
|
662 |
+
}
|
663 |
+
|
664 |
+
/**
|
665 |
+
* adds debug data to the clas level debug string
|
666 |
+
*
|
667 |
+
* @param string $string debug data
|
668 |
+
* @access private
|
669 |
+
*/
|
670 |
+
function xdebug($string){
|
671 |
+
$this->debug('<' . $this->schemaTargetNamespace . '> '.$string);
|
672 |
+
}
|
673 |
+
|
674 |
+
/**
|
675 |
+
* get the PHP type of a user defined type in the schema
|
676 |
+
* PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays
|
677 |
+
* returns false if no type exists, or not w/ the given namespace
|
678 |
+
* else returns a string that is either a native php type, or 'struct'
|
679 |
+
*
|
680 |
+
* @param string $type name of defined type
|
681 |
+
* @param string $ns namespace of type
|
682 |
+
* @return mixed
|
683 |
+
* @access public
|
684 |
+
* @deprecated
|
685 |
+
*/
|
686 |
+
function getPHPType($type,$ns){
|
687 |
+
if(isset($this->typemap[$ns][$type])){
|
688 |
+
//print "found type '$type' and ns $ns in typemap<br>";
|
689 |
+
return $this->typemap[$ns][$type];
|
690 |
+
} elseif(isset($this->complexTypes[$type])){
|
691 |
+
//print "getting type '$type' and ns $ns from complexTypes array<br>";
|
692 |
+
return $this->complexTypes[$type]['phpType'];
|
693 |
+
}
|
694 |
+
return false;
|
695 |
+
}
|
696 |
+
|
697 |
+
/**
|
698 |
+
* returns an associative array of information about a given type
|
699 |
+
* returns false if no type exists by the given name
|
700 |
+
*
|
701 |
+
* For a complexType typeDef = array(
|
702 |
+
* 'restrictionBase' => '',
|
703 |
+
* 'phpType' => '',
|
704 |
+
* 'compositor' => '(sequence|all)',
|
705 |
+
* 'elements' => array(), // refs to elements array
|
706 |
+
* 'attrs' => array() // refs to attributes array
|
707 |
+
* ... and so on (see addComplexType)
|
708 |
+
* )
|
709 |
+
*
|
710 |
+
* For simpleType or element, the array has different keys.
|
711 |
+
*
|
712 |
+
* @param string $type
|
713 |
+
* @return mixed
|
714 |
+
* @access public
|
715 |
+
* @see addComplexType
|
716 |
+
* @see addSimpleType
|
717 |
+
* @see addElement
|
718 |
+
*/
|
719 |
+
function getTypeDef($type){
|
720 |
+
//$this->debug("in getTypeDef for type $type");
|
721 |
+
if (substr($type, -1) == '^') {
|
722 |
+
$is_element = 1;
|
723 |
+
$type = substr($type, 0, -1);
|
724 |
+
} else {
|
725 |
+
$is_element = 0;
|
726 |
+
}
|
727 |
+
|
728 |
+
if((! $is_element) && isset($this->complexTypes[$type])){
|
729 |
+
$this->xdebug("in getTypeDef, found complexType $type");
|
730 |
+
return $this->complexTypes[$type];
|
731 |
+
} elseif((! $is_element) && isset($this->simpleTypes[$type])){
|
732 |
+
$this->xdebug("in getTypeDef, found simpleType $type");
|
733 |
+
if (!isset($this->simpleTypes[$type]['phpType'])) {
|
734 |
+
// get info for type to tack onto the simple type
|
735 |
+
// TODO: can this ever really apply (i.e. what is a simpleType really?)
|
736 |
+
$uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
|
737 |
+
$ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
|
738 |
+
$etype = $this->getTypeDef($uqType);
|
739 |
+
if ($etype) {
|
740 |
+
$this->xdebug("in getTypeDef, found type for simpleType $type:");
|
741 |
+
$this->xdebug($this->varDump($etype));
|
742 |
+
if (isset($etype['phpType'])) {
|
743 |
+
$this->simpleTypes[$type]['phpType'] = $etype['phpType'];
|
744 |
+
}
|
745 |
+
if (isset($etype['elements'])) {
|
746 |
+
$this->simpleTypes[$type]['elements'] = $etype['elements'];
|
747 |
+
}
|
748 |
+
}
|
749 |
+
}
|
750 |
+
return $this->simpleTypes[$type];
|
751 |
+
} elseif(isset($this->elements[$type])){
|
752 |
+
$this->xdebug("in getTypeDef, found element $type");
|
753 |
+
if (!isset($this->elements[$type]['phpType'])) {
|
754 |
+
// get info for type to tack onto the element
|
755 |
+
$uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
|
756 |
+
$ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
|
757 |
+
$etype = $this->getTypeDef($uqType);
|
758 |
+
if ($etype) {
|
759 |
+
$this->xdebug("in getTypeDef, found type for element $type:");
|
760 |
+
$this->xdebug($this->varDump($etype));
|
761 |
+
if (isset($etype['phpType'])) {
|
762 |
+
$this->elements[$type]['phpType'] = $etype['phpType'];
|
763 |
+
}
|
764 |
+
if (isset($etype['elements'])) {
|
765 |
+
$this->elements[$type]['elements'] = $etype['elements'];
|
766 |
+
}
|
767 |
+
if (isset($etype['extensionBase'])) {
|
768 |
+
$this->elements[$type]['extensionBase'] = $etype['extensionBase'];
|
769 |
+
}
|
770 |
+
} elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
|
771 |
+
$this->xdebug("in getTypeDef, element $type is an XSD type");
|
772 |
+
$this->elements[$type]['phpType'] = 'scalar';
|
773 |
+
}
|
774 |
+
}
|
775 |
+
return $this->elements[$type];
|
776 |
+
} elseif(isset($this->attributes[$type])){
|
777 |
+
$this->xdebug("in getTypeDef, found attribute $type");
|
778 |
+
return $this->attributes[$type];
|
779 |
+
} elseif (preg_match('/_ContainedType$/', $type)) {
|
780 |
+
$this->xdebug("in getTypeDef, have an untyped element $type");
|
781 |
+
$typeDef['typeClass'] = 'simpleType';
|
782 |
+
$typeDef['phpType'] = 'scalar';
|
783 |
+
$typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
|
784 |
+
return $typeDef;
|
785 |
+
}
|
786 |
+
$this->xdebug("in getTypeDef, did not find $type");
|
787 |
+
return false;
|
788 |
+
}
|
789 |
+
|
790 |
+
/**
|
791 |
+
* returns a sample serialization of a given type, or false if no type by the given name
|
792 |
+
*
|
793 |
+
* @param string $type name of type
|
794 |
+
* @return mixed
|
795 |
+
* @access public
|
796 |
+
* @deprecated
|
797 |
+
*/
|
798 |
+
function serializeTypeDef($type){
|
799 |
+
//print "in sTD() for type $type<br>";
|
800 |
+
if($typeDef = $this->getTypeDef($type)){
|
801 |
+
$str .= '<'.$type;
|
802 |
+
if(is_array($typeDef['attrs'])){
|
803 |
+
foreach($typeDef['attrs'] as $attName => $data){
|
804 |
+
$str .= " $attName=\"{type = ".$data['type']."}\"";
|
805 |
+
}
|
806 |
+
}
|
807 |
+
$str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
|
808 |
+
if(count($typeDef['elements']) > 0){
|
809 |
+
$str .= ">";
|
810 |
+
foreach($typeDef['elements'] as $element => $eData){
|
811 |
+
$str .= $this->serializeTypeDef($element);
|
812 |
+
}
|
813 |
+
$str .= "</$type>";
|
814 |
+
} elseif($typeDef['typeClass'] == 'element') {
|
815 |
+
$str .= "></$type>";
|
816 |
+
} else {
|
817 |
+
$str .= "/>";
|
818 |
+
}
|
819 |
+
return $str;
|
820 |
+
}
|
821 |
+
return false;
|
822 |
+
}
|
823 |
+
|
824 |
+
/**
|
825 |
+
* returns HTML form elements that allow a user
|
826 |
+
* to enter values for creating an instance of the given type.
|
827 |
+
*
|
828 |
+
* @param string $name name for type instance
|
829 |
+
* @param string $type name of type
|
830 |
+
* @return string
|
831 |
+
* @access public
|
832 |
+
* @deprecated
|
833 |
+
*/
|
834 |
+
function typeToForm($name,$type){
|
835 |
+
// get typedef
|
836 |
+
if($typeDef = $this->getTypeDef($type)){
|
837 |
+
// if struct
|
838 |
+
if($typeDef['phpType'] == 'struct'){
|
839 |
+
$buffer .= '<table>';
|
840 |
+
foreach($typeDef['elements'] as $child => $childDef){
|
841 |
+
$buffer .= "
|
842 |
+
<tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>
|
843 |
+
<td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";
|
844 |
+
}
|
845 |
+
$buffer .= '</table>';
|
846 |
+
// if array
|
847 |
+
} elseif($typeDef['phpType'] == 'array'){
|
848 |
+
$buffer .= '<table>';
|
849 |
+
for($i=0;$i < 3; $i++){
|
850 |
+
$buffer .= "
|
851 |
+
<tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
|
852 |
+
<td><input type='text' name='parameters[".$name."][]'></td></tr>";
|
853 |
+
}
|
854 |
+
$buffer .= '</table>';
|
855 |
+
// if scalar
|
856 |
+
} else {
|
857 |
+
$buffer .= "<input type='text' name='parameters[$name]'>";
|
858 |
+
}
|
859 |
+
} else {
|
860 |
+
$buffer .= "<input type='text' name='parameters[$name]'>";
|
861 |
+
}
|
862 |
+
return $buffer;
|
863 |
+
}
|
864 |
+
|
865 |
+
/**
|
866 |
+
* adds a complex type to the schema
|
867 |
+
*
|
868 |
+
* example: array
|
869 |
+
*
|
870 |
+
* addType(
|
871 |
+
* 'ArrayOfstring',
|
872 |
+
* 'complexType',
|
873 |
+
* 'array',
|
874 |
+
* '',
|
875 |
+
* 'SOAP-ENC:Array',
|
876 |
+
* array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),
|
877 |
+
* 'xsd:string'
|
878 |
+
* );
|
879 |
+
*
|
880 |
+
* example: PHP associative array ( SOAP Struct )
|
881 |
+
*
|
882 |
+
* addType(
|
883 |
+
* 'SOAPStruct',
|
884 |
+
* 'complexType',
|
885 |
+
* 'struct',
|
886 |
+
* 'all',
|
887 |
+
* array('myVar'=> array('name'=>'myVar','type'=>'string')
|
888 |
+
* );
|
889 |
+
*
|
890 |
+
* @param name
|
891 |
+
* @param typeClass (complexType|simpleType|attribute)
|
892 |
+
* @param phpType: currently supported are array and struct (php assoc array)
|
893 |
+
* @param compositor (all|sequence|choice)
|
894 |
+
* @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
|
895 |
+
* @param elements = array ( name = array(name=>'',type=>'') )
|
896 |
+
* @param attrs = array(
|
897 |
+
* array(
|
898 |
+
* 'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",
|
899 |
+
* "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"
|
900 |
+
* )
|
901 |
+
* )
|
902 |
+
* @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)
|
903 |
+
* @access public
|
904 |
+
* @see getTypeDef
|
905 |
+
*/
|
906 |
+
function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){
|
907 |
+
$this->complexTypes[$name] = array(
|
908 |
+
'name' => $name,
|
909 |
+
'typeClass' => $typeClass,
|
910 |
+
'phpType' => $phpType,
|
911 |
+
'compositor'=> $compositor,
|
912 |
+
'restrictionBase' => $restrictionBase,
|
913 |
+
'elements' => $elements,
|
914 |
+
'attrs' => $attrs,
|
915 |
+
'arrayType' => $arrayType
|
916 |
+
);
|
917 |
+
|
918 |
+
$this->xdebug("addComplexType $name:");
|
919 |
+
$this->appendDebug($this->varDump($this->complexTypes[$name]));
|
920 |
+
}
|
921 |
+
|
922 |
+
/**
|
923 |
+
* adds a simple type to the schema
|
924 |
+
*
|
925 |
+
* @param string $name
|
926 |
+
* @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
|
927 |
+
* @param string $typeClass (should always be simpleType)
|
928 |
+
* @param string $phpType (should always be scalar)
|
929 |
+
* @param array $enumeration array of values
|
930 |
+
* @access public
|
931 |
+
* @see nusoap_xmlschema
|
932 |
+
* @see getTypeDef
|
933 |
+
*/
|
934 |
+
function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
|
935 |
+
$this->simpleTypes[$name] = array(
|
936 |
+
'name' => $name,
|
937 |
+
'typeClass' => $typeClass,
|
938 |
+
'phpType' => $phpType,
|
939 |
+
'type' => $restrictionBase,
|
940 |
+
'enumeration' => $enumeration
|
941 |
+
);
|
942 |
+
|
943 |
+
$this->xdebug("addSimpleType $name:");
|
944 |
+
$this->appendDebug($this->varDump($this->simpleTypes[$name]));
|
945 |
+
}
|
946 |
+
|
947 |
+
/**
|
948 |
+
* adds an element to the schema
|
949 |
+
*
|
950 |
+
* @param array $attrs attributes that must include name and type
|
951 |
+
* @see nusoap_xmlschema
|
952 |
+
* @access public
|
953 |
+
*/
|
954 |
+
function addElement($attrs) {
|
955 |
+
if (! $this->getPrefix($attrs['type'])) {
|
956 |
+
$attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
|
957 |
+
}
|
958 |
+
$this->elements[ $attrs['name'] ] = $attrs;
|
959 |
+
$this->elements[ $attrs['name'] ]['typeClass'] = 'element';
|
960 |
+
|
961 |
+
$this->xdebug("addElement " . $attrs['name']);
|
962 |
+
$this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
|
963 |
+
}
|
964 |
+
}
|
965 |
+
|
966 |
+
/**
|
967 |
+
* Backward compatibility
|
968 |
+
*/
|
969 |
+
class XMLSchema extends nusoap_xmlschema {
|
970 |
+
}
|
971 |
+
|
972 |
+
|
973 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/lib/nusoap.php
ADDED
@@ -0,0 +1,8148 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
$Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
|
5 |
+
|
6 |
+
NuSOAP - Web Services Toolkit for PHP
|
7 |
+
|
8 |
+
Copyright (c) 2002 NuSphere Corporation
|
9 |
+
|
10 |
+
This library is free software; you can redistribute it and/or
|
11 |
+
modify it under the terms of the GNU Lesser General Public
|
12 |
+
License as published by the Free Software Foundation; either
|
13 |
+
version 2.1 of the License, or (at your option) any later version.
|
14 |
+
|
15 |
+
This library is distributed in the hope that it will be useful,
|
16 |
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
17 |
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
18 |
+
Lesser General Public License for more details.
|
19 |
+
|
20 |
+
You should have received a copy of the GNU Lesser General Public
|
21 |
+
License along with this library; if not, write to the Free Software
|
22 |
+
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
23 |
+
|
24 |
+
The NuSOAP project home is:
|
25 |
+
http://sourceforge.net/projects/nusoap/
|
26 |
+
|
27 |
+
The primary support for NuSOAP is the Help forum on the project home page.
|
28 |
+
|
29 |
+
If you have any questions or comments, please email:
|
30 |
+
|
31 |
+
Dietrich Ayala
|
32 |
+
dietrich@ganx4.com
|
33 |
+
http://dietrich.ganx4.com/nusoap
|
34 |
+
|
35 |
+
NuSphere Corporation
|
36 |
+
http://www.nusphere.com
|
37 |
+
|
38 |
+
*/
|
39 |
+
|
40 |
+
/*
|
41 |
+
* Some of the standards implmented in whole or part by NuSOAP:
|
42 |
+
*
|
43 |
+
* SOAP 1.1 (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/)
|
44 |
+
* WSDL 1.1 (http://www.w3.org/TR/2001/NOTE-wsdl-20010315)
|
45 |
+
* SOAP Messages With Attachments (http://www.w3.org/TR/SOAP-attachments)
|
46 |
+
* XML 1.0 (http://www.w3.org/TR/2006/REC-xml-20060816/)
|
47 |
+
* Namespaces in XML 1.0 (http://www.w3.org/TR/2006/REC-xml-names-20060816/)
|
48 |
+
* XML Schema 1.0 (http://www.w3.org/TR/xmlschema-0/)
|
49 |
+
* RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies
|
50 |
+
* RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1
|
51 |
+
* RFC 2617 HTTP Authentication: Basic and Digest Access Authentication
|
52 |
+
*/
|
53 |
+
|
54 |
+
/* load classes
|
55 |
+
|
56 |
+
// necessary classes
|
57 |
+
require_once('class.soapclient.php');
|
58 |
+
require_once('class.soap_val.php');
|
59 |
+
require_once('class.soap_parser.php');
|
60 |
+
require_once('class.soap_fault.php');
|
61 |
+
|
62 |
+
// transport classes
|
63 |
+
require_once('class.soap_transport_http.php');
|
64 |
+
|
65 |
+
// optional add-on classes
|
66 |
+
require_once('class.xmlschema.php');
|
67 |
+
require_once('class.wsdl.php');
|
68 |
+
|
69 |
+
// server class
|
70 |
+
require_once('class.soap_server.php');*/
|
71 |
+
|
72 |
+
// class variable emulation
|
73 |
+
// cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
|
74 |
+
$GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = 9;
|
75 |
+
|
76 |
+
/**
|
77 |
+
*
|
78 |
+
* nusoap_base
|
79 |
+
*
|
80 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
81 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
82 |
+
* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
|
83 |
+
* @access public
|
84 |
+
*/
|
85 |
+
class nusoap_base {
|
86 |
+
/**
|
87 |
+
* Identification for HTTP headers.
|
88 |
+
*
|
89 |
+
* @var string
|
90 |
+
* @access private
|
91 |
+
*/
|
92 |
+
var $title = 'NuSOAP';
|
93 |
+
/**
|
94 |
+
* Version for HTTP headers.
|
95 |
+
*
|
96 |
+
* @var string
|
97 |
+
* @access private
|
98 |
+
*/
|
99 |
+
var $version = '0.9.5';
|
100 |
+
/**
|
101 |
+
* CVS revision for HTTP headers.
|
102 |
+
*
|
103 |
+
* @var string
|
104 |
+
* @access private
|
105 |
+
*/
|
106 |
+
var $revision = '$Revision: 1.123 $';
|
107 |
+
/**
|
108 |
+
* Current error string (manipulated by getError/setError)
|
109 |
+
*
|
110 |
+
* @var string
|
111 |
+
* @access private
|
112 |
+
*/
|
113 |
+
var $error_str = '';
|
114 |
+
/**
|
115 |
+
* Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment)
|
116 |
+
*
|
117 |
+
* @var string
|
118 |
+
* @access private
|
119 |
+
*/
|
120 |
+
var $debug_str = '';
|
121 |
+
/**
|
122 |
+
* toggles automatic encoding of special characters as entities
|
123 |
+
* (should always be true, I think)
|
124 |
+
*
|
125 |
+
* @var boolean
|
126 |
+
* @access private
|
127 |
+
*/
|
128 |
+
var $charencoding = true;
|
129 |
+
/**
|
130 |
+
* the debug level for this instance
|
131 |
+
*
|
132 |
+
* @var integer
|
133 |
+
* @access private
|
134 |
+
*/
|
135 |
+
var $debugLevel;
|
136 |
+
|
137 |
+
/**
|
138 |
+
* set schema version
|
139 |
+
*
|
140 |
+
* @var string
|
141 |
+
* @access public
|
142 |
+
*/
|
143 |
+
var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
|
144 |
+
|
145 |
+
/**
|
146 |
+
* charset encoding for outgoing messages
|
147 |
+
*
|
148 |
+
* @var string
|
149 |
+
* @access public
|
150 |
+
*/
|
151 |
+
var $soap_defencoding = 'ISO-8859-1';
|
152 |
+
//var $soap_defencoding = 'UTF-8';
|
153 |
+
|
154 |
+
/**
|
155 |
+
* namespaces in an array of prefix => uri
|
156 |
+
*
|
157 |
+
* this is "seeded" by a set of constants, but it may be altered by code
|
158 |
+
*
|
159 |
+
* @var array
|
160 |
+
* @access public
|
161 |
+
*/
|
162 |
+
var $namespaces = array(
|
163 |
+
'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
|
164 |
+
'xsd' => 'http://www.w3.org/2001/XMLSchema',
|
165 |
+
'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
|
166 |
+
'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
|
167 |
+
);
|
168 |
+
|
169 |
+
/**
|
170 |
+
* namespaces used in the current context, e.g. during serialization
|
171 |
+
*
|
172 |
+
* @var array
|
173 |
+
* @access private
|
174 |
+
*/
|
175 |
+
var $usedNamespaces = array();
|
176 |
+
|
177 |
+
/**
|
178 |
+
* XML Schema types in an array of uri => (array of xml type => php type)
|
179 |
+
* is this legacy yet?
|
180 |
+
* no, this is used by the nusoap_xmlschema class to verify type => namespace mappings.
|
181 |
+
* @var array
|
182 |
+
* @access public
|
183 |
+
*/
|
184 |
+
var $typemap = array(
|
185 |
+
'http://www.w3.org/2001/XMLSchema' => array(
|
186 |
+
'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
|
187 |
+
'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
|
188 |
+
'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
|
189 |
+
// abstract "any" types
|
190 |
+
'anyType'=>'string','anySimpleType'=>'string',
|
191 |
+
// derived datatypes
|
192 |
+
'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
|
193 |
+
'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
|
194 |
+
'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
|
195 |
+
'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
|
196 |
+
'http://www.w3.org/2000/10/XMLSchema' => array(
|
197 |
+
'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
|
198 |
+
'float'=>'double','dateTime'=>'string',
|
199 |
+
'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
|
200 |
+
'http://www.w3.org/1999/XMLSchema' => array(
|
201 |
+
'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
|
202 |
+
'float'=>'double','dateTime'=>'string',
|
203 |
+
'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
|
204 |
+
'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
|
205 |
+
'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),
|
206 |
+
'http://xml.apache.org/xml-soap' => array('Map')
|
207 |
+
);
|
208 |
+
|
209 |
+
/**
|
210 |
+
* XML entities to convert
|
211 |
+
*
|
212 |
+
* @var array
|
213 |
+
* @access public
|
214 |
+
* @deprecated
|
215 |
+
* @see expandEntities
|
216 |
+
*/
|
217 |
+
var $xmlEntities = array('quot' => '"','amp' => '&',
|
218 |
+
'lt' => '<','gt' => '>','apos' => "'");
|
219 |
+
|
220 |
+
/**
|
221 |
+
* constructor
|
222 |
+
*
|
223 |
+
* @access public
|
224 |
+
*/
|
225 |
+
function nusoap_base() {
|
226 |
+
$this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
|
227 |
+
}
|
228 |
+
|
229 |
+
/**
|
230 |
+
* gets the global debug level, which applies to future instances
|
231 |
+
*
|
232 |
+
* @return integer Debug level 0-9, where 0 turns off
|
233 |
+
* @access public
|
234 |
+
*/
|
235 |
+
function getGlobalDebugLevel() {
|
236 |
+
return $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
|
237 |
+
}
|
238 |
+
|
239 |
+
/**
|
240 |
+
* sets the global debug level, which applies to future instances
|
241 |
+
*
|
242 |
+
* @param int $level Debug level 0-9, where 0 turns off
|
243 |
+
* @access public
|
244 |
+
*/
|
245 |
+
function setGlobalDebugLevel($level) {
|
246 |
+
$GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = $level;
|
247 |
+
}
|
248 |
+
|
249 |
+
/**
|
250 |
+
* gets the debug level for this instance
|
251 |
+
*
|
252 |
+
* @return int Debug level 0-9, where 0 turns off
|
253 |
+
* @access public
|
254 |
+
*/
|
255 |
+
function getDebugLevel() {
|
256 |
+
return $this->debugLevel;
|
257 |
+
}
|
258 |
+
|
259 |
+
/**
|
260 |
+
* sets the debug level for this instance
|
261 |
+
*
|
262 |
+
* @param int $level Debug level 0-9, where 0 turns off
|
263 |
+
* @access public
|
264 |
+
*/
|
265 |
+
function setDebugLevel($level) {
|
266 |
+
$this->debugLevel = $level;
|
267 |
+
}
|
268 |
+
|
269 |
+
/**
|
270 |
+
* adds debug data to the instance debug string with formatting
|
271 |
+
*
|
272 |
+
* @param string $string debug data
|
273 |
+
* @access private
|
274 |
+
*/
|
275 |
+
function debug($string){
|
276 |
+
if ($this->debugLevel > 0) {
|
277 |
+
$this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n");
|
278 |
+
}
|
279 |
+
}
|
280 |
+
|
281 |
+
/**
|
282 |
+
* adds debug data to the instance debug string without formatting
|
283 |
+
*
|
284 |
+
* @param string $string debug data
|
285 |
+
* @access public
|
286 |
+
*/
|
287 |
+
function appendDebug($string){
|
288 |
+
if ($this->debugLevel > 0) {
|
289 |
+
// it would be nice to use a memory stream here to use
|
290 |
+
// memory more efficiently
|
291 |
+
$this->debug_str .= $string;
|
292 |
+
}
|
293 |
+
}
|
294 |
+
|
295 |
+
/**
|
296 |
+
* clears the current debug data for this instance
|
297 |
+
*
|
298 |
+
* @access public
|
299 |
+
*/
|
300 |
+
function clearDebug() {
|
301 |
+
// it would be nice to use a memory stream here to use
|
302 |
+
// memory more efficiently
|
303 |
+
$this->debug_str = '';
|
304 |
+
}
|
305 |
+
|
306 |
+
/**
|
307 |
+
* gets the current debug data for this instance
|
308 |
+
*
|
309 |
+
* @return debug data
|
310 |
+
* @access public
|
311 |
+
*/
|
312 |
+
function &getDebug() {
|
313 |
+
// it would be nice to use a memory stream here to use
|
314 |
+
// memory more efficiently
|
315 |
+
return $this->debug_str;
|
316 |
+
}
|
317 |
+
|
318 |
+
/**
|
319 |
+
* gets the current debug data for this instance as an XML comment
|
320 |
+
* this may change the contents of the debug data
|
321 |
+
*
|
322 |
+
* @return debug data as an XML comment
|
323 |
+
* @access public
|
324 |
+
*/
|
325 |
+
function &getDebugAsXMLComment() {
|
326 |
+
// it would be nice to use a memory stream here to use
|
327 |
+
// memory more efficiently
|
328 |
+
while (strpos($this->debug_str, '--')) {
|
329 |
+
$this->debug_str = str_replace('--', '- -', $this->debug_str);
|
330 |
+
}
|
331 |
+
$ret = "<!--\n" . $this->debug_str . "\n-->";
|
332 |
+
return $ret;
|
333 |
+
}
|
334 |
+
|
335 |
+
/**
|
336 |
+
* expands entities, e.g. changes '<' to '<'.
|
337 |
+
*
|
338 |
+
* @param string $val The string in which to expand entities.
|
339 |
+
* @access private
|
340 |
+
*/
|
341 |
+
function expandEntities($val) {
|
342 |
+
if ($this->charencoding) {
|
343 |
+
$val = str_replace('&', '&', $val);
|
344 |
+
$val = str_replace("'", ''', $val);
|
345 |
+
$val = str_replace('"', '"', $val);
|
346 |
+
$val = str_replace('<', '<', $val);
|
347 |
+
$val = str_replace('>', '>', $val);
|
348 |
+
}
|
349 |
+
return $val;
|
350 |
+
}
|
351 |
+
|
352 |
+
/**
|
353 |
+
* returns error string if present
|
354 |
+
*
|
355 |
+
* @return mixed error string or false
|
356 |
+
* @access public
|
357 |
+
*/
|
358 |
+
function getError(){
|
359 |
+
if($this->error_str != ''){
|
360 |
+
return $this->error_str;
|
361 |
+
}
|
362 |
+
return false;
|
363 |
+
}
|
364 |
+
|
365 |
+
/**
|
366 |
+
* sets error string
|
367 |
+
*
|
368 |
+
* @return boolean $string error string
|
369 |
+
* @access private
|
370 |
+
*/
|
371 |
+
function setError($str){
|
372 |
+
$this->error_str = $str;
|
373 |
+
}
|
374 |
+
|
375 |
+
/**
|
376 |
+
* detect if array is a simple array or a struct (associative array)
|
377 |
+
*
|
378 |
+
* @param mixed $val The PHP array
|
379 |
+
* @return string (arraySimple|arrayStruct)
|
380 |
+
* @access private
|
381 |
+
*/
|
382 |
+
function isArraySimpleOrStruct($val) {
|
383 |
+
$keyList = array_keys($val);
|
384 |
+
foreach ($keyList as $keyListValue) {
|
385 |
+
if (!is_int($keyListValue)) {
|
386 |
+
return 'arrayStruct';
|
387 |
+
}
|
388 |
+
}
|
389 |
+
return 'arraySimple';
|
390 |
+
}
|
391 |
+
|
392 |
+
/**
|
393 |
+
* serializes PHP values in accordance w/ section 5. Type information is
|
394 |
+
* not serialized if $use == 'literal'.
|
395 |
+
*
|
396 |
+
* @param mixed $val The value to serialize
|
397 |
+
* @param string $name The name (local part) of the XML element
|
398 |
+
* @param string $type The XML schema type (local part) for the element
|
399 |
+
* @param string $name_ns The namespace for the name of the XML element
|
400 |
+
* @param string $type_ns The namespace for the type of the element
|
401 |
+
* @param array $attributes The attributes to serialize as name=>value pairs
|
402 |
+
* @param string $use The WSDL "use" (encoded|literal)
|
403 |
+
* @param boolean $soapval Whether this is called from soapval.
|
404 |
+
* @return string The serialized element, possibly with child elements
|
405 |
+
* @access public
|
406 |
+
*/
|
407 |
+
function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded',$soapval=false) {
|
408 |
+
$this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval");
|
409 |
+
$this->appendDebug('value=' . $this->varDump($val));
|
410 |
+
$this->appendDebug('attributes=' . $this->varDump($attributes));
|
411 |
+
|
412 |
+
if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) {
|
413 |
+
$this->debug("serialize_val: serialize soapval");
|
414 |
+
$xml = $val->serialize($use);
|
415 |
+
$this->appendDebug($val->getDebug());
|
416 |
+
$val->clearDebug();
|
417 |
+
$this->debug("serialize_val of soapval returning $xml");
|
418 |
+
return $xml;
|
419 |
+
}
|
420 |
+
// force valid name if necessary
|
421 |
+
if (is_numeric($name)) {
|
422 |
+
$name = '__numeric_' . $name;
|
423 |
+
} elseif (! $name) {
|
424 |
+
$name = 'noname';
|
425 |
+
}
|
426 |
+
// if name has ns, add ns prefix to name
|
427 |
+
$xmlns = '';
|
428 |
+
if($name_ns){
|
429 |
+
$prefix = 'nu'.rand(1000,9999);
|
430 |
+
$name = $prefix.':'.$name;
|
431 |
+
$xmlns .= " xmlns:$prefix=\"$name_ns\"";
|
432 |
+
}
|
433 |
+
// if type is prefixed, create type prefix
|
434 |
+
if($type_ns != '' && $type_ns == $this->namespaces['xsd']){
|
435 |
+
// need to fix this. shouldn't default to xsd if no ns specified
|
436 |
+
// w/o checking against typemap
|
437 |
+
$type_prefix = 'xsd';
|
438 |
+
} elseif($type_ns){
|
439 |
+
$type_prefix = 'ns'.rand(1000,9999);
|
440 |
+
$xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
|
441 |
+
}
|
442 |
+
// serialize attributes if present
|
443 |
+
$atts = '';
|
444 |
+
if($attributes){
|
445 |
+
foreach($attributes as $k => $v){
|
446 |
+
$atts .= " $k=\"".$this->expandEntities($v).'"';
|
447 |
+
}
|
448 |
+
}
|
449 |
+
// serialize null value
|
450 |
+
if (is_null($val)) {
|
451 |
+
$this->debug("serialize_val: serialize null");
|
452 |
+
if ($use == 'literal') {
|
453 |
+
// TODO: depends on minOccurs
|
454 |
+
$xml = "<$name$xmlns$atts/>";
|
455 |
+
$this->debug("serialize_val returning $xml");
|
456 |
+
return $xml;
|
457 |
+
} else {
|
458 |
+
if (isset($type) && isset($type_prefix)) {
|
459 |
+
$type_str = " xsi:type=\"$type_prefix:$type\"";
|
460 |
+
} else {
|
461 |
+
$type_str = '';
|
462 |
+
}
|
463 |
+
$xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>";
|
464 |
+
$this->debug("serialize_val returning $xml");
|
465 |
+
return $xml;
|
466 |
+
}
|
467 |
+
}
|
468 |
+
// serialize if an xsd built-in primitive type
|
469 |
+
if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){
|
470 |
+
$this->debug("serialize_val: serialize xsd built-in primitive type");
|
471 |
+
if (is_bool($val)) {
|
472 |
+
if ($type == 'boolean') {
|
473 |
+
$val = $val ? 'true' : 'false';
|
474 |
+
} elseif (! $val) {
|
475 |
+
$val = 0;
|
476 |
+
}
|
477 |
+
} else if (is_string($val)) {
|
478 |
+
$val = $this->expandEntities($val);
|
479 |
+
}
|
480 |
+
if ($use == 'literal') {
|
481 |
+
$xml = "<$name$xmlns$atts>$val</$name>";
|
482 |
+
$this->debug("serialize_val returning $xml");
|
483 |
+
return $xml;
|
484 |
+
} else {
|
485 |
+
$xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>";
|
486 |
+
$this->debug("serialize_val returning $xml");
|
487 |
+
return $xml;
|
488 |
+
}
|
489 |
+
}
|
490 |
+
// detect type and serialize
|
491 |
+
$xml = '';
|
492 |
+
switch(true) {
|
493 |
+
case (is_bool($val) || $type == 'boolean'):
|
494 |
+
$this->debug("serialize_val: serialize boolean");
|
495 |
+
if ($type == 'boolean') {
|
496 |
+
$val = $val ? 'true' : 'false';
|
497 |
+
} elseif (! $val) {
|
498 |
+
$val = 0;
|
499 |
+
}
|
500 |
+
if ($use == 'literal') {
|
501 |
+
$xml .= "<$name$xmlns$atts>$val</$name>";
|
502 |
+
} else {
|
503 |
+
$xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
|
504 |
+
}
|
505 |
+
break;
|
506 |
+
case (is_int($val) || is_long($val) || $type == 'int'):
|
507 |
+
$this->debug("serialize_val: serialize int");
|
508 |
+
if ($use == 'literal') {
|
509 |
+
$xml .= "<$name$xmlns$atts>$val</$name>";
|
510 |
+
} else {
|
511 |
+
$xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
|
512 |
+
}
|
513 |
+
break;
|
514 |
+
case (is_float($val)|| is_double($val) || $type == 'float'):
|
515 |
+
$this->debug("serialize_val: serialize float");
|
516 |
+
if ($use == 'literal') {
|
517 |
+
$xml .= "<$name$xmlns$atts>$val</$name>";
|
518 |
+
} else {
|
519 |
+
$xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
|
520 |
+
}
|
521 |
+
break;
|
522 |
+
case (is_string($val) || $type == 'string'):
|
523 |
+
$this->debug("serialize_val: serialize string");
|
524 |
+
$val = $this->expandEntities($val);
|
525 |
+
if ($use == 'literal') {
|
526 |
+
$xml .= "<$name$xmlns$atts>$val</$name>";
|
527 |
+
} else {
|
528 |
+
$xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
|
529 |
+
}
|
530 |
+
break;
|
531 |
+
case is_object($val):
|
532 |
+
$this->debug("serialize_val: serialize object");
|
533 |
+
if (get_class($val) == 'soapval') {
|
534 |
+
$this->debug("serialize_val: serialize soapval object");
|
535 |
+
$pXml = $val->serialize($use);
|
536 |
+
$this->appendDebug($val->getDebug());
|
537 |
+
$val->clearDebug();
|
538 |
+
} else {
|
539 |
+
if (! $name) {
|
540 |
+
$name = get_class($val);
|
541 |
+
$this->debug("In serialize_val, used class name $name as element name");
|
542 |
+
} else {
|
543 |
+
$this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
|
544 |
+
}
|
545 |
+
foreach(get_object_vars($val) as $k => $v){
|
546 |
+
$pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use);
|
547 |
+
}
|
548 |
+
}
|
549 |
+
if(isset($type) && isset($type_prefix)){
|
550 |
+
$type_str = " xsi:type=\"$type_prefix:$type\"";
|
551 |
+
} else {
|
552 |
+
$type_str = '';
|
553 |
+
}
|
554 |
+
if ($use == 'literal') {
|
555 |
+
$xml .= "<$name$xmlns$atts>$pXml</$name>";
|
556 |
+
} else {
|
557 |
+
$xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";
|
558 |
+
}
|
559 |
+
break;
|
560 |
+
break;
|
561 |
+
case (is_array($val) || $type):
|
562 |
+
// detect if struct or array
|
563 |
+
$valueType = $this->isArraySimpleOrStruct($val);
|
564 |
+
if($valueType=='arraySimple' || preg_match('/^ArrayOf/',$type)){
|
565 |
+
$this->debug("serialize_val: serialize array");
|
566 |
+
$i = 0;
|
567 |
+
if(is_array($val) && count($val)> 0){
|
568 |
+
foreach($val as $v){
|
569 |
+
if(is_object($v) && get_class($v) == 'soapval'){
|
570 |
+
$tt_ns = $v->type_ns;
|
571 |
+
$tt = $v->type;
|
572 |
+
} elseif (is_array($v)) {
|
573 |
+
$tt = $this->isArraySimpleOrStruct($v);
|
574 |
+
} else {
|
575 |
+
$tt = gettype($v);
|
576 |
+
}
|
577 |
+
$array_types[$tt] = 1;
|
578 |
+
// TODO: for literal, the name should be $name
|
579 |
+
$xml .= $this->serialize_val($v,'item',false,false,false,false,$use);
|
580 |
+
++$i;
|
581 |
+
}
|
582 |
+
if(count($array_types) > 1){
|
583 |
+
$array_typename = 'xsd:anyType';
|
584 |
+
} elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
|
585 |
+
if ($tt == 'integer') {
|
586 |
+
$tt = 'int';
|
587 |
+
}
|
588 |
+
$array_typename = 'xsd:'.$tt;
|
589 |
+
} elseif(isset($tt) && $tt == 'arraySimple'){
|
590 |
+
$array_typename = 'SOAP-ENC:Array';
|
591 |
+
} elseif(isset($tt) && $tt == 'arrayStruct'){
|
592 |
+
$array_typename = 'unnamed_struct_use_soapval';
|
593 |
+
} else {
|
594 |
+
// if type is prefixed, create type prefix
|
595 |
+
if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){
|
596 |
+
$array_typename = 'xsd:' . $tt;
|
597 |
+
} elseif ($tt_ns) {
|
598 |
+
$tt_prefix = 'ns' . rand(1000, 9999);
|
599 |
+
$array_typename = "$tt_prefix:$tt";
|
600 |
+
$xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
|
601 |
+
} else {
|
602 |
+
$array_typename = $tt;
|
603 |
+
}
|
604 |
+
}
|
605 |
+
$array_type = $i;
|
606 |
+
if ($use == 'literal') {
|
607 |
+
$type_str = '';
|
608 |
+
} else if (isset($type) && isset($type_prefix)) {
|
609 |
+
$type_str = " xsi:type=\"$type_prefix:$type\"";
|
610 |
+
} else {
|
611 |
+
$type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"";
|
612 |
+
}
|
613 |
+
// empty array
|
614 |
+
} else {
|
615 |
+
if ($use == 'literal') {
|
616 |
+
$type_str = '';
|
617 |
+
} else if (isset($type) && isset($type_prefix)) {
|
618 |
+
$type_str = " xsi:type=\"$type_prefix:$type\"";
|
619 |
+
} else {
|
620 |
+
$type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
|
621 |
+
}
|
622 |
+
}
|
623 |
+
// TODO: for array in literal, there is no wrapper here
|
624 |
+
$xml = "<$name$xmlns$type_str$atts>".$xml."</$name>";
|
625 |
+
} else {
|
626 |
+
// got a struct
|
627 |
+
$this->debug("serialize_val: serialize struct");
|
628 |
+
if(isset($type) && isset($type_prefix)){
|
629 |
+
$type_str = " xsi:type=\"$type_prefix:$type\"";
|
630 |
+
} else {
|
631 |
+
$type_str = '';
|
632 |
+
}
|
633 |
+
if ($use == 'literal') {
|
634 |
+
$xml .= "<$name$xmlns$atts>";
|
635 |
+
} else {
|
636 |
+
$xml .= "<$name$xmlns$type_str$atts>";
|
637 |
+
}
|
638 |
+
foreach($val as $k => $v){
|
639 |
+
// Apache Map
|
640 |
+
if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
|
641 |
+
$xml .= '<item>';
|
642 |
+
$xml .= $this->serialize_val($k,'key',false,false,false,false,$use);
|
643 |
+
$xml .= $this->serialize_val($v,'value',false,false,false,false,$use);
|
644 |
+
$xml .= '</item>';
|
645 |
+
} else {
|
646 |
+
$xml .= $this->serialize_val($v,$k,false,false,false,false,$use);
|
647 |
+
}
|
648 |
+
}
|
649 |
+
$xml .= "</$name>";
|
650 |
+
}
|
651 |
+
break;
|
652 |
+
default:
|
653 |
+
$this->debug("serialize_val: serialize unknown");
|
654 |
+
$xml .= 'not detected, got '.gettype($val).' for '.$val;
|
655 |
+
break;
|
656 |
+
}
|
657 |
+
$this->debug("serialize_val returning $xml");
|
658 |
+
return $xml;
|
659 |
+
}
|
660 |
+
|
661 |
+
/**
|
662 |
+
* serializes a message
|
663 |
+
*
|
664 |
+
* @param string $body the XML of the SOAP body
|
665 |
+
* @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
|
666 |
+
* @param array $namespaces optional the namespaces used in generating the body and headers
|
667 |
+
* @param string $style optional (rpc|document)
|
668 |
+
* @param string $use optional (encoded|literal)
|
669 |
+
* @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
|
670 |
+
* @return string the message
|
671 |
+
* @access public
|
672 |
+
*/
|
673 |
+
function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded',$encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'){
|
674 |
+
// TODO: add an option to automatically run utf8_encode on $body and $headers
|
675 |
+
// if $this->soap_defencoding is UTF-8. Not doing this automatically allows
|
676 |
+
// one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
|
677 |
+
|
678 |
+
$this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");
|
679 |
+
$this->debug("headers:");
|
680 |
+
$this->appendDebug($this->varDump($headers));
|
681 |
+
$this->debug("namespaces:");
|
682 |
+
$this->appendDebug($this->varDump($namespaces));
|
683 |
+
|
684 |
+
// serialize namespaces
|
685 |
+
$ns_string = '';
|
686 |
+
foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
|
687 |
+
$ns_string .= " xmlns:$k=\"$v\"";
|
688 |
+
}
|
689 |
+
if($encodingStyle) {
|
690 |
+
$ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
|
691 |
+
}
|
692 |
+
|
693 |
+
// serialize headers
|
694 |
+
if($headers){
|
695 |
+
if (is_array($headers)) {
|
696 |
+
$xml = '';
|
697 |
+
foreach ($headers as $k => $v) {
|
698 |
+
if (is_object($v) && get_class($v) == 'soapval') {
|
699 |
+
$xml .= $this->serialize_val($v, false, false, false, false, false, $use);
|
700 |
+
} else {
|
701 |
+
$xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
|
702 |
+
}
|
703 |
+
}
|
704 |
+
$headers = $xml;
|
705 |
+
$this->debug("In serializeEnvelope, serialized array of headers to $headers");
|
706 |
+
}
|
707 |
+
$headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
|
708 |
+
}
|
709 |
+
// serialize envelope
|
710 |
+
return
|
711 |
+
'<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
|
712 |
+
'<SOAP-ENV:Envelope'.$ns_string.">".
|
713 |
+
$headers.
|
714 |
+
"<SOAP-ENV:Body>".
|
715 |
+
$body.
|
716 |
+
"</SOAP-ENV:Body>".
|
717 |
+
"</SOAP-ENV:Envelope>";
|
718 |
+
}
|
719 |
+
|
720 |
+
/**
|
721 |
+
* formats a string to be inserted into an HTML stream
|
722 |
+
*
|
723 |
+
* @param string $str The string to format
|
724 |
+
* @return string The formatted string
|
725 |
+
* @access public
|
726 |
+
* @deprecated
|
727 |
+
*/
|
728 |
+
function formatDump($str){
|
729 |
+
$str = htmlspecialchars($str);
|
730 |
+
return nl2br($str);
|
731 |
+
}
|
732 |
+
|
733 |
+
/**
|
734 |
+
* contracts (changes namespace to prefix) a qualified name
|
735 |
+
*
|
736 |
+
* @param string $qname qname
|
737 |
+
* @return string contracted qname
|
738 |
+
* @access private
|
739 |
+
*/
|
740 |
+
function contractQname($qname){
|
741 |
+
// get element namespace
|
742 |
+
//$this->xdebug("Contract $qname");
|
743 |
+
if (strrpos($qname, ':')) {
|
744 |
+
// get unqualified name
|
745 |
+
$name = substr($qname, strrpos($qname, ':') + 1);
|
746 |
+
// get ns
|
747 |
+
$ns = substr($qname, 0, strrpos($qname, ':'));
|
748 |
+
$p = $this->getPrefixFromNamespace($ns);
|
749 |
+
if ($p) {
|
750 |
+
return $p . ':' . $name;
|
751 |
+
}
|
752 |
+
return $qname;
|
753 |
+
} else {
|
754 |
+
return $qname;
|
755 |
+
}
|
756 |
+
}
|
757 |
+
|
758 |
+
/**
|
759 |
+
* expands (changes prefix to namespace) a qualified name
|
760 |
+
*
|
761 |
+
* @param string $qname qname
|
762 |
+
* @return string expanded qname
|
763 |
+
* @access private
|
764 |
+
*/
|
765 |
+
function expandQname($qname){
|
766 |
+
// get element prefix
|
767 |
+
if(strpos($qname,':') && !preg_match('/^http:\/\//',$qname)){
|
768 |
+
// get unqualified name
|
769 |
+
$name = substr(strstr($qname,':'),1);
|
770 |
+
// get ns prefix
|
771 |
+
$prefix = substr($qname,0,strpos($qname,':'));
|
772 |
+
if(isset($this->namespaces[$prefix])){
|
773 |
+
return $this->namespaces[$prefix].':'.$name;
|
774 |
+
} else {
|
775 |
+
return $qname;
|
776 |
+
}
|
777 |
+
} else {
|
778 |
+
return $qname;
|
779 |
+
}
|
780 |
+
}
|
781 |
+
|
782 |
+
/**
|
783 |
+
* returns the local part of a prefixed string
|
784 |
+
* returns the original string, if not prefixed
|
785 |
+
*
|
786 |
+
* @param string $str The prefixed string
|
787 |
+
* @return string The local part
|
788 |
+
* @access public
|
789 |
+
*/
|
790 |
+
function getLocalPart($str){
|
791 |
+
if($sstr = strrchr($str,':')){
|
792 |
+
// get unqualified name
|
793 |
+
return substr( $sstr, 1 );
|
794 |
+
} else {
|
795 |
+
return $str;
|
796 |
+
}
|
797 |
+
}
|
798 |
+
|
799 |
+
/**
|
800 |
+
* returns the prefix part of a prefixed string
|
801 |
+
* returns false, if not prefixed
|
802 |
+
*
|
803 |
+
* @param string $str The prefixed string
|
804 |
+
* @return mixed The prefix or false if there is no prefix
|
805 |
+
* @access public
|
806 |
+
*/
|
807 |
+
function getPrefix($str){
|
808 |
+
if($pos = strrpos($str,':')){
|
809 |
+
// get prefix
|
810 |
+
return substr($str,0,$pos);
|
811 |
+
}
|
812 |
+
return false;
|
813 |
+
}
|
814 |
+
|
815 |
+
/**
|
816 |
+
* pass it a prefix, it returns a namespace
|
817 |
+
*
|
818 |
+
* @param string $prefix The prefix
|
819 |
+
* @return mixed The namespace, false if no namespace has the specified prefix
|
820 |
+
* @access public
|
821 |
+
*/
|
822 |
+
function getNamespaceFromPrefix($prefix){
|
823 |
+
if (isset($this->namespaces[$prefix])) {
|
824 |
+
return $this->namespaces[$prefix];
|
825 |
+
}
|
826 |
+
//$this->setError("No namespace registered for prefix '$prefix'");
|
827 |
+
return false;
|
828 |
+
}
|
829 |
+
|
830 |
+
/**
|
831 |
+
* returns the prefix for a given namespace (or prefix)
|
832 |
+
* or false if no prefixes registered for the given namespace
|
833 |
+
*
|
834 |
+
* @param string $ns The namespace
|
835 |
+
* @return mixed The prefix, false if the namespace has no prefixes
|
836 |
+
* @access public
|
837 |
+
*/
|
838 |
+
function getPrefixFromNamespace($ns) {
|
839 |
+
foreach ($this->namespaces as $p => $n) {
|
840 |
+
if ($ns == $n || $ns == $p) {
|
841 |
+
$this->usedNamespaces[$p] = $n;
|
842 |
+
return $p;
|
843 |
+
}
|
844 |
+
}
|
845 |
+
return false;
|
846 |
+
}
|
847 |
+
|
848 |
+
/**
|
849 |
+
* returns the time in ODBC canonical form with microseconds
|
850 |
+
*
|
851 |
+
* @return string The time in ODBC canonical form with microseconds
|
852 |
+
* @access public
|
853 |
+
*/
|
854 |
+
function getmicrotime() {
|
855 |
+
if (function_exists('gettimeofday')) {
|
856 |
+
$tod = gettimeofday();
|
857 |
+
$sec = $tod['sec'];
|
858 |
+
$usec = $tod['usec'];
|
859 |
+
} else {
|
860 |
+
$sec = time();
|
861 |
+
$usec = 0;
|
862 |
+
}
|
863 |
+
return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
|
864 |
+
}
|
865 |
+
|
866 |
+
/**
|
867 |
+
* Returns a string with the output of var_dump
|
868 |
+
*
|
869 |
+
* @param mixed $data The variable to var_dump
|
870 |
+
* @return string The output of var_dump
|
871 |
+
* @access public
|
872 |
+
*/
|
873 |
+
function varDump($data) {
|
874 |
+
ob_start();
|
875 |
+
var_dump($data);
|
876 |
+
$ret_val = ob_get_contents();
|
877 |
+
ob_end_clean();
|
878 |
+
return $ret_val;
|
879 |
+
}
|
880 |
+
|
881 |
+
/**
|
882 |
+
* represents the object as a string
|
883 |
+
*
|
884 |
+
* @return string
|
885 |
+
* @access public
|
886 |
+
*/
|
887 |
+
function __toString() {
|
888 |
+
return $this->varDump($this);
|
889 |
+
}
|
890 |
+
}
|
891 |
+
|
892 |
+
// XML Schema Datatype Helper Functions
|
893 |
+
|
894 |
+
//xsd:dateTime helpers
|
895 |
+
|
896 |
+
/**
|
897 |
+
* convert unix timestamp to ISO 8601 compliant date string
|
898 |
+
*
|
899 |
+
* @param int $timestamp Unix time stamp
|
900 |
+
* @param boolean $utc Whether the time stamp is UTC or local
|
901 |
+
* @return mixed ISO 8601 date string or false
|
902 |
+
* @access public
|
903 |
+
*/
|
904 |
+
function timestamp_to_iso8601($timestamp,$utc=true){
|
905 |
+
$datestr = date('Y-m-d\TH:i:sO',$timestamp);
|
906 |
+
$pos = strrpos($datestr, "+");
|
907 |
+
if ($pos === FALSE) {
|
908 |
+
$pos = strrpos($datestr, "-");
|
909 |
+
}
|
910 |
+
if ($pos !== FALSE) {
|
911 |
+
if (strlen($datestr) == $pos + 5) {
|
912 |
+
$datestr = substr($datestr, 0, $pos + 3) . ':' . substr($datestr, -2);
|
913 |
+
}
|
914 |
+
}
|
915 |
+
if($utc){
|
916 |
+
$pattern = '/'.
|
917 |
+
'([0-9]{4})-'. // centuries & years CCYY-
|
918 |
+
'([0-9]{2})-'. // months MM-
|
919 |
+
'([0-9]{2})'. // days DD
|
920 |
+
'T'. // separator T
|
921 |
+
'([0-9]{2}):'. // hours hh:
|
922 |
+
'([0-9]{2}):'. // minutes mm:
|
923 |
+
'([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
|
924 |
+
'(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
|
925 |
+
'/';
|
926 |
+
|
927 |
+
if(preg_match($pattern,$datestr,$regs)){
|
928 |
+
return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
|
929 |
+
}
|
930 |
+
return false;
|
931 |
+
} else {
|
932 |
+
return $datestr;
|
933 |
+
}
|
934 |
+
}
|
935 |
+
|
936 |
+
/**
|
937 |
+
* convert ISO 8601 compliant date string to unix timestamp
|
938 |
+
*
|
939 |
+
* @param string $datestr ISO 8601 compliant date string
|
940 |
+
* @return mixed Unix timestamp (int) or false
|
941 |
+
* @access public
|
942 |
+
*/
|
943 |
+
function iso8601_to_timestamp($datestr){
|
944 |
+
$pattern = '/'.
|
945 |
+
'([0-9]{4})-'. // centuries & years CCYY-
|
946 |
+
'([0-9]{2})-'. // months MM-
|
947 |
+
'([0-9]{2})'. // days DD
|
948 |
+
'T'. // separator T
|
949 |
+
'([0-9]{2}):'. // hours hh:
|
950 |
+
'([0-9]{2}):'. // minutes mm:
|
951 |
+
'([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
|
952 |
+
'(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
|
953 |
+
'/';
|
954 |
+
if(preg_match($pattern,$datestr,$regs)){
|
955 |
+
// not utc
|
956 |
+
if($regs[8] != 'Z'){
|
957 |
+
$op = substr($regs[8],0,1);
|
958 |
+
$h = substr($regs[8],1,2);
|
959 |
+
$m = substr($regs[8],strlen($regs[8])-2,2);
|
960 |
+
if($op == '-'){
|
961 |
+
$regs[4] = $regs[4] + $h;
|
962 |
+
$regs[5] = $regs[5] + $m;
|
963 |
+
} elseif($op == '+'){
|
964 |
+
$regs[4] = $regs[4] - $h;
|
965 |
+
$regs[5] = $regs[5] - $m;
|
966 |
+
}
|
967 |
+
}
|
968 |
+
return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
|
969 |
+
// return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
|
970 |
+
} else {
|
971 |
+
return false;
|
972 |
+
}
|
973 |
+
}
|
974 |
+
|
975 |
+
/**
|
976 |
+
* sleeps some number of microseconds
|
977 |
+
*
|
978 |
+
* @param string $usec the number of microseconds to sleep
|
979 |
+
* @access public
|
980 |
+
* @deprecated
|
981 |
+
*/
|
982 |
+
function usleepWindows($usec)
|
983 |
+
{
|
984 |
+
$start = gettimeofday();
|
985 |
+
|
986 |
+
do
|
987 |
+
{
|
988 |
+
$stop = gettimeofday();
|
989 |
+
$timePassed = 1000000 * ($stop['sec'] - $start['sec'])
|
990 |
+
+ $stop['usec'] - $start['usec'];
|
991 |
+
}
|
992 |
+
while ($timePassed < $usec);
|
993 |
+
}
|
994 |
+
|
995 |
+
?><?php
|
996 |
+
|
997 |
+
|
998 |
+
|
999 |
+
/**
|
1000 |
+
* Contains information for a SOAP fault.
|
1001 |
+
* Mainly used for returning faults from deployed functions
|
1002 |
+
* in a server instance.
|
1003 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
1004 |
+
* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
|
1005 |
+
* @access public
|
1006 |
+
*/
|
1007 |
+
class nusoap_fault extends nusoap_base {
|
1008 |
+
/**
|
1009 |
+
* The fault code (client|server)
|
1010 |
+
* @var string
|
1011 |
+
* @access private
|
1012 |
+
*/
|
1013 |
+
var $faultcode;
|
1014 |
+
/**
|
1015 |
+
* The fault actor
|
1016 |
+
* @var string
|
1017 |
+
* @access private
|
1018 |
+
*/
|
1019 |
+
var $faultactor;
|
1020 |
+
/**
|
1021 |
+
* The fault string, a description of the fault
|
1022 |
+
* @var string
|
1023 |
+
* @access private
|
1024 |
+
*/
|
1025 |
+
var $faultstring;
|
1026 |
+
/**
|
1027 |
+
* The fault detail, typically a string or array of string
|
1028 |
+
* @var mixed
|
1029 |
+
* @access private
|
1030 |
+
*/
|
1031 |
+
var $faultdetail;
|
1032 |
+
|
1033 |
+
/**
|
1034 |
+
* constructor
|
1035 |
+
*
|
1036 |
+
* @param string $faultcode (SOAP-ENV:Client | SOAP-ENV:Server)
|
1037 |
+
* @param string $faultactor only used when msg routed between multiple actors
|
1038 |
+
* @param string $faultstring human readable error message
|
1039 |
+
* @param mixed $faultdetail detail, typically a string or array of string
|
1040 |
+
*/
|
1041 |
+
function nusoap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){
|
1042 |
+
parent::nusoap_base();
|
1043 |
+
$this->faultcode = $faultcode;
|
1044 |
+
$this->faultactor = $faultactor;
|
1045 |
+
$this->faultstring = $faultstring;
|
1046 |
+
$this->faultdetail = $faultdetail;
|
1047 |
+
}
|
1048 |
+
|
1049 |
+
/**
|
1050 |
+
* serialize a fault
|
1051 |
+
*
|
1052 |
+
* @return string The serialization of the fault instance.
|
1053 |
+
* @access public
|
1054 |
+
*/
|
1055 |
+
function serialize(){
|
1056 |
+
$ns_string = '';
|
1057 |
+
foreach($this->namespaces as $k => $v){
|
1058 |
+
$ns_string .= "\n xmlns:$k=\"$v\"";
|
1059 |
+
}
|
1060 |
+
$return_msg =
|
1061 |
+
'<?xml version="1.0" encoding="'.$this->soap_defencoding.'"?>'.
|
1062 |
+
'<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.">\n".
|
1063 |
+
'<SOAP-ENV:Body>'.
|
1064 |
+
'<SOAP-ENV:Fault>'.
|
1065 |
+
$this->serialize_val($this->faultcode, 'faultcode').
|
1066 |
+
$this->serialize_val($this->faultactor, 'faultactor').
|
1067 |
+
$this->serialize_val($this->faultstring, 'faultstring').
|
1068 |
+
$this->serialize_val($this->faultdetail, 'detail').
|
1069 |
+
'</SOAP-ENV:Fault>'.
|
1070 |
+
'</SOAP-ENV:Body>'.
|
1071 |
+
'</SOAP-ENV:Envelope>';
|
1072 |
+
return $return_msg;
|
1073 |
+
}
|
1074 |
+
}
|
1075 |
+
|
1076 |
+
/**
|
1077 |
+
* Backward compatibility
|
1078 |
+
*/
|
1079 |
+
class soap_fault extends nusoap_fault {
|
1080 |
+
}
|
1081 |
+
|
1082 |
+
?><?php
|
1083 |
+
|
1084 |
+
|
1085 |
+
|
1086 |
+
/**
|
1087 |
+
* parses an XML Schema, allows access to it's data, other utility methods.
|
1088 |
+
* imperfect, no validation... yet, but quite functional.
|
1089 |
+
*
|
1090 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
1091 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
1092 |
+
* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
|
1093 |
+
* @access public
|
1094 |
+
*/
|
1095 |
+
class nusoap_xmlschema extends nusoap_base {
|
1096 |
+
|
1097 |
+
// files
|
1098 |
+
var $schema = '';
|
1099 |
+
var $xml = '';
|
1100 |
+
// namespaces
|
1101 |
+
var $enclosingNamespaces;
|
1102 |
+
// schema info
|
1103 |
+
var $schemaInfo = array();
|
1104 |
+
var $schemaTargetNamespace = '';
|
1105 |
+
// types, elements, attributes defined by the schema
|
1106 |
+
var $attributes = array();
|
1107 |
+
var $complexTypes = array();
|
1108 |
+
var $complexTypeStack = array();
|
1109 |
+
var $currentComplexType = null;
|
1110 |
+
var $elements = array();
|
1111 |
+
var $elementStack = array();
|
1112 |
+
var $currentElement = null;
|
1113 |
+
var $simpleTypes = array();
|
1114 |
+
var $simpleTypeStack = array();
|
1115 |
+
var $currentSimpleType = null;
|
1116 |
+
// imports
|
1117 |
+
var $imports = array();
|
1118 |
+
// parser vars
|
1119 |
+
var $parser;
|
1120 |
+
var $position = 0;
|
1121 |
+
var $depth = 0;
|
1122 |
+
var $depth_array = array();
|
1123 |
+
var $message = array();
|
1124 |
+
var $defaultNamespace = array();
|
1125 |
+
|
1126 |
+
/**
|
1127 |
+
* constructor
|
1128 |
+
*
|
1129 |
+
* @param string $schema schema document URI
|
1130 |
+
* @param string $xml xml document URI
|
1131 |
+
* @param string $namespaces namespaces defined in enclosing XML
|
1132 |
+
* @access public
|
1133 |
+
*/
|
1134 |
+
function nusoap_xmlschema($schema='',$xml='',$namespaces=array()){
|
1135 |
+
parent::nusoap_base();
|
1136 |
+
$this->debug('nusoap_xmlschema class instantiated, inside constructor');
|
1137 |
+
// files
|
1138 |
+
$this->schema = $schema;
|
1139 |
+
$this->xml = $xml;
|
1140 |
+
|
1141 |
+
// namespaces
|
1142 |
+
$this->enclosingNamespaces = $namespaces;
|
1143 |
+
$this->namespaces = array_merge($this->namespaces, $namespaces);
|
1144 |
+
|
1145 |
+
// parse schema file
|
1146 |
+
if($schema != ''){
|
1147 |
+
$this->debug('initial schema file: '.$schema);
|
1148 |
+
$this->parseFile($schema, 'schema');
|
1149 |
+
}
|
1150 |
+
|
1151 |
+
// parse xml file
|
1152 |
+
if($xml != ''){
|
1153 |
+
$this->debug('initial xml file: '.$xml);
|
1154 |
+
$this->parseFile($xml, 'xml');
|
1155 |
+
}
|
1156 |
+
|
1157 |
+
}
|
1158 |
+
|
1159 |
+
/**
|
1160 |
+
* parse an XML file
|
1161 |
+
*
|
1162 |
+
* @param string $xml path/URL to XML file
|
1163 |
+
* @param string $type (schema | xml)
|
1164 |
+
* @return boolean
|
1165 |
+
* @access public
|
1166 |
+
*/
|
1167 |
+
function parseFile($xml,$type){
|
1168 |
+
// parse xml file
|
1169 |
+
if($xml != ""){
|
1170 |
+
$xmlStr = @join("",@file($xml));
|
1171 |
+
if($xmlStr == ""){
|
1172 |
+
$msg = 'Error reading XML from '.$xml;
|
1173 |
+
$this->setError($msg);
|
1174 |
+
$this->debug($msg);
|
1175 |
+
return false;
|
1176 |
+
} else {
|
1177 |
+
$this->debug("parsing $xml");
|
1178 |
+
$this->parseString($xmlStr,$type);
|
1179 |
+
$this->debug("done parsing $xml");
|
1180 |
+
return true;
|
1181 |
+
}
|
1182 |
+
}
|
1183 |
+
return false;
|
1184 |
+
}
|
1185 |
+
|
1186 |
+
/**
|
1187 |
+
* parse an XML string
|
1188 |
+
*
|
1189 |
+
* @param string $xml path or URL
|
1190 |
+
* @param string $type (schema|xml)
|
1191 |
+
* @access private
|
1192 |
+
*/
|
1193 |
+
function parseString($xml,$type){
|
1194 |
+
// parse xml string
|
1195 |
+
if($xml != ""){
|
1196 |
+
|
1197 |
+
// Create an XML parser.
|
1198 |
+
$this->parser = xml_parser_create();
|
1199 |
+
// Set the options for parsing the XML data.
|
1200 |
+
xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
|
1201 |
+
|
1202 |
+
// Set the object for the parser.
|
1203 |
+
xml_set_object($this->parser, $this);
|
1204 |
+
|
1205 |
+
// Set the element handlers for the parser.
|
1206 |
+
if($type == "schema"){
|
1207 |
+
xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
|
1208 |
+
xml_set_character_data_handler($this->parser,'schemaCharacterData');
|
1209 |
+
} elseif($type == "xml"){
|
1210 |
+
xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');
|
1211 |
+
xml_set_character_data_handler($this->parser,'xmlCharacterData');
|
1212 |
+
}
|
1213 |
+
|
1214 |
+
// Parse the XML file.
|
1215 |
+
if(!xml_parse($this->parser,$xml,true)){
|
1216 |
+
// Display an error message.
|
1217 |
+
$errstr = sprintf('XML error parsing XML schema on line %d: %s',
|
1218 |
+
xml_get_current_line_number($this->parser),
|
1219 |
+
xml_error_string(xml_get_error_code($this->parser))
|
1220 |
+
);
|
1221 |
+
$this->debug($errstr);
|
1222 |
+
$this->debug("XML payload:\n" . $xml);
|
1223 |
+
$this->setError($errstr);
|
1224 |
+
}
|
1225 |
+
|
1226 |
+
xml_parser_free($this->parser);
|
1227 |
+
} else{
|
1228 |
+
$this->debug('no xml passed to parseString()!!');
|
1229 |
+
$this->setError('no xml passed to parseString()!!');
|
1230 |
+
}
|
1231 |
+
}
|
1232 |
+
|
1233 |
+
/**
|
1234 |
+
* gets a type name for an unnamed type
|
1235 |
+
*
|
1236 |
+
* @param string Element name
|
1237 |
+
* @return string A type name for an unnamed type
|
1238 |
+
* @access private
|
1239 |
+
*/
|
1240 |
+
function CreateTypeName($ename) {
|
1241 |
+
$scope = '';
|
1242 |
+
for ($i = 0; $i < count($this->complexTypeStack); $i++) {
|
1243 |
+
$scope .= $this->complexTypeStack[$i] . '_';
|
1244 |
+
}
|
1245 |
+
return $scope . $ename . '_ContainedType';
|
1246 |
+
}
|
1247 |
+
|
1248 |
+
/**
|
1249 |
+
* start-element handler
|
1250 |
+
*
|
1251 |
+
* @param string $parser XML parser object
|
1252 |
+
* @param string $name element name
|
1253 |
+
* @param string $attrs associative array of attributes
|
1254 |
+
* @access private
|
1255 |
+
*/
|
1256 |
+
function schemaStartElement($parser, $name, $attrs) {
|
1257 |
+
|
1258 |
+
// position in the total number of elements, starting from 0
|
1259 |
+
$pos = $this->position++;
|
1260 |
+
$depth = $this->depth++;
|
1261 |
+
// set self as current value for this depth
|
1262 |
+
$this->depth_array[$depth] = $pos;
|
1263 |
+
$this->message[$pos] = array('cdata' => '');
|
1264 |
+
if ($depth > 0) {
|
1265 |
+
$this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
|
1266 |
+
} else {
|
1267 |
+
$this->defaultNamespace[$pos] = false;
|
1268 |
+
}
|
1269 |
+
|
1270 |
+
// get element prefix
|
1271 |
+
if($prefix = $this->getPrefix($name)){
|
1272 |
+
// get unqualified name
|
1273 |
+
$name = $this->getLocalPart($name);
|
1274 |
+
} else {
|
1275 |
+
$prefix = '';
|
1276 |
+
}
|
1277 |
+
|
1278 |
+
// loop thru attributes, expanding, and registering namespace declarations
|
1279 |
+
if(count($attrs) > 0){
|
1280 |
+
foreach($attrs as $k => $v){
|
1281 |
+
// if ns declarations, add to class level array of valid namespaces
|
1282 |
+
if(preg_match('/^xmlns/',$k)){
|
1283 |
+
//$this->xdebug("$k: $v");
|
1284 |
+
//$this->xdebug('ns_prefix: '.$this->getPrefix($k));
|
1285 |
+
if($ns_prefix = substr(strrchr($k,':'),1)){
|
1286 |
+
//$this->xdebug("Add namespace[$ns_prefix] = $v");
|
1287 |
+
$this->namespaces[$ns_prefix] = $v;
|
1288 |
+
} else {
|
1289 |
+
$this->defaultNamespace[$pos] = $v;
|
1290 |
+
if (! $this->getPrefixFromNamespace($v)) {
|
1291 |
+
$this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
|
1292 |
+
}
|
1293 |
+
}
|
1294 |
+
if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){
|
1295 |
+
$this->XMLSchemaVersion = $v;
|
1296 |
+
$this->namespaces['xsi'] = $v.'-instance';
|
1297 |
+
}
|
1298 |
+
}
|
1299 |
+
}
|
1300 |
+
foreach($attrs as $k => $v){
|
1301 |
+
// expand each attribute
|
1302 |
+
$k = strpos($k,':') ? $this->expandQname($k) : $k;
|
1303 |
+
$v = strpos($v,':') ? $this->expandQname($v) : $v;
|
1304 |
+
$eAttrs[$k] = $v;
|
1305 |
+
}
|
1306 |
+
$attrs = $eAttrs;
|
1307 |
+
} else {
|
1308 |
+
$attrs = array();
|
1309 |
+
}
|
1310 |
+
// find status, register data
|
1311 |
+
switch($name){
|
1312 |
+
case 'all': // (optional) compositor content for a complexType
|
1313 |
+
case 'choice':
|
1314 |
+
case 'group':
|
1315 |
+
case 'sequence':
|
1316 |
+
//$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
|
1317 |
+
$this->complexTypes[$this->currentComplexType]['compositor'] = $name;
|
1318 |
+
//if($name == 'all' || $name == 'sequence'){
|
1319 |
+
// $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
|
1320 |
+
//}
|
1321 |
+
break;
|
1322 |
+
case 'attribute': // complexType attribute
|
1323 |
+
//$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
|
1324 |
+
$this->xdebug("parsing attribute:");
|
1325 |
+
$this->appendDebug($this->varDump($attrs));
|
1326 |
+
if (!isset($attrs['form'])) {
|
1327 |
+
// TODO: handle globals
|
1328 |
+
$attrs['form'] = $this->schemaInfo['attributeFormDefault'];
|
1329 |
+
}
|
1330 |
+
if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
|
1331 |
+
$v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
|
1332 |
+
if (!strpos($v, ':')) {
|
1333 |
+
// no namespace in arrayType attribute value...
|
1334 |
+
if ($this->defaultNamespace[$pos]) {
|
1335 |
+
// ...so use the default
|
1336 |
+
$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
|
1337 |
+
}
|
1338 |
+
}
|
1339 |
+
}
|
1340 |
+
if(isset($attrs['name'])){
|
1341 |
+
$this->attributes[$attrs['name']] = $attrs;
|
1342 |
+
$aname = $attrs['name'];
|
1343 |
+
} elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
|
1344 |
+
if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
|
1345 |
+
$aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
|
1346 |
+
} else {
|
1347 |
+
$aname = '';
|
1348 |
+
}
|
1349 |
+
} elseif(isset($attrs['ref'])){
|
1350 |
+
$aname = $attrs['ref'];
|
1351 |
+
$this->attributes[$attrs['ref']] = $attrs;
|
1352 |
+
}
|
1353 |
+
|
1354 |
+
if($this->currentComplexType){ // This should *always* be
|
1355 |
+
$this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
|
1356 |
+
}
|
1357 |
+
// arrayType attribute
|
1358 |
+
if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){
|
1359 |
+
$this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
|
1360 |
+
$prefix = $this->getPrefix($aname);
|
1361 |
+
if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
|
1362 |
+
$v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
|
1363 |
+
} else {
|
1364 |
+
$v = '';
|
1365 |
+
}
|
1366 |
+
if(strpos($v,'[,]')){
|
1367 |
+
$this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
|
1368 |
+
}
|
1369 |
+
$v = substr($v,0,strpos($v,'[')); // clip the []
|
1370 |
+
if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
|
1371 |
+
$v = $this->XMLSchemaVersion.':'.$v;
|
1372 |
+
}
|
1373 |
+
$this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
|
1374 |
+
}
|
1375 |
+
break;
|
1376 |
+
case 'complexContent': // (optional) content for a complexType
|
1377 |
+
$this->xdebug("do nothing for element $name");
|
1378 |
+
break;
|
1379 |
+
case 'complexType':
|
1380 |
+
array_push($this->complexTypeStack, $this->currentComplexType);
|
1381 |
+
if(isset($attrs['name'])){
|
1382 |
+
// TODO: what is the scope of named complexTypes that appear
|
1383 |
+
// nested within other c complexTypes?
|
1384 |
+
$this->xdebug('processing named complexType '.$attrs['name']);
|
1385 |
+
//$this->currentElement = false;
|
1386 |
+
$this->currentComplexType = $attrs['name'];
|
1387 |
+
$this->complexTypes[$this->currentComplexType] = $attrs;
|
1388 |
+
$this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
|
1389 |
+
// This is for constructs like
|
1390 |
+
// <complexType name="ListOfString" base="soap:Array">
|
1391 |
+
// <sequence>
|
1392 |
+
// <element name="string" type="xsd:string"
|
1393 |
+
// minOccurs="0" maxOccurs="unbounded" />
|
1394 |
+
// </sequence>
|
1395 |
+
// </complexType>
|
1396 |
+
if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
|
1397 |
+
$this->xdebug('complexType is unusual array');
|
1398 |
+
$this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
|
1399 |
+
} else {
|
1400 |
+
$this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
|
1401 |
+
}
|
1402 |
+
} else {
|
1403 |
+
$name = $this->CreateTypeName($this->currentElement);
|
1404 |
+
$this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
|
1405 |
+
$this->currentComplexType = $name;
|
1406 |
+
//$this->currentElement = false;
|
1407 |
+
$this->complexTypes[$this->currentComplexType] = $attrs;
|
1408 |
+
$this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
|
1409 |
+
// This is for constructs like
|
1410 |
+
// <complexType name="ListOfString" base="soap:Array">
|
1411 |
+
// <sequence>
|
1412 |
+
// <element name="string" type="xsd:string"
|
1413 |
+
// minOccurs="0" maxOccurs="unbounded" />
|
1414 |
+
// </sequence>
|
1415 |
+
// </complexType>
|
1416 |
+
if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
|
1417 |
+
$this->xdebug('complexType is unusual array');
|
1418 |
+
$this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
|
1419 |
+
} else {
|
1420 |
+
$this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
|
1421 |
+
}
|
1422 |
+
}
|
1423 |
+
$this->complexTypes[$this->currentComplexType]['simpleContent'] = 'false';
|
1424 |
+
break;
|
1425 |
+
case 'element':
|
1426 |
+
array_push($this->elementStack, $this->currentElement);
|
1427 |
+
if (!isset($attrs['form'])) {
|
1428 |
+
if ($this->currentComplexType) {
|
1429 |
+
$attrs['form'] = $this->schemaInfo['elementFormDefault'];
|
1430 |
+
} else {
|
1431 |
+
// global
|
1432 |
+
$attrs['form'] = 'qualified';
|
1433 |
+
}
|
1434 |
+
}
|
1435 |
+
if(isset($attrs['type'])){
|
1436 |
+
$this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']);
|
1437 |
+
if (! $this->getPrefix($attrs['type'])) {
|
1438 |
+
if ($this->defaultNamespace[$pos]) {
|
1439 |
+
$attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
|
1440 |
+
$this->xdebug('used default namespace to make type ' . $attrs['type']);
|
1441 |
+
}
|
1442 |
+
}
|
1443 |
+
// This is for constructs like
|
1444 |
+
// <complexType name="ListOfString" base="soap:Array">
|
1445 |
+
// <sequence>
|
1446 |
+
// <element name="string" type="xsd:string"
|
1447 |
+
// minOccurs="0" maxOccurs="unbounded" />
|
1448 |
+
// </sequence>
|
1449 |
+
// </complexType>
|
1450 |
+
if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
|
1451 |
+
$this->xdebug('arrayType for unusual array is ' . $attrs['type']);
|
1452 |
+
$this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
|
1453 |
+
}
|
1454 |
+
$this->currentElement = $attrs['name'];
|
1455 |
+
$ename = $attrs['name'];
|
1456 |
+
} elseif(isset($attrs['ref'])){
|
1457 |
+
$this->xdebug("processing element as ref to ".$attrs['ref']);
|
1458 |
+
$this->currentElement = "ref to ".$attrs['ref'];
|
1459 |
+
$ename = $this->getLocalPart($attrs['ref']);
|
1460 |
+
} else {
|
1461 |
+
$type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
|
1462 |
+
$this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
|
1463 |
+
$this->currentElement = $attrs['name'];
|
1464 |
+
$attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
|
1465 |
+
$ename = $attrs['name'];
|
1466 |
+
}
|
1467 |
+
if (isset($ename) && $this->currentComplexType) {
|
1468 |
+
$this->xdebug("add element $ename to complexType $this->currentComplexType");
|
1469 |
+
$this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
|
1470 |
+
} elseif (!isset($attrs['ref'])) {
|
1471 |
+
$this->xdebug("add element $ename to elements array");
|
1472 |
+
$this->elements[ $attrs['name'] ] = $attrs;
|
1473 |
+
$this->elements[ $attrs['name'] ]['typeClass'] = 'element';
|
1474 |
+
}
|
1475 |
+
break;
|
1476 |
+
case 'enumeration': // restriction value list member
|
1477 |
+
$this->xdebug('enumeration ' . $attrs['value']);
|
1478 |
+
if ($this->currentSimpleType) {
|
1479 |
+
$this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
|
1480 |
+
} elseif ($this->currentComplexType) {
|
1481 |
+
$this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
|
1482 |
+
}
|
1483 |
+
break;
|
1484 |
+
case 'extension': // simpleContent or complexContent type extension
|
1485 |
+
$this->xdebug('extension ' . $attrs['base']);
|
1486 |
+
if ($this->currentComplexType) {
|
1487 |
+
$ns = $this->getPrefix($attrs['base']);
|
1488 |
+
if ($ns == '') {
|
1489 |
+
$this->complexTypes[$this->currentComplexType]['extensionBase'] = $this->schemaTargetNamespace . ':' . $attrs['base'];
|
1490 |
+
} else {
|
1491 |
+
$this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
|
1492 |
+
}
|
1493 |
+
} else {
|
1494 |
+
$this->xdebug('no current complexType to set extensionBase');
|
1495 |
+
}
|
1496 |
+
break;
|
1497 |
+
case 'import':
|
1498 |
+
if (isset($attrs['schemaLocation'])) {
|
1499 |
+
$this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
|
1500 |
+
$this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
|
1501 |
+
} else {
|
1502 |
+
$this->xdebug('import namespace ' . $attrs['namespace']);
|
1503 |
+
$this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
|
1504 |
+
if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
|
1505 |
+
$this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
|
1506 |
+
}
|
1507 |
+
}
|
1508 |
+
break;
|
1509 |
+
case 'include':
|
1510 |
+
if (isset($attrs['schemaLocation'])) {
|
1511 |
+
$this->xdebug('include into namespace ' . $this->schemaTargetNamespace . ' from ' . $attrs['schemaLocation']);
|
1512 |
+
$this->imports[$this->schemaTargetNamespace][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
|
1513 |
+
} else {
|
1514 |
+
$this->xdebug('ignoring invalid XML Schema construct: include without schemaLocation attribute');
|
1515 |
+
}
|
1516 |
+
break;
|
1517 |
+
case 'list': // simpleType value list
|
1518 |
+
$this->xdebug("do nothing for element $name");
|
1519 |
+
break;
|
1520 |
+
case 'restriction': // simpleType, simpleContent or complexContent value restriction
|
1521 |
+
$this->xdebug('restriction ' . $attrs['base']);
|
1522 |
+
if($this->currentSimpleType){
|
1523 |
+
$this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
|
1524 |
+
} elseif($this->currentComplexType){
|
1525 |
+
$this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
|
1526 |
+
if(strstr($attrs['base'],':') == ':Array'){
|
1527 |
+
$this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
|
1528 |
+
}
|
1529 |
+
}
|
1530 |
+
break;
|
1531 |
+
case 'schema':
|
1532 |
+
$this->schemaInfo = $attrs;
|
1533 |
+
$this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
|
1534 |
+
if (isset($attrs['targetNamespace'])) {
|
1535 |
+
$this->schemaTargetNamespace = $attrs['targetNamespace'];
|
1536 |
+
}
|
1537 |
+
if (!isset($attrs['elementFormDefault'])) {
|
1538 |
+
$this->schemaInfo['elementFormDefault'] = 'unqualified';
|
1539 |
+
}
|
1540 |
+
if (!isset($attrs['attributeFormDefault'])) {
|
1541 |
+
$this->schemaInfo['attributeFormDefault'] = 'unqualified';
|
1542 |
+
}
|
1543 |
+
break;
|
1544 |
+
case 'simpleContent': // (optional) content for a complexType
|
1545 |
+
if ($this->currentComplexType) { // This should *always* be
|
1546 |
+
$this->complexTypes[$this->currentComplexType]['simpleContent'] = 'true';
|
1547 |
+
} else {
|
1548 |
+
$this->xdebug("do nothing for element $name because there is no current complexType");
|
1549 |
+
}
|
1550 |
+
break;
|
1551 |
+
case 'simpleType':
|
1552 |
+
array_push($this->simpleTypeStack, $this->currentSimpleType);
|
1553 |
+
if(isset($attrs['name'])){
|
1554 |
+
$this->xdebug("processing simpleType for name " . $attrs['name']);
|
1555 |
+
$this->currentSimpleType = $attrs['name'];
|
1556 |
+
$this->simpleTypes[ $attrs['name'] ] = $attrs;
|
1557 |
+
$this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
|
1558 |
+
$this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
|
1559 |
+
} else {
|
1560 |
+
$name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
|
1561 |
+
$this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
|
1562 |
+
$this->currentSimpleType = $name;
|
1563 |
+
//$this->currentElement = false;
|
1564 |
+
$this->simpleTypes[$this->currentSimpleType] = $attrs;
|
1565 |
+
$this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
|
1566 |
+
}
|
1567 |
+
break;
|
1568 |
+
case 'union': // simpleType type list
|
1569 |
+
$this->xdebug("do nothing for element $name");
|
1570 |
+
break;
|
1571 |
+
default:
|
1572 |
+
$this->xdebug("do not have any logic to process element $name");
|
1573 |
+
}
|
1574 |
+
}
|
1575 |
+
|
1576 |
+
/**
|
1577 |
+
* end-element handler
|
1578 |
+
*
|
1579 |
+
* @param string $parser XML parser object
|
1580 |
+
* @param string $name element name
|
1581 |
+
* @access private
|
1582 |
+
*/
|
1583 |
+
function schemaEndElement($parser, $name) {
|
1584 |
+
// bring depth down a notch
|
1585 |
+
$this->depth--;
|
1586 |
+
// position of current element is equal to the last value left in depth_array for my depth
|
1587 |
+
if(isset($this->depth_array[$this->depth])){
|
1588 |
+
$pos = $this->depth_array[$this->depth];
|
1589 |
+
}
|
1590 |
+
// get element prefix
|
1591 |
+
if ($prefix = $this->getPrefix($name)){
|
1592 |
+
// get unqualified name
|
1593 |
+
$name = $this->getLocalPart($name);
|
1594 |
+
} else {
|
1595 |
+
$prefix = '';
|
1596 |
+
}
|
1597 |
+
// move on...
|
1598 |
+
if($name == 'complexType'){
|
1599 |
+
$this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
|
1600 |
+
$this->xdebug($this->varDump($this->complexTypes[$this->currentComplexType]));
|
1601 |
+
$this->currentComplexType = array_pop($this->complexTypeStack);
|
1602 |
+
//$this->currentElement = false;
|
1603 |
+
}
|
1604 |
+
if($name == 'element'){
|
1605 |
+
$this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
|
1606 |
+
$this->currentElement = array_pop($this->elementStack);
|
1607 |
+
}
|
1608 |
+
if($name == 'simpleType'){
|
1609 |
+
$this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
|
1610 |
+
$this->xdebug($this->varDump($this->simpleTypes[$this->currentSimpleType]));
|
1611 |
+
$this->currentSimpleType = array_pop($this->simpleTypeStack);
|
1612 |
+
}
|
1613 |
+
}
|
1614 |
+
|
1615 |
+
/**
|
1616 |
+
* element content handler
|
1617 |
+
*
|
1618 |
+
* @param string $parser XML parser object
|
1619 |
+
* @param string $data element content
|
1620 |
+
* @access private
|
1621 |
+
*/
|
1622 |
+
function schemaCharacterData($parser, $data){
|
1623 |
+
$pos = $this->depth_array[$this->depth - 1];
|
1624 |
+
$this->message[$pos]['cdata'] .= $data;
|
1625 |
+
}
|
1626 |
+
|
1627 |
+
/**
|
1628 |
+
* serialize the schema
|
1629 |
+
*
|
1630 |
+
* @access public
|
1631 |
+
*/
|
1632 |
+
function serializeSchema(){
|
1633 |
+
|
1634 |
+
$schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
|
1635 |
+
$xml = '';
|
1636 |
+
// imports
|
1637 |
+
if (sizeof($this->imports) > 0) {
|
1638 |
+
foreach($this->imports as $ns => $list) {
|
1639 |
+
foreach ($list as $ii) {
|
1640 |
+
if ($ii['location'] != '') {
|
1641 |
+
$xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
|
1642 |
+
} else {
|
1643 |
+
$xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
|
1644 |
+
}
|
1645 |
+
}
|
1646 |
+
}
|
1647 |
+
}
|
1648 |
+
// complex types
|
1649 |
+
foreach($this->complexTypes as $typeName => $attrs){
|
1650 |
+
$contentStr = '';
|
1651 |
+
// serialize child elements
|
1652 |
+
if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){
|
1653 |
+
foreach($attrs['elements'] as $element => $eParts){
|
1654 |
+
if(isset($eParts['ref'])){
|
1655 |
+
$contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n";
|
1656 |
+
} else {
|
1657 |
+
$contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
|
1658 |
+
foreach ($eParts as $aName => $aValue) {
|
1659 |
+
// handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
|
1660 |
+
if ($aName != 'name' && $aName != 'type') {
|
1661 |
+
$contentStr .= " $aName=\"$aValue\"";
|
1662 |
+
}
|
1663 |
+
}
|
1664 |
+
$contentStr .= "/>\n";
|
1665 |
+
}
|
1666 |
+
}
|
1667 |
+
// compositor wraps elements
|
1668 |
+
if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
|
1669 |
+
$contentStr = " <$schemaPrefix:$attrs[compositor]>\n".$contentStr." </$schemaPrefix:$attrs[compositor]>\n";
|
1670 |
+
}
|
1671 |
+
}
|
1672 |
+
// attributes
|
1673 |
+
if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){
|
1674 |
+
foreach($attrs['attrs'] as $attr => $aParts){
|
1675 |
+
$contentStr .= " <$schemaPrefix:attribute";
|
1676 |
+
foreach ($aParts as $a => $v) {
|
1677 |
+
if ($a == 'ref' || $a == 'type') {
|
1678 |
+
$contentStr .= " $a=\"".$this->contractQName($v).'"';
|
1679 |
+
} elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
|
1680 |
+
$this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
|
1681 |
+
$contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"';
|
1682 |
+
} else {
|
1683 |
+
$contentStr .= " $a=\"$v\"";
|
1684 |
+
}
|
1685 |
+
}
|
1686 |
+
$contentStr .= "/>\n";
|
1687 |
+
}
|
1688 |
+
}
|
1689 |
+
// if restriction
|
1690 |
+
if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){
|
1691 |
+
$contentStr = " <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr." </$schemaPrefix:restriction>\n";
|
1692 |
+
// complex or simple content
|
1693 |
+
if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){
|
1694 |
+
$contentStr = " <$schemaPrefix:complexContent>\n".$contentStr." </$schemaPrefix:complexContent>\n";
|
1695 |
+
}
|
1696 |
+
}
|
1697 |
+
// finalize complex type
|
1698 |
+
if($contentStr != ''){
|
1699 |
+
$contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n";
|
1700 |
+
} else {
|
1701 |
+
$contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
|
1702 |
+
}
|
1703 |
+
$xml .= $contentStr;
|
1704 |
+
}
|
1705 |
+
// simple types
|
1706 |
+
if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){
|
1707 |
+
foreach($this->simpleTypes as $typeName => $eParts){
|
1708 |
+
$xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\">\n";
|
1709 |
+
if (isset($eParts['enumeration'])) {
|
1710 |
+
foreach ($eParts['enumeration'] as $e) {
|
1711 |
+
$xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n";
|
1712 |
+
}
|
1713 |
+
}
|
1714 |
+
$xml .= " </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
|
1715 |
+
}
|
1716 |
+
}
|
1717 |
+
// elements
|
1718 |
+
if(isset($this->elements) && count($this->elements) > 0){
|
1719 |
+
foreach($this->elements as $element => $eParts){
|
1720 |
+
$xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n";
|
1721 |
+
}
|
1722 |
+
}
|
1723 |
+
// attributes
|
1724 |
+
if(isset($this->attributes) && count($this->attributes) > 0){
|
1725 |
+
foreach($this->attributes as $attr => $aParts){
|
1726 |
+
$xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>";
|
1727 |
+
}
|
1728 |
+
}
|
1729 |
+
// finish 'er up
|
1730 |
+
$attr = '';
|
1731 |
+
foreach ($this->schemaInfo as $k => $v) {
|
1732 |
+
if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {
|
1733 |
+
$attr .= " $k=\"$v\"";
|
1734 |
+
}
|
1735 |
+
}
|
1736 |
+
$el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
|
1737 |
+
foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
|
1738 |
+
$el .= " xmlns:$nsp=\"$ns\"";
|
1739 |
+
}
|
1740 |
+
$xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
|
1741 |
+
return $xml;
|
1742 |
+
}
|
1743 |
+
|
1744 |
+
/**
|
1745 |
+
* adds debug data to the clas level debug string
|
1746 |
+
*
|
1747 |
+
* @param string $string debug data
|
1748 |
+
* @access private
|
1749 |
+
*/
|
1750 |
+
function xdebug($string){
|
1751 |
+
$this->debug('<' . $this->schemaTargetNamespace . '> '.$string);
|
1752 |
+
}
|
1753 |
+
|
1754 |
+
/**
|
1755 |
+
* get the PHP type of a user defined type in the schema
|
1756 |
+
* PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays
|
1757 |
+
* returns false if no type exists, or not w/ the given namespace
|
1758 |
+
* else returns a string that is either a native php type, or 'struct'
|
1759 |
+
*
|
1760 |
+
* @param string $type name of defined type
|
1761 |
+
* @param string $ns namespace of type
|
1762 |
+
* @return mixed
|
1763 |
+
* @access public
|
1764 |
+
* @deprecated
|
1765 |
+
*/
|
1766 |
+
function getPHPType($type,$ns){
|
1767 |
+
if(isset($this->typemap[$ns][$type])){
|
1768 |
+
//print "found type '$type' and ns $ns in typemap<br>";
|
1769 |
+
return $this->typemap[$ns][$type];
|
1770 |
+
} elseif(isset($this->complexTypes[$type])){
|
1771 |
+
//print "getting type '$type' and ns $ns from complexTypes array<br>";
|
1772 |
+
return $this->complexTypes[$type]['phpType'];
|
1773 |
+
}
|
1774 |
+
return false;
|
1775 |
+
}
|
1776 |
+
|
1777 |
+
/**
|
1778 |
+
* returns an associative array of information about a given type
|
1779 |
+
* returns false if no type exists by the given name
|
1780 |
+
*
|
1781 |
+
* For a complexType typeDef = array(
|
1782 |
+
* 'restrictionBase' => '',
|
1783 |
+
* 'phpType' => '',
|
1784 |
+
* 'compositor' => '(sequence|all)',
|
1785 |
+
* 'elements' => array(), // refs to elements array
|
1786 |
+
* 'attrs' => array() // refs to attributes array
|
1787 |
+
* ... and so on (see addComplexType)
|
1788 |
+
* )
|
1789 |
+
*
|
1790 |
+
* For simpleType or element, the array has different keys.
|
1791 |
+
*
|
1792 |
+
* @param string $type
|
1793 |
+
* @return mixed
|
1794 |
+
* @access public
|
1795 |
+
* @see addComplexType
|
1796 |
+
* @see addSimpleType
|
1797 |
+
* @see addElement
|
1798 |
+
*/
|
1799 |
+
function getTypeDef($type){
|
1800 |
+
//$this->debug("in getTypeDef for type $type");
|
1801 |
+
if (substr($type, -1) == '^') {
|
1802 |
+
$is_element = 1;
|
1803 |
+
$type = substr($type, 0, -1);
|
1804 |
+
} else {
|
1805 |
+
$is_element = 0;
|
1806 |
+
}
|
1807 |
+
|
1808 |
+
if((! $is_element) && isset($this->complexTypes[$type])){
|
1809 |
+
$this->xdebug("in getTypeDef, found complexType $type");
|
1810 |
+
return $this->complexTypes[$type];
|
1811 |
+
} elseif((! $is_element) && isset($this->simpleTypes[$type])){
|
1812 |
+
$this->xdebug("in getTypeDef, found simpleType $type");
|
1813 |
+
if (!isset($this->simpleTypes[$type]['phpType'])) {
|
1814 |
+
// get info for type to tack onto the simple type
|
1815 |
+
// TODO: can this ever really apply (i.e. what is a simpleType really?)
|
1816 |
+
$uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
|
1817 |
+
$ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
|
1818 |
+
$etype = $this->getTypeDef($uqType);
|
1819 |
+
if ($etype) {
|
1820 |
+
$this->xdebug("in getTypeDef, found type for simpleType $type:");
|
1821 |
+
$this->xdebug($this->varDump($etype));
|
1822 |
+
if (isset($etype['phpType'])) {
|
1823 |
+
$this->simpleTypes[$type]['phpType'] = $etype['phpType'];
|
1824 |
+
}
|
1825 |
+
if (isset($etype['elements'])) {
|
1826 |
+
$this->simpleTypes[$type]['elements'] = $etype['elements'];
|
1827 |
+
}
|
1828 |
+
}
|
1829 |
+
}
|
1830 |
+
return $this->simpleTypes[$type];
|
1831 |
+
} elseif(isset($this->elements[$type])){
|
1832 |
+
$this->xdebug("in getTypeDef, found element $type");
|
1833 |
+
if (!isset($this->elements[$type]['phpType'])) {
|
1834 |
+
// get info for type to tack onto the element
|
1835 |
+
$uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
|
1836 |
+
$ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
|
1837 |
+
$etype = $this->getTypeDef($uqType);
|
1838 |
+
if ($etype) {
|
1839 |
+
$this->xdebug("in getTypeDef, found type for element $type:");
|
1840 |
+
$this->xdebug($this->varDump($etype));
|
1841 |
+
if (isset($etype['phpType'])) {
|
1842 |
+
$this->elements[$type]['phpType'] = $etype['phpType'];
|
1843 |
+
}
|
1844 |
+
if (isset($etype['elements'])) {
|
1845 |
+
$this->elements[$type]['elements'] = $etype['elements'];
|
1846 |
+
}
|
1847 |
+
if (isset($etype['extensionBase'])) {
|
1848 |
+
$this->elements[$type]['extensionBase'] = $etype['extensionBase'];
|
1849 |
+
}
|
1850 |
+
} elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
|
1851 |
+
$this->xdebug("in getTypeDef, element $type is an XSD type");
|
1852 |
+
$this->elements[$type]['phpType'] = 'scalar';
|
1853 |
+
}
|
1854 |
+
}
|
1855 |
+
return $this->elements[$type];
|
1856 |
+
} elseif(isset($this->attributes[$type])){
|
1857 |
+
$this->xdebug("in getTypeDef, found attribute $type");
|
1858 |
+
return $this->attributes[$type];
|
1859 |
+
} elseif (preg_match('/_ContainedType$/', $type)) {
|
1860 |
+
$this->xdebug("in getTypeDef, have an untyped element $type");
|
1861 |
+
$typeDef['typeClass'] = 'simpleType';
|
1862 |
+
$typeDef['phpType'] = 'scalar';
|
1863 |
+
$typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
|
1864 |
+
return $typeDef;
|
1865 |
+
}
|
1866 |
+
$this->xdebug("in getTypeDef, did not find $type");
|
1867 |
+
return false;
|
1868 |
+
}
|
1869 |
+
|
1870 |
+
/**
|
1871 |
+
* returns a sample serialization of a given type, or false if no type by the given name
|
1872 |
+
*
|
1873 |
+
* @param string $type name of type
|
1874 |
+
* @return mixed
|
1875 |
+
* @access public
|
1876 |
+
* @deprecated
|
1877 |
+
*/
|
1878 |
+
function serializeTypeDef($type){
|
1879 |
+
//print "in sTD() for type $type<br>";
|
1880 |
+
if($typeDef = $this->getTypeDef($type)){
|
1881 |
+
$str .= '<'.$type;
|
1882 |
+
if(is_array($typeDef['attrs'])){
|
1883 |
+
foreach($typeDef['attrs'] as $attName => $data){
|
1884 |
+
$str .= " $attName=\"{type = ".$data['type']."}\"";
|
1885 |
+
}
|
1886 |
+
}
|
1887 |
+
$str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
|
1888 |
+
if(count($typeDef['elements']) > 0){
|
1889 |
+
$str .= ">";
|
1890 |
+
foreach($typeDef['elements'] as $element => $eData){
|
1891 |
+
$str .= $this->serializeTypeDef($element);
|
1892 |
+
}
|
1893 |
+
$str .= "</$type>";
|
1894 |
+
} elseif($typeDef['typeClass'] == 'element') {
|
1895 |
+
$str .= "></$type>";
|
1896 |
+
} else {
|
1897 |
+
$str .= "/>";
|
1898 |
+
}
|
1899 |
+
return $str;
|
1900 |
+
}
|
1901 |
+
return false;
|
1902 |
+
}
|
1903 |
+
|
1904 |
+
/**
|
1905 |
+
* returns HTML form elements that allow a user
|
1906 |
+
* to enter values for creating an instance of the given type.
|
1907 |
+
*
|
1908 |
+
* @param string $name name for type instance
|
1909 |
+
* @param string $type name of type
|
1910 |
+
* @return string
|
1911 |
+
* @access public
|
1912 |
+
* @deprecated
|
1913 |
+
*/
|
1914 |
+
function typeToForm($name,$type){
|
1915 |
+
// get typedef
|
1916 |
+
if($typeDef = $this->getTypeDef($type)){
|
1917 |
+
// if struct
|
1918 |
+
if($typeDef['phpType'] == 'struct'){
|
1919 |
+
$buffer .= '<table>';
|
1920 |
+
foreach($typeDef['elements'] as $child => $childDef){
|
1921 |
+
$buffer .= "
|
1922 |
+
<tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>
|
1923 |
+
<td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";
|
1924 |
+
}
|
1925 |
+
$buffer .= '</table>';
|
1926 |
+
// if array
|
1927 |
+
} elseif($typeDef['phpType'] == 'array'){
|
1928 |
+
$buffer .= '<table>';
|
1929 |
+
for($i=0;$i < 3; $i++){
|
1930 |
+
$buffer .= "
|
1931 |
+
<tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
|
1932 |
+
<td><input type='text' name='parameters[".$name."][]'></td></tr>";
|
1933 |
+
}
|
1934 |
+
$buffer .= '</table>';
|
1935 |
+
// if scalar
|
1936 |
+
} else {
|
1937 |
+
$buffer .= "<input type='text' name='parameters[$name]'>";
|
1938 |
+
}
|
1939 |
+
} else {
|
1940 |
+
$buffer .= "<input type='text' name='parameters[$name]'>";
|
1941 |
+
}
|
1942 |
+
return $buffer;
|
1943 |
+
}
|
1944 |
+
|
1945 |
+
/**
|
1946 |
+
* adds a complex type to the schema
|
1947 |
+
*
|
1948 |
+
* example: array
|
1949 |
+
*
|
1950 |
+
* addType(
|
1951 |
+
* 'ArrayOfstring',
|
1952 |
+
* 'complexType',
|
1953 |
+
* 'array',
|
1954 |
+
* '',
|
1955 |
+
* 'SOAP-ENC:Array',
|
1956 |
+
* array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),
|
1957 |
+
* 'xsd:string'
|
1958 |
+
* );
|
1959 |
+
*
|
1960 |
+
* example: PHP associative array ( SOAP Struct )
|
1961 |
+
*
|
1962 |
+
* addType(
|
1963 |
+
* 'SOAPStruct',
|
1964 |
+
* 'complexType',
|
1965 |
+
* 'struct',
|
1966 |
+
* 'all',
|
1967 |
+
* array('myVar'=> array('name'=>'myVar','type'=>'string')
|
1968 |
+
* );
|
1969 |
+
*
|
1970 |
+
* @param name
|
1971 |
+
* @param typeClass (complexType|simpleType|attribute)
|
1972 |
+
* @param phpType: currently supported are array and struct (php assoc array)
|
1973 |
+
* @param compositor (all|sequence|choice)
|
1974 |
+
* @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
|
1975 |
+
* @param elements = array ( name = array(name=>'',type=>'') )
|
1976 |
+
* @param attrs = array(
|
1977 |
+
* array(
|
1978 |
+
* 'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",
|
1979 |
+
* "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"
|
1980 |
+
* )
|
1981 |
+
* )
|
1982 |
+
* @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)
|
1983 |
+
* @access public
|
1984 |
+
* @see getTypeDef
|
1985 |
+
*/
|
1986 |
+
function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){
|
1987 |
+
$this->complexTypes[$name] = array(
|
1988 |
+
'name' => $name,
|
1989 |
+
'typeClass' => $typeClass,
|
1990 |
+
'phpType' => $phpType,
|
1991 |
+
'compositor'=> $compositor,
|
1992 |
+
'restrictionBase' => $restrictionBase,
|
1993 |
+
'elements' => $elements,
|
1994 |
+
'attrs' => $attrs,
|
1995 |
+
'arrayType' => $arrayType
|
1996 |
+
);
|
1997 |
+
|
1998 |
+
$this->xdebug("addComplexType $name:");
|
1999 |
+
$this->appendDebug($this->varDump($this->complexTypes[$name]));
|
2000 |
+
}
|
2001 |
+
|
2002 |
+
/**
|
2003 |
+
* adds a simple type to the schema
|
2004 |
+
*
|
2005 |
+
* @param string $name
|
2006 |
+
* @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
|
2007 |
+
* @param string $typeClass (should always be simpleType)
|
2008 |
+
* @param string $phpType (should always be scalar)
|
2009 |
+
* @param array $enumeration array of values
|
2010 |
+
* @access public
|
2011 |
+
* @see nusoap_xmlschema
|
2012 |
+
* @see getTypeDef
|
2013 |
+
*/
|
2014 |
+
function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
|
2015 |
+
$this->simpleTypes[$name] = array(
|
2016 |
+
'name' => $name,
|
2017 |
+
'typeClass' => $typeClass,
|
2018 |
+
'phpType' => $phpType,
|
2019 |
+
'type' => $restrictionBase,
|
2020 |
+
'enumeration' => $enumeration
|
2021 |
+
);
|
2022 |
+
|
2023 |
+
$this->xdebug("addSimpleType $name:");
|
2024 |
+
$this->appendDebug($this->varDump($this->simpleTypes[$name]));
|
2025 |
+
}
|
2026 |
+
|
2027 |
+
/**
|
2028 |
+
* adds an element to the schema
|
2029 |
+
*
|
2030 |
+
* @param array $attrs attributes that must include name and type
|
2031 |
+
* @see nusoap_xmlschema
|
2032 |
+
* @access public
|
2033 |
+
*/
|
2034 |
+
function addElement($attrs) {
|
2035 |
+
if (! $this->getPrefix($attrs['type'])) {
|
2036 |
+
$attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
|
2037 |
+
}
|
2038 |
+
$this->elements[ $attrs['name'] ] = $attrs;
|
2039 |
+
$this->elements[ $attrs['name'] ]['typeClass'] = 'element';
|
2040 |
+
|
2041 |
+
$this->xdebug("addElement " . $attrs['name']);
|
2042 |
+
$this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
|
2043 |
+
}
|
2044 |
+
}
|
2045 |
+
|
2046 |
+
/**
|
2047 |
+
* Backward compatibility
|
2048 |
+
*/
|
2049 |
+
class XMLSchema extends nusoap_xmlschema {
|
2050 |
+
}
|
2051 |
+
|
2052 |
+
?><?php
|
2053 |
+
|
2054 |
+
|
2055 |
+
|
2056 |
+
/**
|
2057 |
+
* For creating serializable abstractions of native PHP types. This class
|
2058 |
+
* allows element name/namespace, XSD type, and XML attributes to be
|
2059 |
+
* associated with a value. This is extremely useful when WSDL is not
|
2060 |
+
* used, but is also useful when WSDL is used with polymorphic types, including
|
2061 |
+
* xsd:anyType and user-defined types.
|
2062 |
+
*
|
2063 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
2064 |
+
* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
|
2065 |
+
* @access public
|
2066 |
+
*/
|
2067 |
+
class soapval extends nusoap_base {
|
2068 |
+
/**
|
2069 |
+
* The XML element name
|
2070 |
+
*
|
2071 |
+
* @var string
|
2072 |
+
* @access private
|
2073 |
+
*/
|
2074 |
+
var $name;
|
2075 |
+
/**
|
2076 |
+
* The XML type name (string or false)
|
2077 |
+
*
|
2078 |
+
* @var mixed
|
2079 |
+
* @access private
|
2080 |
+
*/
|
2081 |
+
var $type;
|
2082 |
+
/**
|
2083 |
+
* The PHP value
|
2084 |
+
*
|
2085 |
+
* @var mixed
|
2086 |
+
* @access private
|
2087 |
+
*/
|
2088 |
+
var $value;
|
2089 |
+
/**
|
2090 |
+
* The XML element namespace (string or false)
|
2091 |
+
*
|
2092 |
+
* @var mixed
|
2093 |
+
* @access private
|
2094 |
+
*/
|
2095 |
+
var $element_ns;
|
2096 |
+
/**
|
2097 |
+
* The XML type namespace (string or false)
|
2098 |
+
*
|
2099 |
+
* @var mixed
|
2100 |
+
* @access private
|
2101 |
+
*/
|
2102 |
+
var $type_ns;
|
2103 |
+
/**
|
2104 |
+
* The XML element attributes (array or false)
|
2105 |
+
*
|
2106 |
+
* @var mixed
|
2107 |
+
* @access private
|
2108 |
+
*/
|
2109 |
+
var $attributes;
|
2110 |
+
|
2111 |
+
/**
|
2112 |
+
* constructor
|
2113 |
+
*
|
2114 |
+
* @param string $name optional name
|
2115 |
+
* @param mixed $type optional type name
|
2116 |
+
* @param mixed $value optional value
|
2117 |
+
* @param mixed $element_ns optional namespace of value
|
2118 |
+
* @param mixed $type_ns optional namespace of type
|
2119 |
+
* @param mixed $attributes associative array of attributes to add to element serialization
|
2120 |
+
* @access public
|
2121 |
+
*/
|
2122 |
+
function soapval($name='soapval',$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false) {
|
2123 |
+
parent::nusoap_base();
|
2124 |
+
$this->name = $name;
|
2125 |
+
$this->type = $type;
|
2126 |
+
$this->value = $value;
|
2127 |
+
$this->element_ns = $element_ns;
|
2128 |
+
$this->type_ns = $type_ns;
|
2129 |
+
$this->attributes = $attributes;
|
2130 |
+
}
|
2131 |
+
|
2132 |
+
/**
|
2133 |
+
* return serialized value
|
2134 |
+
*
|
2135 |
+
* @param string $use The WSDL use value (encoded|literal)
|
2136 |
+
* @return string XML data
|
2137 |
+
* @access public
|
2138 |
+
*/
|
2139 |
+
function serialize($use='encoded') {
|
2140 |
+
return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true);
|
2141 |
+
}
|
2142 |
+
|
2143 |
+
/**
|
2144 |
+
* decodes a soapval object into a PHP native type
|
2145 |
+
*
|
2146 |
+
* @return mixed
|
2147 |
+
* @access public
|
2148 |
+
*/
|
2149 |
+
function decode(){
|
2150 |
+
return $this->value;
|
2151 |
+
}
|
2152 |
+
}
|
2153 |
+
|
2154 |
+
|
2155 |
+
|
2156 |
+
?><?php
|
2157 |
+
|
2158 |
+
|
2159 |
+
|
2160 |
+
/**
|
2161 |
+
* transport class for sending/receiving data via HTTP and HTTPS
|
2162 |
+
* NOTE: PHP must be compiled with the CURL extension for HTTPS support
|
2163 |
+
*
|
2164 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
2165 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
2166 |
+
* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
|
2167 |
+
* @access public
|
2168 |
+
*/
|
2169 |
+
class soap_transport_http extends nusoap_base {
|
2170 |
+
|
2171 |
+
var $url = '';
|
2172 |
+
var $uri = '';
|
2173 |
+
var $digest_uri = '';
|
2174 |
+
var $scheme = '';
|
2175 |
+
var $host = '';
|
2176 |
+
var $port = '';
|
2177 |
+
var $path = '';
|
2178 |
+
var $request_method = 'POST';
|
2179 |
+
var $protocol_version = '1.0';
|
2180 |
+
var $encoding = '';
|
2181 |
+
var $outgoing_headers = array();
|
2182 |
+
var $incoming_headers = array();
|
2183 |
+
var $incoming_cookies = array();
|
2184 |
+
var $outgoing_payload = '';
|
2185 |
+
var $incoming_payload = '';
|
2186 |
+
var $response_status_line; // HTTP response status line
|
2187 |
+
var $useSOAPAction = true;
|
2188 |
+
var $persistentConnection = false;
|
2189 |
+
var $ch = false; // cURL handle
|
2190 |
+
var $ch_options = array(); // cURL custom options
|
2191 |
+
var $use_curl = false; // force cURL use
|
2192 |
+
var $proxy = null; // proxy information (associative array)
|
2193 |
+
var $username = '';
|
2194 |
+
var $password = '';
|
2195 |
+
var $authtype = '';
|
2196 |
+
var $digestRequest = array();
|
2197 |
+
var $certRequest = array(); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional)
|
2198 |
+
// cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'
|
2199 |
+
// sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
|
2200 |
+
// sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'
|
2201 |
+
// passphrase: SSL key password/passphrase
|
2202 |
+
// certpassword: SSL certificate password
|
2203 |
+
// verifypeer: default is 1
|
2204 |
+
// verifyhost: default is 1
|
2205 |
+
|
2206 |
+
/**
|
2207 |
+
* constructor
|
2208 |
+
*
|
2209 |
+
* @param string $url The URL to which to connect
|
2210 |
+
* @param array $curl_options User-specified cURL options
|
2211 |
+
* @param boolean $use_curl Whether to try to force cURL use
|
2212 |
+
* @access public
|
2213 |
+
*/
|
2214 |
+
function soap_transport_http($url, $curl_options = NULL, $use_curl = false){
|
2215 |
+
parent::nusoap_base();
|
2216 |
+
$this->debug("ctor url=$url use_curl=$use_curl curl_options:");
|
2217 |
+
$this->appendDebug($this->varDump($curl_options));
|
2218 |
+
$this->setURL($url);
|
2219 |
+
if (is_array($curl_options)) {
|
2220 |
+
$this->ch_options = $curl_options;
|
2221 |
+
}
|
2222 |
+
$this->use_curl = $use_curl;
|
2223 |
+
preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
|
2224 |
+
$this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')');
|
2225 |
+
}
|
2226 |
+
|
2227 |
+
/**
|
2228 |
+
* sets a cURL option
|
2229 |
+
*
|
2230 |
+
* @param mixed $option The cURL option (always integer?)
|
2231 |
+
* @param mixed $value The cURL option value
|
2232 |
+
* @access private
|
2233 |
+
*/
|
2234 |
+
function setCurlOption($option, $value) {
|
2235 |
+
$this->debug("setCurlOption option=$option, value=");
|
2236 |
+
$this->appendDebug($this->varDump($value));
|
2237 |
+
curl_setopt($this->ch, $option, $value);
|
2238 |
+
}
|
2239 |
+
|
2240 |
+
/**
|
2241 |
+
* sets an HTTP header
|
2242 |
+
*
|
2243 |
+
* @param string $name The name of the header
|
2244 |
+
* @param string $value The value of the header
|
2245 |
+
* @access private
|
2246 |
+
*/
|
2247 |
+
function setHeader($name, $value) {
|
2248 |
+
$this->outgoing_headers[$name] = $value;
|
2249 |
+
$this->debug("set header $name: $value");
|
2250 |
+
}
|
2251 |
+
|
2252 |
+
/**
|
2253 |
+
* unsets an HTTP header
|
2254 |
+
*
|
2255 |
+
* @param string $name The name of the header
|
2256 |
+
* @access private
|
2257 |
+
*/
|
2258 |
+
function unsetHeader($name) {
|
2259 |
+
if (isset($this->outgoing_headers[$name])) {
|
2260 |
+
$this->debug("unset header $name");
|
2261 |
+
unset($this->outgoing_headers[$name]);
|
2262 |
+
}
|
2263 |
+
}
|
2264 |
+
|
2265 |
+
/**
|
2266 |
+
* sets the URL to which to connect
|
2267 |
+
*
|
2268 |
+
* @param string $url The URL to which to connect
|
2269 |
+
* @access private
|
2270 |
+
*/
|
2271 |
+
function setURL($url) {
|
2272 |
+
$this->url = $url;
|
2273 |
+
|
2274 |
+
$u = parse_url($url);
|
2275 |
+
foreach($u as $k => $v){
|
2276 |
+
$this->debug("parsed URL $k = $v");
|
2277 |
+
$this->$k = $v;
|
2278 |
+
}
|
2279 |
+
|
2280 |
+
// add any GET params to path
|
2281 |
+
if(isset($u['query']) && $u['query'] != ''){
|
2282 |
+
$this->path .= '?' . $u['query'];
|
2283 |
+
}
|
2284 |
+
|
2285 |
+
// set default port
|
2286 |
+
if(!isset($u['port'])){
|
2287 |
+
if($u['scheme'] == 'https'){
|
2288 |
+
$this->port = 443;
|
2289 |
+
} else {
|
2290 |
+
$this->port = 80;
|
2291 |
+
}
|
2292 |
+
}
|
2293 |
+
|
2294 |
+
$this->uri = $this->path;
|
2295 |
+
$this->digest_uri = $this->uri;
|
2296 |
+
|
2297 |
+
// build headers
|
2298 |
+
if (!isset($u['port'])) {
|
2299 |
+
$this->setHeader('Host', $this->host);
|
2300 |
+
} else {
|
2301 |
+
$this->setHeader('Host', $this->host.':'.$this->port);
|
2302 |
+
}
|
2303 |
+
|
2304 |
+
if (isset($u['user']) && $u['user'] != '') {
|
2305 |
+
$this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : '');
|
2306 |
+
}
|
2307 |
+
}
|
2308 |
+
|
2309 |
+
/**
|
2310 |
+
* gets the I/O method to use
|
2311 |
+
*
|
2312 |
+
* @return string I/O method to use (socket|curl|unknown)
|
2313 |
+
* @access private
|
2314 |
+
*/
|
2315 |
+
function io_method() {
|
2316 |
+
if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm'))
|
2317 |
+
return 'curl';
|
2318 |
+
if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm'))
|
2319 |
+
return 'socket';
|
2320 |
+
return 'unknown';
|
2321 |
+
}
|
2322 |
+
|
2323 |
+
/**
|
2324 |
+
* establish an HTTP connection
|
2325 |
+
*
|
2326 |
+
* @param integer $timeout set connection timeout in seconds
|
2327 |
+
* @param integer $response_timeout set response timeout in seconds
|
2328 |
+
* @return boolean true if connected, false if not
|
2329 |
+
* @access private
|
2330 |
+
*/
|
2331 |
+
function connect($connection_timeout=0,$response_timeout=30){
|
2332 |
+
// For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like
|
2333 |
+
// "regular" socket.
|
2334 |
+
// TODO: disabled for now because OpenSSL must be *compiled* in (not just
|
2335 |
+
// loaded), and until PHP5 stream_get_wrappers is not available.
|
2336 |
+
// if ($this->scheme == 'https') {
|
2337 |
+
// if (version_compare(phpversion(), '4.3.0') >= 0) {
|
2338 |
+
// if (extension_loaded('openssl')) {
|
2339 |
+
// $this->scheme = 'ssl';
|
2340 |
+
// $this->debug('Using SSL over OpenSSL');
|
2341 |
+
// }
|
2342 |
+
// }
|
2343 |
+
// }
|
2344 |
+
$this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
|
2345 |
+
if ($this->io_method() == 'socket') {
|
2346 |
+
if (!is_array($this->proxy)) {
|
2347 |
+
$host = $this->host;
|
2348 |
+
$port = $this->port;
|
2349 |
+
} else {
|
2350 |
+
$host = $this->proxy['host'];
|
2351 |
+
$port = $this->proxy['port'];
|
2352 |
+
}
|
2353 |
+
|
2354 |
+
// use persistent connection
|
2355 |
+
if($this->persistentConnection && isset($this->fp) && is_resource($this->fp)){
|
2356 |
+
if (!feof($this->fp)) {
|
2357 |
+
$this->debug('Re-use persistent connection');
|
2358 |
+
return true;
|
2359 |
+
}
|
2360 |
+
fclose($this->fp);
|
2361 |
+
$this->debug('Closed persistent connection at EOF');
|
2362 |
+
}
|
2363 |
+
|
2364 |
+
// munge host if using OpenSSL
|
2365 |
+
if ($this->scheme == 'ssl') {
|
2366 |
+
$host = 'ssl://' . $host;
|
2367 |
+
}
|
2368 |
+
$this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);
|
2369 |
+
|
2370 |
+
// open socket
|
2371 |
+
if($connection_timeout > 0){
|
2372 |
+
$this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str, $connection_timeout);
|
2373 |
+
} else {
|
2374 |
+
$this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str);
|
2375 |
+
}
|
2376 |
+
|
2377 |
+
// test pointer
|
2378 |
+
if(!$this->fp) {
|
2379 |
+
$msg = 'Couldn\'t open socket connection to server ' . $this->url;
|
2380 |
+
if ($this->errno) {
|
2381 |
+
$msg .= ', Error ('.$this->errno.'): '.$this->error_str;
|
2382 |
+
} else {
|
2383 |
+
$msg .= ' prior to connect(). This is often a problem looking up the host name.';
|
2384 |
+
}
|
2385 |
+
$this->debug($msg);
|
2386 |
+
$this->setError($msg);
|
2387 |
+
return false;
|
2388 |
+
}
|
2389 |
+
|
2390 |
+
// set response timeout
|
2391 |
+
$this->debug('set response timeout to ' . $response_timeout);
|
2392 |
+
socket_set_timeout( $this->fp, $response_timeout);
|
2393 |
+
|
2394 |
+
$this->debug('socket connected');
|
2395 |
+
return true;
|
2396 |
+
} else if ($this->io_method() == 'curl') {
|
2397 |
+
if (!extension_loaded('curl')) {
|
2398 |
+
// $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
|
2399 |
+
$this->setError('The PHP cURL Extension is required for HTTPS or NLTM. You will need to re-build or update your PHP to include cURL or change php.ini to load the PHP cURL extension.');
|
2400 |
+
return false;
|
2401 |
+
}
|
2402 |
+
// Avoid warnings when PHP does not have these options
|
2403 |
+
if (defined('CURLOPT_CONNECTIONTIMEOUT'))
|
2404 |
+
$CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT;
|
2405 |
+
else
|
2406 |
+
$CURLOPT_CONNECTIONTIMEOUT = 78;
|
2407 |
+
if (defined('CURLOPT_HTTPAUTH'))
|
2408 |
+
$CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH;
|
2409 |
+
else
|
2410 |
+
$CURLOPT_HTTPAUTH = 107;
|
2411 |
+
if (defined('CURLOPT_PROXYAUTH'))
|
2412 |
+
$CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH;
|
2413 |
+
else
|
2414 |
+
$CURLOPT_PROXYAUTH = 111;
|
2415 |
+
if (defined('CURLAUTH_BASIC'))
|
2416 |
+
$CURLAUTH_BASIC = CURLAUTH_BASIC;
|
2417 |
+
else
|
2418 |
+
$CURLAUTH_BASIC = 1;
|
2419 |
+
if (defined('CURLAUTH_DIGEST'))
|
2420 |
+
$CURLAUTH_DIGEST = CURLAUTH_DIGEST;
|
2421 |
+
else
|
2422 |
+
$CURLAUTH_DIGEST = 2;
|
2423 |
+
if (defined('CURLAUTH_NTLM'))
|
2424 |
+
$CURLAUTH_NTLM = CURLAUTH_NTLM;
|
2425 |
+
else
|
2426 |
+
$CURLAUTH_NTLM = 8;
|
2427 |
+
|
2428 |
+
$this->debug('connect using cURL');
|
2429 |
+
// init CURL
|
2430 |
+
$this->ch = curl_init();
|
2431 |
+
// set url
|
2432 |
+
$hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host";
|
2433 |
+
// add path
|
2434 |
+
$hostURL .= $this->path;
|
2435 |
+
$this->setCurlOption(CURLOPT_URL, $hostURL);
|
2436 |
+
// follow location headers (re-directs)
|
2437 |
+
if (ini_get('safe_mode') || ini_get('open_basedir')) {
|
2438 |
+
$this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION');
|
2439 |
+
$this->debug('safe_mode = ');
|
2440 |
+
$this->appendDebug($this->varDump(ini_get('safe_mode')));
|
2441 |
+
$this->debug('open_basedir = ');
|
2442 |
+
$this->appendDebug($this->varDump(ini_get('open_basedir')));
|
2443 |
+
} else {
|
2444 |
+
$this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1);
|
2445 |
+
}
|
2446 |
+
// ask for headers in the response output
|
2447 |
+
$this->setCurlOption(CURLOPT_HEADER, 1);
|
2448 |
+
// ask for the response output as the return value
|
2449 |
+
$this->setCurlOption(CURLOPT_RETURNTRANSFER, 1);
|
2450 |
+
// encode
|
2451 |
+
// We manage this ourselves through headers and encoding
|
2452 |
+
// if(function_exists('gzuncompress')){
|
2453 |
+
// $this->setCurlOption(CURLOPT_ENCODING, 'deflate');
|
2454 |
+
// }
|
2455 |
+
// persistent connection
|
2456 |
+
if ($this->persistentConnection) {
|
2457 |
+
// I believe the following comment is now bogus, having applied to
|
2458 |
+
// the code when it used CURLOPT_CUSTOMREQUEST to send the request.
|
2459 |
+
// The way we send data, we cannot use persistent connections, since
|
2460 |
+
// there will be some "junk" at the end of our request.
|
2461 |
+
//$this->setCurlOption(CURL_HTTP_VERSION_1_1, true);
|
2462 |
+
$this->persistentConnection = false;
|
2463 |
+
$this->setHeader('Connection', 'close');
|
2464 |
+
}
|
2465 |
+
// set timeouts
|
2466 |
+
if ($connection_timeout != 0) {
|
2467 |
+
$this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);
|
2468 |
+
}
|
2469 |
+
if ($response_timeout != 0) {
|
2470 |
+
$this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout);
|
2471 |
+
}
|
2472 |
+
|
2473 |
+
if ($this->scheme == 'https') {
|
2474 |
+
$this->debug('set cURL SSL verify options');
|
2475 |
+
// recent versions of cURL turn on peer/host checking by default,
|
2476 |
+
// while PHP binaries are not compiled with a default location for the
|
2477 |
+
// CA cert bundle, so disable peer/host checking.
|
2478 |
+
//$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');
|
2479 |
+
$this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0);
|
2480 |
+
$this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0);
|
2481 |
+
|
2482 |
+
// support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)
|
2483 |
+
if ($this->authtype == 'certificate') {
|
2484 |
+
$this->debug('set cURL certificate options');
|
2485 |
+
if (isset($this->certRequest['cainfofile'])) {
|
2486 |
+
$this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']);
|
2487 |
+
}
|
2488 |
+
if (isset($this->certRequest['verifypeer'])) {
|
2489 |
+
$this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);
|
2490 |
+
} else {
|
2491 |
+
$this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1);
|
2492 |
+
}
|
2493 |
+
if (isset($this->certRequest['verifyhost'])) {
|
2494 |
+
$this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);
|
2495 |
+
} else {
|
2496 |
+
$this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1);
|
2497 |
+
}
|
2498 |
+
if (isset($this->certRequest['sslcertfile'])) {
|
2499 |
+
$this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);
|
2500 |
+
}
|
2501 |
+
if (isset($this->certRequest['sslkeyfile'])) {
|
2502 |
+
$this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);
|
2503 |
+
}
|
2504 |
+
if (isset($this->certRequest['passphrase'])) {
|
2505 |
+
$this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']);
|
2506 |
+
}
|
2507 |
+
if (isset($this->certRequest['certpassword'])) {
|
2508 |
+
$this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']);
|
2509 |
+
}
|
2510 |
+
}
|
2511 |
+
}
|
2512 |
+
if ($this->authtype && ($this->authtype != 'certificate')) {
|
2513 |
+
if ($this->username) {
|
2514 |
+
$this->debug('set cURL username/password');
|
2515 |
+
$this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password");
|
2516 |
+
}
|
2517 |
+
if ($this->authtype == 'basic') {
|
2518 |
+
$this->debug('set cURL for Basic authentication');
|
2519 |
+
$this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC);
|
2520 |
+
}
|
2521 |
+
if ($this->authtype == 'digest') {
|
2522 |
+
$this->debug('set cURL for digest authentication');
|
2523 |
+
$this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST);
|
2524 |
+
}
|
2525 |
+
if ($this->authtype == 'ntlm') {
|
2526 |
+
$this->debug('set cURL for NTLM authentication');
|
2527 |
+
$this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM);
|
2528 |
+
}
|
2529 |
+
}
|
2530 |
+
if (is_array($this->proxy)) {
|
2531 |
+
$this->debug('set cURL proxy options');
|
2532 |
+
if ($this->proxy['port'] != '') {
|
2533 |
+
$this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'].':'.$this->proxy['port']);
|
2534 |
+
} else {
|
2535 |
+
$this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']);
|
2536 |
+
}
|
2537 |
+
if ($this->proxy['username'] || $this->proxy['password']) {
|
2538 |
+
$this->debug('set cURL proxy authentication options');
|
2539 |
+
$this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'].':'.$this->proxy['password']);
|
2540 |
+
if ($this->proxy['authtype'] == 'basic') {
|
2541 |
+
$this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC);
|
2542 |
+
}
|
2543 |
+
if ($this->proxy['authtype'] == 'ntlm') {
|
2544 |
+
$this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM);
|
2545 |
+
}
|
2546 |
+
}
|
2547 |
+
}
|
2548 |
+
$this->debug('cURL connection set up');
|
2549 |
+
return true;
|
2550 |
+
} else {
|
2551 |
+
$this->setError('Unknown scheme ' . $this->scheme);
|
2552 |
+
$this->debug('Unknown scheme ' . $this->scheme);
|
2553 |
+
return false;
|
2554 |
+
}
|
2555 |
+
}
|
2556 |
+
|
2557 |
+
/**
|
2558 |
+
* sends the SOAP request and gets the SOAP response via HTTP[S]
|
2559 |
+
*
|
2560 |
+
* @param string $data message data
|
2561 |
+
* @param integer $timeout set connection timeout in seconds
|
2562 |
+
* @param integer $response_timeout set response timeout in seconds
|
2563 |
+
* @param array $cookies cookies to send
|
2564 |
+
* @return string data
|
2565 |
+
* @access public
|
2566 |
+
*/
|
2567 |
+
function send($data, $timeout=0, $response_timeout=30, $cookies=NULL) {
|
2568 |
+
|
2569 |
+
$this->debug('entered send() with data of length: '.strlen($data));
|
2570 |
+
|
2571 |
+
$this->tryagain = true;
|
2572 |
+
$tries = 0;
|
2573 |
+
while ($this->tryagain) {
|
2574 |
+
$this->tryagain = false;
|
2575 |
+
if ($tries++ < 2) {
|
2576 |
+
// make connnection
|
2577 |
+
if (!$this->connect($timeout, $response_timeout)){
|
2578 |
+
return false;
|
2579 |
+
}
|
2580 |
+
|
2581 |
+
// send request
|
2582 |
+
if (!$this->sendRequest($data, $cookies)){
|
2583 |
+
return false;
|
2584 |
+
}
|
2585 |
+
|
2586 |
+
// get response
|
2587 |
+
$respdata = $this->getResponse();
|
2588 |
+
} else {
|
2589 |
+
$this->setError("Too many tries to get an OK response ($this->response_status_line)");
|
2590 |
+
}
|
2591 |
+
}
|
2592 |
+
$this->debug('end of send()');
|
2593 |
+
return $respdata;
|
2594 |
+
}
|
2595 |
+
|
2596 |
+
|
2597 |
+
/**
|
2598 |
+
* sends the SOAP request and gets the SOAP response via HTTPS using CURL
|
2599 |
+
*
|
2600 |
+
* @param string $data message data
|
2601 |
+
* @param integer $timeout set connection timeout in seconds
|
2602 |
+
* @param integer $response_timeout set response timeout in seconds
|
2603 |
+
* @param array $cookies cookies to send
|
2604 |
+
* @return string data
|
2605 |
+
* @access public
|
2606 |
+
* @deprecated
|
2607 |
+
*/
|
2608 |
+
function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies) {
|
2609 |
+
return $this->send($data, $timeout, $response_timeout, $cookies);
|
2610 |
+
}
|
2611 |
+
|
2612 |
+
/**
|
2613 |
+
* if authenticating, set user credentials here
|
2614 |
+
*
|
2615 |
+
* @param string $username
|
2616 |
+
* @param string $password
|
2617 |
+
* @param string $authtype (basic|digest|certificate|ntlm)
|
2618 |
+
* @param array $digestRequest (keys must be nonce, nc, realm, qop)
|
2619 |
+
* @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
|
2620 |
+
* @access public
|
2621 |
+
*/
|
2622 |
+
function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array()) {
|
2623 |
+
$this->debug("setCredentials username=$username authtype=$authtype digestRequest=");
|
2624 |
+
$this->appendDebug($this->varDump($digestRequest));
|
2625 |
+
$this->debug("certRequest=");
|
2626 |
+
$this->appendDebug($this->varDump($certRequest));
|
2627 |
+
// cf. RFC 2617
|
2628 |
+
if ($authtype == 'basic') {
|
2629 |
+
$this->setHeader('Authorization', 'Basic '.base64_encode(str_replace(':','',$username).':'.$password));
|
2630 |
+
} elseif ($authtype == 'digest') {
|
2631 |
+
if (isset($digestRequest['nonce'])) {
|
2632 |
+
$digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
|
2633 |
+
|
2634 |
+
// calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)
|
2635 |
+
|
2636 |
+
// A1 = unq(username-value) ":" unq(realm-value) ":" passwd
|
2637 |
+
$A1 = $username. ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password;
|
2638 |
+
|
2639 |
+
// H(A1) = MD5(A1)
|
2640 |
+
$HA1 = md5($A1);
|
2641 |
+
|
2642 |
+
// A2 = Method ":" digest-uri-value
|
2643 |
+
$A2 = $this->request_method . ':' . $this->digest_uri;
|
2644 |
+
|
2645 |
+
// H(A2)
|
2646 |
+
$HA2 = md5($A2);
|
2647 |
+
|
2648 |
+
// KD(secret, data) = H(concat(secret, ":", data))
|
2649 |
+
// if qop == auth:
|
2650 |
+
// request-digest = <"> < KD ( H(A1), unq(nonce-value)
|
2651 |
+
// ":" nc-value
|
2652 |
+
// ":" unq(cnonce-value)
|
2653 |
+
// ":" unq(qop-value)
|
2654 |
+
// ":" H(A2)
|
2655 |
+
// ) <">
|
2656 |
+
// if qop is missing,
|
2657 |
+
// request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
|
2658 |
+
|
2659 |
+
$unhashedDigest = '';
|
2660 |
+
$nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';
|
2661 |
+
$cnonce = $nonce;
|
2662 |
+
if ($digestRequest['qop'] != '') {
|
2663 |
+
$unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
|
2664 |
+
} else {
|
2665 |
+
$unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
|
2666 |
+
}
|
2667 |
+
|
2668 |
+
$hashedDigest = md5($unhashedDigest);
|
2669 |
+
|
2670 |
+
$opaque = '';
|
2671 |
+
if (isset($digestRequest['opaque'])) {
|
2672 |
+
$opaque = ', opaque="' . $digestRequest['opaque'] . '"';
|
2673 |
+
}
|
2674 |
+
|
2675 |
+
$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 . '"');
|
2676 |
+
}
|
2677 |
+
} elseif ($authtype == 'certificate') {
|
2678 |
+
$this->certRequest = $certRequest;
|
2679 |
+
$this->debug('Authorization header not set for certificate');
|
2680 |
+
} elseif ($authtype == 'ntlm') {
|
2681 |
+
// do nothing
|
2682 |
+
$this->debug('Authorization header not set for ntlm');
|
2683 |
+
}
|
2684 |
+
$this->username = $username;
|
2685 |
+
$this->password = $password;
|
2686 |
+
$this->authtype = $authtype;
|
2687 |
+
$this->digestRequest = $digestRequest;
|
2688 |
+
}
|
2689 |
+
|
2690 |
+
/**
|
2691 |
+
* set the soapaction value
|
2692 |
+
*
|
2693 |
+
* @param string $soapaction
|
2694 |
+
* @access public
|
2695 |
+
*/
|
2696 |
+
function setSOAPAction($soapaction) {
|
2697 |
+
$this->setHeader('SOAPAction', '"' . $soapaction . '"');
|
2698 |
+
}
|
2699 |
+
|
2700 |
+
/**
|
2701 |
+
* use http encoding
|
2702 |
+
*
|
2703 |
+
* @param string $enc encoding style. supported values: gzip, deflate, or both
|
2704 |
+
* @access public
|
2705 |
+
*/
|
2706 |
+
function setEncoding($enc='gzip, deflate') {
|
2707 |
+
if (function_exists('gzdeflate')) {
|
2708 |
+
$this->protocol_version = '1.1';
|
2709 |
+
$this->setHeader('Accept-Encoding', $enc);
|
2710 |
+
if (!isset($this->outgoing_headers['Connection'])) {
|
2711 |
+
$this->setHeader('Connection', 'close');
|
2712 |
+
$this->persistentConnection = false;
|
2713 |
+
}
|
2714 |
+
// deprecated as of PHP 5.3.0
|
2715 |
+
//set_magic_quotes_runtime(0);
|
2716 |
+
$this->encoding = $enc;
|
2717 |
+
}
|
2718 |
+
}
|
2719 |
+
|
2720 |
+
/**
|
2721 |
+
* set proxy info here
|
2722 |
+
*
|
2723 |
+
* @param string $proxyhost use an empty string to remove proxy
|
2724 |
+
* @param string $proxyport
|
2725 |
+
* @param string $proxyusername
|
2726 |
+
* @param string $proxypassword
|
2727 |
+
* @param string $proxyauthtype (basic|ntlm)
|
2728 |
+
* @access public
|
2729 |
+
*/
|
2730 |
+
function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic') {
|
2731 |
+
if ($proxyhost) {
|
2732 |
+
$this->proxy = array(
|
2733 |
+
'host' => $proxyhost,
|
2734 |
+
'port' => $proxyport,
|
2735 |
+
'username' => $proxyusername,
|
2736 |
+
'password' => $proxypassword,
|
2737 |
+
'authtype' => $proxyauthtype
|
2738 |
+
);
|
2739 |
+
if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') {
|
2740 |
+
$this->setHeader('Proxy-Authorization', ' Basic '.base64_encode($proxyusername.':'.$proxypassword));
|
2741 |
+
}
|
2742 |
+
} else {
|
2743 |
+
$this->debug('remove proxy');
|
2744 |
+
$proxy = null;
|
2745 |
+
unsetHeader('Proxy-Authorization');
|
2746 |
+
}
|
2747 |
+
}
|
2748 |
+
|
2749 |
+
|
2750 |
+
/**
|
2751 |
+
* Test if the given string starts with a header that is to be skipped.
|
2752 |
+
* Skippable headers result from chunked transfer and proxy requests.
|
2753 |
+
*
|
2754 |
+
* @param string $data The string to check.
|
2755 |
+
* @returns boolean Whether a skippable header was found.
|
2756 |
+
* @access private
|
2757 |
+
*/
|
2758 |
+
function isSkippableCurlHeader(&$data) {
|
2759 |
+
$skipHeaders = array( 'HTTP/1.1 100',
|
2760 |
+
'HTTP/1.0 301',
|
2761 |
+
'HTTP/1.1 301',
|
2762 |
+
'HTTP/1.0 302',
|
2763 |
+
'HTTP/1.1 302',
|
2764 |
+
'HTTP/1.0 401',
|
2765 |
+
'HTTP/1.1 401',
|
2766 |
+
'HTTP/1.0 200 Connection established');
|
2767 |
+
foreach ($skipHeaders as $hd) {
|
2768 |
+
$prefix = substr($data, 0, strlen($hd));
|
2769 |
+
if ($prefix == $hd) return true;
|
2770 |
+
}
|
2771 |
+
|
2772 |
+
return false;
|
2773 |
+
}
|
2774 |
+
|
2775 |
+
/**
|
2776 |
+
* decode a string that is encoded w/ "chunked' transfer encoding
|
2777 |
+
* as defined in RFC2068 19.4.6
|
2778 |
+
*
|
2779 |
+
* @param string $buffer
|
2780 |
+
* @param string $lb
|
2781 |
+
* @returns string
|
2782 |
+
* @access public
|
2783 |
+
* @deprecated
|
2784 |
+
*/
|
2785 |
+
function decodeChunked($buffer, $lb){
|
2786 |
+
// length := 0
|
2787 |
+
$length = 0;
|
2788 |
+
$new = '';
|
2789 |
+
|
2790 |
+
// read chunk-size, chunk-extension (if any) and CRLF
|
2791 |
+
// get the position of the linebreak
|
2792 |
+
$chunkend = strpos($buffer, $lb);
|
2793 |
+
if ($chunkend == FALSE) {
|
2794 |
+
$this->debug('no linebreak found in decodeChunked');
|
2795 |
+
return $new;
|
2796 |
+
}
|
2797 |
+
$temp = substr($buffer,0,$chunkend);
|
2798 |
+
$chunk_size = hexdec( trim($temp) );
|
2799 |
+
$chunkstart = $chunkend + strlen($lb);
|
2800 |
+
// while (chunk-size > 0) {
|
2801 |
+
while ($chunk_size > 0) {
|
2802 |
+
$this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
|
2803 |
+
$chunkend = strpos( $buffer, $lb, $chunkstart + $chunk_size);
|
2804 |
+
|
2805 |
+
// Just in case we got a broken connection
|
2806 |
+
if ($chunkend == FALSE) {
|
2807 |
+
$chunk = substr($buffer,$chunkstart);
|
2808 |
+
// append chunk-data to entity-body
|
2809 |
+
$new .= $chunk;
|
2810 |
+
$length += strlen($chunk);
|
2811 |
+
break;
|
2812 |
+
}
|
2813 |
+
|
2814 |
+
// read chunk-data and CRLF
|
2815 |
+
$chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart);
|
2816 |
+
// append chunk-data to entity-body
|
2817 |
+
$new .= $chunk;
|
2818 |
+
// length := length + chunk-size
|
2819 |
+
$length += strlen($chunk);
|
2820 |
+
// read chunk-size and CRLF
|
2821 |
+
$chunkstart = $chunkend + strlen($lb);
|
2822 |
+
|
2823 |
+
$chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
|
2824 |
+
if ($chunkend == FALSE) {
|
2825 |
+
break; //Just in case we got a broken connection
|
2826 |
+
}
|
2827 |
+
$temp = substr($buffer,$chunkstart,$chunkend-$chunkstart);
|
2828 |
+
$chunk_size = hexdec( trim($temp) );
|
2829 |
+
$chunkstart = $chunkend;
|
2830 |
+
}
|
2831 |
+
return $new;
|
2832 |
+
}
|
2833 |
+
|
2834 |
+
/**
|
2835 |
+
* Writes the payload, including HTTP headers, to $this->outgoing_payload.
|
2836 |
+
*
|
2837 |
+
* @param string $data HTTP body
|
2838 |
+
* @param string $cookie_str data for HTTP Cookie header
|
2839 |
+
* @return void
|
2840 |
+
* @access private
|
2841 |
+
*/
|
2842 |
+
function buildPayload($data, $cookie_str = '') {
|
2843 |
+
// Note: for cURL connections, $this->outgoing_payload is ignored,
|
2844 |
+
// as is the Content-Length header, but these are still created as
|
2845 |
+
// debugging guides.
|
2846 |
+
|
2847 |
+
// add content-length header
|
2848 |
+
if ($this->request_method != 'GET') {
|
2849 |
+
$this->setHeader('Content-Length', strlen($data));
|
2850 |
+
}
|
2851 |
+
|
2852 |
+
// start building outgoing payload:
|
2853 |
+
if ($this->proxy) {
|
2854 |
+
$uri = $this->url;
|
2855 |
+
} else {
|
2856 |
+
$uri = $this->uri;
|
2857 |
+
}
|
2858 |
+
$req = "$this->request_method $uri HTTP/$this->protocol_version";
|
2859 |
+
$this->debug("HTTP request: $req");
|
2860 |
+
$this->outgoing_payload = "$req\r\n";
|
2861 |
+
|
2862 |
+
// loop thru headers, serializing
|
2863 |
+
foreach($this->outgoing_headers as $k => $v){
|
2864 |
+
$hdr = $k.': '.$v;
|
2865 |
+
$this->debug("HTTP header: $hdr");
|
2866 |
+
$this->outgoing_payload .= "$hdr\r\n";
|
2867 |
+
}
|
2868 |
+
|
2869 |
+
// add any cookies
|
2870 |
+
if ($cookie_str != '') {
|
2871 |
+
$hdr = 'Cookie: '.$cookie_str;
|
2872 |
+
$this->debug("HTTP header: $hdr");
|
2873 |
+
$this->outgoing_payload .= "$hdr\r\n";
|
2874 |
+
}
|
2875 |
+
|
2876 |
+
// header/body separator
|
2877 |
+
$this->outgoing_payload .= "\r\n";
|
2878 |
+
|
2879 |
+
// add data
|
2880 |
+
$this->outgoing_payload .= $data;
|
2881 |
+
}
|
2882 |
+
|
2883 |
+
/**
|
2884 |
+
* sends the SOAP request via HTTP[S]
|
2885 |
+
*
|
2886 |
+
* @param string $data message data
|
2887 |
+
* @param array $cookies cookies to send
|
2888 |
+
* @return boolean true if OK, false if problem
|
2889 |
+
* @access private
|
2890 |
+
*/
|
2891 |
+
function sendRequest($data, $cookies = NULL) {
|
2892 |
+
// build cookie string
|
2893 |
+
$cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));
|
2894 |
+
|
2895 |
+
// build payload
|
2896 |
+
$this->buildPayload($data, $cookie_str);
|
2897 |
+
|
2898 |
+
if ($this->io_method() == 'socket') {
|
2899 |
+
// send payload
|
2900 |
+
if(!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
|
2901 |
+
$this->setError('couldn\'t write message data to socket');
|
2902 |
+
$this->debug('couldn\'t write message data to socket');
|
2903 |
+
return false;
|
2904 |
+
}
|
2905 |
+
$this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
|
2906 |
+
return true;
|
2907 |
+
} else if ($this->io_method() == 'curl') {
|
2908 |
+
// set payload
|
2909 |
+
// cURL does say this should only be the verb, and in fact it
|
2910 |
+
// turns out that the URI and HTTP version are appended to this, which
|
2911 |
+
// some servers refuse to work with (so we no longer use this method!)
|
2912 |
+
//$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
|
2913 |
+
$curl_headers = array();
|
2914 |
+
foreach($this->outgoing_headers as $k => $v){
|
2915 |
+
if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') {
|
2916 |
+
$this->debug("Skip cURL header $k: $v");
|
2917 |
+
} else {
|
2918 |
+
$curl_headers[] = "$k: $v";
|
2919 |
+
}
|
2920 |
+
}
|
2921 |
+
if ($cookie_str != '') {
|
2922 |
+
$curl_headers[] = 'Cookie: ' . $cookie_str;
|
2923 |
+
}
|
2924 |
+
$this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers);
|
2925 |
+
$this->debug('set cURL HTTP headers');
|
2926 |
+
if ($this->request_method == "POST") {
|
2927 |
+
$this->setCurlOption(CURLOPT_POST, 1);
|
2928 |
+
$this->setCurlOption(CURLOPT_POSTFIELDS, $data);
|
2929 |
+
$this->debug('set cURL POST data');
|
2930 |
+
} else {
|
2931 |
+
}
|
2932 |
+
// insert custom user-set cURL options
|
2933 |
+
foreach ($this->ch_options as $key => $val) {
|
2934 |
+
$this->setCurlOption($key, $val);
|
2935 |
+
}
|
2936 |
+
|
2937 |
+
$this->debug('set cURL payload');
|
2938 |
+
return true;
|
2939 |
+
}
|
2940 |
+
}
|
2941 |
+
|
2942 |
+
/**
|
2943 |
+
* gets the SOAP response via HTTP[S]
|
2944 |
+
*
|
2945 |
+
* @return string the response (also sets member variables like incoming_payload)
|
2946 |
+
* @access private
|
2947 |
+
*/
|
2948 |
+
function getResponse(){
|
2949 |
+
$this->incoming_payload = '';
|
2950 |
+
|
2951 |
+
if ($this->io_method() == 'socket') {
|
2952 |
+
// loop until headers have been retrieved
|
2953 |
+
$data = '';
|
2954 |
+
while (!isset($lb)){
|
2955 |
+
|
2956 |
+
// We might EOF during header read.
|
2957 |
+
if(feof($this->fp)) {
|
2958 |
+
$this->incoming_payload = $data;
|
2959 |
+
$this->debug('found no headers before EOF after length ' . strlen($data));
|
2960 |
+
$this->debug("received before EOF:\n" . $data);
|
2961 |
+
$this->setError('server failed to send headers');
|
2962 |
+
return false;
|
2963 |
+
}
|
2964 |
+
|
2965 |
+
$tmp = fgets($this->fp, 256);
|
2966 |
+
$tmplen = strlen($tmp);
|
2967 |
+
$this->debug("read line of $tmplen bytes: " . trim($tmp));
|
2968 |
+
|
2969 |
+
if ($tmplen == 0) {
|
2970 |
+
$this->incoming_payload = $data;
|
2971 |
+
$this->debug('socket read of headers timed out after length ' . strlen($data));
|
2972 |
+
$this->debug("read before timeout: " . $data);
|
2973 |
+
$this->setError('socket read of headers timed out');
|
2974 |
+
return false;
|
2975 |
+
}
|
2976 |
+
|
2977 |
+
$data .= $tmp;
|
2978 |
+
$pos = strpos($data,"\r\n\r\n");
|
2979 |
+
if($pos > 1){
|
2980 |
+
$lb = "\r\n";
|
2981 |
+
} else {
|
2982 |
+
$pos = strpos($data,"\n\n");
|
2983 |
+
if($pos > 1){
|
2984 |
+
$lb = "\n";
|
2985 |
+
}
|
2986 |
+
}
|
2987 |
+
// remove 100 headers
|
2988 |
+
if (isset($lb) && preg_match('/^HTTP\/1.1 100/',$data)) {
|
2989 |
+
unset($lb);
|
2990 |
+
$data = '';
|
2991 |
+
}//
|
2992 |
+
}
|
2993 |
+
// store header data
|
2994 |
+
$this->incoming_payload .= $data;
|
2995 |
+
$this->debug('found end of headers after length ' . strlen($data));
|
2996 |
+
// process headers
|
2997 |
+
$header_data = trim(substr($data,0,$pos));
|
2998 |
+
$header_array = explode($lb,$header_data);
|
2999 |
+
$this->incoming_headers = array();
|
3000 |
+
$this->incoming_cookies = array();
|
3001 |
+
foreach($header_array as $header_line){
|
3002 |
+
$arr = explode(':',$header_line, 2);
|
3003 |
+
if(count($arr) > 1){
|
3004 |
+
$header_name = strtolower(trim($arr[0]));
|
3005 |
+
$this->incoming_headers[$header_name] = trim($arr[1]);
|
3006 |
+
if ($header_name == 'set-cookie') {
|
3007 |
+
// TODO: allow multiple cookies from parseCookie
|
3008 |
+
$cookie = $this->parseCookie(trim($arr[1]));
|
3009 |
+
if ($cookie) {
|
3010 |
+
$this->incoming_cookies[] = $cookie;
|
3011 |
+
$this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
|
3012 |
+
} else {
|
3013 |
+
$this->debug('did not find cookie in ' . trim($arr[1]));
|
3014 |
+
}
|
3015 |
+
}
|
3016 |
+
} else if (isset($header_name)) {
|
3017 |
+
// append continuation line to previous header
|
3018 |
+
$this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
|
3019 |
+
}
|
3020 |
+
}
|
3021 |
+
|
3022 |
+
// loop until msg has been received
|
3023 |
+
if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') {
|
3024 |
+
$content_length = 2147483647; // ignore any content-length header
|
3025 |
+
$chunked = true;
|
3026 |
+
$this->debug("want to read chunked content");
|
3027 |
+
} elseif (isset($this->incoming_headers['content-length'])) {
|
3028 |
+
$content_length = $this->incoming_headers['content-length'];
|
3029 |
+
$chunked = false;
|
3030 |
+
$this->debug("want to read content of length $content_length");
|
3031 |
+
} else {
|
3032 |
+
$content_length = 2147483647;
|
3033 |
+
$chunked = false;
|
3034 |
+
$this->debug("want to read content to EOF");
|
3035 |
+
}
|
3036 |
+
$data = '';
|
3037 |
+
do {
|
3038 |
+
if ($chunked) {
|
3039 |
+
$tmp = fgets($this->fp, 256);
|
3040 |
+
$tmplen = strlen($tmp);
|
3041 |
+
$this->debug("read chunk line of $tmplen bytes");
|
3042 |
+
if ($tmplen == 0) {
|
3043 |
+
$this->incoming_payload = $data;
|
3044 |
+
$this->debug('socket read of chunk length timed out after length ' . strlen($data));
|
3045 |
+
$this->debug("read before timeout:\n" . $data);
|
3046 |
+
$this->setError('socket read of chunk length timed out');
|
3047 |
+
return false;
|
3048 |
+
}
|
3049 |
+
$content_length = hexdec(trim($tmp));
|
3050 |
+
$this->debug("chunk length $content_length");
|
3051 |
+
}
|
3052 |
+
$strlen = 0;
|
3053 |
+
while (($strlen < $content_length) && (!feof($this->fp))) {
|
3054 |
+
$readlen = min(8192, $content_length - $strlen);
|
3055 |
+
$tmp = fread($this->fp, $readlen);
|
3056 |
+
$tmplen = strlen($tmp);
|
3057 |
+
$this->debug("read buffer of $tmplen bytes");
|
3058 |
+
if (($tmplen == 0) && (!feof($this->fp))) {
|
3059 |
+
$this->incoming_payload = $data;
|
3060 |
+
$this->debug('socket read of body timed out after length ' . strlen($data));
|
3061 |
+
$this->debug("read before timeout:\n" . $data);
|
3062 |
+
$this->setError('socket read of body timed out');
|
3063 |
+
return false;
|
3064 |
+
}
|
3065 |
+
$strlen += $tmplen;
|
3066 |
+
$data .= $tmp;
|
3067 |
+
}
|
3068 |
+
if ($chunked && ($content_length > 0)) {
|
3069 |
+
$tmp = fgets($this->fp, 256);
|
3070 |
+
$tmplen = strlen($tmp);
|
3071 |
+
$this->debug("read chunk terminator of $tmplen bytes");
|
3072 |
+
if ($tmplen == 0) {
|
3073 |
+
$this->incoming_payload = $data;
|
3074 |
+
$this->debug('socket read of chunk terminator timed out after length ' . strlen($data));
|
3075 |
+
$this->debug("read before timeout:\n" . $data);
|
3076 |
+
$this->setError('socket read of chunk terminator timed out');
|
3077 |
+
return false;
|
3078 |
+
}
|
3079 |
+
}
|
3080 |
+
} while ($chunked && ($content_length > 0) && (!feof($this->fp)));
|
3081 |
+
if (feof($this->fp)) {
|
3082 |
+
$this->debug('read to EOF');
|
3083 |
+
}
|
3084 |
+
$this->debug('read body of length ' . strlen($data));
|
3085 |
+
$this->incoming_payload .= $data;
|
3086 |
+
$this->debug('received a total of '.strlen($this->incoming_payload).' bytes of data from server');
|
3087 |
+
|
3088 |
+
// close filepointer
|
3089 |
+
if(
|
3090 |
+
(isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') ||
|
3091 |
+
(! $this->persistentConnection) || feof($this->fp)){
|
3092 |
+
fclose($this->fp);
|
3093 |
+
$this->fp = false;
|
3094 |
+
$this->debug('closed socket');
|
3095 |
+
}
|
3096 |
+
|
3097 |
+
// connection was closed unexpectedly
|
3098 |
+
if($this->incoming_payload == ''){
|
3099 |
+
$this->setError('no response from server');
|
3100 |
+
return false;
|
3101 |
+
}
|
3102 |
+
|
3103 |
+
// decode transfer-encoding
|
3104 |
+
// if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){
|
3105 |
+
// if(!$data = $this->decodeChunked($data, $lb)){
|
3106 |
+
// $this->setError('Decoding of chunked data failed');
|
3107 |
+
// return false;
|
3108 |
+
// }
|
3109 |
+
//print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";
|
3110 |
+
// set decoded payload
|
3111 |
+
// $this->incoming_payload = $header_data.$lb.$lb.$data;
|
3112 |
+
// }
|
3113 |
+
|
3114 |
+
} else if ($this->io_method() == 'curl') {
|
3115 |
+
// send and receive
|
3116 |
+
$this->debug('send and receive with cURL');
|
3117 |
+
$this->incoming_payload = curl_exec($this->ch);
|
3118 |
+
$data = $this->incoming_payload;
|
3119 |
+
|
3120 |
+
$cErr = curl_error($this->ch);
|
3121 |
+
if ($cErr != '') {
|
3122 |
+
$err = 'cURL ERROR: '.curl_errno($this->ch).': '.$cErr.'<br>';
|
3123 |
+
// TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE
|
3124 |
+
foreach(curl_getinfo($this->ch) as $k => $v){
|
3125 |
+
$err .= "$k: $v<br>";
|
3126 |
+
}
|
3127 |
+
$this->debug($err);
|
3128 |
+
$this->setError($err);
|
3129 |
+
curl_close($this->ch);
|
3130 |
+
return false;
|
3131 |
+
} else {
|
3132 |
+
//echo '<pre>';
|
3133 |
+
//var_dump(curl_getinfo($this->ch));
|
3134 |
+
//echo '</pre>';
|
3135 |
+
}
|
3136 |
+
// close curl
|
3137 |
+
$this->debug('No cURL error, closing cURL');
|
3138 |
+
curl_close($this->ch);
|
3139 |
+
|
3140 |
+
// try removing skippable headers
|
3141 |
+
$savedata = $data;
|
3142 |
+
while ($this->isSkippableCurlHeader($data)) {
|
3143 |
+
$this->debug("Found HTTP header to skip");
|
3144 |
+
if ($pos = strpos($data,"\r\n\r\n")) {
|
3145 |
+
$data = ltrim(substr($data,$pos));
|
3146 |
+
} elseif($pos = strpos($data,"\n\n") ) {
|
3147 |
+
$data = ltrim(substr($data,$pos));
|
3148 |
+
}
|
3149 |
+
}
|
3150 |
+
|
3151 |
+
if ($data == '') {
|
3152 |
+
// have nothing left; just remove 100 header(s)
|
3153 |
+
$data = $savedata;
|
3154 |
+
while (preg_match('/^HTTP\/1.1 100/',$data)) {
|
3155 |
+
if ($pos = strpos($data,"\r\n\r\n")) {
|
3156 |
+
$data = ltrim(substr($data,$pos));
|
3157 |
+
} elseif($pos = strpos($data,"\n\n") ) {
|
3158 |
+
$data = ltrim(substr($data,$pos));
|
3159 |
+
}
|
3160 |
+
}
|
3161 |
+
}
|
3162 |
+
|
3163 |
+
// separate content from HTTP headers
|
3164 |
+
if ($pos = strpos($data,"\r\n\r\n")) {
|
3165 |
+
$lb = "\r\n";
|
3166 |
+
} elseif( $pos = strpos($data,"\n\n")) {
|
3167 |
+
$lb = "\n";
|
3168 |
+
} else {
|
3169 |
+
$this->debug('no proper separation of headers and document');
|
3170 |
+
$this->setError('no proper separation of headers and document');
|
3171 |
+
return false;
|
3172 |
+
}
|
3173 |
+
$header_data = trim(substr($data,0,$pos));
|
3174 |
+
$header_array = explode($lb,$header_data);
|
3175 |
+
$data = ltrim(substr($data,$pos));
|
3176 |
+
$this->debug('found proper separation of headers and document');
|
3177 |
+
$this->debug('cleaned data, stringlen: '.strlen($data));
|
3178 |
+
// clean headers
|
3179 |
+
foreach ($header_array as $header_line) {
|
3180 |
+
$arr = explode(':',$header_line,2);
|
3181 |
+
if(count($arr) > 1){
|
3182 |
+
$header_name = strtolower(trim($arr[0]));
|
3183 |
+
$this->incoming_headers[$header_name] = trim($arr[1]);
|
3184 |
+
if ($header_name == 'set-cookie') {
|
3185 |
+
// TODO: allow multiple cookies from parseCookie
|
3186 |
+
$cookie = $this->parseCookie(trim($arr[1]));
|
3187 |
+
if ($cookie) {
|
3188 |
+
$this->incoming_cookies[] = $cookie;
|
3189 |
+
$this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
|
3190 |
+
} else {
|
3191 |
+
$this->debug('did not find cookie in ' . trim($arr[1]));
|
3192 |
+
}
|
3193 |
+
}
|
3194 |
+
} else if (isset($header_name)) {
|
3195 |
+
// append continuation line to previous header
|
3196 |
+
$this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
|
3197 |
+
}
|
3198 |
+
}
|
3199 |
+
}
|
3200 |
+
|
3201 |
+
$this->response_status_line = $header_array[0];
|
3202 |
+
$arr = explode(' ', $this->response_status_line, 3);
|
3203 |
+
$http_version = $arr[0];
|
3204 |
+
$http_status = intval($arr[1]);
|
3205 |
+
$http_reason = count($arr) > 2 ? $arr[2] : '';
|
3206 |
+
|
3207 |
+
// see if we need to resend the request with http digest authentication
|
3208 |
+
if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) {
|
3209 |
+
$this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']);
|
3210 |
+
$this->setURL($this->incoming_headers['location']);
|
3211 |
+
$this->tryagain = true;
|
3212 |
+
return false;
|
3213 |
+
}
|
3214 |
+
|
3215 |
+
// see if we need to resend the request with http digest authentication
|
3216 |
+
if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) {
|
3217 |
+
$this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']);
|
3218 |
+
if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) {
|
3219 |
+
$this->debug('Server wants digest authentication');
|
3220 |
+
// remove "Digest " from our elements
|
3221 |
+
$digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);
|
3222 |
+
|
3223 |
+
// parse elements into array
|
3224 |
+
$digestElements = explode(',', $digestString);
|
3225 |
+
foreach ($digestElements as $val) {
|
3226 |
+
$tempElement = explode('=', trim($val), 2);
|
3227 |
+
$digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);
|
3228 |
+
}
|
3229 |
+
|
3230 |
+
// should have (at least) qop, realm, nonce
|
3231 |
+
if (isset($digestRequest['nonce'])) {
|
3232 |
+
$this->setCredentials($this->username, $this->password, 'digest', $digestRequest);
|
3233 |
+
$this->tryagain = true;
|
3234 |
+
return false;
|
3235 |
+
}
|
3236 |
+
}
|
3237 |
+
$this->debug('HTTP authentication failed');
|
3238 |
+
$this->setError('HTTP authentication failed');
|
3239 |
+
return false;
|
3240 |
+
}
|
3241 |
+
|
3242 |
+
if (
|
3243 |
+
($http_status >= 300 && $http_status <= 307) ||
|
3244 |
+
($http_status >= 400 && $http_status <= 417) ||
|
3245 |
+
($http_status >= 501 && $http_status <= 505)
|
3246 |
+
) {
|
3247 |
+
$this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");
|
3248 |
+
return false;
|
3249 |
+
}
|
3250 |
+
|
3251 |
+
// decode content-encoding
|
3252 |
+
if(isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != ''){
|
3253 |
+
if(strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip'){
|
3254 |
+
// if decoding works, use it. else assume data wasn't gzencoded
|
3255 |
+
if(function_exists('gzinflate')){
|
3256 |
+
//$timer->setMarker('starting decoding of gzip/deflated content');
|
3257 |
+
// IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress)
|
3258 |
+
// this means there are no Zlib headers, although there should be
|
3259 |
+
$this->debug('The gzinflate function exists');
|
3260 |
+
$datalen = strlen($data);
|
3261 |
+
if ($this->incoming_headers['content-encoding'] == 'deflate') {
|
3262 |
+
if ($degzdata = @gzinflate($data)) {
|
3263 |
+
$data = $degzdata;
|
3264 |
+
$this->debug('The payload has been inflated to ' . strlen($data) . ' bytes');
|
3265 |
+
if (strlen($data) < $datalen) {
|
3266 |
+
// test for the case that the payload has been compressed twice
|
3267 |
+
$this->debug('The inflated payload is smaller than the gzipped one; try again');
|
3268 |
+
if ($degzdata = @gzinflate($data)) {
|
3269 |
+
$data = $degzdata;
|
3270 |
+
$this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes');
|
3271 |
+
}
|
3272 |
+
}
|
3273 |
+
} else {
|
3274 |
+
$this->debug('Error using gzinflate to inflate the payload');
|
3275 |
+
$this->setError('Error using gzinflate to inflate the payload');
|
3276 |
+
}
|
3277 |
+
} elseif ($this->incoming_headers['content-encoding'] == 'gzip') {
|
3278 |
+
if ($degzdata = @gzinflate(substr($data, 10))) { // do our best
|
3279 |
+
$data = $degzdata;
|
3280 |
+
$this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes');
|
3281 |
+
if (strlen($data) < $datalen) {
|
3282 |
+
// test for the case that the payload has been compressed twice
|
3283 |
+
$this->debug('The un-gzipped payload is smaller than the gzipped one; try again');
|
3284 |
+
if ($degzdata = @gzinflate(substr($data, 10))) {
|
3285 |
+
$data = $degzdata;
|
3286 |
+
$this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes');
|
3287 |
+
}
|
3288 |
+
}
|
3289 |
+
} else {
|
3290 |
+
$this->debug('Error using gzinflate to un-gzip the payload');
|
3291 |
+
$this->setError('Error using gzinflate to un-gzip the payload');
|
3292 |
+
}
|
3293 |
+
}
|
3294 |
+
//$timer->setMarker('finished decoding of gzip/deflated content');
|
3295 |
+
//print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";
|
3296 |
+
// set decoded payload
|
3297 |
+
$this->incoming_payload = $header_data.$lb.$lb.$data;
|
3298 |
+
} else {
|
3299 |
+
$this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
|
3300 |
+
$this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
|
3301 |
+
}
|
3302 |
+
} else {
|
3303 |
+
$this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
|
3304 |
+
$this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
|
3305 |
+
}
|
3306 |
+
} else {
|
3307 |
+
$this->debug('No Content-Encoding header');
|
3308 |
+
}
|
3309 |
+
|
3310 |
+
if(strlen($data) == 0){
|
3311 |
+
$this->debug('no data after headers!');
|
3312 |
+
$this->setError('no data present after HTTP headers');
|
3313 |
+
return false;
|
3314 |
+
}
|
3315 |
+
|
3316 |
+
return $data;
|
3317 |
+
}
|
3318 |
+
|
3319 |
+
/**
|
3320 |
+
* sets the content-type for the SOAP message to be sent
|
3321 |
+
*
|
3322 |
+
* @param string $type the content type, MIME style
|
3323 |
+
* @param mixed $charset character set used for encoding (or false)
|
3324 |
+
* @access public
|
3325 |
+
*/
|
3326 |
+
function setContentType($type, $charset = false) {
|
3327 |
+
$this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
|
3328 |
+
}
|
3329 |
+
|
3330 |
+
/**
|
3331 |
+
* specifies that an HTTP persistent connection should be used
|
3332 |
+
*
|
3333 |
+
* @return boolean whether the request was honored by this method.
|
3334 |
+
* @access public
|
3335 |
+
*/
|
3336 |
+
function usePersistentConnection(){
|
3337 |
+
if (isset($this->outgoing_headers['Accept-Encoding'])) {
|
3338 |
+
return false;
|
3339 |
+
}
|
3340 |
+
$this->protocol_version = '1.1';
|
3341 |
+
$this->persistentConnection = true;
|
3342 |
+
$this->setHeader('Connection', 'Keep-Alive');
|
3343 |
+
return true;
|
3344 |
+
}
|
3345 |
+
|
3346 |
+
/**
|
3347 |
+
* parse an incoming Cookie into it's parts
|
3348 |
+
*
|
3349 |
+
* @param string $cookie_str content of cookie
|
3350 |
+
* @return array with data of that cookie
|
3351 |
+
* @access private
|
3352 |
+
*/
|
3353 |
+
/*
|
3354 |
+
* TODO: allow a Set-Cookie string to be parsed into multiple cookies
|
3355 |
+
*/
|
3356 |
+
function parseCookie($cookie_str) {
|
3357 |
+
$cookie_str = str_replace('; ', ';', $cookie_str) . ';';
|
3358 |
+
$data = preg_split('/;/', $cookie_str);
|
3359 |
+
$value_str = $data[0];
|
3360 |
+
|
3361 |
+
$cookie_param = 'domain=';
|
3362 |
+
$start = strpos($cookie_str, $cookie_param);
|
3363 |
+
if ($start > 0) {
|
3364 |
+
$domain = substr($cookie_str, $start + strlen($cookie_param));
|
3365 |
+
$domain = substr($domain, 0, strpos($domain, ';'));
|
3366 |
+
} else {
|
3367 |
+
$domain = '';
|
3368 |
+
}
|
3369 |
+
|
3370 |
+
$cookie_param = 'expires=';
|
3371 |
+
$start = strpos($cookie_str, $cookie_param);
|
3372 |
+
if ($start > 0) {
|
3373 |
+
$expires = substr($cookie_str, $start + strlen($cookie_param));
|
3374 |
+
$expires = substr($expires, 0, strpos($expires, ';'));
|
3375 |
+
} else {
|
3376 |
+
$expires = '';
|
3377 |
+
}
|
3378 |
+
|
3379 |
+
$cookie_param = 'path=';
|
3380 |
+
$start = strpos($cookie_str, $cookie_param);
|
3381 |
+
if ( $start > 0 ) {
|
3382 |
+
$path = substr($cookie_str, $start + strlen($cookie_param));
|
3383 |
+
$path = substr($path, 0, strpos($path, ';'));
|
3384 |
+
} else {
|
3385 |
+
$path = '/';
|
3386 |
+
}
|
3387 |
+
|
3388 |
+
$cookie_param = ';secure;';
|
3389 |
+
if (strpos($cookie_str, $cookie_param) !== FALSE) {
|
3390 |
+
$secure = true;
|
3391 |
+
} else {
|
3392 |
+
$secure = false;
|
3393 |
+
}
|
3394 |
+
|
3395 |
+
$sep_pos = strpos($value_str, '=');
|
3396 |
+
|
3397 |
+
if ($sep_pos) {
|
3398 |
+
$name = substr($value_str, 0, $sep_pos);
|
3399 |
+
$value = substr($value_str, $sep_pos + 1);
|
3400 |
+
$cookie= array( 'name' => $name,
|
3401 |
+
'value' => $value,
|
3402 |
+
'domain' => $domain,
|
3403 |
+
'path' => $path,
|
3404 |
+
'expires' => $expires,
|
3405 |
+
'secure' => $secure
|
3406 |
+
);
|
3407 |
+
return $cookie;
|
3408 |
+
}
|
3409 |
+
return false;
|
3410 |
+
}
|
3411 |
+
|
3412 |
+
/**
|
3413 |
+
* sort out cookies for the current request
|
3414 |
+
*
|
3415 |
+
* @param array $cookies array with all cookies
|
3416 |
+
* @param boolean $secure is the send-content secure or not?
|
3417 |
+
* @return string for Cookie-HTTP-Header
|
3418 |
+
* @access private
|
3419 |
+
*/
|
3420 |
+
function getCookiesForRequest($cookies, $secure=false) {
|
3421 |
+
$cookie_str = '';
|
3422 |
+
if ((! is_null($cookies)) && (is_array($cookies))) {
|
3423 |
+
foreach ($cookies as $cookie) {
|
3424 |
+
if (! is_array($cookie)) {
|
3425 |
+
continue;
|
3426 |
+
}
|
3427 |
+
$this->debug("check cookie for validity: ".$cookie['name'].'='.$cookie['value']);
|
3428 |
+
if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
|
3429 |
+
if (strtotime($cookie['expires']) <= time()) {
|
3430 |
+
$this->debug('cookie has expired');
|
3431 |
+
continue;
|
3432 |
+
}
|
3433 |
+
}
|
3434 |
+
if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) {
|
3435 |
+
$domain = preg_quote($cookie['domain']);
|
3436 |
+
if (! preg_match("'.*$domain$'i", $this->host)) {
|
3437 |
+
$this->debug('cookie has different domain');
|
3438 |
+
continue;
|
3439 |
+
}
|
3440 |
+
}
|
3441 |
+
if ((isset($cookie['path'])) && (! empty($cookie['path']))) {
|
3442 |
+
$path = preg_quote($cookie['path']);
|
3443 |
+
if (! preg_match("'^$path.*'i", $this->path)) {
|
3444 |
+
$this->debug('cookie is for a different path');
|
3445 |
+
continue;
|
3446 |
+
}
|
3447 |
+
}
|
3448 |
+
if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) {
|
3449 |
+
$this->debug('cookie is secure, transport is not');
|
3450 |
+
continue;
|
3451 |
+
}
|
3452 |
+
$cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';
|
3453 |
+
$this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']);
|
3454 |
+
}
|
3455 |
+
}
|
3456 |
+
return $cookie_str;
|
3457 |
+
}
|
3458 |
+
}
|
3459 |
+
|
3460 |
+
?><?php
|
3461 |
+
|
3462 |
+
|
3463 |
+
|
3464 |
+
/**
|
3465 |
+
*
|
3466 |
+
* nusoap_server allows the user to create a SOAP server
|
3467 |
+
* that is capable of receiving messages and returning responses
|
3468 |
+
*
|
3469 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
3470 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
3471 |
+
* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
|
3472 |
+
* @access public
|
3473 |
+
*/
|
3474 |
+
class nusoap_server extends nusoap_base {
|
3475 |
+
/**
|
3476 |
+
* HTTP headers of request
|
3477 |
+
* @var array
|
3478 |
+
* @access private
|
3479 |
+
*/
|
3480 |
+
var $headers = array();
|
3481 |
+
/**
|
3482 |
+
* HTTP request
|
3483 |
+
* @var string
|
3484 |
+
* @access private
|
3485 |
+
*/
|
3486 |
+
var $request = '';
|
3487 |
+
/**
|
3488 |
+
* SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text)
|
3489 |
+
* @var string
|
3490 |
+
* @access public
|
3491 |
+
*/
|
3492 |
+
var $requestHeaders = '';
|
3493 |
+
/**
|
3494 |
+
* SOAP Headers from request (parsed)
|
3495 |
+
* @var mixed
|
3496 |
+
* @access public
|
3497 |
+
*/
|
3498 |
+
var $requestHeader = NULL;
|
3499 |
+
/**
|
3500 |
+
* SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text)
|
3501 |
+
* @var string
|
3502 |
+
* @access public
|
3503 |
+
*/
|
3504 |
+
var $document = '';
|
3505 |
+
/**
|
3506 |
+
* SOAP payload for request (text)
|
3507 |
+
* @var string
|
3508 |
+
* @access public
|
3509 |
+
*/
|
3510 |
+
var $requestSOAP = '';
|
3511 |
+
/**
|
3512 |
+
* requested method namespace URI
|
3513 |
+
* @var string
|
3514 |
+
* @access private
|
3515 |
+
*/
|
3516 |
+
var $methodURI = '';
|
3517 |
+
/**
|
3518 |
+
* name of method requested
|
3519 |
+
* @var string
|
3520 |
+
* @access private
|
3521 |
+
*/
|
3522 |
+
var $methodname = '';
|
3523 |
+
/**
|
3524 |
+
* method parameters from request
|
3525 |
+
* @var array
|
3526 |
+
* @access private
|
3527 |
+
*/
|
3528 |
+
var $methodparams = array();
|
3529 |
+
/**
|
3530 |
+
* SOAP Action from request
|
3531 |
+
* @var string
|
3532 |
+
* @access private
|
3533 |
+
*/
|
3534 |
+
var $SOAPAction = '';
|
3535 |
+
/**
|
3536 |
+
* character set encoding of incoming (request) messages
|
3537 |
+
* @var string
|
3538 |
+
* @access public
|
3539 |
+
*/
|
3540 |
+
var $xml_encoding = '';
|
3541 |
+
/**
|
3542 |
+
* toggles whether the parser decodes element content w/ utf8_decode()
|
3543 |
+
* @var boolean
|
3544 |
+
* @access public
|
3545 |
+
*/
|
3546 |
+
var $decode_utf8 = true;
|
3547 |
+
|
3548 |
+
/**
|
3549 |
+
* HTTP headers of response
|
3550 |
+
* @var array
|
3551 |
+
* @access public
|
3552 |
+
*/
|
3553 |
+
var $outgoing_headers = array();
|
3554 |
+
/**
|
3555 |
+
* HTTP response
|
3556 |
+
* @var string
|
3557 |
+
* @access private
|
3558 |
+
*/
|
3559 |
+
var $response = '';
|
3560 |
+
/**
|
3561 |
+
* SOAP headers for response (text or array of soapval or associative array)
|
3562 |
+
* @var mixed
|
3563 |
+
* @access public
|
3564 |
+
*/
|
3565 |
+
var $responseHeaders = '';
|
3566 |
+
/**
|
3567 |
+
* SOAP payload for response (text)
|
3568 |
+
* @var string
|
3569 |
+
* @access private
|
3570 |
+
*/
|
3571 |
+
var $responseSOAP = '';
|
3572 |
+
/**
|
3573 |
+
* method return value to place in response
|
3574 |
+
* @var mixed
|
3575 |
+
* @access private
|
3576 |
+
*/
|
3577 |
+
var $methodreturn = false;
|
3578 |
+
/**
|
3579 |
+
* whether $methodreturn is a string of literal XML
|
3580 |
+
* @var boolean
|
3581 |
+
* @access public
|
3582 |
+
*/
|
3583 |
+
var $methodreturnisliteralxml = false;
|
3584 |
+
/**
|
3585 |
+
* SOAP fault for response (or false)
|
3586 |
+
* @var mixed
|
3587 |
+
* @access private
|
3588 |
+
*/
|
3589 |
+
var $fault = false;
|
3590 |
+
/**
|
3591 |
+
* text indication of result (for debugging)
|
3592 |
+
* @var string
|
3593 |
+
* @access private
|
3594 |
+
*/
|
3595 |
+
var $result = 'successful';
|
3596 |
+
|
3597 |
+
/**
|
3598 |
+
* assoc array of operations => opData; operations are added by the register()
|
3599 |
+
* method or by parsing an external WSDL definition
|
3600 |
+
* @var array
|
3601 |
+
* @access private
|
3602 |
+
*/
|
3603 |
+
var $operations = array();
|
3604 |
+
/**
|
3605 |
+
* wsdl instance (if one)
|
3606 |
+
* @var mixed
|
3607 |
+
* @access private
|
3608 |
+
*/
|
3609 |
+
var $wsdl = false;
|
3610 |
+
/**
|
3611 |
+
* URL for WSDL (if one)
|
3612 |
+
* @var mixed
|
3613 |
+
* @access private
|
3614 |
+
*/
|
3615 |
+
var $externalWSDLURL = false;
|
3616 |
+
/**
|
3617 |
+
* whether to append debug to response as XML comment
|
3618 |
+
* @var boolean
|
3619 |
+
* @access public
|
3620 |
+
*/
|
3621 |
+
var $debug_flag = false;
|
3622 |
+
|
3623 |
+
|
3624 |
+
/**
|
3625 |
+
* constructor
|
3626 |
+
* the optional parameter is a path to a WSDL file that you'd like to bind the server instance to.
|
3627 |
+
*
|
3628 |
+
* @param mixed $wsdl file path or URL (string), or wsdl instance (object)
|
3629 |
+
* @access public
|
3630 |
+
*/
|
3631 |
+
function nusoap_server($wsdl=false){
|
3632 |
+
parent::nusoap_base();
|
3633 |
+
// turn on debugging?
|
3634 |
+
global $debug;
|
3635 |
+
global $HTTP_SERVER_VARS;
|
3636 |
+
|
3637 |
+
if (isset($_SERVER)) {
|
3638 |
+
$this->debug("_SERVER is defined:");
|
3639 |
+
$this->appendDebug($this->varDump($_SERVER));
|
3640 |
+
} elseif (isset($HTTP_SERVER_VARS)) {
|
3641 |
+
$this->debug("HTTP_SERVER_VARS is defined:");
|
3642 |
+
$this->appendDebug($this->varDump($HTTP_SERVER_VARS));
|
3643 |
+
} else {
|
3644 |
+
$this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
|
3645 |
+
}
|
3646 |
+
|
3647 |
+
if (isset($debug)) {
|
3648 |
+
$this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
|
3649 |
+
$this->debug_flag = $debug;
|
3650 |
+
} elseif (isset($_SERVER['QUERY_STRING'])) {
|
3651 |
+
$qs = explode('&', $_SERVER['QUERY_STRING']);
|
3652 |
+
foreach ($qs as $v) {
|
3653 |
+
if (substr($v, 0, 6) == 'debug=') {
|
3654 |
+
$this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
|
3655 |
+
$this->debug_flag = substr($v, 6);
|
3656 |
+
}
|
3657 |
+
}
|
3658 |
+
} elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
|
3659 |
+
$qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
|
3660 |
+
foreach ($qs as $v) {
|
3661 |
+
if (substr($v, 0, 6) == 'debug=') {
|
3662 |
+
$this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
|
3663 |
+
$this->debug_flag = substr($v, 6);
|
3664 |
+
}
|
3665 |
+
}
|
3666 |
+
}
|
3667 |
+
|
3668 |
+
// wsdl
|
3669 |
+
if($wsdl){
|
3670 |
+
$this->debug("In nusoap_server, WSDL is specified");
|
3671 |
+
if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
|
3672 |
+
$this->wsdl = $wsdl;
|
3673 |
+
$this->externalWSDLURL = $this->wsdl->wsdl;
|
3674 |
+
$this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
|
3675 |
+
} else {
|
3676 |
+
$this->debug('Create wsdl from ' . $wsdl);
|
3677 |
+
$this->wsdl = new wsdl($wsdl);
|
3678 |
+
$this->externalWSDLURL = $wsdl;
|
3679 |
+
}
|
3680 |
+
$this->appendDebug($this->wsdl->getDebug());
|
3681 |
+
$this->wsdl->clearDebug();
|
3682 |
+
if($err = $this->wsdl->getError()){
|
3683 |
+
die('WSDL ERROR: '.$err);
|
3684 |
+
}
|
3685 |
+
}
|
3686 |
+
}
|
3687 |
+
|
3688 |
+
/**
|
3689 |
+
* processes request and returns response
|
3690 |
+
*
|
3691 |
+
* @param string $data usually is the value of $HTTP_RAW_POST_DATA
|
3692 |
+
* @access public
|
3693 |
+
*/
|
3694 |
+
function service($data){
|
3695 |
+
global $HTTP_SERVER_VARS;
|
3696 |
+
|
3697 |
+
if (isset($_SERVER['REQUEST_METHOD'])) {
|
3698 |
+
$rm = $_SERVER['REQUEST_METHOD'];
|
3699 |
+
} elseif (isset($HTTP_SERVER_VARS['REQUEST_METHOD'])) {
|
3700 |
+
$rm = $HTTP_SERVER_VARS['REQUEST_METHOD'];
|
3701 |
+
} else {
|
3702 |
+
$rm = '';
|
3703 |
+
}
|
3704 |
+
|
3705 |
+
if (isset($_SERVER['QUERY_STRING'])) {
|
3706 |
+
$qs = $_SERVER['QUERY_STRING'];
|
3707 |
+
} elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
|
3708 |
+
$qs = $HTTP_SERVER_VARS['QUERY_STRING'];
|
3709 |
+
} else {
|
3710 |
+
$qs = '';
|
3711 |
+
}
|
3712 |
+
$this->debug("In service, request method=$rm query string=$qs strlen(\$data)=" . strlen($data));
|
3713 |
+
|
3714 |
+
if ($rm == 'POST') {
|
3715 |
+
$this->debug("In service, invoke the request");
|
3716 |
+
$this->parse_request($data);
|
3717 |
+
if (! $this->fault) {
|
3718 |
+
$this->invoke_method();
|
3719 |
+
}
|
3720 |
+
if (! $this->fault) {
|
3721 |
+
$this->serialize_return();
|
3722 |
+
}
|
3723 |
+
$this->send_response();
|
3724 |
+
} elseif (preg_match('/wsdl/', $qs) ){
|
3725 |
+
$this->debug("In service, this is a request for WSDL");
|
3726 |
+
if ($this->externalWSDLURL){
|
3727 |
+
if (strpos($this->externalWSDLURL, "http://") !== false) { // assume URL
|
3728 |
+
$this->debug("In service, re-direct for WSDL");
|
3729 |
+
header('Location: '.$this->externalWSDLURL);
|
3730 |
+
} else { // assume file
|
3731 |
+
$this->debug("In service, use file passthru for WSDL");
|
3732 |
+
header("Content-Type: text/xml\r\n");
|
3733 |
+
$pos = strpos($this->externalWSDLURL, "file://");
|
3734 |
+
if ($pos === false) {
|
3735 |
+
$filename = $this->externalWSDLURL;
|
3736 |
+
} else {
|
3737 |
+
$filename = substr($this->externalWSDLURL, $pos + 7);
|
3738 |
+
}
|
3739 |
+
$fp = fopen($this->externalWSDLURL, 'r');
|
3740 |
+
fpassthru($fp);
|
3741 |
+
}
|
3742 |
+
} elseif ($this->wsdl) {
|
3743 |
+
$this->debug("In service, serialize WSDL");
|
3744 |
+
header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
|
3745 |
+
print $this->wsdl->serialize($this->debug_flag);
|
3746 |
+
if ($this->debug_flag) {
|
3747 |
+
$this->debug('wsdl:');
|
3748 |
+
$this->appendDebug($this->varDump($this->wsdl));
|
3749 |
+
print $this->getDebugAsXMLComment();
|
3750 |
+
}
|
3751 |
+
} else {
|
3752 |
+
$this->debug("In service, there is no WSDL");
|
3753 |
+
header("Content-Type: text/html; charset=ISO-8859-1\r\n");
|
3754 |
+
print "This service does not provide WSDL";
|
3755 |
+
}
|
3756 |
+
} elseif ($this->wsdl) {
|
3757 |
+
$this->debug("In service, return Web description");
|
3758 |
+
print $this->wsdl->webDescription();
|
3759 |
+
} else {
|
3760 |
+
$this->debug("In service, no Web description");
|
3761 |
+
header("Content-Type: text/html; charset=ISO-8859-1\r\n");
|
3762 |
+
print "This service does not provide a Web description";
|
3763 |
+
}
|
3764 |
+
}
|
3765 |
+
|
3766 |
+
/**
|
3767 |
+
* parses HTTP request headers.
|
3768 |
+
*
|
3769 |
+
* The following fields are set by this function (when successful)
|
3770 |
+
*
|
3771 |
+
* headers
|
3772 |
+
* request
|
3773 |
+
* xml_encoding
|
3774 |
+
* SOAPAction
|
3775 |
+
*
|
3776 |
+
* @access private
|
3777 |
+
*/
|
3778 |
+
function parse_http_headers() {
|
3779 |
+
global $HTTP_SERVER_VARS;
|
3780 |
+
|
3781 |
+
$this->request = '';
|
3782 |
+
$this->SOAPAction = '';
|
3783 |
+
if(function_exists('getallheaders')){
|
3784 |
+
$this->debug("In parse_http_headers, use getallheaders");
|
3785 |
+
$headers = getallheaders();
|
3786 |
+
foreach($headers as $k=>$v){
|
3787 |
+
$k = strtolower($k);
|
3788 |
+
$this->headers[$k] = $v;
|
3789 |
+
$this->request .= "$k: $v\r\n";
|
3790 |
+
$this->debug("$k: $v");
|
3791 |
+
}
|
3792 |
+
// get SOAPAction header
|
3793 |
+
if(isset($this->headers['soapaction'])){
|
3794 |
+
$this->SOAPAction = str_replace('"','',$this->headers['soapaction']);
|
3795 |
+
}
|
3796 |
+
// get the character encoding of the incoming request
|
3797 |
+
if(isset($this->headers['content-type']) && strpos($this->headers['content-type'],'=')){
|
3798 |
+
$enc = str_replace('"','',substr(strstr($this->headers["content-type"],'='),1));
|
3799 |
+
if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
|
3800 |
+
$this->xml_encoding = strtoupper($enc);
|
3801 |
+
} else {
|
3802 |
+
$this->xml_encoding = 'US-ASCII';
|
3803 |
+
}
|
3804 |
+
} else {
|
3805 |
+
// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
|
3806 |
+
$this->xml_encoding = 'ISO-8859-1';
|
3807 |
+
}
|
3808 |
+
} elseif(isset($_SERVER) && is_array($_SERVER)){
|
3809 |
+
$this->debug("In parse_http_headers, use _SERVER");
|
3810 |
+
foreach ($_SERVER as $k => $v) {
|
3811 |
+
if (substr($k, 0, 5) == 'HTTP_') {
|
3812 |
+
$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
|
3813 |
+
} else {
|
3814 |
+
$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
|
3815 |
+
}
|
3816 |
+
if ($k == 'soapaction') {
|
3817 |
+
// get SOAPAction header
|
3818 |
+
$k = 'SOAPAction';
|
3819 |
+
$v = str_replace('"', '', $v);
|
3820 |
+
$v = str_replace('\\', '', $v);
|
3821 |
+
$this->SOAPAction = $v;
|
3822 |
+
} else if ($k == 'content-type') {
|
3823 |
+
// get the character encoding of the incoming request
|
3824 |
+
if (strpos($v, '=')) {
|
3825 |
+
$enc = substr(strstr($v, '='), 1);
|
3826 |
+
$enc = str_replace('"', '', $enc);
|
3827 |
+
$enc = str_replace('\\', '', $enc);
|
3828 |
+
if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
|
3829 |
+
$this->xml_encoding = strtoupper($enc);
|
3830 |
+
} else {
|
3831 |
+
$this->xml_encoding = 'US-ASCII';
|
3832 |
+
}
|
3833 |
+
} else {
|
3834 |
+
// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
|
3835 |
+
$this->xml_encoding = 'ISO-8859-1';
|
3836 |
+
}
|
3837 |
+
}
|
3838 |
+
$this->headers[$k] = $v;
|
3839 |
+
$this->request .= "$k: $v\r\n";
|
3840 |
+
$this->debug("$k: $v");
|
3841 |
+
}
|
3842 |
+
} elseif (is_array($HTTP_SERVER_VARS)) {
|
3843 |
+
$this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
|
3844 |
+
foreach ($HTTP_SERVER_VARS as $k => $v) {
|
3845 |
+
if (substr($k, 0, 5) == 'HTTP_') {
|
3846 |
+
$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); $k = strtolower(substr($k, 5));
|
3847 |
+
} else {
|
3848 |
+
$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); $k = strtolower($k);
|
3849 |
+
}
|
3850 |
+
if ($k == 'soapaction') {
|
3851 |
+
// get SOAPAction header
|
3852 |
+
$k = 'SOAPAction';
|
3853 |
+
$v = str_replace('"', '', $v);
|
3854 |
+
$v = str_replace('\\', '', $v);
|
3855 |
+
$this->SOAPAction = $v;
|
3856 |
+
} else if ($k == 'content-type') {
|
3857 |
+
// get the character encoding of the incoming request
|
3858 |
+
if (strpos($v, '=')) {
|
3859 |
+
$enc = substr(strstr($v, '='), 1);
|
3860 |
+
$enc = str_replace('"', '', $enc);
|
3861 |
+
$enc = str_replace('\\', '', $enc);
|
3862 |
+
if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
|
3863 |
+
$this->xml_encoding = strtoupper($enc);
|
3864 |
+
} else {
|
3865 |
+
$this->xml_encoding = 'US-ASCII';
|
3866 |
+
}
|
3867 |
+
} else {
|
3868 |
+
// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
|
3869 |
+
$this->xml_encoding = 'ISO-8859-1';
|
3870 |
+
}
|
3871 |
+
}
|
3872 |
+
$this->headers[$k] = $v;
|
3873 |
+
$this->request .= "$k: $v\r\n";
|
3874 |
+
$this->debug("$k: $v");
|
3875 |
+
}
|
3876 |
+
} else {
|
3877 |
+
$this->debug("In parse_http_headers, HTTP headers not accessible");
|
3878 |
+
$this->setError("HTTP headers not accessible");
|
3879 |
+
}
|
3880 |
+
}
|
3881 |
+
|
3882 |
+
/**
|
3883 |
+
* parses a request
|
3884 |
+
*
|
3885 |
+
* The following fields are set by this function (when successful)
|
3886 |
+
*
|
3887 |
+
* headers
|
3888 |
+
* request
|
3889 |
+
* xml_encoding
|
3890 |
+
* SOAPAction
|
3891 |
+
* request
|
3892 |
+
* requestSOAP
|
3893 |
+
* methodURI
|
3894 |
+
* methodname
|
3895 |
+
* methodparams
|
3896 |
+
* requestHeaders
|
3897 |
+
* document
|
3898 |
+
*
|
3899 |
+
* This sets the fault field on error
|
3900 |
+
*
|
3901 |
+
* @param string $data XML string
|
3902 |
+
* @access private
|
3903 |
+
*/
|
3904 |
+
function parse_request($data='') {
|
3905 |
+
$this->debug('entering parse_request()');
|
3906 |
+
$this->parse_http_headers();
|
3907 |
+
$this->debug('got character encoding: '.$this->xml_encoding);
|
3908 |
+
// uncompress if necessary
|
3909 |
+
if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
|
3910 |
+
$this->debug('got content encoding: ' . $this->headers['content-encoding']);
|
3911 |
+
if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
|
3912 |
+
// if decoding works, use it. else assume data wasn't gzencoded
|
3913 |
+
if (function_exists('gzuncompress')) {
|
3914 |
+
if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
|
3915 |
+
$data = $degzdata;
|
3916 |
+
} elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
|
3917 |
+
$data = $degzdata;
|
3918 |
+
} else {
|
3919 |
+
$this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
|
3920 |
+
return;
|
3921 |
+
}
|
3922 |
+
} else {
|
3923 |
+
$this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
|
3924 |
+
return;
|
3925 |
+
}
|
3926 |
+
}
|
3927 |
+
}
|
3928 |
+
$this->request .= "\r\n".$data;
|
3929 |
+
$data = $this->parseRequest($this->headers, $data);
|
3930 |
+
$this->requestSOAP = $data;
|
3931 |
+
$this->debug('leaving parse_request');
|
3932 |
+
}
|
3933 |
+
|
3934 |
+
/**
|
3935 |
+
* invokes a PHP function for the requested SOAP method
|
3936 |
+
*
|
3937 |
+
* The following fields are set by this function (when successful)
|
3938 |
+
*
|
3939 |
+
* methodreturn
|
3940 |
+
*
|
3941 |
+
* Note that the PHP function that is called may also set the following
|
3942 |
+
* fields to affect the response sent to the client
|
3943 |
+
*
|
3944 |
+
* responseHeaders
|
3945 |
+
* outgoing_headers
|
3946 |
+
*
|
3947 |
+
* This sets the fault field on error
|
3948 |
+
*
|
3949 |
+
* @access private
|
3950 |
+
*/
|
3951 |
+
function invoke_method() {
|
3952 |
+
$this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
|
3953 |
+
|
3954 |
+
//
|
3955 |
+
// if you are debugging in this area of the code, your service uses a class to implement methods,
|
3956 |
+
// you use SOAP RPC, and the client is .NET, please be aware of the following...
|
3957 |
+
// when the .NET wsdl.exe utility generates a proxy, it will remove the '.' or '..' from the
|
3958 |
+
// method name. that is fine for naming the .NET methods. it is not fine for properly constructing
|
3959 |
+
// the XML request and reading the XML response. you need to add the RequestElementName and
|
3960 |
+
// ResponseElementName to the System.Web.Services.Protocols.SoapRpcMethodAttribute that wsdl.exe
|
3961 |
+
// generates for the method. these parameters are used to specify the correct XML element names
|
3962 |
+
// for .NET to use, i.e. the names with the '.' in them.
|
3963 |
+
//
|
3964 |
+
$orig_methodname = $this->methodname;
|
3965 |
+
if ($this->wsdl) {
|
3966 |
+
if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
|
3967 |
+
$this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
|
3968 |
+
$this->appendDebug('opData=' . $this->varDump($this->opData));
|
3969 |
+
} elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
|
3970 |
+
// Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
|
3971 |
+
$this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
|
3972 |
+
$this->appendDebug('opData=' . $this->varDump($this->opData));
|
3973 |
+
$this->methodname = $this->opData['name'];
|
3974 |
+
} else {
|
3975 |
+
$this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
|
3976 |
+
$this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
|
3977 |
+
return;
|
3978 |
+
}
|
3979 |
+
} else {
|
3980 |
+
$this->debug('in invoke_method, no WSDL to validate method');
|
3981 |
+
}
|
3982 |
+
|
3983 |
+
// if a . is present in $this->methodname, we see if there is a class in scope,
|
3984 |
+
// which could be referred to. We will also distinguish between two deliminators,
|
3985 |
+
// to allow methods to be called a the class or an instance
|
3986 |
+
if (strpos($this->methodname, '..') > 0) {
|
3987 |
+
$delim = '..';
|
3988 |
+
} else if (strpos($this->methodname, '.') > 0) {
|
3989 |
+
$delim = '.';
|
3990 |
+
} else {
|
3991 |
+
$delim = '';
|
3992 |
+
}
|
3993 |
+
$this->debug("in invoke_method, delim=$delim");
|
3994 |
+
|
3995 |
+
$class = '';
|
3996 |
+
$method = '';
|
3997 |
+
if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1) {
|
3998 |
+
$try_class = substr($this->methodname, 0, strpos($this->methodname, $delim));
|
3999 |
+
if (class_exists($try_class)) {
|
4000 |
+
// get the class and method name
|
4001 |
+
$class = $try_class;
|
4002 |
+
$method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
|
4003 |
+
$this->debug("in invoke_method, class=$class method=$method delim=$delim");
|
4004 |
+
} else {
|
4005 |
+
$this->debug("in invoke_method, class=$try_class not found");
|
4006 |
+
}
|
4007 |
+
} else {
|
4008 |
+
$try_class = '';
|
4009 |
+
$this->debug("in invoke_method, no class to try");
|
4010 |
+
}
|
4011 |
+
|
4012 |
+
// does method exist?
|
4013 |
+
if ($class == '') {
|
4014 |
+
if (!function_exists($this->methodname)) {
|
4015 |
+
$this->debug("in invoke_method, function '$this->methodname' not found!");
|
4016 |
+
$this->result = 'fault: method not found';
|
4017 |
+
$this->fault('SOAP-ENV:Client',"method '$this->methodname'('$orig_methodname') not defined in service('$try_class' '$delim')");
|
4018 |
+
return;
|
4019 |
+
}
|
4020 |
+
} else {
|
4021 |
+
$method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
|
4022 |
+
if (!in_array($method_to_compare, get_class_methods($class))) {
|
4023 |
+
$this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
|
4024 |
+
$this->result = 'fault: method not found';
|
4025 |
+
$this->fault('SOAP-ENV:Client',"method '$this->methodname'/'$method_to_compare'('$orig_methodname') not defined in service/'$class'('$try_class' '$delim')");
|
4026 |
+
return;
|
4027 |
+
}
|
4028 |
+
}
|
4029 |
+
|
4030 |
+
// evaluate message, getting back parameters
|
4031 |
+
// verify that request parameters match the method's signature
|
4032 |
+
if(! $this->verify_method($this->methodname,$this->methodparams)){
|
4033 |
+
// debug
|
4034 |
+
$this->debug('ERROR: request not verified against method signature');
|
4035 |
+
$this->result = 'fault: request failed validation against method signature';
|
4036 |
+
// return fault
|
4037 |
+
$this->fault('SOAP-ENV:Client',"Operation '$this->methodname' not defined in service.");
|
4038 |
+
return;
|
4039 |
+
}
|
4040 |
+
|
4041 |
+
// if there are parameters to pass
|
4042 |
+
$this->debug('in invoke_method, params:');
|
4043 |
+
$this->appendDebug($this->varDump($this->methodparams));
|
4044 |
+
$this->debug("in invoke_method, calling '$this->methodname'");
|
4045 |
+
if (!function_exists('call_user_func_array')) {
|
4046 |
+
if ($class == '') {
|
4047 |
+
$this->debug('in invoke_method, calling function using eval()');
|
4048 |
+
$funcCall = "\$this->methodreturn = $this->methodname(";
|
4049 |
+
} else {
|
4050 |
+
if ($delim == '..') {
|
4051 |
+
$this->debug('in invoke_method, calling class method using eval()');
|
4052 |
+
$funcCall = "\$this->methodreturn = ".$class."::".$method."(";
|
4053 |
+
} else {
|
4054 |
+
$this->debug('in invoke_method, calling instance method using eval()');
|
4055 |
+
// generate unique instance name
|
4056 |
+
$instname = "\$inst_".time();
|
4057 |
+
$funcCall = $instname." = new ".$class."(); ";
|
4058 |
+
$funcCall .= "\$this->methodreturn = ".$instname."->".$method."(";
|
4059 |
+
}
|
4060 |
+
}
|
4061 |
+
if ($this->methodparams) {
|
4062 |
+
foreach ($this->methodparams as $param) {
|
4063 |
+
if (is_array($param) || is_object($param)) {
|
4064 |
+
$this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
|
4065 |
+
return;
|
4066 |
+
}
|
4067 |
+
$funcCall .= "\"$param\",";
|
4068 |
+
}
|
4069 |
+
$funcCall = substr($funcCall, 0, -1);
|
4070 |
+
}
|
4071 |
+
$funcCall .= ');';
|
4072 |
+
$this->debug('in invoke_method, function call: '.$funcCall);
|
4073 |
+
@eval($funcCall);
|
4074 |
+
} else {
|
4075 |
+
if ($class == '') {
|
4076 |
+
$this->debug('in invoke_method, calling function using call_user_func_array()');
|
4077 |
+
$call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array()
|
4078 |
+
} elseif ($delim == '..') {
|
4079 |
+
$this->debug('in invoke_method, calling class method using call_user_func_array()');
|
4080 |
+
$call_arg = array ($class, $method);
|
4081 |
+
} else {
|
4082 |
+
$this->debug('in invoke_method, calling instance method using call_user_func_array()');
|
4083 |
+
$instance = new $class ();
|
4084 |
+
$call_arg = array(&$instance, $method);
|
4085 |
+
}
|
4086 |
+
if (is_array($this->methodparams)) {
|
4087 |
+
$this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
|
4088 |
+
} else {
|
4089 |
+
$this->methodreturn = call_user_func_array($call_arg, array());
|
4090 |
+
}
|
4091 |
+
}
|
4092 |
+
$this->debug('in invoke_method, methodreturn:');
|
4093 |
+
$this->appendDebug($this->varDump($this->methodreturn));
|
4094 |
+
$this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn));
|
4095 |
+
}
|
4096 |
+
|
4097 |
+
/**
|
4098 |
+
* serializes the return value from a PHP function into a full SOAP Envelope
|
4099 |
+
*
|
4100 |
+
* The following fields are set by this function (when successful)
|
4101 |
+
*
|
4102 |
+
* responseSOAP
|
4103 |
+
*
|
4104 |
+
* This sets the fault field on error
|
4105 |
+
*
|
4106 |
+
* @access private
|
4107 |
+
*/
|
4108 |
+
function serialize_return() {
|
4109 |
+
$this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
|
4110 |
+
// if fault
|
4111 |
+
if (isset($this->methodreturn) && is_object($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) {
|
4112 |
+
$this->debug('got a fault object from method');
|
4113 |
+
$this->fault = $this->methodreturn;
|
4114 |
+
return;
|
4115 |
+
} elseif ($this->methodreturnisliteralxml) {
|
4116 |
+
$return_val = $this->methodreturn;
|
4117 |
+
// returned value(s)
|
4118 |
+
} else {
|
4119 |
+
$this->debug('got a(n) '.gettype($this->methodreturn).' from method');
|
4120 |
+
$this->debug('serializing return value');
|
4121 |
+
if($this->wsdl){
|
4122 |
+
if (sizeof($this->opData['output']['parts']) > 1) {
|
4123 |
+
$this->debug('more than one output part, so use the method return unchanged');
|
4124 |
+
$opParams = $this->methodreturn;
|
4125 |
+
} elseif (sizeof($this->opData['output']['parts']) == 1) {
|
4126 |
+
$this->debug('exactly one output part, so wrap the method return in a simple array');
|
4127 |
+
// TODO: verify that it is not already wrapped!
|
4128 |
+
//foreach ($this->opData['output']['parts'] as $name => $type) {
|
4129 |
+
// $this->debug('wrap in element named ' . $name);
|
4130 |
+
//}
|
4131 |
+
$opParams = array($this->methodreturn);
|
4132 |
+
}
|
4133 |
+
$return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams);
|
4134 |
+
$this->appendDebug($this->wsdl->getDebug());
|
4135 |
+
$this->wsdl->clearDebug();
|
4136 |
+
if($errstr = $this->wsdl->getError()){
|
4137 |
+
$this->debug('got wsdl error: '.$errstr);
|
4138 |
+
$this->fault('SOAP-ENV:Server', 'unable to serialize result');
|
4139 |
+
return;
|
4140 |
+
}
|
4141 |
+
} else {
|
4142 |
+
if (isset($this->methodreturn)) {
|
4143 |
+
$return_val = $this->serialize_val($this->methodreturn, 'return');
|
4144 |
+
} else {
|
4145 |
+
$return_val = '';
|
4146 |
+
$this->debug('in absence of WSDL, assume void return for backward compatibility');
|
4147 |
+
}
|
4148 |
+
}
|
4149 |
+
}
|
4150 |
+
$this->debug('return value:');
|
4151 |
+
$this->appendDebug($this->varDump($return_val));
|
4152 |
+
|
4153 |
+
$this->debug('serializing response');
|
4154 |
+
if ($this->wsdl) {
|
4155 |
+
$this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
|
4156 |
+
if ($this->opData['style'] == 'rpc') {
|
4157 |
+
$this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
|
4158 |
+
if ($this->opData['output']['use'] == 'literal') {
|
4159 |
+
// 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
|
4160 |
+
if ($this->methodURI) {
|
4161 |
+
$payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
|
4162 |
+
} else {
|
4163 |
+
$payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
|
4164 |
+
}
|
4165 |
+
} else {
|
4166 |
+
if ($this->methodURI) {
|
4167 |
+
$payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
|
4168 |
+
} else {
|
4169 |
+
$payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
|
4170 |
+
}
|
4171 |
+
}
|
4172 |
+
} else {
|
4173 |
+
$this->debug('style is not rpc for serialization: assume document');
|
4174 |
+
$payload = $return_val;
|
4175 |
+
}
|
4176 |
+
} else {
|
4177 |
+
$this->debug('do not have WSDL for serialization: assume rpc/encoded');
|
4178 |
+
$payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
|
4179 |
+
}
|
4180 |
+
$this->result = 'successful';
|
4181 |
+
if($this->wsdl){
|
4182 |
+
//if($this->debug_flag){
|
4183 |
+
$this->appendDebug($this->wsdl->getDebug());
|
4184 |
+
// }
|
4185 |
+
if (isset($this->opData['output']['encodingStyle'])) {
|
4186 |
+
$encodingStyle = $this->opData['output']['encodingStyle'];
|
4187 |
+
} else {
|
4188 |
+
$encodingStyle = '';
|
4189 |
+
}
|
4190 |
+
// Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
|
4191 |
+
$this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$this->opData['output']['use'],$encodingStyle);
|
4192 |
+
} else {
|
4193 |
+
$this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders);
|
4194 |
+
}
|
4195 |
+
$this->debug("Leaving serialize_return");
|
4196 |
+
}
|
4197 |
+
|
4198 |
+
/**
|
4199 |
+
* sends an HTTP response
|
4200 |
+
*
|
4201 |
+
* The following fields are set by this function (when successful)
|
4202 |
+
*
|
4203 |
+
* outgoing_headers
|
4204 |
+
* response
|
4205 |
+
*
|
4206 |
+
* @access private
|
4207 |
+
*/
|
4208 |
+
function send_response() {
|
4209 |
+
$this->debug('Enter send_response');
|
4210 |
+
if ($this->fault) {
|
4211 |
+
$payload = $this->fault->serialize();
|
4212 |
+
$this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
|
4213 |
+
$this->outgoing_headers[] = "Status: 500 Internal Server Error";
|
4214 |
+
} else {
|
4215 |
+
$payload = $this->responseSOAP;
|
4216 |
+
// Some combinations of PHP+Web server allow the Status
|
4217 |
+
// to come through as a header. Since OK is the default
|
4218 |
+
// just do nothing.
|
4219 |
+
// $this->outgoing_headers[] = "HTTP/1.0 200 OK";
|
4220 |
+
// $this->outgoing_headers[] = "Status: 200 OK";
|
4221 |
+
}
|
4222 |
+
// add debug data if in debug mode
|
4223 |
+
if(isset($this->debug_flag) && $this->debug_flag){
|
4224 |
+
$payload .= $this->getDebugAsXMLComment();
|
4225 |
+
}
|
4226 |
+
$this->outgoing_headers[] = "Server: $this->title Server v$this->version";
|
4227 |
+
preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
|
4228 |
+
$this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")";
|
4229 |
+
// Let the Web server decide about this
|
4230 |
+
//$this->outgoing_headers[] = "Connection: Close\r\n";
|
4231 |
+
$payload = $this->getHTTPBody($payload);
|
4232 |
+
$type = $this->getHTTPContentType();
|
4233 |
+
$charset = $this->getHTTPContentTypeCharset();
|
4234 |
+
$this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
|
4235 |
+
//begin code to compress payload - by John
|
4236 |
+
// NOTE: there is no way to know whether the Web server will also compress
|
4237 |
+
// this data.
|
4238 |
+
if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {
|
4239 |
+
if (strstr($this->headers['accept-encoding'], 'gzip')) {
|
4240 |
+
if (function_exists('gzencode')) {
|
4241 |
+
if (isset($this->debug_flag) && $this->debug_flag) {
|
4242 |
+
$payload .= "<!-- Content being gzipped -->";
|
4243 |
+
}
|
4244 |
+
$this->outgoing_headers[] = "Content-Encoding: gzip";
|
4245 |
+
$payload = gzencode($payload);
|
4246 |
+
} else {
|
4247 |
+
if (isset($this->debug_flag) && $this->debug_flag) {
|
4248 |
+
$payload .= "<!-- Content will not be gzipped: no gzencode -->";
|
4249 |
+
}
|
4250 |
+
}
|
4251 |
+
} elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
|
4252 |
+
// Note: MSIE requires gzdeflate output (no Zlib header and checksum),
|
4253 |
+
// instead of gzcompress output,
|
4254 |
+
// which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
|
4255 |
+
if (function_exists('gzdeflate')) {
|
4256 |
+
if (isset($this->debug_flag) && $this->debug_flag) {
|
4257 |
+
$payload .= "<!-- Content being deflated -->";
|
4258 |
+
}
|
4259 |
+
$this->outgoing_headers[] = "Content-Encoding: deflate";
|
4260 |
+
$payload = gzdeflate($payload);
|
4261 |
+
} else {
|
4262 |
+
if (isset($this->debug_flag) && $this->debug_flag) {
|
4263 |
+
$payload .= "<!-- Content will not be deflated: no gzcompress -->";
|
4264 |
+
}
|
4265 |
+
}
|
4266 |
+
}
|
4267 |
+
}
|
4268 |
+
//end code
|
4269 |
+
$this->outgoing_headers[] = "Content-Length: ".strlen($payload);
|
4270 |
+
reset($this->outgoing_headers);
|
4271 |
+
foreach($this->outgoing_headers as $hdr){
|
4272 |
+
header($hdr, false);
|
4273 |
+
}
|
4274 |
+
print $payload;
|
4275 |
+
$this->response = join("\r\n",$this->outgoing_headers)."\r\n\r\n".$payload;
|
4276 |
+
}
|
4277 |
+
|
4278 |
+
/**
|
4279 |
+
* takes the value that was created by parsing the request
|
4280 |
+
* and compares to the method's signature, if available.
|
4281 |
+
*
|
4282 |
+
* @param string $operation The operation to be invoked
|
4283 |
+
* @param array $request The array of parameter values
|
4284 |
+
* @return boolean Whether the operation was found
|
4285 |
+
* @access private
|
4286 |
+
*/
|
4287 |
+
function verify_method($operation,$request){
|
4288 |
+
if(isset($this->wsdl) && is_object($this->wsdl)){
|
4289 |
+
if($this->wsdl->getOperationData($operation)){
|
4290 |
+
return true;
|
4291 |
+
}
|
4292 |
+
} elseif(isset($this->operations[$operation])){
|
4293 |
+
return true;
|
4294 |
+
}
|
4295 |
+
return false;
|
4296 |
+
}
|
4297 |
+
|
4298 |
+
/**
|
4299 |
+
* processes SOAP message received from client
|
4300 |
+
*
|
4301 |
+
* @param array $headers The HTTP headers
|
4302 |
+
* @param string $data unprocessed request data from client
|
4303 |
+
* @return mixed value of the message, decoded into a PHP type
|
4304 |
+
* @access private
|
4305 |
+
*/
|
4306 |
+
function parseRequest($headers, $data) {
|
4307 |
+
$this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' headers:');
|
4308 |
+
$this->appendDebug($this->varDump($headers));
|
4309 |
+
if (!isset($headers['content-type'])) {
|
4310 |
+
$this->setError('Request not of type text/xml (no content-type header)');
|
4311 |
+
return false;
|
4312 |
+
}
|
4313 |
+
if (!strstr($headers['content-type'], 'text/xml')) {
|
4314 |
+
$this->setError('Request not of type text/xml');
|
4315 |
+
return false;
|
4316 |
+
}
|
4317 |
+
if (strpos($headers['content-type'], '=')) {
|
4318 |
+
$enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
|
4319 |
+
$this->debug('Got response encoding: ' . $enc);
|
4320 |
+
if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
|
4321 |
+
$this->xml_encoding = strtoupper($enc);
|
4322 |
+
} else {
|
4323 |
+
$this->xml_encoding = 'US-ASCII';
|
4324 |
+
}
|
4325 |
+
} else {
|
4326 |
+
// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
|
4327 |
+
$this->xml_encoding = 'ISO-8859-1';
|
4328 |
+
}
|
4329 |
+
$this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
|
4330 |
+
// parse response, get soap parser obj
|
4331 |
+
$parser = new nusoap_parser($data,$this->xml_encoding,'',$this->decode_utf8);
|
4332 |
+
// parser debug
|
4333 |
+
$this->debug("parser debug: \n".$parser->getDebug());
|
4334 |
+
// if fault occurred during message parsing
|
4335 |
+
if($err = $parser->getError()){
|
4336 |
+
$this->result = 'fault: error in msg parsing: '.$err;
|
4337 |
+
$this->fault('SOAP-ENV:Client',"error in msg parsing:\n".$err);
|
4338 |
+
// else successfully parsed request into soapval object
|
4339 |
+
} else {
|
4340 |
+
// get/set methodname
|
4341 |
+
$this->methodURI = $parser->root_struct_namespace;
|
4342 |
+
$this->methodname = $parser->root_struct_name;
|
4343 |
+
$this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI);
|
4344 |
+
$this->debug('calling parser->get_soapbody()');
|
4345 |
+
$this->methodparams = $parser->get_soapbody();
|
4346 |
+
// get SOAP headers
|
4347 |
+
$this->requestHeaders = $parser->getHeaders();
|
4348 |
+
// get SOAP Header
|
4349 |
+
$this->requestHeader = $parser->get_soapheader();
|
4350 |
+
// add document for doclit support
|
4351 |
+
$this->document = $parser->document;
|
4352 |
+
}
|
4353 |
+
}
|
4354 |
+
|
4355 |
+
/**
|
4356 |
+
* gets the HTTP body for the current response.
|
4357 |
+
*
|
4358 |
+
* @param string $soapmsg The SOAP payload
|
4359 |
+
* @return string The HTTP body, which includes the SOAP payload
|
4360 |
+
* @access private
|
4361 |
+
*/
|
4362 |
+
function getHTTPBody($soapmsg) {
|
4363 |
+
return $soapmsg;
|
4364 |
+
}
|
4365 |
+
|
4366 |
+
/**
|
4367 |
+
* gets the HTTP content type for the current response.
|
4368 |
+
*
|
4369 |
+
* Note: getHTTPBody must be called before this.
|
4370 |
+
*
|
4371 |
+
* @return string the HTTP content type for the current response.
|
4372 |
+
* @access private
|
4373 |
+
*/
|
4374 |
+
function getHTTPContentType() {
|
4375 |
+
return 'text/xml';
|
4376 |
+
}
|
4377 |
+
|
4378 |
+
/**
|
4379 |
+
* gets the HTTP content type charset for the current response.
|
4380 |
+
* returns false for non-text content types.
|
4381 |
+
*
|
4382 |
+
* Note: getHTTPBody must be called before this.
|
4383 |
+
*
|
4384 |
+
* @return string the HTTP content type charset for the current response.
|
4385 |
+
* @access private
|
4386 |
+
*/
|
4387 |
+
function getHTTPContentTypeCharset() {
|
4388 |
+
return $this->soap_defencoding;
|
4389 |
+
}
|
4390 |
+
|
4391 |
+
/**
|
4392 |
+
* add a method to the dispatch map (this has been replaced by the register method)
|
4393 |
+
*
|
4394 |
+
* @param string $methodname
|
4395 |
+
* @param string $in array of input values
|
4396 |
+
* @param string $out array of output values
|
4397 |
+
* @access public
|
4398 |
+
* @deprecated
|
4399 |
+
*/
|
4400 |
+
function add_to_map($methodname,$in,$out){
|
4401 |
+
$this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
|
4402 |
+
}
|
4403 |
+
|
4404 |
+
/**
|
4405 |
+
* register a service function with the server
|
4406 |
+
*
|
4407 |
+
* @param string $name the name of the PHP function, class.method or class..method
|
4408 |
+
* @param array $in assoc array of input values: key = param name, value = param type
|
4409 |
+
* @param array $out assoc array of output values: key = param name, value = param type
|
4410 |
+
* @param mixed $namespace the element namespace for the method or false
|
4411 |
+
* @param mixed $soapaction the soapaction for the method or false
|
4412 |
+
* @param mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically
|
4413 |
+
* @param mixed $use optional (encoded|literal) or false
|
4414 |
+
* @param string $documentation optional Description to include in WSDL
|
4415 |
+
* @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
|
4416 |
+
* @access public
|
4417 |
+
*/
|
4418 |
+
function register($name,$in=array(),$out=array(),$namespace=false,$soapaction=false,$style=false,$use=false,$documentation='',$encodingStyle=''){
|
4419 |
+
global $HTTP_SERVER_VARS;
|
4420 |
+
|
4421 |
+
if($this->externalWSDLURL){
|
4422 |
+
die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
|
4423 |
+
}
|
4424 |
+
if (! $name) {
|
4425 |
+
die('You must specify a name when you register an operation');
|
4426 |
+
}
|
4427 |
+
if (!is_array($in)) {
|
4428 |
+
die('You must provide an array for operation inputs');
|
4429 |
+
}
|
4430 |
+
if (!is_array($out)) {
|
4431 |
+
die('You must provide an array for operation outputs');
|
4432 |
+
}
|
4433 |
+
if(false == $namespace) {
|
4434 |
+
}
|
4435 |
+
if(false == $soapaction) {
|
4436 |
+
if (isset($_SERVER)) {
|
4437 |
+
$SERVER_NAME = $_SERVER['SERVER_NAME'];
|
4438 |
+
$SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
|
4439 |
+
$HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
|
4440 |
+
} elseif (isset($HTTP_SERVER_VARS)) {
|
4441 |
+
$SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
|
4442 |
+
$SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
|
4443 |
+
$HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
|
4444 |
+
} else {
|
4445 |
+
$this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
|
4446 |
+
}
|
4447 |
+
if ($HTTPS == '1' || $HTTPS == 'on') {
|
4448 |
+
$SCHEME = 'https';
|
4449 |
+
} else {
|
4450 |
+
$SCHEME = 'http';
|
4451 |
+
}
|
4452 |
+
$soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
|
4453 |
+
}
|
4454 |
+
if(false == $style) {
|
4455 |
+
$style = "rpc";
|
4456 |
+
}
|
4457 |
+
if(false == $use) {
|
4458 |
+
$use = "encoded";
|
4459 |
+
}
|
4460 |
+
if ($use == 'encoded' && $encodingStyle == '') {
|
4461 |
+
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
|
4462 |
+
}
|
4463 |
+
|
4464 |
+
$this->operations[$name] = array(
|
4465 |
+
'name' => $name,
|
4466 |
+
'in' => $in,
|
4467 |
+
'out' => $out,
|
4468 |
+
'namespace' => $namespace,
|
4469 |
+
'soapaction' => $soapaction,
|
4470 |
+
'style' => $style);
|
4471 |
+
if($this->wsdl){
|
4472 |
+
$this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use,$documentation,$encodingStyle);
|
4473 |
+
}
|
4474 |
+
return true;
|
4475 |
+
}
|
4476 |
+
|
4477 |
+
/**
|
4478 |
+
* Specify a fault to be returned to the client.
|
4479 |
+
* This also acts as a flag to the server that a fault has occured.
|
4480 |
+
*
|
4481 |
+
* @param string $faultcode
|
4482 |
+
* @param string $faultstring
|
4483 |
+
* @param string $faultactor
|
4484 |
+
* @param string $faultdetail
|
4485 |
+
* @access public
|
4486 |
+
*/
|
4487 |
+
function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){
|
4488 |
+
if ($faultdetail == '' && $this->debug_flag) {
|
4489 |
+
$faultdetail = $this->getDebug();
|
4490 |
+
}
|
4491 |
+
$this->fault = new nusoap_fault($faultcode,$faultactor,$faultstring,$faultdetail);
|
4492 |
+
$this->fault->soap_defencoding = $this->soap_defencoding;
|
4493 |
+
}
|
4494 |
+
|
4495 |
+
/**
|
4496 |
+
* Sets up wsdl object.
|
4497 |
+
* Acts as a flag to enable internal WSDL generation
|
4498 |
+
*
|
4499 |
+
* @param string $serviceName, name of the service
|
4500 |
+
* @param mixed $namespace optional 'tns' service namespace or false
|
4501 |
+
* @param mixed $endpoint optional URL of service endpoint or false
|
4502 |
+
* @param string $style optional (rpc|document) WSDL style (also specified by operation)
|
4503 |
+
* @param string $transport optional SOAP transport
|
4504 |
+
* @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false
|
4505 |
+
*/
|
4506 |
+
function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
|
4507 |
+
{
|
4508 |
+
global $HTTP_SERVER_VARS;
|
4509 |
+
|
4510 |
+
if (isset($_SERVER)) {
|
4511 |
+
$SERVER_NAME = $_SERVER['SERVER_NAME'];
|
4512 |
+
$SERVER_PORT = $_SERVER['SERVER_PORT'];
|
4513 |
+
$SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
|
4514 |
+
$HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
|
4515 |
+
} elseif (isset($HTTP_SERVER_VARS)) {
|
4516 |
+
$SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
|
4517 |
+
$SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
|
4518 |
+
$SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
|
4519 |
+
$HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
|
4520 |
+
} else {
|
4521 |
+
$this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
|
4522 |
+
}
|
4523 |
+
// If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)
|
4524 |
+
$colon = strpos($SERVER_NAME,":");
|
4525 |
+
if ($colon) {
|
4526 |
+
$SERVER_NAME = substr($SERVER_NAME, 0, $colon);
|
4527 |
+
}
|
4528 |
+
if ($SERVER_PORT == 80) {
|
4529 |
+
$SERVER_PORT = '';
|
4530 |
+
} else {
|
4531 |
+
$SERVER_PORT = ':' . $SERVER_PORT;
|
4532 |
+
}
|
4533 |
+
if(false == $namespace) {
|
4534 |
+
$namespace = "http://$SERVER_NAME/soap/$serviceName";
|
4535 |
+
}
|
4536 |
+
|
4537 |
+
if(false == $endpoint) {
|
4538 |
+
if ($HTTPS == '1' || $HTTPS == 'on') {
|
4539 |
+
$SCHEME = 'https';
|
4540 |
+
} else {
|
4541 |
+
$SCHEME = 'http';
|
4542 |
+
}
|
4543 |
+
$endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
|
4544 |
+
}
|
4545 |
+
|
4546 |
+
if(false == $schemaTargetNamespace) {
|
4547 |
+
$schemaTargetNamespace = $namespace;
|
4548 |
+
}
|
4549 |
+
|
4550 |
+
$this->wsdl = new wsdl;
|
4551 |
+
$this->wsdl->serviceName = $serviceName;
|
4552 |
+
$this->wsdl->endpoint = $endpoint;
|
4553 |
+
$this->wsdl->namespaces['tns'] = $namespace;
|
4554 |
+
$this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
|
4555 |
+
$this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
|
4556 |
+
if ($schemaTargetNamespace != $namespace) {
|
4557 |
+
$this->wsdl->namespaces['types'] = $schemaTargetNamespace;
|
4558 |
+
}
|
4559 |
+
$this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces);
|
4560 |
+
if ($style == 'document') {
|
4561 |
+
$this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified';
|
4562 |
+
}
|
4563 |
+
$this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
|
4564 |
+
$this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
|
4565 |
+
$this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
|
4566 |
+
$this->wsdl->bindings[$serviceName.'Binding'] = array(
|
4567 |
+
'name'=>$serviceName.'Binding',
|
4568 |
+
'style'=>$style,
|
4569 |
+
'transport'=>$transport,
|
4570 |
+
'portType'=>$serviceName.'PortType');
|
4571 |
+
$this->wsdl->ports[$serviceName.'Port'] = array(
|
4572 |
+
'binding'=>$serviceName.'Binding',
|
4573 |
+
'location'=>$endpoint,
|
4574 |
+
'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/');
|
4575 |
+
}
|
4576 |
+
}
|
4577 |
+
|
4578 |
+
/**
|
4579 |
+
* Backward compatibility
|
4580 |
+
*/
|
4581 |
+
class soap_server extends nusoap_server {
|
4582 |
+
}
|
4583 |
+
|
4584 |
+
?><?php
|
4585 |
+
|
4586 |
+
|
4587 |
+
|
4588 |
+
/**
|
4589 |
+
* parses a WSDL file, allows access to it's data, other utility methods.
|
4590 |
+
* also builds WSDL structures programmatically.
|
4591 |
+
*
|
4592 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
4593 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
4594 |
+
* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
|
4595 |
+
* @access public
|
4596 |
+
*/
|
4597 |
+
class wsdl extends nusoap_base {
|
4598 |
+
// URL or filename of the root of this WSDL
|
4599 |
+
var $wsdl;
|
4600 |
+
// define internal arrays of bindings, ports, operations, messages, etc.
|
4601 |
+
var $schemas = array();
|
4602 |
+
var $currentSchema;
|
4603 |
+
var $message = array();
|
4604 |
+
var $complexTypes = array();
|
4605 |
+
var $messages = array();
|
4606 |
+
var $currentMessage;
|
4607 |
+
var $currentOperation;
|
4608 |
+
var $portTypes = array();
|
4609 |
+
var $currentPortType;
|
4610 |
+
var $bindings = array();
|
4611 |
+
var $currentBinding;
|
4612 |
+
var $ports = array();
|
4613 |
+
var $currentPort;
|
4614 |
+
var $opData = array();
|
4615 |
+
var $status = '';
|
4616 |
+
var $documentation = false;
|
4617 |
+
var $endpoint = '';
|
4618 |
+
// array of wsdl docs to import
|
4619 |
+
var $import = array();
|
4620 |
+
// parser vars
|
4621 |
+
var $parser;
|
4622 |
+
var $position = 0;
|
4623 |
+
var $depth = 0;
|
4624 |
+
var $depth_array = array();
|
4625 |
+
// for getting wsdl
|
4626 |
+
var $proxyhost = '';
|
4627 |
+
var $proxyport = '';
|
4628 |
+
var $proxyusername = '';
|
4629 |
+
var $proxypassword = '';
|
4630 |
+
var $timeout = 0;
|
4631 |
+
var $response_timeout = 30;
|
4632 |
+
var $curl_options = array(); // User-specified cURL options
|
4633 |
+
var $use_curl = false; // whether to always try to use cURL
|
4634 |
+
// for HTTP authentication
|
4635 |
+
var $username = ''; // Username for HTTP authentication
|
4636 |
+
var $password = ''; // Password for HTTP authentication
|
4637 |
+
var $authtype = ''; // Type of HTTP authentication
|
4638 |
+
var $certRequest = array(); // Certificate for HTTP SSL authentication
|
4639 |
+
|
4640 |
+
/**
|
4641 |
+
* constructor
|
4642 |
+
*
|
4643 |
+
* @param string $wsdl WSDL document URL
|
4644 |
+
* @param string $proxyhost
|
4645 |
+
* @param string $proxyport
|
4646 |
+
* @param string $proxyusername
|
4647 |
+
* @param string $proxypassword
|
4648 |
+
* @param integer $timeout set the connection timeout
|
4649 |
+
* @param integer $response_timeout set the response timeout
|
4650 |
+
* @param array $curl_options user-specified cURL options
|
4651 |
+
* @param boolean $use_curl try to use cURL
|
4652 |
+
* @access public
|
4653 |
+
*/
|
4654 |
+
function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30,$curl_options=null,$use_curl=false){
|
4655 |
+
parent::nusoap_base();
|
4656 |
+
$this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
|
4657 |
+
$this->proxyhost = $proxyhost;
|
4658 |
+
$this->proxyport = $proxyport;
|
4659 |
+
$this->proxyusername = $proxyusername;
|
4660 |
+
$this->proxypassword = $proxypassword;
|
4661 |
+
$this->timeout = $timeout;
|
4662 |
+
$this->response_timeout = $response_timeout;
|
4663 |
+
if (is_array($curl_options))
|
4664 |
+
$this->curl_options = $curl_options;
|
4665 |
+
$this->use_curl = $use_curl;
|
4666 |
+
$this->fetchWSDL($wsdl);
|
4667 |
+
}
|
4668 |
+
|
4669 |
+
/**
|
4670 |
+
* fetches the WSDL document and parses it
|
4671 |
+
*
|
4672 |
+
* @access public
|
4673 |
+
*/
|
4674 |
+
function fetchWSDL($wsdl) {
|
4675 |
+
$this->debug("parse and process WSDL path=$wsdl");
|
4676 |
+
$this->wsdl = $wsdl;
|
4677 |
+
// parse wsdl file
|
4678 |
+
if ($this->wsdl != "") {
|
4679 |
+
$this->parseWSDL($this->wsdl);
|
4680 |
+
}
|
4681 |
+
// imports
|
4682 |
+
// TODO: handle imports more properly, grabbing them in-line and nesting them
|
4683 |
+
$imported_urls = array();
|
4684 |
+
$imported = 1;
|
4685 |
+
while ($imported > 0) {
|
4686 |
+
$imported = 0;
|
4687 |
+
// Schema imports
|
4688 |
+
foreach ($this->schemas as $ns => $list) {
|
4689 |
+
foreach ($list as $xs) {
|
4690 |
+
$wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
|
4691 |
+
foreach ($xs->imports as $ns2 => $list2) {
|
4692 |
+
for ($ii = 0; $ii < count($list2); $ii++) {
|
4693 |
+
if (! $list2[$ii]['loaded']) {
|
4694 |
+
$this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
|
4695 |
+
$url = $list2[$ii]['location'];
|
4696 |
+
if ($url != '') {
|
4697 |
+
$urlparts = parse_url($url);
|
4698 |
+
if (!isset($urlparts['host'])) {
|
4699 |
+
$url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') .
|
4700 |
+
substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
|
4701 |
+
}
|
4702 |
+
if (! in_array($url, $imported_urls)) {
|
4703 |
+
$this->parseWSDL($url);
|
4704 |
+
$imported++;
|
4705 |
+
$imported_urls[] = $url;
|
4706 |
+
}
|
4707 |
+
} else {
|
4708 |
+
$this->debug("Unexpected scenario: empty URL for unloaded import");
|
4709 |
+
}
|
4710 |
+
}
|
4711 |
+
}
|
4712 |
+
}
|
4713 |
+
}
|
4714 |
+
}
|
4715 |
+
// WSDL imports
|
4716 |
+
$wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
|
4717 |
+
foreach ($this->import as $ns => $list) {
|
4718 |
+
for ($ii = 0; $ii < count($list); $ii++) {
|
4719 |
+
if (! $list[$ii]['loaded']) {
|
4720 |
+
$this->import[$ns][$ii]['loaded'] = true;
|
4721 |
+
$url = $list[$ii]['location'];
|
4722 |
+
if ($url != '') {
|
4723 |
+
$urlparts = parse_url($url);
|
4724 |
+
if (!isset($urlparts['host'])) {
|
4725 |
+
$url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
|
4726 |
+
substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
|
4727 |
+
}
|
4728 |
+
if (! in_array($url, $imported_urls)) {
|
4729 |
+
$this->parseWSDL($url);
|
4730 |
+
$imported++;
|
4731 |
+
$imported_urls[] = $url;
|
4732 |
+
}
|
4733 |
+
} else {
|
4734 |
+
$this->debug("Unexpected scenario: empty URL for unloaded import");
|
4735 |
+
}
|
4736 |
+
}
|
4737 |
+
}
|
4738 |
+
}
|
4739 |
+
}
|
4740 |
+
// add new data to operation data
|
4741 |
+
foreach($this->bindings as $binding => $bindingData) {
|
4742 |
+
if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
|
4743 |
+
foreach($bindingData['operations'] as $operation => $data) {
|
4744 |
+
$this->debug('post-parse data gathering for ' . $operation);
|
4745 |
+
$this->bindings[$binding]['operations'][$operation]['input'] =
|
4746 |
+
isset($this->bindings[$binding]['operations'][$operation]['input']) ?
|
4747 |
+
array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
|
4748 |
+
$this->portTypes[ $bindingData['portType'] ][$operation]['input'];
|
4749 |
+
$this->bindings[$binding]['operations'][$operation]['output'] =
|
4750 |
+
isset($this->bindings[$binding]['operations'][$operation]['output']) ?
|
4751 |
+
array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
|
4752 |
+
$this->portTypes[ $bindingData['portType'] ][$operation]['output'];
|
4753 |
+
if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])){
|
4754 |
+
$this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
|
4755 |
+
}
|
4756 |
+
if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])){
|
4757 |
+
$this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
|
4758 |
+
}
|
4759 |
+
// Set operation style if necessary, but do not override one already provided
|
4760 |
+
if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) {
|
4761 |
+
$this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
|
4762 |
+
}
|
4763 |
+
$this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
|
4764 |
+
$this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
|
4765 |
+
$this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
|
4766 |
+
}
|
4767 |
+
}
|
4768 |
+
}
|
4769 |
+
}
|
4770 |
+
|
4771 |
+
/**
|
4772 |
+
* parses the wsdl document
|
4773 |
+
*
|
4774 |
+
* @param string $wsdl path or URL
|
4775 |
+
* @access private
|
4776 |
+
*/
|
4777 |
+
function parseWSDL($wsdl = '') {
|
4778 |
+
$this->debug("parse WSDL at path=$wsdl");
|
4779 |
+
|
4780 |
+
if ($wsdl == '') {
|
4781 |
+
$this->debug('no wsdl passed to parseWSDL()!!');
|
4782 |
+
$this->setError('no wsdl passed to parseWSDL()!!');
|
4783 |
+
return false;
|
4784 |
+
}
|
4785 |
+
|
4786 |
+
// parse $wsdl for url format
|
4787 |
+
$wsdl_props = parse_url($wsdl);
|
4788 |
+
|
4789 |
+
if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
|
4790 |
+
$this->debug('getting WSDL http(s) URL ' . $wsdl);
|
4791 |
+
// get wsdl
|
4792 |
+
$tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl);
|
4793 |
+
$tr->request_method = 'GET';
|
4794 |
+
$tr->useSOAPAction = false;
|
4795 |
+
if($this->proxyhost && $this->proxyport){
|
4796 |
+
$tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
|
4797 |
+
}
|
4798 |
+
if ($this->authtype != '') {
|
4799 |
+
$tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
|
4800 |
+
}
|
4801 |
+
$tr->setEncoding('gzip, deflate');
|
4802 |
+
$wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
|
4803 |
+
//$this->debug("WSDL request\n" . $tr->outgoing_payload);
|
4804 |
+
//$this->debug("WSDL response\n" . $tr->incoming_payload);
|
4805 |
+
$this->appendDebug($tr->getDebug());
|
4806 |
+
// catch errors
|
4807 |
+
if($err = $tr->getError() ){
|
4808 |
+
$errstr = 'Getting ' . $wsdl . ' - HTTP ERROR: '.$err;
|
4809 |
+
$this->debug($errstr);
|
4810 |
+
$this->setError($errstr);
|
4811 |
+
unset($tr);
|
4812 |
+
return false;
|
4813 |
+
}
|
4814 |
+
unset($tr);
|
4815 |
+
$this->debug("got WSDL URL");
|
4816 |
+
} else {
|
4817 |
+
// $wsdl is not http(s), so treat it as a file URL or plain file path
|
4818 |
+
if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
|
4819 |
+
$path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
|
4820 |
+
} else {
|
4821 |
+
$path = $wsdl;
|
4822 |
+
}
|
4823 |
+
$this->debug('getting WSDL file ' . $path);
|
4824 |
+
if ($fp = @fopen($path, 'r')) {
|
4825 |
+
$wsdl_string = '';
|
4826 |
+
while ($data = fread($fp, 32768)) {
|
4827 |
+
$wsdl_string .= $data;
|
4828 |
+
}
|
4829 |
+
fclose($fp);
|
4830 |
+
} else {
|
4831 |
+
$errstr = "Bad path to WSDL file $path";
|
4832 |
+
$this->debug($errstr);
|
4833 |
+
$this->setError($errstr);
|
4834 |
+
return false;
|
4835 |
+
}
|
4836 |
+
}
|
4837 |
+
$this->debug('Parse WSDL');
|
4838 |
+
// end new code added
|
4839 |
+
// Create an XML parser.
|
4840 |
+
$this->parser = xml_parser_create();
|
4841 |
+
// Set the options for parsing the XML data.
|
4842 |
+
// xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
|
4843 |
+
xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
|
4844 |
+
// Set the object for the parser.
|
4845 |
+
xml_set_object($this->parser, $this);
|
4846 |
+
// Set the element handlers for the parser.
|
4847 |
+
xml_set_element_handler($this->parser, 'start_element', 'end_element');
|
4848 |
+
xml_set_character_data_handler($this->parser, 'character_data');
|
4849 |
+
// Parse the XML file.
|
4850 |
+
if (!xml_parse($this->parser, $wsdl_string, true)) {
|
4851 |
+
// Display an error message.
|
4852 |
+
$errstr = sprintf(
|
4853 |
+
'XML error parsing WSDL from %s on line %d: %s',
|
4854 |
+
$wsdl,
|
4855 |
+
xml_get_current_line_number($this->parser),
|
4856 |
+
xml_error_string(xml_get_error_code($this->parser))
|
4857 |
+
);
|
4858 |
+
$this->debug($errstr);
|
4859 |
+
$this->debug("XML payload:\n" . $wsdl_string);
|
4860 |
+
$this->setError($errstr);
|
4861 |
+
return false;
|
4862 |
+
}
|
4863 |
+
// free the parser
|
4864 |
+
xml_parser_free($this->parser);
|
4865 |
+
$this->debug('Parsing WSDL done');
|
4866 |
+
// catch wsdl parse errors
|
4867 |
+
if($this->getError()){
|
4868 |
+
return false;
|
4869 |
+
}
|
4870 |
+
return true;
|
4871 |
+
}
|
4872 |
+
|
4873 |
+
/**
|
4874 |
+
* start-element handler
|
4875 |
+
*
|
4876 |
+
* @param string $parser XML parser object
|
4877 |
+
* @param string $name element name
|
4878 |
+
* @param string $attrs associative array of attributes
|
4879 |
+
* @access private
|
4880 |
+
*/
|
4881 |
+
function start_element($parser, $name, $attrs)
|
4882 |
+
{
|
4883 |
+
if ($this->status == 'schema') {
|
4884 |
+
$this->currentSchema->schemaStartElement($parser, $name, $attrs);
|
4885 |
+
$this->appendDebug($this->currentSchema->getDebug());
|
4886 |
+
$this->currentSchema->clearDebug();
|
4887 |
+
} elseif (preg_match('/schema$/', $name)) {
|
4888 |
+
$this->debug('Parsing WSDL schema');
|
4889 |
+
// $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
|
4890 |
+
$this->status = 'schema';
|
4891 |
+
$this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
|
4892 |
+
$this->currentSchema->schemaStartElement($parser, $name, $attrs);
|
4893 |
+
$this->appendDebug($this->currentSchema->getDebug());
|
4894 |
+
$this->currentSchema->clearDebug();
|
4895 |
+
} else {
|
4896 |
+
// position in the total number of elements, starting from 0
|
4897 |
+
$pos = $this->position++;
|
4898 |
+
$depth = $this->depth++;
|
4899 |
+
// set self as current value for this depth
|
4900 |
+
$this->depth_array[$depth] = $pos;
|
4901 |
+
$this->message[$pos] = array('cdata' => '');
|
4902 |
+
// process attributes
|
4903 |
+
if (count($attrs) > 0) {
|
4904 |
+
// register namespace declarations
|
4905 |
+
foreach($attrs as $k => $v) {
|
4906 |
+
if (preg_match('/^xmlns/',$k)) {
|
4907 |
+
if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
|
4908 |
+
$this->namespaces[$ns_prefix] = $v;
|
4909 |
+
} else {
|
4910 |
+
$this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
|
4911 |
+
}
|
4912 |
+
if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
|
4913 |
+
$this->XMLSchemaVersion = $v;
|
4914 |
+
$this->namespaces['xsi'] = $v . '-instance';
|
4915 |
+
}
|
4916 |
+
}
|
4917 |
+
}
|
4918 |
+
// expand each attribute prefix to its namespace
|
4919 |
+
foreach($attrs as $k => $v) {
|
4920 |
+
$k = strpos($k, ':') ? $this->expandQname($k) : $k;
|
4921 |
+
if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
|
4922 |
+
$v = strpos($v, ':') ? $this->expandQname($v) : $v;
|
4923 |
+
}
|
4924 |
+
$eAttrs[$k] = $v;
|
4925 |
+
}
|
4926 |
+
$attrs = $eAttrs;
|
4927 |
+
} else {
|
4928 |
+
$attrs = array();
|
4929 |
+
}
|
4930 |
+
// get element prefix, namespace and name
|
4931 |
+
if (preg_match('/:/', $name)) {
|
4932 |
+
// get ns prefix
|
4933 |
+
$prefix = substr($name, 0, strpos($name, ':'));
|
4934 |
+
// get ns
|
4935 |
+
$namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : '';
|
4936 |
+
// get unqualified name
|
4937 |
+
$name = substr(strstr($name, ':'), 1);
|
4938 |
+
}
|
4939 |
+
// process attributes, expanding any prefixes to namespaces
|
4940 |
+
// find status, register data
|
4941 |
+
switch ($this->status) {
|
4942 |
+
case 'message':
|
4943 |
+
if ($name == 'part') {
|
4944 |
+
if (isset($attrs['type'])) {
|
4945 |
+
$this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs));
|
4946 |
+
$this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
|
4947 |
+
}
|
4948 |
+
if (isset($attrs['element'])) {
|
4949 |
+
$this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));
|
4950 |
+
$this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';
|
4951 |
+
}
|
4952 |
+
}
|
4953 |
+
break;
|
4954 |
+
case 'portType':
|
4955 |
+
switch ($name) {
|
4956 |
+
case 'operation':
|
4957 |
+
$this->currentPortOperation = $attrs['name'];
|
4958 |
+
$this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
|
4959 |
+
if (isset($attrs['parameterOrder'])) {
|
4960 |
+
$this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
|
4961 |
+
}
|
4962 |
+
break;
|
4963 |
+
case 'documentation':
|
4964 |
+
$this->documentation = true;
|
4965 |
+
break;
|
4966 |
+
// merge input/output data
|
4967 |
+
default:
|
4968 |
+
$m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
|
4969 |
+
$this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
|
4970 |
+
break;
|
4971 |
+
}
|
4972 |
+
break;
|
4973 |
+
case 'binding':
|
4974 |
+
switch ($name) {
|
4975 |
+
case 'binding':
|
4976 |
+
// get ns prefix
|
4977 |
+
if (isset($attrs['style'])) {
|
4978 |
+
$this->bindings[$this->currentBinding]['prefix'] = $prefix;
|
4979 |
+
}
|
4980 |
+
$this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
|
4981 |
+
break;
|
4982 |
+
case 'header':
|
4983 |
+
$this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
|
4984 |
+
break;
|
4985 |
+
case 'operation':
|
4986 |
+
if (isset($attrs['soapAction'])) {
|
4987 |
+
$this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
|
4988 |
+
}
|
4989 |
+
if (isset($attrs['style'])) {
|
4990 |
+
$this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
|
4991 |
+
}
|
4992 |
+
if (isset($attrs['name'])) {
|
4993 |
+
$this->currentOperation = $attrs['name'];
|
4994 |
+
$this->debug("current binding operation: $this->currentOperation");
|
4995 |
+
$this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
|
4996 |
+
$this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
|
4997 |
+
$this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
|
4998 |
+
}
|
4999 |
+
break;
|
5000 |
+
case 'input':
|
5001 |
+
$this->opStatus = 'input';
|
5002 |
+
break;
|
5003 |
+
case 'output':
|
5004 |
+
$this->opStatus = 'output';
|
5005 |
+
break;
|
5006 |
+
case 'body':
|
5007 |
+
if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
|
5008 |
+
$this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
|
5009 |
+
} else {
|
5010 |
+
$this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
|
5011 |
+
}
|
5012 |
+
break;
|
5013 |
+
}
|
5014 |
+
break;
|
5015 |
+
case 'service':
|
5016 |
+
switch ($name) {
|
5017 |
+
case 'port':
|
5018 |
+
$this->currentPort = $attrs['name'];
|
5019 |
+
$this->debug('current port: ' . $this->currentPort);
|
5020 |
+
$this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
|
5021 |
+
|
5022 |
+
break;
|
5023 |
+
case 'address':
|
5024 |
+
$this->ports[$this->currentPort]['location'] = $attrs['location'];
|
5025 |
+
$this->ports[$this->currentPort]['bindingType'] = $namespace;
|
5026 |
+
$this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;
|
5027 |
+
$this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
|
5028 |
+
break;
|
5029 |
+
}
|
5030 |
+
break;
|
5031 |
+
}
|
5032 |
+
// set status
|
5033 |
+
switch ($name) {
|
5034 |
+
case 'import':
|
5035 |
+
if (isset($attrs['location'])) {
|
5036 |
+
$this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
|
5037 |
+
$this->debug('parsing import ' . $attrs['namespace']. ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]).')');
|
5038 |
+
} else {
|
5039 |
+
$this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
|
5040 |
+
if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
|
5041 |
+
$this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
|
5042 |
+
}
|
5043 |
+
$this->debug('parsing import ' . $attrs['namespace']. ' - [no location] (' . count($this->import[$attrs['namespace']]).')');
|
5044 |
+
}
|
5045 |
+
break;
|
5046 |
+
//wait for schema
|
5047 |
+
//case 'types':
|
5048 |
+
// $this->status = 'schema';
|
5049 |
+
// break;
|
5050 |
+
case 'message':
|
5051 |
+
$this->status = 'message';
|
5052 |
+
$this->messages[$attrs['name']] = array();
|
5053 |
+
$this->currentMessage = $attrs['name'];
|
5054 |
+
break;
|
5055 |
+
case 'portType':
|
5056 |
+
$this->status = 'portType';
|
5057 |
+
$this->portTypes[$attrs['name']] = array();
|
5058 |
+
$this->currentPortType = $attrs['name'];
|
5059 |
+
break;
|
5060 |
+
case "binding":
|
5061 |
+
if (isset($attrs['name'])) {
|
5062 |
+
// get binding name
|
5063 |
+
if (strpos($attrs['name'], ':')) {
|
5064 |
+
$this->currentBinding = $this->getLocalPart($attrs['name']);
|
5065 |
+
} else {
|
5066 |
+
$this->currentBinding = $attrs['name'];
|
5067 |
+
}
|
5068 |
+
$this->status = 'binding';
|
5069 |
+
$this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
|
5070 |
+
$this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
|
5071 |
+
}
|
5072 |
+
break;
|
5073 |
+
case 'service':
|
5074 |
+
$this->serviceName = $attrs['name'];
|
5075 |
+
$this->status = 'service';
|
5076 |
+
$this->debug('current service: ' . $this->serviceName);
|
5077 |
+
break;
|
5078 |
+
case 'definitions':
|
5079 |
+
foreach ($attrs as $name => $value) {
|
5080 |
+
$this->wsdl_info[$name] = $value;
|
5081 |
+
}
|
5082 |
+
break;
|
5083 |
+
}
|
5084 |
+
}
|
5085 |
+
}
|
5086 |
+
|
5087 |
+
/**
|
5088 |
+
* end-element handler
|
5089 |
+
*
|
5090 |
+
* @param string $parser XML parser object
|
5091 |
+
* @param string $name element name
|
5092 |
+
* @access private
|
5093 |
+
*/
|
5094 |
+
function end_element($parser, $name){
|
5095 |
+
// unset schema status
|
5096 |
+
if (/*preg_match('/types$/', $name) ||*/ preg_match('/schema$/', $name)) {
|
5097 |
+
$this->status = "";
|
5098 |
+
$this->appendDebug($this->currentSchema->getDebug());
|
5099 |
+
$this->currentSchema->clearDebug();
|
5100 |
+
$this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
|
5101 |
+
$this->debug('Parsing WSDL schema done');
|
5102 |
+
}
|
5103 |
+
if ($this->status == 'schema') {
|
5104 |
+
$this->currentSchema->schemaEndElement($parser, $name);
|
5105 |
+
} else {
|
5106 |
+
// bring depth down a notch
|
5107 |
+
$this->depth--;
|
5108 |
+
}
|
5109 |
+
// end documentation
|
5110 |
+
if ($this->documentation) {
|
5111 |
+
//TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
|
5112 |
+
//$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
|
5113 |
+
$this->documentation = false;
|
5114 |
+
}
|
5115 |
+
}
|
5116 |
+
|
5117 |
+
/**
|
5118 |
+
* element content handler
|
5119 |
+
*
|
5120 |
+
* @param string $parser XML parser object
|
5121 |
+
* @param string $data element content
|
5122 |
+
* @access private
|
5123 |
+
*/
|
5124 |
+
function character_data($parser, $data)
|
5125 |
+
{
|
5126 |
+
$pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
|
5127 |
+
if (isset($this->message[$pos]['cdata'])) {
|
5128 |
+
$this->message[$pos]['cdata'] .= $data;
|
5129 |
+
}
|
5130 |
+
if ($this->documentation) {
|
5131 |
+
$this->documentation .= $data;
|
5132 |
+
}
|
5133 |
+
}
|
5134 |
+
|
5135 |
+
/**
|
5136 |
+
* if authenticating, set user credentials here
|
5137 |
+
*
|
5138 |
+
* @param string $username
|
5139 |
+
* @param string $password
|
5140 |
+
* @param string $authtype (basic|digest|certificate|ntlm)
|
5141 |
+
* @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
|
5142 |
+
* @access public
|
5143 |
+
*/
|
5144 |
+
function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
|
5145 |
+
$this->debug("setCredentials username=$username authtype=$authtype certRequest=");
|
5146 |
+
$this->appendDebug($this->varDump($certRequest));
|
5147 |
+
$this->username = $username;
|
5148 |
+
$this->password = $password;
|
5149 |
+
$this->authtype = $authtype;
|
5150 |
+
$this->certRequest = $certRequest;
|
5151 |
+
}
|
5152 |
+
|
5153 |
+
function getBindingData($binding)
|
5154 |
+
{
|
5155 |
+
if (is_array($this->bindings[$binding])) {
|
5156 |
+
return $this->bindings[$binding];
|
5157 |
+
}
|
5158 |
+
}
|
5159 |
+
|
5160 |
+
/**
|
5161 |
+
* returns an assoc array of operation names => operation data
|
5162 |
+
*
|
5163 |
+
* @param string $portName WSDL port name
|
5164 |
+
* @param string $bindingType eg: soap, smtp, dime (only soap and soap12 are currently supported)
|
5165 |
+
* @return array
|
5166 |
+
* @access public
|
5167 |
+
*/
|
5168 |
+
function getOperations($portName = '', $bindingType = 'soap') {
|
5169 |
+
$ops = array();
|
5170 |
+
if ($bindingType == 'soap') {
|
5171 |
+
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
|
5172 |
+
} elseif ($bindingType == 'soap12') {
|
5173 |
+
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
|
5174 |
+
} else {
|
5175 |
+
$this->debug("getOperations bindingType $bindingType may not be supported");
|
5176 |
+
}
|
5177 |
+
$this->debug("getOperations for port '$portName' bindingType $bindingType");
|
5178 |
+
// loop thru ports
|
5179 |
+
foreach($this->ports as $port => $portData) {
|
5180 |
+
$this->debug("getOperations checking port $port bindingType " . $portData['bindingType']);
|
5181 |
+
if ($portName == '' || $port == $portName) {
|
5182 |
+
// binding type of port matches parameter
|
5183 |
+
if ($portData['bindingType'] == $bindingType) {
|
5184 |
+
$this->debug("getOperations found port $port bindingType $bindingType");
|
5185 |
+
//$this->debug("port data: " . $this->varDump($portData));
|
5186 |
+
//$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
|
5187 |
+
// merge bindings
|
5188 |
+
if (isset($this->bindings[ $portData['binding'] ]['operations'])) {
|
5189 |
+
$ops = array_merge ($ops, $this->bindings[ $portData['binding'] ]['operations']);
|
5190 |
+
}
|
5191 |
+
}
|
5192 |
+
}
|
5193 |
+
}
|
5194 |
+
if (count($ops) == 0) {
|
5195 |
+
$this->debug("getOperations found no operations for port '$portName' bindingType $bindingType");
|
5196 |
+
}
|
5197 |
+
return $ops;
|
5198 |
+
}
|
5199 |
+
|
5200 |
+
/**
|
5201 |
+
* returns an associative array of data necessary for calling an operation
|
5202 |
+
*
|
5203 |
+
* @param string $operation name of operation
|
5204 |
+
* @param string $bindingType type of binding eg: soap, soap12
|
5205 |
+
* @return array
|
5206 |
+
* @access public
|
5207 |
+
*/
|
5208 |
+
function getOperationData($operation, $bindingType = 'soap')
|
5209 |
+
{
|
5210 |
+
if ($bindingType == 'soap') {
|
5211 |
+
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
|
5212 |
+
} elseif ($bindingType == 'soap12') {
|
5213 |
+
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
|
5214 |
+
}
|
5215 |
+
// loop thru ports
|
5216 |
+
foreach($this->ports as $port => $portData) {
|
5217 |
+
// binding type of port matches parameter
|
5218 |
+
if ($portData['bindingType'] == $bindingType) {
|
5219 |
+
// get binding
|
5220 |
+
//foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
|
5221 |
+
foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {
|
5222 |
+
// note that we could/should also check the namespace here
|
5223 |
+
if ($operation == $bOperation) {
|
5224 |
+
$opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];
|
5225 |
+
return $opData;
|
5226 |
+
}
|
5227 |
+
}
|
5228 |
+
}
|
5229 |
+
}
|
5230 |
+
}
|
5231 |
+
|
5232 |
+
/**
|
5233 |
+
* returns an associative array of data necessary for calling an operation
|
5234 |
+
*
|
5235 |
+
* @param string $soapAction soapAction for operation
|
5236 |
+
* @param string $bindingType type of binding eg: soap, soap12
|
5237 |
+
* @return array
|
5238 |
+
* @access public
|
5239 |
+
*/
|
5240 |
+
function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') {
|
5241 |
+
if ($bindingType == 'soap') {
|
5242 |
+
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
|
5243 |
+
} elseif ($bindingType == 'soap12') {
|
5244 |
+
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
|
5245 |
+
}
|
5246 |
+
// loop thru ports
|
5247 |
+
foreach($this->ports as $port => $portData) {
|
5248 |
+
// binding type of port matches parameter
|
5249 |
+
if ($portData['bindingType'] == $bindingType) {
|
5250 |
+
// loop through operations for the binding
|
5251 |
+
foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
|
5252 |
+
if ($opData['soapAction'] == $soapAction) {
|
5253 |
+
return $opData;
|
5254 |
+
}
|
5255 |
+
}
|
5256 |
+
}
|
5257 |
+
}
|
5258 |
+
}
|
5259 |
+
|
5260 |
+
/**
|
5261 |
+
* returns an array of information about a given type
|
5262 |
+
* returns false if no type exists by the given name
|
5263 |
+
*
|
5264 |
+
* typeDef = array(
|
5265 |
+
* 'elements' => array(), // refs to elements array
|
5266 |
+
* 'restrictionBase' => '',
|
5267 |
+
* 'phpType' => '',
|
5268 |
+
* 'order' => '(sequence|all)',
|
5269 |
+
* 'attrs' => array() // refs to attributes array
|
5270 |
+
* )
|
5271 |
+
*
|
5272 |
+
* @param string $type the type
|
5273 |
+
* @param string $ns namespace (not prefix) of the type
|
5274 |
+
* @return mixed
|
5275 |
+
* @access public
|
5276 |
+
* @see nusoap_xmlschema
|
5277 |
+
*/
|
5278 |
+
function getTypeDef($type, $ns) {
|
5279 |
+
$this->debug("in getTypeDef: type=$type, ns=$ns");
|
5280 |
+
if ((! $ns) && isset($this->namespaces['tns'])) {
|
5281 |
+
$ns = $this->namespaces['tns'];
|
5282 |
+
$this->debug("in getTypeDef: type namespace forced to $ns");
|
5283 |
+
}
|
5284 |
+
if (!isset($this->schemas[$ns])) {
|
5285 |
+
foreach ($this->schemas as $ns0 => $schema0) {
|
5286 |
+
if (strcasecmp($ns, $ns0) == 0) {
|
5287 |
+
$this->debug("in getTypeDef: replacing schema namespace $ns with $ns0");
|
5288 |
+
$ns = $ns0;
|
5289 |
+
break;
|
5290 |
+
}
|
5291 |
+
}
|
5292 |
+
}
|
5293 |
+
if (isset($this->schemas[$ns])) {
|
5294 |
+
$this->debug("in getTypeDef: have schema for namespace $ns");
|
5295 |
+
for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
|
5296 |
+
$xs = &$this->schemas[$ns][$i];
|
5297 |
+
$t = $xs->getTypeDef($type);
|
5298 |
+
$this->appendDebug($xs->getDebug());
|
5299 |
+
$xs->clearDebug();
|
5300 |
+
if ($t) {
|
5301 |
+
$this->debug("in getTypeDef: found type $type");
|
5302 |
+
if (!isset($t['phpType'])) {
|
5303 |
+
// get info for type to tack onto the element
|
5304 |
+
$uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
|
5305 |
+
$ns = substr($t['type'], 0, strrpos($t['type'], ':'));
|
5306 |
+
$etype = $this->getTypeDef($uqType, $ns);
|
5307 |
+
if ($etype) {
|
5308 |
+
$this->debug("found type for [element] $type:");
|
5309 |
+
$this->debug($this->varDump($etype));
|
5310 |
+
if (isset($etype['phpType'])) {
|
5311 |
+
$t['phpType'] = $etype['phpType'];
|
5312 |
+
}
|
5313 |
+
if (isset($etype['elements'])) {
|
5314 |
+
$t['elements'] = $etype['elements'];
|
5315 |
+
}
|
5316 |
+
if (isset($etype['attrs'])) {
|
5317 |
+
$t['attrs'] = $etype['attrs'];
|
5318 |
+
}
|
5319 |
+
} else {
|
5320 |
+
$this->debug("did not find type for [element] $type");
|
5321 |
+
}
|
5322 |
+
}
|
5323 |
+
return $t;
|
5324 |
+
}
|
5325 |
+
}
|
5326 |
+
$this->debug("in getTypeDef: did not find type $type");
|
5327 |
+
} else {
|
5328 |
+
$this->debug("in getTypeDef: do not have schema for namespace $ns");
|
5329 |
+
}
|
5330 |
+
return false;
|
5331 |
+
}
|
5332 |
+
|
5333 |
+
/**
|
5334 |
+
* prints html description of services
|
5335 |
+
*
|
5336 |
+
* @access private
|
5337 |
+
*/
|
5338 |
+
function webDescription(){
|
5339 |
+
global $HTTP_SERVER_VARS;
|
5340 |
+
|
5341 |
+
if (isset($_SERVER)) {
|
5342 |
+
$PHP_SELF = $_SERVER['PHP_SELF'];
|
5343 |
+
} elseif (isset($HTTP_SERVER_VARS)) {
|
5344 |
+
$PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
|
5345 |
+
} else {
|
5346 |
+
$this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
|
5347 |
+
}
|
5348 |
+
|
5349 |
+
$b = '
|
5350 |
+
<html><head><title>NuSOAP: '.$this->serviceName.'</title>
|
5351 |
+
<style type="text/css">
|
5352 |
+
body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
|
5353 |
+
p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
|
5354 |
+
pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
|
5355 |
+
ul { margin-top: 10px; margin-left: 20px; }
|
5356 |
+
li { list-style-type: none; margin-top: 10px; color: #000000; }
|
5357 |
+
.content{
|
5358 |
+
margin-left: 0px; padding-bottom: 2em; }
|
5359 |
+
.nav {
|
5360 |
+
padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
|
5361 |
+
margin-top: 10px; margin-left: 0px; color: #000000;
|
5362 |
+
background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
|
5363 |
+
.title {
|
5364 |
+
font-family: arial; font-size: 26px; color: #ffffff;
|
5365 |
+
background-color: #999999; width: 100%;
|
5366 |
+
margin-left: 0px; margin-right: 0px;
|
5367 |
+
padding-top: 10px; padding-bottom: 10px;}
|
5368 |
+
.hidden {
|
5369 |
+
position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
|
5370 |
+
font-family: arial; overflow: hidden; width: 600;
|
5371 |
+
padding: 20px; font-size: 10px; background-color: #999999;
|
5372 |
+
layer-background-color:#FFFFFF; }
|
5373 |
+
a,a:active { color: charcoal; font-weight: bold; }
|
5374 |
+
a:visited { color: #666666; font-weight: bold; }
|
5375 |
+
a:hover { color: cc3300; font-weight: bold; }
|
5376 |
+
</style>
|
5377 |
+
<script language="JavaScript" type="text/javascript">
|
5378 |
+
<!--
|
5379 |
+
// POP-UP CAPTIONS...
|
5380 |
+
function lib_bwcheck(){ //Browsercheck (needed)
|
5381 |
+
this.ver=navigator.appVersion
|
5382 |
+
this.agent=navigator.userAgent
|
5383 |
+
this.dom=document.getElementById?1:0
|
5384 |
+
this.opera5=this.agent.indexOf("Opera 5")>-1
|
5385 |
+
this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
|
5386 |
+
this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
|
5387 |
+
this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
|
5388 |
+
this.ie=this.ie4||this.ie5||this.ie6
|
5389 |
+
this.mac=this.agent.indexOf("Mac")>-1
|
5390 |
+
this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
|
5391 |
+
this.ns4=(document.layers && !this.dom)?1:0;
|
5392 |
+
this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
|
5393 |
+
return this
|
5394 |
+
}
|
5395 |
+
var bw = new lib_bwcheck()
|
5396 |
+
//Makes crossbrowser object.
|
5397 |
+
function makeObj(obj){
|
5398 |
+
this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
|
5399 |
+
if(!this.evnt) return false
|
5400 |
+
this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
|
5401 |
+
this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
|
5402 |
+
this.writeIt=b_writeIt;
|
5403 |
+
return this
|
5404 |
+
}
|
5405 |
+
// A unit of measure that will be added when setting the position of a layer.
|
5406 |
+
//var px = bw.ns4||window.opera?"":"px";
|
5407 |
+
function b_writeIt(text){
|
5408 |
+
if (bw.ns4){this.wref.write(text);this.wref.close()}
|
5409 |
+
else this.wref.innerHTML = text
|
5410 |
+
}
|
5411 |
+
//Shows the messages
|
5412 |
+
var oDesc;
|
5413 |
+
function popup(divid){
|
5414 |
+
if(oDesc = new makeObj(divid)){
|
5415 |
+
oDesc.css.visibility = "visible"
|
5416 |
+
}
|
5417 |
+
}
|
5418 |
+
function popout(){ // Hides message
|
5419 |
+
if(oDesc) oDesc.css.visibility = "hidden"
|
5420 |
+
}
|
5421 |
+
//-->
|
5422 |
+
</script>
|
5423 |
+
</head>
|
5424 |
+
<body>
|
5425 |
+
<div class=content>
|
5426 |
+
<br><br>
|
5427 |
+
<div class=title>'.$this->serviceName.'</div>
|
5428 |
+
<div class=nav>
|
5429 |
+
<p>View the <a href="'.$PHP_SELF.'?wsdl">WSDL</a> for the service.
|
5430 |
+
Click on an operation name to view it's details.</p>
|
5431 |
+
<ul>';
|
5432 |
+
foreach($this->getOperations() as $op => $data){
|
5433 |
+
$b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
|
5434 |
+
// create hidden div
|
5435 |
+
$b .= "<div id='$op' class='hidden'>
|
5436 |
+
<a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
|
5437 |
+
foreach($data as $donnie => $marie){ // loop through opdata
|
5438 |
+
if($donnie == 'input' || $donnie == 'output'){ // show input/output data
|
5439 |
+
$b .= "<font color='white'>".ucfirst($donnie).':</font><br>';
|
5440 |
+
foreach($marie as $captain => $tenille){ // loop through data
|
5441 |
+
if($captain == 'parts'){ // loop thru parts
|
5442 |
+
$b .= " $captain:<br>";
|
5443 |
+
//if(is_array($tenille)){
|
5444 |
+
foreach($tenille as $joanie => $chachi){
|
5445 |
+
$b .= " $joanie: $chachi<br>";
|
5446 |
+
}
|
5447 |
+
//}
|
5448 |
+
} else {
|
5449 |
+
$b .= " $captain: $tenille<br>";
|
5450 |
+
}
|
5451 |
+
}
|
5452 |
+
} else {
|
5453 |
+
$b .= "<font color='white'>".ucfirst($donnie).":</font> $marie<br>";
|
5454 |
+
}
|
5455 |
+
}
|
5456 |
+
$b .= '</div>';
|
5457 |
+
}
|
5458 |
+
$b .= '
|
5459 |
+
<ul>
|
5460 |
+
</div>
|
5461 |
+
</div></body></html>';
|
5462 |
+
return $b;
|
5463 |
+
}
|
5464 |
+
|
5465 |
+
/**
|
5466 |
+
* serialize the parsed wsdl
|
5467 |
+
*
|
5468 |
+
* @param mixed $debug whether to put debug=1 in endpoint URL
|
5469 |
+
* @return string serialization of WSDL
|
5470 |
+
* @access public
|
5471 |
+
*/
|
5472 |
+
function serialize($debug = 0)
|
5473 |
+
{
|
5474 |
+
$xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
|
5475 |
+
$xml .= "\n<definitions";
|
5476 |
+
foreach($this->namespaces as $k => $v) {
|
5477 |
+
$xml .= " xmlns:$k=\"$v\"";
|
5478 |
+
}
|
5479 |
+
// 10.9.02 - add poulter fix for wsdl and tns declarations
|
5480 |
+
if (isset($this->namespaces['wsdl'])) {
|
5481 |
+
$xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
|
5482 |
+
}
|
5483 |
+
if (isset($this->namespaces['tns'])) {
|
5484 |
+
$xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
|
5485 |
+
}
|
5486 |
+
$xml .= '>';
|
5487 |
+
// imports
|
5488 |
+
if (sizeof($this->import) > 0) {
|
5489 |
+
foreach($this->import as $ns => $list) {
|
5490 |
+
foreach ($list as $ii) {
|
5491 |
+
if ($ii['location'] != '') {
|
5492 |
+
$xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
|
5493 |
+
} else {
|
5494 |
+
$xml .= '<import namespace="' . $ns . '" />';
|
5495 |
+
}
|
5496 |
+
}
|
5497 |
+
}
|
5498 |
+
}
|
5499 |
+
// types
|
5500 |
+
if (count($this->schemas)>=1) {
|
5501 |
+
$xml .= "\n<types>\n";
|
5502 |
+
foreach ($this->schemas as $ns => $list) {
|
5503 |
+
foreach ($list as $xs) {
|
5504 |
+
$xml .= $xs->serializeSchema();
|
5505 |
+
}
|
5506 |
+
}
|
5507 |
+
$xml .= '</types>';
|
5508 |
+
}
|
5509 |
+
// messages
|
5510 |
+
if (count($this->messages) >= 1) {
|
5511 |
+
foreach($this->messages as $msgName => $msgParts) {
|
5512 |
+
$xml .= "\n<message name=\"" . $msgName . '">';
|
5513 |
+
if(is_array($msgParts)){
|
5514 |
+
foreach($msgParts as $partName => $partType) {
|
5515 |
+
// print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
|
5516 |
+
if (strpos($partType, ':')) {
|
5517 |
+
$typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
|
5518 |
+
} elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
|
5519 |
+
// print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
|
5520 |
+
$typePrefix = 'xsd';
|
5521 |
+
} else {
|
5522 |
+
foreach($this->typemap as $ns => $types) {
|
5523 |
+
if (isset($types[$partType])) {
|
5524 |
+
$typePrefix = $this->getPrefixFromNamespace($ns);
|
5525 |
+
}
|
5526 |
+
}
|
5527 |
+
if (!isset($typePrefix)) {
|
5528 |
+
die("$partType has no namespace!");
|
5529 |
+
}
|
5530 |
+
}
|
5531 |
+
$ns = $this->getNamespaceFromPrefix($typePrefix);
|
5532 |
+
$localPart = $this->getLocalPart($partType);
|
5533 |
+
$typeDef = $this->getTypeDef($localPart, $ns);
|
5534 |
+
if ($typeDef['typeClass'] == 'element') {
|
5535 |
+
$elementortype = 'element';
|
5536 |
+
if (substr($localPart, -1) == '^') {
|
5537 |
+
$localPart = substr($localPart, 0, -1);
|
5538 |
+
}
|
5539 |
+
} else {
|
5540 |
+
$elementortype = 'type';
|
5541 |
+
}
|
5542 |
+
$xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
|
5543 |
+
}
|
5544 |
+
}
|
5545 |
+
$xml .= '</message>';
|
5546 |
+
}
|
5547 |
+
}
|
5548 |
+
// bindings & porttypes
|
5549 |
+
if (count($this->bindings) >= 1) {
|
5550 |
+
$binding_xml = '';
|
5551 |
+
$portType_xml = '';
|
5552 |
+
foreach($this->bindings as $bindingName => $attrs) {
|
5553 |
+
$binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
|
5554 |
+
$binding_xml .= "\n" . ' <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
|
5555 |
+
$portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
|
5556 |
+
foreach($attrs['operations'] as $opName => $opParts) {
|
5557 |
+
$binding_xml .= "\n" . ' <operation name="' . $opName . '">';
|
5558 |
+
$binding_xml .= "\n" . ' <soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $opParts['style'] . '"/>';
|
5559 |
+
if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
|
5560 |
+
$enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
|
5561 |
+
} else {
|
5562 |
+
$enc_style = '';
|
5563 |
+
}
|
5564 |
+
$binding_xml .= "\n" . ' <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
|
5565 |
+
if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
|
5566 |
+
$enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
|
5567 |
+
} else {
|
5568 |
+
$enc_style = '';
|
5569 |
+
}
|
5570 |
+
$binding_xml .= "\n" . ' <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
|
5571 |
+
$binding_xml .= "\n" . ' </operation>';
|
5572 |
+
$portType_xml .= "\n" . ' <operation name="' . $opParts['name'] . '"';
|
5573 |
+
if (isset($opParts['parameterOrder'])) {
|
5574 |
+
$portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
|
5575 |
+
}
|
5576 |
+
$portType_xml .= '>';
|
5577 |
+
if(isset($opParts['documentation']) && $opParts['documentation'] != '') {
|
5578 |
+
$portType_xml .= "\n" . ' <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
|
5579 |
+
}
|
5580 |
+
$portType_xml .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>';
|
5581 |
+
$portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>';
|
5582 |
+
$portType_xml .= "\n" . ' </operation>';
|
5583 |
+
}
|
5584 |
+
$portType_xml .= "\n" . '</portType>';
|
5585 |
+
$binding_xml .= "\n" . '</binding>';
|
5586 |
+
}
|
5587 |
+
$xml .= $portType_xml . $binding_xml;
|
5588 |
+
}
|
5589 |
+
// services
|
5590 |
+
$xml .= "\n<service name=\"" . $this->serviceName . '">';
|
5591 |
+
if (count($this->ports) >= 1) {
|
5592 |
+
foreach($this->ports as $pName => $attrs) {
|
5593 |
+
$xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
|
5594 |
+
$xml .= "\n" . ' <soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>';
|
5595 |
+
$xml .= "\n" . ' </port>';
|
5596 |
+
}
|
5597 |
+
}
|
5598 |
+
$xml .= "\n" . '</service>';
|
5599 |
+
return $xml . "\n</definitions>";
|
5600 |
+
}
|
5601 |
+
|
5602 |
+
/**
|
5603 |
+
* determine whether a set of parameters are unwrapped
|
5604 |
+
* when they are expect to be wrapped, Microsoft-style.
|
5605 |
+
*
|
5606 |
+
* @param string $type the type (element name) of the wrapper
|
5607 |
+
* @param array $parameters the parameter values for the SOAP call
|
5608 |
+
* @return boolean whether they parameters are unwrapped (and should be wrapped)
|
5609 |
+
* @access private
|
5610 |
+
*/
|
5611 |
+
function parametersMatchWrapped($type, &$parameters) {
|
5612 |
+
$this->debug("in parametersMatchWrapped type=$type, parameters=");
|
5613 |
+
$this->appendDebug($this->varDump($parameters));
|
5614 |
+
|
5615 |
+
// split type into namespace:unqualified-type
|
5616 |
+
if (strpos($type, ':')) {
|
5617 |
+
$uqType = substr($type, strrpos($type, ':') + 1);
|
5618 |
+
$ns = substr($type, 0, strrpos($type, ':'));
|
5619 |
+
$this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns");
|
5620 |
+
if ($this->getNamespaceFromPrefix($ns)) {
|
5621 |
+
$ns = $this->getNamespaceFromPrefix($ns);
|
5622 |
+
$this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns");
|
5623 |
+
}
|
5624 |
+
} else {
|
5625 |
+
// TODO: should the type be compared to types in XSD, and the namespace
|
5626 |
+
// set to XSD if the type matches?
|
5627 |
+
$this->debug("in parametersMatchWrapped: No namespace for type $type");
|
5628 |
+
$ns = '';
|
5629 |
+
$uqType = $type;
|
5630 |
+
}
|
5631 |
+
|
5632 |
+
// get the type information
|
5633 |
+
if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
|
5634 |
+
$this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type.");
|
5635 |
+
return false;
|
5636 |
+
}
|
5637 |
+
$this->debug("in parametersMatchWrapped: found typeDef=");
|
5638 |
+
$this->appendDebug($this->varDump($typeDef));
|
5639 |
+
if (substr($uqType, -1) == '^') {
|
5640 |
+
$uqType = substr($uqType, 0, -1);
|
5641 |
+
}
|
5642 |
+
$phpType = $typeDef['phpType'];
|
5643 |
+
$arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '');
|
5644 |
+
$this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType");
|
5645 |
+
|
5646 |
+
// we expect a complexType or element of complexType
|
5647 |
+
if ($phpType != 'struct') {
|
5648 |
+
$this->debug("in parametersMatchWrapped: not a struct");
|
5649 |
+
return false;
|
5650 |
+
}
|
5651 |
+
|
5652 |
+
// see whether the parameter names match the elements
|
5653 |
+
if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
|
5654 |
+
$elements = 0;
|
5655 |
+
$matches = 0;
|
5656 |
+
foreach ($typeDef['elements'] as $name => $attrs) {
|
5657 |
+
if (isset($parameters[$name])) {
|
5658 |
+
$this->debug("in parametersMatchWrapped: have parameter named $name");
|
5659 |
+
$matches++;
|
5660 |
+
} else {
|
5661 |
+
$this->debug("in parametersMatchWrapped: do not have parameter named $name");
|
5662 |
+
}
|
5663 |
+
$elements++;
|
5664 |
+
}
|
5665 |
+
|
5666 |
+
$this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names");
|
5667 |
+
if ($matches == 0) {
|
5668 |
+
return false;
|
5669 |
+
}
|
5670 |
+
return true;
|
5671 |
+
}
|
5672 |
+
|
5673 |
+
// since there are no elements for the type, if the user passed no
|
5674 |
+
// parameters, the parameters match wrapped.
|
5675 |
+
$this->debug("in parametersMatchWrapped: no elements type $ns:$uqType");
|
5676 |
+
return count($parameters) == 0;
|
5677 |
+
}
|
5678 |
+
|
5679 |
+
/**
|
5680 |
+
* serialize PHP values according to a WSDL message definition
|
5681 |
+
* contrary to the method name, this is not limited to RPC
|
5682 |
+
*
|
5683 |
+
* TODO
|
5684 |
+
* - multi-ref serialization
|
5685 |
+
* - validate PHP values against type definitions, return errors if invalid
|
5686 |
+
*
|
5687 |
+
* @param string $operation operation name
|
5688 |
+
* @param string $direction (input|output)
|
5689 |
+
* @param mixed $parameters parameter value(s)
|
5690 |
+
* @param string $bindingType (soap|soap12)
|
5691 |
+
* @return mixed parameters serialized as XML or false on error (e.g. operation not found)
|
5692 |
+
* @access public
|
5693 |
+
*/
|
5694 |
+
function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap') {
|
5695 |
+
$this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");
|
5696 |
+
$this->appendDebug('parameters=' . $this->varDump($parameters));
|
5697 |
+
|
5698 |
+
if ($direction != 'input' && $direction != 'output') {
|
5699 |
+
$this->debug('The value of the \$direction argument needs to be either "input" or "output"');
|
5700 |
+
$this->setError('The value of the \$direction argument needs to be either "input" or "output"');
|
5701 |
+
return false;
|
5702 |
+
}
|
5703 |
+
if (!$opData = $this->getOperationData($operation, $bindingType)) {
|
5704 |
+
$this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
|
5705 |
+
$this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
|
5706 |
+
return false;
|
5707 |
+
}
|
5708 |
+
$this->debug('in serializeRPCParameters: opData:');
|
5709 |
+
$this->appendDebug($this->varDump($opData));
|
5710 |
+
|
5711 |
+
// Get encoding style for output and set to current
|
5712 |
+
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
|
5713 |
+
if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
|
5714 |
+
$encodingStyle = $opData['output']['encodingStyle'];
|
5715 |
+
$enc_style = $encodingStyle;
|
5716 |
+
}
|
5717 |
+
|
5718 |
+
// set input params
|
5719 |
+
$xml = '';
|
5720 |
+
if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
|
5721 |
+
$parts = &$opData[$direction]['parts'];
|
5722 |
+
$part_count = sizeof($parts);
|
5723 |
+
$style = $opData['style'];
|
5724 |
+
$use = $opData[$direction]['use'];
|
5725 |
+
$this->debug("have $part_count part(s) to serialize using $style/$use");
|
5726 |
+
if (is_array($parameters)) {
|
5727 |
+
$parametersArrayType = $this->isArraySimpleOrStruct($parameters);
|
5728 |
+
$parameter_count = count($parameters);
|
5729 |
+
$this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize");
|
5730 |
+
// check for Microsoft-style wrapped parameters
|
5731 |
+
if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) {
|
5732 |
+
$this->debug('check whether the caller has wrapped the parameters');
|
5733 |
+
if ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1) {
|
5734 |
+
// TODO: consider checking here for double-wrapping, when
|
5735 |
+
// service function wraps, then NuSOAP wraps again
|
5736 |
+
$this->debug("change simple array to associative with 'parameters' element");
|
5737 |
+
$parameters['parameters'] = $parameters[0];
|
5738 |
+
unset($parameters[0]);
|
5739 |
+
}
|
5740 |
+
if (($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) {
|
5741 |
+
$this->debug('check whether caller\'s parameters match the wrapped ones');
|
5742 |
+
if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) {
|
5743 |
+
$this->debug('wrap the parameters for the caller');
|
5744 |
+
$parameters = array('parameters' => $parameters);
|
5745 |
+
$parameter_count = 1;
|
5746 |
+
}
|
5747 |
+
}
|
5748 |
+
}
|
5749 |
+
foreach ($parts as $name => $type) {
|
5750 |
+
$this->debug("serializing part $name of type $type");
|
5751 |
+
// Track encoding style
|
5752 |
+
if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
|
5753 |
+
$encodingStyle = $opData[$direction]['encodingStyle'];
|
5754 |
+
$enc_style = $encodingStyle;
|
5755 |
+
} else {
|
5756 |
+
$enc_style = false;
|
5757 |
+
}
|
5758 |
+
// NOTE: add error handling here
|
5759 |
+
// if serializeType returns false, then catch global error and fault
|
5760 |
+
if ($parametersArrayType == 'arraySimple') {
|
5761 |
+
$p = array_shift($parameters);
|
5762 |
+
$this->debug('calling serializeType w/indexed param');
|
5763 |
+
$xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
|
5764 |
+
} elseif (isset($parameters[$name])) {
|
5765 |
+
$this->debug('calling serializeType w/named param');
|
5766 |
+
$xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
|
5767 |
+
} else {
|
5768 |
+
// TODO: only send nillable
|
5769 |
+
$this->debug('calling serializeType w/null param');
|
5770 |
+
$xml .= $this->serializeType($name, $type, null, $use, $enc_style);
|
5771 |
+
}
|
5772 |
+
}
|
5773 |
+
} else {
|
5774 |
+
$this->debug('no parameters passed.');
|
5775 |
+
}
|
5776 |
+
}
|
5777 |
+
$this->debug("serializeRPCParameters returning: $xml");
|
5778 |
+
return $xml;
|
5779 |
+
}
|
5780 |
+
|
5781 |
+
/**
|
5782 |
+
* serialize a PHP value according to a WSDL message definition
|
5783 |
+
*
|
5784 |
+
* TODO
|
5785 |
+
* - multi-ref serialization
|
5786 |
+
* - validate PHP values against type definitions, return errors if invalid
|
5787 |
+
*
|
5788 |
+
* @param string $operation operation name
|
5789 |
+
* @param string $direction (input|output)
|
5790 |
+
* @param mixed $parameters parameter value(s)
|
5791 |
+
* @return mixed parameters serialized as XML or false on error (e.g. operation not found)
|
5792 |
+
* @access public
|
5793 |
+
* @deprecated
|
5794 |
+
*/
|
5795 |
+
function serializeParameters($operation, $direction, $parameters)
|
5796 |
+
{
|
5797 |
+
$this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
|
5798 |
+
$this->appendDebug('parameters=' . $this->varDump($parameters));
|
5799 |
+
|
5800 |
+
if ($direction != 'input' && $direction != 'output') {
|
5801 |
+
$this->debug('The value of the \$direction argument needs to be either "input" or "output"');
|
5802 |
+
$this->setError('The value of the \$direction argument needs to be either "input" or "output"');
|
5803 |
+
return false;
|
5804 |
+
}
|
5805 |
+
if (!$opData = $this->getOperationData($operation)) {
|
5806 |
+
$this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
|
5807 |
+
$this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
|
5808 |
+
return false;
|
5809 |
+
}
|
5810 |
+
$this->debug('opData:');
|
5811 |
+
$this->appendDebug($this->varDump($opData));
|
5812 |
+
|
5813 |
+
// Get encoding style for output and set to current
|
5814 |
+
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
|
5815 |
+
if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
|
5816 |
+
$encodingStyle = $opData['output']['encodingStyle'];
|
5817 |
+
$enc_style = $encodingStyle;
|
5818 |
+
}
|
5819 |
+
|
5820 |
+
// set input params
|
5821 |
+
$xml = '';
|
5822 |
+
if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
|
5823 |
+
|
5824 |
+
$use = $opData[$direction]['use'];
|
5825 |
+
$this->debug("use=$use");
|
5826 |
+
$this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
|
5827 |
+
if (is_array($parameters)) {
|
5828 |
+
$parametersArrayType = $this->isArraySimpleOrStruct($parameters);
|
5829 |
+
$this->debug('have ' . $parametersArrayType . ' parameters');
|
5830 |
+
foreach($opData[$direction]['parts'] as $name => $type) {
|
5831 |
+
$this->debug('serializing part "'.$name.'" of type "'.$type.'"');
|
5832 |
+
// Track encoding style
|
5833 |
+
if(isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
|
5834 |
+
$encodingStyle = $opData[$direction]['encodingStyle'];
|
5835 |
+
$enc_style = $encodingStyle;
|
5836 |
+
} else {
|
5837 |
+
$enc_style = false;
|
5838 |
+
}
|
5839 |
+
// NOTE: add error handling here
|
5840 |
+
// if serializeType returns false, then catch global error and fault
|
5841 |
+
if ($parametersArrayType == 'arraySimple') {
|
5842 |
+
$p = array_shift($parameters);
|
5843 |
+
$this->debug('calling serializeType w/indexed param');
|
5844 |
+
$xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
|
5845 |
+
} elseif (isset($parameters[$name])) {
|
5846 |
+
$this->debug('calling serializeType w/named param');
|
5847 |
+
$xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
|
5848 |
+
} else {
|
5849 |
+
// TODO: only send nillable
|
5850 |
+
$this->debug('calling serializeType w/null param');
|
5851 |
+
$xml .= $this->serializeType($name, $type, null, $use, $enc_style);
|
5852 |
+
}
|
5853 |
+
}
|
5854 |
+
} else {
|
5855 |
+
$this->debug('no parameters passed.');
|
5856 |
+
}
|
5857 |
+
}
|
5858 |
+
$this->debug("serializeParameters returning: $xml");
|
5859 |
+
return $xml;
|
5860 |
+
}
|
5861 |
+
|
5862 |
+
/**
|
5863 |
+
* serializes a PHP value according a given type definition
|
5864 |
+
*
|
5865 |
+
* @param string $name name of value (part or element)
|
5866 |
+
* @param string $type XML schema type of value (type or element)
|
5867 |
+
* @param mixed $value a native PHP value (parameter value)
|
5868 |
+
* @param string $use use for part (encoded|literal)
|
5869 |
+
* @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
|
5870 |
+
* @param boolean $unqualified a kludge for what should be XML namespace form handling
|
5871 |
+
* @return string value serialized as an XML string
|
5872 |
+
* @access private
|
5873 |
+
*/
|
5874 |
+
function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
|
5875 |
+
{
|
5876 |
+
$this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));
|
5877 |
+
$this->appendDebug("value=" . $this->varDump($value));
|
5878 |
+
if($use == 'encoded' && $encodingStyle) {
|
5879 |
+
$encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
|
5880 |
+
}
|
5881 |
+
|
5882 |
+
// if a soapval has been supplied, let its type override the WSDL
|
5883 |
+
if (is_object($value) && get_class($value) == 'soapval') {
|
5884 |
+
if ($value->type_ns) {
|
5885 |
+
$type = $value->type_ns . ':' . $value->type;
|
5886 |
+
$forceType = true;
|
5887 |
+
$this->debug("in serializeType: soapval overrides type to $type");
|
5888 |
+
} elseif ($value->type) {
|
5889 |
+
$type = $value->type;
|
5890 |
+
$forceType = true;
|
5891 |
+
$this->debug("in serializeType: soapval overrides type to $type");
|
5892 |
+
} else {
|
5893 |
+
$forceType = false;
|
5894 |
+
$this->debug("in serializeType: soapval does not override type");
|
5895 |
+
}
|
5896 |
+
$attrs = $value->attributes;
|
5897 |
+
$value = $value->value;
|
5898 |
+
$this->debug("in serializeType: soapval overrides value to $value");
|
5899 |
+
if ($attrs) {
|
5900 |
+
if (!is_array($value)) {
|
5901 |
+
$value['!'] = $value;
|
5902 |
+
}
|
5903 |
+
foreach ($attrs as $n => $v) {
|
5904 |
+
$value['!' . $n] = $v;
|
5905 |
+
}
|
5906 |
+
$this->debug("in serializeType: soapval provides attributes");
|
5907 |
+
}
|
5908 |
+
} else {
|
5909 |
+
$forceType = false;
|
5910 |
+
}
|
5911 |
+
|
5912 |
+
$xml = '';
|
5913 |
+
if (strpos($type, ':')) {
|
5914 |
+
$uqType = substr($type, strrpos($type, ':') + 1);
|
5915 |
+
$ns = substr($type, 0, strrpos($type, ':'));
|
5916 |
+
$this->debug("in serializeType: got a prefixed type: $uqType, $ns");
|
5917 |
+
if ($this->getNamespaceFromPrefix($ns)) {
|
5918 |
+
$ns = $this->getNamespaceFromPrefix($ns);
|
5919 |
+
$this->debug("in serializeType: expanded prefixed type: $uqType, $ns");
|
5920 |
+
}
|
5921 |
+
|
5922 |
+
if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/'){
|
5923 |
+
$this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
|
5924 |
+
if ($unqualified && $use == 'literal') {
|
5925 |
+
$elementNS = " xmlns=\"\"";
|
5926 |
+
} else {
|
5927 |
+
$elementNS = '';
|
5928 |
+
}
|
5929 |
+
if (is_null($value)) {
|
5930 |
+
if ($use == 'literal') {
|
5931 |
+
// TODO: depends on minOccurs
|
5932 |
+
$xml = "<$name$elementNS/>";
|
5933 |
+
} else {
|
5934 |
+
// TODO: depends on nillable, which should be checked before calling this method
|
5935 |
+
$xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
|
5936 |
+
}
|
5937 |
+
$this->debug("in serializeType: returning: $xml");
|
5938 |
+
return $xml;
|
5939 |
+
}
|
5940 |
+
if ($uqType == 'Array') {
|
5941 |
+
// JBoss/Axis does this sometimes
|
5942 |
+
return $this->serialize_val($value, $name, false, false, false, false, $use);
|
5943 |
+
}
|
5944 |
+
if ($uqType == 'boolean') {
|
5945 |
+
if ((is_string($value) && $value == 'false') || (! $value)) {
|
5946 |
+
$value = 'false';
|
5947 |
+
} else {
|
5948 |
+
$value = 'true';
|
5949 |
+
}
|
5950 |
+
}
|
5951 |
+
if ($uqType == 'string' && gettype($value) == 'string') {
|
5952 |
+
$value = $this->expandEntities($value);
|
5953 |
+
}
|
5954 |
+
if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {
|
5955 |
+
$value = sprintf("%.0lf", $value);
|
5956 |
+
}
|
5957 |
+
// it's a scalar
|
5958 |
+
// TODO: what about null/nil values?
|
5959 |
+
// check type isn't a custom type extending xmlschema namespace
|
5960 |
+
if (!$this->getTypeDef($uqType, $ns)) {
|
5961 |
+
if ($use == 'literal') {
|
5962 |
+
if ($forceType) {
|
5963 |
+
$xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
|
5964 |
+
} else {
|
5965 |
+
$xml = "<$name$elementNS>$value</$name>";
|
5966 |
+
}
|
5967 |
+
} else {
|
5968 |
+
$xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
|
5969 |
+
}
|
5970 |
+
$this->debug("in serializeType: returning: $xml");
|
5971 |
+
return $xml;
|
5972 |
+
}
|
5973 |
+
$this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');
|
5974 |
+
} else if ($ns == 'http://xml.apache.org/xml-soap') {
|
5975 |
+
$this->debug('in serializeType: appears to be Apache SOAP type');
|
5976 |
+
if ($uqType == 'Map') {
|
5977 |
+
$tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
|
5978 |
+
if (! $tt_prefix) {
|
5979 |
+
$this->debug('in serializeType: Add namespace for Apache SOAP type');
|
5980 |
+
$tt_prefix = 'ns' . rand(1000, 9999);
|
5981 |
+
$this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap';
|
5982 |
+
// force this to be added to usedNamespaces
|
5983 |
+
$tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
|
5984 |
+
}
|
5985 |
+
$contents = '';
|
5986 |
+
foreach($value as $k => $v) {
|
5987 |
+
$this->debug("serializing map element: key $k, value $v");
|
5988 |
+
$contents .= '<item>';
|
5989 |
+
$contents .= $this->serialize_val($k,'key',false,false,false,false,$use);
|
5990 |
+
$contents .= $this->serialize_val($v,'value',false,false,false,false,$use);
|
5991 |
+
$contents .= '</item>';
|
5992 |
+
}
|
5993 |
+
if ($use == 'literal') {
|
5994 |
+
if ($forceType) {
|
5995 |
+
$xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
|
5996 |
+
} else {
|
5997 |
+
$xml = "<$name>$contents</$name>";
|
5998 |
+
}
|
5999 |
+
} else {
|
6000 |
+
$xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
|
6001 |
+
}
|
6002 |
+
$this->debug("in serializeType: returning: $xml");
|
6003 |
+
return $xml;
|
6004 |
+
}
|
6005 |
+
$this->debug('in serializeType: Apache SOAP type, but only support Map');
|
6006 |
+
}
|
6007 |
+
} else {
|
6008 |
+
// TODO: should the type be compared to types in XSD, and the namespace
|
6009 |
+
// set to XSD if the type matches?
|
6010 |
+
$this->debug("in serializeType: No namespace for type $type");
|
6011 |
+
$ns = '';
|
6012 |
+
$uqType = $type;
|
6013 |
+
}
|
6014 |
+
if(!$typeDef = $this->getTypeDef($uqType, $ns)){
|
6015 |
+
$this->setError("$type ($uqType) is not a supported type.");
|
6016 |
+
$this->debug("in serializeType: $type ($uqType) is not a supported type.");
|
6017 |
+
return false;
|
6018 |
+
} else {
|
6019 |
+
$this->debug("in serializeType: found typeDef");
|
6020 |
+
$this->appendDebug('typeDef=' . $this->varDump($typeDef));
|
6021 |
+
if (substr($uqType, -1) == '^') {
|
6022 |
+
$uqType = substr($uqType, 0, -1);
|
6023 |
+
}
|
6024 |
+
}
|
6025 |
+
if (!isset($typeDef['phpType'])) {
|
6026 |
+
$this->setError("$type ($uqType) has no phpType.");
|
6027 |
+
$this->debug("in serializeType: $type ($uqType) has no phpType.");
|
6028 |
+
return false;
|
6029 |
+
}
|
6030 |
+
$phpType = $typeDef['phpType'];
|
6031 |
+
$this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') );
|
6032 |
+
// if php type == struct, map value to the <all> element names
|
6033 |
+
if ($phpType == 'struct') {
|
6034 |
+
if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
|
6035 |
+
$elementName = $uqType;
|
6036 |
+
if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
|
6037 |
+
$elementNS = " xmlns=\"$ns\"";
|
6038 |
+
} else {
|
6039 |
+
$elementNS = " xmlns=\"\"";
|
6040 |
+
}
|
6041 |
+
} else {
|
6042 |
+
$elementName = $name;
|
6043 |
+
if ($unqualified) {
|
6044 |
+
$elementNS = " xmlns=\"\"";
|
6045 |
+
} else {
|
6046 |
+
$elementNS = '';
|
6047 |
+
}
|
6048 |
+
}
|
6049 |
+
if (is_null($value)) {
|
6050 |
+
if ($use == 'literal') {
|
6051 |
+
// TODO: depends on minOccurs and nillable
|
6052 |
+
$xml = "<$elementName$elementNS/>";
|
6053 |
+
} else {
|
6054 |
+
$xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
|
6055 |
+
}
|
6056 |
+
$this->debug("in serializeType: returning: $xml");
|
6057 |
+
return $xml;
|
6058 |
+
}
|
6059 |
+
if (is_object($value)) {
|
6060 |
+
$value = get_object_vars($value);
|
6061 |
+
}
|
6062 |
+
if (is_array($value)) {
|
6063 |
+
$elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
|
6064 |
+
if ($use == 'literal') {
|
6065 |
+
if ($forceType) {
|
6066 |
+
$xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
|
6067 |
+
} else {
|
6068 |
+
$xml = "<$elementName$elementNS$elementAttrs>";
|
6069 |
+
}
|
6070 |
+
} else {
|
6071 |
+
$xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
|
6072 |
+
}
|
6073 |
+
|
6074 |
+
if (isset($typeDef['simpleContent']) && $typeDef['simpleContent'] == 'true') {
|
6075 |
+
if (isset($value['!'])) {
|
6076 |
+
$xml .= $value['!'];
|
6077 |
+
$this->debug("in serializeType: serialized simpleContent for type $type");
|
6078 |
+
} else {
|
6079 |
+
$this->debug("in serializeType: no simpleContent to serialize for type $type");
|
6080 |
+
}
|
6081 |
+
} else {
|
6082 |
+
// complexContent
|
6083 |
+
$xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
|
6084 |
+
}
|
6085 |
+
$xml .= "</$elementName>";
|
6086 |
+
} else {
|
6087 |
+
$this->debug("in serializeType: phpType is struct, but value is not an array");
|
6088 |
+
$this->setError("phpType is struct, but value is not an array: see debug output for details");
|
6089 |
+
$xml = '';
|
6090 |
+
}
|
6091 |
+
} elseif ($phpType == 'array') {
|
6092 |
+
if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
|
6093 |
+
$elementNS = " xmlns=\"$ns\"";
|
6094 |
+
} else {
|
6095 |
+
if ($unqualified) {
|
6096 |
+
$elementNS = " xmlns=\"\"";
|
6097 |
+
} else {
|
6098 |
+
$elementNS = '';
|
6099 |
+
}
|
6100 |
+
}
|
6101 |
+
if (is_null($value)) {
|
6102 |
+
if ($use == 'literal') {
|
6103 |
+
// TODO: depends on minOccurs
|
6104 |
+
$xml = "<$name$elementNS/>";
|
6105 |
+
} else {
|
6106 |
+
$xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
|
6107 |
+
$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
|
6108 |
+
":Array\" " .
|
6109 |
+
$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
|
6110 |
+
':arrayType="' .
|
6111 |
+
$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .
|
6112 |
+
':' .
|
6113 |
+
$this->getLocalPart($typeDef['arrayType'])."[0]\"/>";
|
6114 |
+
}
|
6115 |
+
$this->debug("in serializeType: returning: $xml");
|
6116 |
+
return $xml;
|
6117 |
+
}
|
6118 |
+
if (isset($typeDef['multidimensional'])) {
|
6119 |
+
$nv = array();
|
6120 |
+
foreach($value as $v) {
|
6121 |
+
$cols = ',' . sizeof($v);
|
6122 |
+
$nv = array_merge($nv, $v);
|
6123 |
+
}
|
6124 |
+
$value = $nv;
|
6125 |
+
} else {
|
6126 |
+
$cols = '';
|
6127 |
+
}
|
6128 |
+
if (is_array($value) && sizeof($value) >= 1) {
|
6129 |
+
$rows = sizeof($value);
|
6130 |
+
$contents = '';
|
6131 |
+
foreach($value as $k => $v) {
|
6132 |
+
$this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");
|
6133 |
+
//if (strpos($typeDef['arrayType'], ':') ) {
|
6134 |
+
if (!in_array($typeDef['arrayType'],$this->typemap['http://www.w3.org/2001/XMLSchema'])) {
|
6135 |
+
$contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
|
6136 |
+
} else {
|
6137 |
+
$contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
|
6138 |
+
}
|
6139 |
+
}
|
6140 |
+
} else {
|
6141 |
+
$rows = 0;
|
6142 |
+
$contents = null;
|
6143 |
+
}
|
6144 |
+
// TODO: for now, an empty value will be serialized as a zero element
|
6145 |
+
// array. Revisit this when coding the handling of null/nil values.
|
6146 |
+
if ($use == 'literal') {
|
6147 |
+
$xml = "<$name$elementNS>"
|
6148 |
+
.$contents
|
6149 |
+
."</$name>";
|
6150 |
+
} else {
|
6151 |
+
$xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '.
|
6152 |
+
$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
|
6153 |
+
.':arrayType="'
|
6154 |
+
.$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
|
6155 |
+
.":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">"
|
6156 |
+
.$contents
|
6157 |
+
."</$name>";
|
6158 |
+
}
|
6159 |
+
} elseif ($phpType == 'scalar') {
|
6160 |
+
if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
|
6161 |
+
$elementNS = " xmlns=\"$ns\"";
|
6162 |
+
} else {
|
6163 |
+
if ($unqualified) {
|
6164 |
+
$elementNS = " xmlns=\"\"";
|
6165 |
+
} else {
|
6166 |
+
$elementNS = '';
|
6167 |
+
}
|
6168 |
+
}
|
6169 |
+
if ($use == 'literal') {
|
6170 |
+
if ($forceType) {
|
6171 |
+
$xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
|
6172 |
+
} else {
|
6173 |
+
$xml = "<$name$elementNS>$value</$name>";
|
6174 |
+
}
|
6175 |
+
} else {
|
6176 |
+
$xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
|
6177 |
+
}
|
6178 |
+
}
|
6179 |
+
$this->debug("in serializeType: returning: $xml");
|
6180 |
+
return $xml;
|
6181 |
+
}
|
6182 |
+
|
6183 |
+
/**
|
6184 |
+
* serializes the attributes for a complexType
|
6185 |
+
*
|
6186 |
+
* @param array $typeDef our internal representation of an XML schema type (or element)
|
6187 |
+
* @param mixed $value a native PHP value (parameter value)
|
6188 |
+
* @param string $ns the namespace of the type
|
6189 |
+
* @param string $uqType the local part of the type
|
6190 |
+
* @return string value serialized as an XML string
|
6191 |
+
* @access private
|
6192 |
+
*/
|
6193 |
+
function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) {
|
6194 |
+
$this->debug("serializeComplexTypeAttributes for XML Schema type $ns:$uqType");
|
6195 |
+
$xml = '';
|
6196 |
+
if (isset($typeDef['extensionBase'])) {
|
6197 |
+
$nsx = $this->getPrefix($typeDef['extensionBase']);
|
6198 |
+
$uqTypex = $this->getLocalPart($typeDef['extensionBase']);
|
6199 |
+
if ($this->getNamespaceFromPrefix($nsx)) {
|
6200 |
+
$nsx = $this->getNamespaceFromPrefix($nsx);
|
6201 |
+
}
|
6202 |
+
if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) {
|
6203 |
+
$this->debug("serialize attributes for extension base $nsx:$uqTypex");
|
6204 |
+
$xml .= $this->serializeComplexTypeAttributes($typeDefx, $value, $nsx, $uqTypex);
|
6205 |
+
} else {
|
6206 |
+
$this->debug("extension base $nsx:$uqTypex is not a supported type");
|
6207 |
+
}
|
6208 |
+
}
|
6209 |
+
if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
|
6210 |
+
$this->debug("serialize attributes for XML Schema type $ns:$uqType");
|
6211 |
+
if (is_array($value)) {
|
6212 |
+
$xvalue = $value;
|
6213 |
+
} elseif (is_object($value)) {
|
6214 |
+
$xvalue = get_object_vars($value);
|
6215 |
+
} else {
|
6216 |
+
$this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
|
6217 |
+
$xvalue = array();
|
6218 |
+
}
|
6219 |
+
foreach ($typeDef['attrs'] as $aName => $attrs) {
|
6220 |
+
if (isset($xvalue['!' . $aName])) {
|
6221 |
+
$xname = '!' . $aName;
|
6222 |
+
$this->debug("value provided for attribute $aName with key $xname");
|
6223 |
+
} elseif (isset($xvalue[$aName])) {
|
6224 |
+
$xname = $aName;
|
6225 |
+
$this->debug("value provided for attribute $aName with key $xname");
|
6226 |
+
} elseif (isset($attrs['default'])) {
|
6227 |
+
$xname = '!' . $aName;
|
6228 |
+
$xvalue[$xname] = $attrs['default'];
|
6229 |
+
$this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);
|
6230 |
+
} else {
|
6231 |
+
$xname = '';
|
6232 |
+
$this->debug("no value provided for attribute $aName");
|
6233 |
+
}
|
6234 |
+
if ($xname) {
|
6235 |
+
$xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";
|
6236 |
+
}
|
6237 |
+
}
|
6238 |
+
} else {
|
6239 |
+
$this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
|
6240 |
+
}
|
6241 |
+
return $xml;
|
6242 |
+
}
|
6243 |
+
|
6244 |
+
/**
|
6245 |
+
* serializes the elements for a complexType
|
6246 |
+
*
|
6247 |
+
* @param array $typeDef our internal representation of an XML schema type (or element)
|
6248 |
+
* @param mixed $value a native PHP value (parameter value)
|
6249 |
+
* @param string $ns the namespace of the type
|
6250 |
+
* @param string $uqType the local part of the type
|
6251 |
+
* @param string $use use for part (encoded|literal)
|
6252 |
+
* @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
|
6253 |
+
* @return string value serialized as an XML string
|
6254 |
+
* @access private
|
6255 |
+
*/
|
6256 |
+
function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) {
|
6257 |
+
$this->debug("in serializeComplexTypeElements for XML Schema type $ns:$uqType");
|
6258 |
+
$xml = '';
|
6259 |
+
if (isset($typeDef['extensionBase'])) {
|
6260 |
+
$nsx = $this->getPrefix($typeDef['extensionBase']);
|
6261 |
+
$uqTypex = $this->getLocalPart($typeDef['extensionBase']);
|
6262 |
+
if ($this->getNamespaceFromPrefix($nsx)) {
|
6263 |
+
$nsx = $this->getNamespaceFromPrefix($nsx);
|
6264 |
+
}
|
6265 |
+
if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) {
|
6266 |
+
$this->debug("serialize elements for extension base $nsx:$uqTypex");
|
6267 |
+
$xml .= $this->serializeComplexTypeElements($typeDefx, $value, $nsx, $uqTypex, $use, $encodingStyle);
|
6268 |
+
} else {
|
6269 |
+
$this->debug("extension base $nsx:$uqTypex is not a supported type");
|
6270 |
+
}
|
6271 |
+
}
|
6272 |
+
if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
|
6273 |
+
$this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
|
6274 |
+
if (is_array($value)) {
|
6275 |
+
$xvalue = $value;
|
6276 |
+
} elseif (is_object($value)) {
|
6277 |
+
$xvalue = get_object_vars($value);
|
6278 |
+
} else {
|
6279 |
+
$this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
|
6280 |
+
$xvalue = array();
|
6281 |
+
}
|
6282 |
+
// toggle whether all elements are present - ideally should validate against schema
|
6283 |
+
if (count($typeDef['elements']) != count($xvalue)){
|
6284 |
+
$optionals = true;
|
6285 |
+
}
|
6286 |
+
foreach ($typeDef['elements'] as $eName => $attrs) {
|
6287 |
+
if (!isset($xvalue[$eName])) {
|
6288 |
+
if (isset($attrs['default'])) {
|
6289 |
+
$xvalue[$eName] = $attrs['default'];
|
6290 |
+
$this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);
|
6291 |
+
}
|
6292 |
+
}
|
6293 |
+
// if user took advantage of a minOccurs=0, then only serialize named parameters
|
6294 |
+
if (isset($optionals)
|
6295 |
+
&& (!isset($xvalue[$eName]))
|
6296 |
+
&& ( (!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')
|
6297 |
+
){
|
6298 |
+
if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {
|
6299 |
+
$this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
|
6300 |
+
}
|
6301 |
+
// do nothing
|
6302 |
+
$this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");
|
6303 |
+
} else {
|
6304 |
+
// get value
|
6305 |
+
if (isset($xvalue[$eName])) {
|
6306 |
+
$v = $xvalue[$eName];
|
6307 |
+
} else {
|
6308 |
+
$v = null;
|
6309 |
+
}
|
6310 |
+
if (isset($attrs['form'])) {
|
6311 |
+
$unqualified = ($attrs['form'] == 'unqualified');
|
6312 |
+
} else {
|
6313 |
+
$unqualified = false;
|
6314 |
+
}
|
6315 |
+
if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
|
6316 |
+
$vv = $v;
|
6317 |
+
foreach ($vv as $k => $v) {
|
6318 |
+
if (isset($attrs['type']) || isset($attrs['ref'])) {
|
6319 |
+
// serialize schema-defined type
|
6320 |
+
$xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
|
6321 |
+
} else {
|
6322 |
+
// serialize generic type (can this ever really happen?)
|
6323 |
+
$this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
|
6324 |
+
$xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
|
6325 |
+
}
|
6326 |
+
}
|
6327 |
+
} else {
|
6328 |
+
if (is_null($v) && isset($attrs['minOccurs']) && $attrs['minOccurs'] == '0') {
|
6329 |
+
// do nothing
|
6330 |
+
} elseif (is_null($v) && isset($attrs['nillable']) && $attrs['nillable'] == 'true') {
|
6331 |
+
// TODO: serialize a nil correctly, but for now serialize schema-defined type
|
6332 |
+
$xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
|
6333 |
+
} elseif (isset($attrs['type']) || isset($attrs['ref'])) {
|
6334 |
+
// serialize schema-defined type
|
6335 |
+
$xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
|
6336 |
+
} else {
|
6337 |
+
// serialize generic type (can this ever really happen?)
|
6338 |
+
$this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
|
6339 |
+
$xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
|
6340 |
+
}
|
6341 |
+
}
|
6342 |
+
}
|
6343 |
+
}
|
6344 |
+
} else {
|
6345 |
+
$this->debug("no elements to serialize for XML Schema type $ns:$uqType");
|
6346 |
+
}
|
6347 |
+
return $xml;
|
6348 |
+
}
|
6349 |
+
|
6350 |
+
/**
|
6351 |
+
* adds an XML Schema complex type to the WSDL types
|
6352 |
+
*
|
6353 |
+
* @param string $name
|
6354 |
+
* @param string $typeClass (complexType|simpleType|attribute)
|
6355 |
+
* @param string $phpType currently supported are array and struct (php assoc array)
|
6356 |
+
* @param string $compositor (all|sequence|choice)
|
6357 |
+
* @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
|
6358 |
+
* @param array $elements e.g. array ( name => array(name=>'',type=>'') )
|
6359 |
+
* @param array $attrs e.g. array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]'))
|
6360 |
+
* @param string $arrayType as namespace:name (xsd:string)
|
6361 |
+
* @see nusoap_xmlschema
|
6362 |
+
* @access public
|
6363 |
+
*/
|
6364 |
+
function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') {
|
6365 |
+
if (count($elements) > 0) {
|
6366 |
+
$eElements = array();
|
6367 |
+
foreach($elements as $n => $e){
|
6368 |
+
// expand each element
|
6369 |
+
$ee = array();
|
6370 |
+
foreach ($e as $k => $v) {
|
6371 |
+
$k = strpos($k,':') ? $this->expandQname($k) : $k;
|
6372 |
+
$v = strpos($v,':') ? $this->expandQname($v) : $v;
|
6373 |
+
$ee[$k] = $v;
|
6374 |
+
}
|
6375 |
+
$eElements[$n] = $ee;
|
6376 |
+
}
|
6377 |
+
$elements = $eElements;
|
6378 |
+
}
|
6379 |
+
|
6380 |
+
if (count($attrs) > 0) {
|
6381 |
+
foreach($attrs as $n => $a){
|
6382 |
+
// expand each attribute
|
6383 |
+
foreach ($a as $k => $v) {
|
6384 |
+
$k = strpos($k,':') ? $this->expandQname($k) : $k;
|
6385 |
+
$v = strpos($v,':') ? $this->expandQname($v) : $v;
|
6386 |
+
$aa[$k] = $v;
|
6387 |
+
}
|
6388 |
+
$eAttrs[$n] = $aa;
|
6389 |
+
}
|
6390 |
+
$attrs = $eAttrs;
|
6391 |
+
}
|
6392 |
+
|
6393 |
+
$restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
|
6394 |
+
$arrayType = strpos($arrayType,':') ? $this->expandQname($arrayType) : $arrayType;
|
6395 |
+
|
6396 |
+
$typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
|
6397 |
+
$this->schemas[$typens][0]->addComplexType($name,$typeClass,$phpType,$compositor,$restrictionBase,$elements,$attrs,$arrayType);
|
6398 |
+
}
|
6399 |
+
|
6400 |
+
/**
|
6401 |
+
* adds an XML Schema simple type to the WSDL types
|
6402 |
+
*
|
6403 |
+
* @param string $name
|
6404 |
+
* @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
|
6405 |
+
* @param string $typeClass (should always be simpleType)
|
6406 |
+
* @param string $phpType (should always be scalar)
|
6407 |
+
* @param array $enumeration array of values
|
6408 |
+
* @see nusoap_xmlschema
|
6409 |
+
* @access public
|
6410 |
+
*/
|
6411 |
+
function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
|
6412 |
+
$restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
|
6413 |
+
|
6414 |
+
$typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
|
6415 |
+
$this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
|
6416 |
+
}
|
6417 |
+
|
6418 |
+
/**
|
6419 |
+
* adds an element to the WSDL types
|
6420 |
+
*
|
6421 |
+
* @param array $attrs attributes that must include name and type
|
6422 |
+
* @see nusoap_xmlschema
|
6423 |
+
* @access public
|
6424 |
+
*/
|
6425 |
+
function addElement($attrs) {
|
6426 |
+
$typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
|
6427 |
+
$this->schemas[$typens][0]->addElement($attrs);
|
6428 |
+
}
|
6429 |
+
|
6430 |
+
/**
|
6431 |
+
* register an operation with the server
|
6432 |
+
*
|
6433 |
+
* @param string $name operation (method) name
|
6434 |
+
* @param array $in assoc array of input values: key = param name, value = param type
|
6435 |
+
* @param array $out assoc array of output values: key = param name, value = param type
|
6436 |
+
* @param string $namespace optional The namespace for the operation
|
6437 |
+
* @param string $soapaction optional The soapaction for the operation
|
6438 |
+
* @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
|
6439 |
+
* @param string $use (encoded|literal) optional The use for the parameters (cannot mix right now)
|
6440 |
+
* @param string $documentation optional The description to include in the WSDL
|
6441 |
+
* @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
|
6442 |
+
* @access public
|
6443 |
+
*/
|
6444 |
+
function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = ''){
|
6445 |
+
if ($use == 'encoded' && $encodingStyle == '') {
|
6446 |
+
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
|
6447 |
+
}
|
6448 |
+
|
6449 |
+
if ($style == 'document') {
|
6450 |
+
$elements = array();
|
6451 |
+
foreach ($in as $n => $t) {
|
6452 |
+
$elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified');
|
6453 |
+
}
|
6454 |
+
$this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
|
6455 |
+
$this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
|
6456 |
+
$in = array('parameters' => 'tns:' . $name . '^');
|
6457 |
+
|
6458 |
+
$elements = array();
|
6459 |
+
foreach ($out as $n => $t) {
|
6460 |
+
$elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified');
|
6461 |
+
}
|
6462 |
+
$this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
|
6463 |
+
$this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
|
6464 |
+
$out = array('parameters' => 'tns:' . $name . 'Response' . '^');
|
6465 |
+
}
|
6466 |
+
|
6467 |
+
// get binding
|
6468 |
+
$this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =
|
6469 |
+
array(
|
6470 |
+
'name' => $name,
|
6471 |
+
'binding' => $this->serviceName . 'Binding',
|
6472 |
+
'endpoint' => $this->endpoint,
|
6473 |
+
'soapAction' => $soapaction,
|
6474 |
+
'style' => $style,
|
6475 |
+
'input' => array(
|
6476 |
+
'use' => $use,
|
6477 |
+
'namespace' => $namespace,
|
6478 |
+
'encodingStyle' => $encodingStyle,
|
6479 |
+
'message' => $name . 'Request',
|
6480 |
+
'parts' => $in),
|
6481 |
+
'output' => array(
|
6482 |
+
'use' => $use,
|
6483 |
+
'namespace' => $namespace,
|
6484 |
+
'encodingStyle' => $encodingStyle,
|
6485 |
+
'message' => $name . 'Response',
|
6486 |
+
'parts' => $out),
|
6487 |
+
'namespace' => $namespace,
|
6488 |
+
'transport' => 'http://schemas.xmlsoap.org/soap/http',
|
6489 |
+
'documentation' => $documentation);
|
6490 |
+
// add portTypes
|
6491 |
+
// add messages
|
6492 |
+
if($in)
|
6493 |
+
{
|
6494 |
+
foreach($in as $pName => $pType)
|
6495 |
+
{
|
6496 |
+
if(strpos($pType,':')) {
|
6497 |
+
$pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
|
6498 |
+
}
|
6499 |
+
$this->messages[$name.'Request'][$pName] = $pType;
|
6500 |
+
}
|
6501 |
+
} else {
|
6502 |
+
$this->messages[$name.'Request']= '0';
|
6503 |
+
}
|
6504 |
+
if($out)
|
6505 |
+
{
|
6506 |
+
foreach($out as $pName => $pType)
|
6507 |
+
{
|
6508 |
+
if(strpos($pType,':')) {
|
6509 |
+
$pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
|
6510 |
+
}
|
6511 |
+
$this->messages[$name.'Response'][$pName] = $pType;
|
6512 |
+
}
|
6513 |
+
} else {
|
6514 |
+
$this->messages[$name.'Response']= '0';
|
6515 |
+
}
|
6516 |
+
return true;
|
6517 |
+
}
|
6518 |
+
}
|
6519 |
+
?><?php
|
6520 |
+
|
6521 |
+
|
6522 |
+
|
6523 |
+
/**
|
6524 |
+
*
|
6525 |
+
* nusoap_parser class parses SOAP XML messages into native PHP values
|
6526 |
+
*
|
6527 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
6528 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
6529 |
+
* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
|
6530 |
+
* @access public
|
6531 |
+
*/
|
6532 |
+
class nusoap_parser extends nusoap_base {
|
6533 |
+
|
6534 |
+
var $xml = '';
|
6535 |
+
var $xml_encoding = '';
|
6536 |
+
var $method = '';
|
6537 |
+
var $root_struct = '';
|
6538 |
+
var $root_struct_name = '';
|
6539 |
+
var $root_struct_namespace = '';
|
6540 |
+
var $root_header = '';
|
6541 |
+
var $document = ''; // incoming SOAP body (text)
|
6542 |
+
// determines where in the message we are (envelope,header,body,method)
|
6543 |
+
var $status = '';
|
6544 |
+
var $position = 0;
|
6545 |
+
var $depth = 0;
|
6546 |
+
var $default_namespace = '';
|
6547 |
+
var $namespaces = array();
|
6548 |
+
var $message = array();
|
6549 |
+
var $parent = '';
|
6550 |
+
var $fault = false;
|
6551 |
+
var $fault_code = '';
|
6552 |
+
var $fault_str = '';
|
6553 |
+
var $fault_detail = '';
|
6554 |
+
var $depth_array = array();
|
6555 |
+
var $debug_flag = true;
|
6556 |
+
var $soapresponse = NULL; // parsed SOAP Body
|
6557 |
+
var $soapheader = NULL; // parsed SOAP Header
|
6558 |
+
var $responseHeaders = ''; // incoming SOAP headers (text)
|
6559 |
+
var $body_position = 0;
|
6560 |
+
// for multiref parsing:
|
6561 |
+
// array of id => pos
|
6562 |
+
var $ids = array();
|
6563 |
+
// array of id => hrefs => pos
|
6564 |
+
var $multirefs = array();
|
6565 |
+
// toggle for auto-decoding element content
|
6566 |
+
var $decode_utf8 = true;
|
6567 |
+
|
6568 |
+
/**
|
6569 |
+
* constructor that actually does the parsing
|
6570 |
+
*
|
6571 |
+
* @param string $xml SOAP message
|
6572 |
+
* @param string $encoding character encoding scheme of message
|
6573 |
+
* @param string $method method for which XML is parsed (unused?)
|
6574 |
+
* @param string $decode_utf8 whether to decode UTF-8 to ISO-8859-1
|
6575 |
+
* @access public
|
6576 |
+
*/
|
6577 |
+
function nusoap_parser($xml,$encoding='UTF-8',$method='',$decode_utf8=true){
|
6578 |
+
parent::nusoap_base();
|
6579 |
+
$this->xml = $xml;
|
6580 |
+
$this->xml_encoding = $encoding;
|
6581 |
+
$this->method = $method;
|
6582 |
+
$this->decode_utf8 = $decode_utf8;
|
6583 |
+
|
6584 |
+
// Check whether content has been read.
|
6585 |
+
if(!empty($xml)){
|
6586 |
+
// Check XML encoding
|
6587 |
+
$pos_xml = strpos($xml, '<?xml');
|
6588 |
+
if ($pos_xml !== FALSE) {
|
6589 |
+
$xml_decl = substr($xml, $pos_xml, strpos($xml, '?>', $pos_xml + 2) - $pos_xml + 1);
|
6590 |
+
if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
|
6591 |
+
$xml_encoding = $res[1];
|
6592 |
+
if (strtoupper($xml_encoding) != $encoding) {
|
6593 |
+
$err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";
|
6594 |
+
$this->debug($err);
|
6595 |
+
if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') {
|
6596 |
+
$this->setError($err);
|
6597 |
+
return;
|
6598 |
+
}
|
6599 |
+
// when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed
|
6600 |
+
} else {
|
6601 |
+
$this->debug('Charset from HTTP Content-Type matches encoding from XML declaration');
|
6602 |
+
}
|
6603 |
+
} else {
|
6604 |
+
$this->debug('No encoding specified in XML declaration');
|
6605 |
+
}
|
6606 |
+
} else {
|
6607 |
+
$this->debug('No XML declaration');
|
6608 |
+
}
|
6609 |
+
$this->debug('Entering nusoap_parser(), length='.strlen($xml).', encoding='.$encoding);
|
6610 |
+
// Create an XML parser - why not xml_parser_create_ns?
|
6611 |
+
$this->parser = xml_parser_create($this->xml_encoding);
|
6612 |
+
// Set the options for parsing the XML data.
|
6613 |
+
//xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
|
6614 |
+
xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
|
6615 |
+
xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
|
6616 |
+
// Set the object for the parser.
|
6617 |
+
xml_set_object($this->parser, $this);
|
6618 |
+
// Set the element handlers for the parser.
|
6619 |
+
xml_set_element_handler($this->parser, 'start_element','end_element');
|
6620 |
+
xml_set_character_data_handler($this->parser,'character_data');
|
6621 |
+
|
6622 |
+
// Parse the XML file.
|
6623 |
+
if(!xml_parse($this->parser,$xml,true)){
|
6624 |
+
// Display an error message.
|
6625 |
+
$err = sprintf('XML error parsing SOAP payload on line %d: %s',
|
6626 |
+
xml_get_current_line_number($this->parser),
|
6627 |
+
xml_error_string(xml_get_error_code($this->parser)));
|
6628 |
+
$this->debug($err);
|
6629 |
+
$this->debug("XML payload:\n" . $xml);
|
6630 |
+
$this->setError($err);
|
6631 |
+
} else {
|
6632 |
+
$this->debug('in nusoap_parser ctor, message:');
|
6633 |
+
$this->appendDebug($this->varDump($this->message));
|
6634 |
+
$this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name);
|
6635 |
+
// get final value
|
6636 |
+
$this->soapresponse = $this->message[$this->root_struct]['result'];
|
6637 |
+
// get header value
|
6638 |
+
if($this->root_header != '' && isset($this->message[$this->root_header]['result'])){
|
6639 |
+
$this->soapheader = $this->message[$this->root_header]['result'];
|
6640 |
+
}
|
6641 |
+
// resolve hrefs/ids
|
6642 |
+
if(sizeof($this->multirefs) > 0){
|
6643 |
+
foreach($this->multirefs as $id => $hrefs){
|
6644 |
+
$this->debug('resolving multirefs for id: '.$id);
|
6645 |
+
$idVal = $this->buildVal($this->ids[$id]);
|
6646 |
+
if (is_array($idVal) && isset($idVal['!id'])) {
|
6647 |
+
unset($idVal['!id']);
|
6648 |
+
}
|
6649 |
+
foreach($hrefs as $refPos => $ref){
|
6650 |
+
$this->debug('resolving href at pos '.$refPos);
|
6651 |
+
$this->multirefs[$id][$refPos] = $idVal;
|
6652 |
+
}
|
6653 |
+
}
|
6654 |
+
}
|
6655 |
+
}
|
6656 |
+
xml_parser_free($this->parser);
|
6657 |
+
} else {
|
6658 |
+
$this->debug('xml was empty, didn\'t parse!');
|
6659 |
+
$this->setError('xml was empty, didn\'t parse!');
|
6660 |
+
}
|
6661 |
+
}
|
6662 |
+
|
6663 |
+
/**
|
6664 |
+
* start-element handler
|
6665 |
+
*
|
6666 |
+
* @param resource $parser XML parser object
|
6667 |
+
* @param string $name element name
|
6668 |
+
* @param array $attrs associative array of attributes
|
6669 |
+
* @access private
|
6670 |
+
*/
|
6671 |
+
function start_element($parser, $name, $attrs) {
|
6672 |
+
// position in a total number of elements, starting from 0
|
6673 |
+
// update class level pos
|
6674 |
+
$pos = $this->position++;
|
6675 |
+
// and set mine
|
6676 |
+
$this->message[$pos] = array('pos' => $pos,'children'=>'','cdata'=>'');
|
6677 |
+
// depth = how many levels removed from root?
|
6678 |
+
// set mine as current global depth and increment global depth value
|
6679 |
+
$this->message[$pos]['depth'] = $this->depth++;
|
6680 |
+
|
6681 |
+
// else add self as child to whoever the current parent is
|
6682 |
+
if($pos != 0){
|
6683 |
+
$this->message[$this->parent]['children'] .= '|'.$pos;
|
6684 |
+
}
|
6685 |
+
// set my parent
|
6686 |
+
$this->message[$pos]['parent'] = $this->parent;
|
6687 |
+
// set self as current parent
|
6688 |
+
$this->parent = $pos;
|
6689 |
+
// set self as current value for this depth
|
6690 |
+
$this->depth_array[$this->depth] = $pos;
|
6691 |
+
// get element prefix
|
6692 |
+
if(strpos($name,':')){
|
6693 |
+
// get ns prefix
|
6694 |
+
$prefix = substr($name,0,strpos($name,':'));
|
6695 |
+
// get unqualified name
|
6696 |
+
$name = substr(strstr($name,':'),1);
|
6697 |
+
}
|
6698 |
+
// set status
|
6699 |
+
if ($name == 'Envelope' && $this->status == '') {
|
6700 |
+
$this->status = 'envelope';
|
6701 |
+
} elseif ($name == 'Header' && $this->status == 'envelope') {
|
6702 |
+
$this->root_header = $pos;
|
6703 |
+
$this->status = 'header';
|
6704 |
+
} elseif ($name == 'Body' && $this->status == 'envelope'){
|
6705 |
+
$this->status = 'body';
|
6706 |
+
$this->body_position = $pos;
|
6707 |
+
// set method
|
6708 |
+
} elseif($this->status == 'body' && $pos == ($this->body_position+1)) {
|
6709 |
+
$this->status = 'method';
|
6710 |
+
$this->root_struct_name = $name;
|
6711 |
+
$this->root_struct = $pos;
|
6712 |
+
$this->message[$pos]['type'] = 'struct';
|
6713 |
+
$this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
|
6714 |
+
}
|
6715 |
+
// set my status
|
6716 |
+
$this->message[$pos]['status'] = $this->status;
|
6717 |
+
// set name
|
6718 |
+
$this->message[$pos]['name'] = htmlspecialchars($name);
|
6719 |
+
// set attrs
|
6720 |
+
$this->message[$pos]['attrs'] = $attrs;
|
6721 |
+
|
6722 |
+
// loop through atts, logging ns and type declarations
|
6723 |
+
$attstr = '';
|
6724 |
+
foreach($attrs as $key => $value){
|
6725 |
+
$key_prefix = $this->getPrefix($key);
|
6726 |
+
$key_localpart = $this->getLocalPart($key);
|
6727 |
+
// if ns declarations, add to class level array of valid namespaces
|
6728 |
+
if($key_prefix == 'xmlns'){
|
6729 |
+
if(preg_match('/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/',$value)){
|
6730 |
+
$this->XMLSchemaVersion = $value;
|
6731 |
+
$this->namespaces['xsd'] = $this->XMLSchemaVersion;
|
6732 |
+
$this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance';
|
6733 |
+
}
|
6734 |
+
$this->namespaces[$key_localpart] = $value;
|
6735 |
+
// set method namespace
|
6736 |
+
if($name == $this->root_struct_name){
|
6737 |
+
$this->methodNamespace = $value;
|
6738 |
+
}
|
6739 |
+
// if it's a type declaration, set type
|
6740 |
+
} elseif($key_localpart == 'type'){
|
6741 |
+
if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') {
|
6742 |
+
// do nothing: already processed arrayType
|
6743 |
+
} else {
|
6744 |
+
$value_prefix = $this->getPrefix($value);
|
6745 |
+
$value_localpart = $this->getLocalPart($value);
|
6746 |
+
$this->message[$pos]['type'] = $value_localpart;
|
6747 |
+
$this->message[$pos]['typePrefix'] = $value_prefix;
|
6748 |
+
if(isset($this->namespaces[$value_prefix])){
|
6749 |
+
$this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
|
6750 |
+
} else if(isset($attrs['xmlns:'.$value_prefix])) {
|
6751 |
+
$this->message[$pos]['type_namespace'] = $attrs['xmlns:'.$value_prefix];
|
6752 |
+
}
|
6753 |
+
// should do something here with the namespace of specified type?
|
6754 |
+
}
|
6755 |
+
} elseif($key_localpart == 'arrayType'){
|
6756 |
+
$this->message[$pos]['type'] = 'array';
|
6757 |
+
/* do arrayType ereg here
|
6758 |
+
[1] arrayTypeValue ::= atype asize
|
6759 |
+
[2] atype ::= QName rank*
|
6760 |
+
[3] rank ::= '[' (',')* ']'
|
6761 |
+
[4] asize ::= '[' length~ ']'
|
6762 |
+
[5] length ::= nextDimension* Digit+
|
6763 |
+
[6] nextDimension ::= Digit+ ','
|
6764 |
+
*/
|
6765 |
+
$expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/';
|
6766 |
+
if(preg_match($expr,$value,$regs)){
|
6767 |
+
$this->message[$pos]['typePrefix'] = $regs[1];
|
6768 |
+
$this->message[$pos]['arrayTypePrefix'] = $regs[1];
|
6769 |
+
if (isset($this->namespaces[$regs[1]])) {
|
6770 |
+
$this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];
|
6771 |
+
} else if (isset($attrs['xmlns:'.$regs[1]])) {
|
6772 |
+
$this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:'.$regs[1]];
|
6773 |
+
}
|
6774 |
+
$this->message[$pos]['arrayType'] = $regs[2];
|
6775 |
+
$this->message[$pos]['arraySize'] = $regs[3];
|
6776 |
+
$this->message[$pos]['arrayCols'] = $regs[4];
|
6777 |
+
}
|
6778 |
+
// specifies nil value (or not)
|
6779 |
+
} elseif ($key_localpart == 'nil'){
|
6780 |
+
$this->message[$pos]['nil'] = ($value == 'true' || $value == '1');
|
6781 |
+
// some other attribute
|
6782 |
+
} elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') {
|
6783 |
+
$this->message[$pos]['xattrs']['!' . $key] = $value;
|
6784 |
+
}
|
6785 |
+
|
6786 |
+
if ($key == 'xmlns') {
|
6787 |
+
$this->default_namespace = $value;
|
6788 |
+
}
|
6789 |
+
// log id
|
6790 |
+
if($key == 'id'){
|
6791 |
+
$this->ids[$value] = $pos;
|
6792 |
+
}
|
6793 |
+
// root
|
6794 |
+
if($key_localpart == 'root' && $value == 1){
|
6795 |
+
$this->status = 'method';
|
6796 |
+
$this->root_struct_name = $name;
|
6797 |
+
$this->root_struct = $pos;
|
6798 |
+
$this->debug("found root struct $this->root_struct_name, pos $pos");
|
6799 |
+
}
|
6800 |
+
// for doclit
|
6801 |
+
$attstr .= " $key=\"$value\"";
|
6802 |
+
}
|
6803 |
+
// get namespace - must be done after namespace atts are processed
|
6804 |
+
if(isset($prefix)){
|
6805 |
+
$this->message[$pos]['namespace'] = $this->namespaces[$prefix];
|
6806 |
+
$this->default_namespace = $this->namespaces[$prefix];
|
6807 |
+
} else {
|
6808 |
+
$this->message[$pos]['namespace'] = $this->default_namespace;
|
6809 |
+
}
|
6810 |
+
if($this->status == 'header'){
|
6811 |
+
if ($this->root_header != $pos) {
|
6812 |
+
$this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
|
6813 |
+
}
|
6814 |
+
} elseif($this->root_struct_name != ''){
|
6815 |
+
$this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
|
6816 |
+
}
|
6817 |
+
}
|
6818 |
+
|
6819 |
+
/**
|
6820 |
+
* end-element handler
|
6821 |
+
*
|
6822 |
+
* @param resource $parser XML parser object
|
6823 |
+
* @param string $name element name
|
6824 |
+
* @access private
|
6825 |
+
*/
|
6826 |
+
function end_element($parser, $name) {
|
6827 |
+
// position of current element is equal to the last value left in depth_array for my depth
|
6828 |
+
$pos = $this->depth_array[$this->depth--];
|
6829 |
+
|
6830 |
+
// get element prefix
|
6831 |
+
if(strpos($name,':')){
|
6832 |
+
// get ns prefix
|
6833 |
+
$prefix = substr($name,0,strpos($name,':'));
|
6834 |
+
// get unqualified name
|
6835 |
+
$name = substr(strstr($name,':'),1);
|
6836 |
+
}
|
6837 |
+
|
6838 |
+
// build to native type
|
6839 |
+
if(isset($this->body_position) && $pos > $this->body_position){
|
6840 |
+
// deal w/ multirefs
|
6841 |
+
if(isset($this->message[$pos]['attrs']['href'])){
|
6842 |
+
// get id
|
6843 |
+
$id = substr($this->message[$pos]['attrs']['href'],1);
|
6844 |
+
// add placeholder to href array
|
6845 |
+
$this->multirefs[$id][$pos] = 'placeholder';
|
6846 |
+
// add set a reference to it as the result value
|
6847 |
+
$this->message[$pos]['result'] =& $this->multirefs[$id][$pos];
|
6848 |
+
// build complexType values
|
6849 |
+
} elseif($this->message[$pos]['children'] != ''){
|
6850 |
+
// if result has already been generated (struct/array)
|
6851 |
+
if(!isset($this->message[$pos]['result'])){
|
6852 |
+
$this->message[$pos]['result'] = $this->buildVal($pos);
|
6853 |
+
}
|
6854 |
+
// build complexType values of attributes and possibly simpleContent
|
6855 |
+
} elseif (isset($this->message[$pos]['xattrs'])) {
|
6856 |
+
if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
|
6857 |
+
$this->message[$pos]['xattrs']['!'] = null;
|
6858 |
+
} elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
|
6859 |
+
if (isset($this->message[$pos]['type'])) {
|
6860 |
+
$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'] : '');
|
6861 |
+
} else {
|
6862 |
+
$parent = $this->message[$pos]['parent'];
|
6863 |
+
if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
|
6864 |
+
$this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
|
6865 |
+
} else {
|
6866 |
+
$this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];
|
6867 |
+
}
|
6868 |
+
}
|
6869 |
+
}
|
6870 |
+
$this->message[$pos]['result'] = $this->message[$pos]['xattrs'];
|
6871 |
+
// set value of simpleType (or nil complexType)
|
6872 |
+
} else {
|
6873 |
+
//$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
|
6874 |
+
if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
|
6875 |
+
$this->message[$pos]['xattrs']['!'] = null;
|
6876 |
+
} elseif (isset($this->message[$pos]['type'])) {
|
6877 |
+
$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'] : '');
|
6878 |
+
} else {
|
6879 |
+
$parent = $this->message[$pos]['parent'];
|
6880 |
+
if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
|
6881 |
+
$this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
|
6882 |
+
} else {
|
6883 |
+
$this->message[$pos]['result'] = $this->message[$pos]['cdata'];
|
6884 |
+
}
|
6885 |
+
}
|
6886 |
+
|
6887 |
+
/* add value to parent's result, if parent is struct/array
|
6888 |
+
$parent = $this->message[$pos]['parent'];
|
6889 |
+
if($this->message[$parent]['type'] != 'map'){
|
6890 |
+
if(strtolower($this->message[$parent]['type']) == 'array'){
|
6891 |
+
$this->message[$parent]['result'][] = $this->message[$pos]['result'];
|
6892 |
+
} else {
|
6893 |
+
$this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];
|
6894 |
+
}
|
6895 |
+
}
|
6896 |
+
*/
|
6897 |
+
}
|
6898 |
+
}
|
6899 |
+
|
6900 |
+
// for doclit
|
6901 |
+
if($this->status == 'header'){
|
6902 |
+
if ($this->root_header != $pos) {
|
6903 |
+
$this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
|
6904 |
+
}
|
6905 |
+
} elseif($pos >= $this->root_struct){
|
6906 |
+
$this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
|
6907 |
+
}
|
6908 |
+
// switch status
|
6909 |
+
if ($pos == $this->root_struct){
|
6910 |
+
$this->status = 'body';
|
6911 |
+
$this->root_struct_namespace = $this->message[$pos]['namespace'];
|
6912 |
+
} elseif ($pos == $this->root_header) {
|
6913 |
+
$this->status = 'envelope';
|
6914 |
+
} elseif ($name == 'Body' && $this->status == 'body') {
|
6915 |
+
$this->status = 'envelope';
|
6916 |
+
} elseif ($name == 'Header' && $this->status == 'header') { // will never happen
|
6917 |
+
$this->status = 'envelope';
|
6918 |
+
} elseif ($name == 'Envelope' && $this->status == 'envelope') {
|
6919 |
+
$this->status = '';
|
6920 |
+
}
|
6921 |
+
// set parent back to my parent
|
6922 |
+
$this->parent = $this->message[$pos]['parent'];
|
6923 |
+
}
|
6924 |
+
|
6925 |
+
/**
|
6926 |
+
* element content handler
|
6927 |
+
*
|
6928 |
+
* @param resource $parser XML parser object
|
6929 |
+
* @param string $data element content
|
6930 |
+
* @access private
|
6931 |
+
*/
|
6932 |
+
function character_data($parser, $data){
|
6933 |
+
$pos = $this->depth_array[$this->depth];
|
6934 |
+
if ($this->xml_encoding=='UTF-8'){
|
6935 |
+
// TODO: add an option to disable this for folks who want
|
6936 |
+
// raw UTF-8 that, e.g., might not map to iso-8859-1
|
6937 |
+
// TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
|
6938 |
+
if($this->decode_utf8){
|
6939 |
+
$data = utf8_decode($data);
|
6940 |
+
}
|
6941 |
+
}
|
6942 |
+
$this->message[$pos]['cdata'] .= $data;
|
6943 |
+
// for doclit
|
6944 |
+
if($this->status == 'header'){
|
6945 |
+
$this->responseHeaders .= $data;
|
6946 |
+
} else {
|
6947 |
+
$this->document .= $data;
|
6948 |
+
}
|
6949 |
+
}
|
6950 |
+
|
6951 |
+
/**
|
6952 |
+
* get the parsed message (SOAP Body)
|
6953 |
+
*
|
6954 |
+
* @return mixed
|
6955 |
+
* @access public
|
6956 |
+
* @deprecated use get_soapbody instead
|
6957 |
+
*/
|
6958 |
+
function get_response(){
|
6959 |
+
return $this->soapresponse;
|
6960 |
+
}
|
6961 |
+
|
6962 |
+
/**
|
6963 |
+
* get the parsed SOAP Body (NULL if there was none)
|
6964 |
+
*
|
6965 |
+
* @return mixed
|
6966 |
+
* @access public
|
6967 |
+
*/
|
6968 |
+
function get_soapbody(){
|
6969 |
+
return $this->soapresponse;
|
6970 |
+
}
|
6971 |
+
|
6972 |
+
/**
|
6973 |
+
* get the parsed SOAP Header (NULL if there was none)
|
6974 |
+
*
|
6975 |
+
* @return mixed
|
6976 |
+
* @access public
|
6977 |
+
*/
|
6978 |
+
function get_soapheader(){
|
6979 |
+
return $this->soapheader;
|
6980 |
+
}
|
6981 |
+
|
6982 |
+
/**
|
6983 |
+
* get the unparsed SOAP Header
|
6984 |
+
*
|
6985 |
+
* @return string XML or empty if no Header
|
6986 |
+
* @access public
|
6987 |
+
*/
|
6988 |
+
function getHeaders(){
|
6989 |
+
return $this->responseHeaders;
|
6990 |
+
}
|
6991 |
+
|
6992 |
+
/**
|
6993 |
+
* decodes simple types into PHP variables
|
6994 |
+
*
|
6995 |
+
* @param string $value value to decode
|
6996 |
+
* @param string $type XML type to decode
|
6997 |
+
* @param string $typens XML type namespace to decode
|
6998 |
+
* @return mixed PHP value
|
6999 |
+
* @access private
|
7000 |
+
*/
|
7001 |
+
function decodeSimple($value, $type, $typens) {
|
7002 |
+
// TODO: use the namespace!
|
7003 |
+
if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {
|
7004 |
+
return (string) $value;
|
7005 |
+
}
|
7006 |
+
if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {
|
7007 |
+
return (int) $value;
|
7008 |
+
}
|
7009 |
+
if ($type == 'float' || $type == 'double' || $type == 'decimal') {
|
7010 |
+
return (double) $value;
|
7011 |
+
}
|
7012 |
+
if ($type == 'boolean') {
|
7013 |
+
if (strtolower($value) == 'false' || strtolower($value) == 'f') {
|
7014 |
+
return false;
|
7015 |
+
}
|
7016 |
+
return (boolean) $value;
|
7017 |
+
}
|
7018 |
+
if ($type == 'base64' || $type == 'base64Binary') {
|
7019 |
+
$this->debug('Decode base64 value');
|
7020 |
+
return base64_decode($value);
|
7021 |
+
}
|
7022 |
+
// obscure numeric types
|
7023 |
+
if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
|
7024 |
+
|| $type == 'nonNegativeInteger' || $type == 'positiveInteger'
|
7025 |
+
|| $type == 'unsignedInt'
|
7026 |
+
|| $type == 'unsignedShort' || $type == 'unsignedByte') {
|
7027 |
+
return (int) $value;
|
7028 |
+
}
|
7029 |
+
// bogus: parser treats array with no elements as a simple type
|
7030 |
+
if ($type == 'array') {
|
7031 |
+
return array();
|
7032 |
+
}
|
7033 |
+
// everything else
|
7034 |
+
return (string) $value;
|
7035 |
+
}
|
7036 |
+
|
7037 |
+
/**
|
7038 |
+
* builds response structures for compound values (arrays/structs)
|
7039 |
+
* and scalars
|
7040 |
+
*
|
7041 |
+
* @param integer $pos position in node tree
|
7042 |
+
* @return mixed PHP value
|
7043 |
+
* @access private
|
7044 |
+
*/
|
7045 |
+
function buildVal($pos){
|
7046 |
+
if(!isset($this->message[$pos]['type'])){
|
7047 |
+
$this->message[$pos]['type'] = '';
|
7048 |
+
}
|
7049 |
+
$this->debug('in buildVal() for '.$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]['type']);
|
7050 |
+
// if there are children...
|
7051 |
+
if($this->message[$pos]['children'] != ''){
|
7052 |
+
$this->debug('in buildVal, there are children');
|
7053 |
+
$children = explode('|',$this->message[$pos]['children']);
|
7054 |
+
array_shift($children); // knock off empty
|
7055 |
+
// md array
|
7056 |
+
if(isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != ''){
|
7057 |
+
$r=0; // rowcount
|
7058 |
+
$c=0; // colcount
|
7059 |
+
foreach($children as $child_pos){
|
7060 |
+
$this->debug("in buildVal, got an MD array element: $r, $c");
|
7061 |
+
$params[$r][] = $this->message[$child_pos]['result'];
|
7062 |
+
$c++;
|
7063 |
+
if($c == $this->message[$pos]['arrayCols']){
|
7064 |
+
$c = 0;
|
7065 |
+
$r++;
|
7066 |
+
}
|
7067 |
+
}
|
7068 |
+
// array
|
7069 |
+
} elseif($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array'){
|
7070 |
+
$this->debug('in buildVal, adding array '.$this->message[$pos]['name']);
|
7071 |
+
foreach($children as $child_pos){
|
7072 |
+
$params[] = &$this->message[$child_pos]['result'];
|
7073 |
+
}
|
7074 |
+
// apache Map type: java hashtable
|
7075 |
+
} elseif($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap'){
|
7076 |
+
$this->debug('in buildVal, Java Map '.$this->message[$pos]['name']);
|
7077 |
+
foreach($children as $child_pos){
|
7078 |
+
$kv = explode("|",$this->message[$child_pos]['children']);
|
7079 |
+
$params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];
|
7080 |
+
}
|
7081 |
+
// generic compound type
|
7082 |
+
//} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
|
7083 |
+
} else {
|
7084 |
+
// Apache Vector type: treat as an array
|
7085 |
+
$this->debug('in buildVal, adding Java Vector or generic compound type '.$this->message[$pos]['name']);
|
7086 |
+
if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
|
7087 |
+
$notstruct = 1;
|
7088 |
+
} else {
|
7089 |
+
$notstruct = 0;
|
7090 |
+
}
|
7091 |
+
//
|
7092 |
+
foreach($children as $child_pos){
|
7093 |
+
if($notstruct){
|
7094 |
+
$params[] = &$this->message[$child_pos]['result'];
|
7095 |
+
} else {
|
7096 |
+
if (isset($params[$this->message[$child_pos]['name']])) {
|
7097 |
+
// de-serialize repeated element name into an array
|
7098 |
+
if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) {
|
7099 |
+
$params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]);
|
7100 |
+
}
|
7101 |
+
$params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result'];
|
7102 |
+
} else {
|
7103 |
+
$params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];
|
7104 |
+
}
|
7105 |
+
}
|
7106 |
+
}
|
7107 |
+
}
|
7108 |
+
if (isset($this->message[$pos]['xattrs'])) {
|
7109 |
+
$this->debug('in buildVal, handling attributes');
|
7110 |
+
foreach ($this->message[$pos]['xattrs'] as $n => $v) {
|
7111 |
+
$params[$n] = $v;
|
7112 |
+
}
|
7113 |
+
}
|
7114 |
+
// handle simpleContent
|
7115 |
+
if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
|
7116 |
+
$this->debug('in buildVal, handling simpleContent');
|
7117 |
+
if (isset($this->message[$pos]['type'])) {
|
7118 |
+
$params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
|
7119 |
+
} else {
|
7120 |
+
$parent = $this->message[$pos]['parent'];
|
7121 |
+
if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
|
7122 |
+
$params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
|
7123 |
+
} else {
|
7124 |
+
$params['!'] = $this->message[$pos]['cdata'];
|
7125 |
+
}
|
7126 |
+
}
|
7127 |
+
}
|
7128 |
+
$ret = is_array($params) ? $params : array();
|
7129 |
+
$this->debug('in buildVal, return:');
|
7130 |
+
$this->appendDebug($this->varDump($ret));
|
7131 |
+
return $ret;
|
7132 |
+
} else {
|
7133 |
+
$this->debug('in buildVal, no children, building scalar');
|
7134 |
+
$cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : '';
|
7135 |
+
if (isset($this->message[$pos]['type'])) {
|
7136 |
+
$ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
|
7137 |
+
$this->debug("in buildVal, return: $ret");
|
7138 |
+
return $ret;
|
7139 |
+
}
|
7140 |
+
$parent = $this->message[$pos]['parent'];
|
7141 |
+
if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
|
7142 |
+
$ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
|
7143 |
+
$this->debug("in buildVal, return: $ret");
|
7144 |
+
return $ret;
|
7145 |
+
}
|
7146 |
+
$ret = $this->message[$pos]['cdata'];
|
7147 |
+
$this->debug("in buildVal, return: $ret");
|
7148 |
+
return $ret;
|
7149 |
+
}
|
7150 |
+
}
|
7151 |
+
}
|
7152 |
+
|
7153 |
+
/**
|
7154 |
+
* Backward compatibility
|
7155 |
+
*/
|
7156 |
+
class soap_parser extends nusoap_parser {
|
7157 |
+
}
|
7158 |
+
|
7159 |
+
?><?php
|
7160 |
+
|
7161 |
+
|
7162 |
+
|
7163 |
+
/**
|
7164 |
+
*
|
7165 |
+
* [nu]soapclient higher level class for easy usage.
|
7166 |
+
*
|
7167 |
+
* usage:
|
7168 |
+
*
|
7169 |
+
* // instantiate client with server info
|
7170 |
+
* $soapclient = new nusoap_client( string path [ ,mixed wsdl] );
|
7171 |
+
*
|
7172 |
+
* // call method, get results
|
7173 |
+
* echo $soapclient->call( string methodname [ ,array parameters] );
|
7174 |
+
*
|
7175 |
+
* // bye bye client
|
7176 |
+
* unset($soapclient);
|
7177 |
+
*
|
7178 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
7179 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
7180 |
+
* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
|
7181 |
+
* @access public
|
7182 |
+
*/
|
7183 |
+
class nusoap_client extends nusoap_base {
|
7184 |
+
|
7185 |
+
var $username = ''; // Username for HTTP authentication
|
7186 |
+
var $password = ''; // Password for HTTP authentication
|
7187 |
+
var $authtype = ''; // Type of HTTP authentication
|
7188 |
+
var $certRequest = array(); // Certificate for HTTP SSL authentication
|
7189 |
+
var $requestHeaders = false; // SOAP headers in request (text)
|
7190 |
+
var $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (text)
|
7191 |
+
var $responseHeader = NULL; // SOAP Header from response (parsed)
|
7192 |
+
var $document = ''; // SOAP body response portion (incomplete namespace resolution) (text)
|
7193 |
+
var $endpoint;
|
7194 |
+
var $forceEndpoint = ''; // overrides WSDL endpoint
|
7195 |
+
var $proxyhost = '';
|
7196 |
+
var $proxyport = '';
|
7197 |
+
var $proxyusername = '';
|
7198 |
+
var $proxypassword = '';
|
7199 |
+
var $portName = ''; // port name to use in WSDL
|
7200 |
+
var $xml_encoding = ''; // character set encoding of incoming (response) messages
|
7201 |
+
var $http_encoding = false;
|
7202 |
+
var $timeout = 0; // HTTP connection timeout
|
7203 |
+
var $response_timeout = 30; // HTTP response timeout
|
7204 |
+
var $endpointType = ''; // soap|wsdl, empty for WSDL initialization error
|
7205 |
+
var $persistentConnection = false;
|
7206 |
+
var $defaultRpcParams = false; // This is no longer used
|
7207 |
+
var $request = ''; // HTTP request
|
7208 |
+
var $response = ''; // HTTP response
|
7209 |
+
var $responseData = ''; // SOAP payload of response
|
7210 |
+
var $cookies = array(); // Cookies from response or for request
|
7211 |
+
var $decode_utf8 = true; // toggles whether the parser decodes element content w/ utf8_decode()
|
7212 |
+
var $operations = array(); // WSDL operations, empty for WSDL initialization error
|
7213 |
+
var $curl_options = array(); // User-specified cURL options
|
7214 |
+
var $bindingType = ''; // WSDL operation binding type
|
7215 |
+
var $use_curl = false; // whether to always try to use cURL
|
7216 |
+
|
7217 |
+
/*
|
7218 |
+
* fault related variables
|
7219 |
+
*/
|
7220 |
+
/**
|
7221 |
+
* @var fault
|
7222 |
+
* @access public
|
7223 |
+
*/
|
7224 |
+
var $fault;
|
7225 |
+
/**
|
7226 |
+
* @var faultcode
|
7227 |
+
* @access public
|
7228 |
+
*/
|
7229 |
+
var $faultcode;
|
7230 |
+
/**
|
7231 |
+
* @var faultstring
|
7232 |
+
* @access public
|
7233 |
+
*/
|
7234 |
+
var $faultstring;
|
7235 |
+
/**
|
7236 |
+
* @var faultdetail
|
7237 |
+
* @access public
|
7238 |
+
*/
|
7239 |
+
var $faultdetail;
|
7240 |
+
|
7241 |
+
/**
|
7242 |
+
* constructor
|
7243 |
+
*
|
7244 |
+
* @param mixed $endpoint SOAP server or WSDL URL (string), or wsdl instance (object)
|
7245 |
+
* @param mixed $wsdl optional, set to 'wsdl' or true if using WSDL
|
7246 |
+
* @param string $proxyhost optional
|
7247 |
+
* @param string $proxyport optional
|
7248 |
+
* @param string $proxyusername optional
|
7249 |
+
* @param string $proxypassword optional
|
7250 |
+
* @param integer $timeout set the connection timeout
|
7251 |
+
* @param integer $response_timeout set the response timeout
|
7252 |
+
* @param string $portName optional portName in WSDL document
|
7253 |
+
* @access public
|
7254 |
+
*/
|
7255 |
+
function nusoap_client($endpoint,$wsdl = false,$proxyhost = false,$proxyport = false,$proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30, $portName = ''){
|
7256 |
+
parent::nusoap_base();
|
7257 |
+
$this->endpoint = $endpoint;
|
7258 |
+
$this->proxyhost = $proxyhost;
|
7259 |
+
$this->proxyport = $proxyport;
|
7260 |
+
$this->proxyusername = $proxyusername;
|
7261 |
+
$this->proxypassword = $proxypassword;
|
7262 |
+
$this->timeout = $timeout;
|
7263 |
+
$this->response_timeout = $response_timeout;
|
7264 |
+
$this->portName = $portName;
|
7265 |
+
|
7266 |
+
$this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
|
7267 |
+
$this->appendDebug('endpoint=' . $this->varDump($endpoint));
|
7268 |
+
|
7269 |
+
// make values
|
7270 |
+
if($wsdl){
|
7271 |
+
if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) {
|
7272 |
+
$this->wsdl = $endpoint;
|
7273 |
+
$this->endpoint = $this->wsdl->wsdl;
|
7274 |
+
$this->wsdlFile = $this->endpoint;
|
7275 |
+
$this->debug('existing wsdl instance created from ' . $this->endpoint);
|
7276 |
+
$this->checkWSDL();
|
7277 |
+
} else {
|
7278 |
+
$this->wsdlFile = $this->endpoint;
|
7279 |
+
$this->wsdl = null;
|
7280 |
+
$this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint);
|
7281 |
+
}
|
7282 |
+
$this->endpointType = 'wsdl';
|
7283 |
+
} else {
|
7284 |
+
$this->debug("instantiate SOAP with endpoint at $endpoint");
|
7285 |
+
$this->endpointType = 'soap';
|
7286 |
+
}
|
7287 |
+
}
|
7288 |
+
|
7289 |
+
/**
|
7290 |
+
* calls method, returns PHP native type
|
7291 |
+
*
|
7292 |
+
* @param string $operation SOAP server URL or path
|
7293 |
+
* @param mixed $params An array, associative or simple, of the parameters
|
7294 |
+
* for the method call, or a string that is the XML
|
7295 |
+
* for the call. For rpc style, this call will
|
7296 |
+
* wrap the XML in a tag named after the method, as
|
7297 |
+
* well as the SOAP Envelope and Body. For document
|
7298 |
+
* style, this will only wrap with the Envelope and Body.
|
7299 |
+
* IMPORTANT: when using an array with document style,
|
7300 |
+
* in which case there
|
7301 |
+
* is really one parameter, the root of the fragment
|
7302 |
+
* used in the call, which encloses what programmers
|
7303 |
+
* normally think of parameters. A parameter array
|
7304 |
+
* *must* include the wrapper.
|
7305 |
+
* @param string $namespace optional method namespace (WSDL can override)
|
7306 |
+
* @param string $soapAction optional SOAPAction value (WSDL can override)
|
7307 |
+
* @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
|
7308 |
+
* @param boolean $rpcParams optional (no longer used)
|
7309 |
+
* @param string $style optional (rpc|document) the style to use when serializing parameters (WSDL can override)
|
7310 |
+
* @param string $use optional (encoded|literal) the use when serializing parameters (WSDL can override)
|
7311 |
+
* @return mixed response from SOAP call, normally an associative array mirroring the structure of the XML response, false for certain fatal errors
|
7312 |
+
* @access public
|
7313 |
+
*/
|
7314 |
+
function call($operation,$params=array(),$namespace='http://tempuri.org',$soapAction='',$headers=false,$rpcParams=null,$style='rpc',$use='encoded'){
|
7315 |
+
$this->operation = $operation;
|
7316 |
+
$this->fault = false;
|
7317 |
+
$this->setError('');
|
7318 |
+
$this->request = '';
|
7319 |
+
$this->response = '';
|
7320 |
+
$this->responseData = '';
|
7321 |
+
$this->faultstring = '';
|
7322 |
+
$this->faultcode = '';
|
7323 |
+
$this->opData = array();
|
7324 |
+
|
7325 |
+
$this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType");
|
7326 |
+
$this->appendDebug('params=' . $this->varDump($params));
|
7327 |
+
$this->appendDebug('headers=' . $this->varDump($headers));
|
7328 |
+
if ($headers) {
|
7329 |
+
$this->requestHeaders = $headers;
|
7330 |
+
}
|
7331 |
+
if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
|
7332 |
+
$this->loadWSDL();
|
7333 |
+
if ($this->getError())
|
7334 |
+
return false;
|
7335 |
+
}
|
7336 |
+
// serialize parameters
|
7337 |
+
if($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)){
|
7338 |
+
// use WSDL for operation
|
7339 |
+
$this->opData = $opData;
|
7340 |
+
$this->debug("found operation");
|
7341 |
+
$this->appendDebug('opData=' . $this->varDump($opData));
|
7342 |
+
if (isset($opData['soapAction'])) {
|
7343 |
+
$soapAction = $opData['soapAction'];
|
7344 |
+
}
|
7345 |
+
if (! $this->forceEndpoint) {
|
7346 |
+
$this->endpoint = $opData['endpoint'];
|
7347 |
+
} else {
|
7348 |
+
$this->endpoint = $this->forceEndpoint;
|
7349 |
+
}
|
7350 |
+
$namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] : $namespace;
|
7351 |
+
$style = $opData['style'];
|
7352 |
+
$use = $opData['input']['use'];
|
7353 |
+
// add ns to ns array
|
7354 |
+
if($namespace != '' && !isset($this->wsdl->namespaces[$namespace])){
|
7355 |
+
$nsPrefix = 'ns' . rand(1000, 9999);
|
7356 |
+
$this->wsdl->namespaces[$nsPrefix] = $namespace;
|
7357 |
+
}
|
7358 |
+
$nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);
|
7359 |
+
// serialize payload
|
7360 |
+
if (is_string($params)) {
|
7361 |
+
$this->debug("serializing param string for WSDL operation $operation");
|
7362 |
+
$payload = $params;
|
7363 |
+
} elseif (is_array($params)) {
|
7364 |
+
$this->debug("serializing param array for WSDL operation $operation");
|
7365 |
+
$payload = $this->wsdl->serializeRPCParameters($operation,'input',$params,$this->bindingType);
|
7366 |
+
} else {
|
7367 |
+
$this->debug('params must be array or string');
|
7368 |
+
$this->setError('params must be array or string');
|
7369 |
+
return false;
|
7370 |
+
}
|
7371 |
+
$usedNamespaces = $this->wsdl->usedNamespaces;
|
7372 |
+
if (isset($opData['input']['encodingStyle'])) {
|
7373 |
+
$encodingStyle = $opData['input']['encodingStyle'];
|
7374 |
+
} else {
|
7375 |
+
$encodingStyle = '';
|
7376 |
+
}
|
7377 |
+
$this->appendDebug($this->wsdl->getDebug());
|
7378 |
+
$this->wsdl->clearDebug();
|
7379 |
+
if ($errstr = $this->wsdl->getError()) {
|
7380 |
+
$this->debug('got wsdl error: '.$errstr);
|
7381 |
+
$this->setError('wsdl error: '.$errstr);
|
7382 |
+
return false;
|
7383 |
+
}
|
7384 |
+
} elseif($this->endpointType == 'wsdl') {
|
7385 |
+
// operation not in WSDL
|
7386 |
+
$this->appendDebug($this->wsdl->getDebug());
|
7387 |
+
$this->wsdl->clearDebug();
|
7388 |
+
$this->setError('operation '.$operation.' not present in WSDL.');
|
7389 |
+
$this->debug("operation '$operation' not present in WSDL.");
|
7390 |
+
return false;
|
7391 |
+
} else {
|
7392 |
+
// no WSDL
|
7393 |
+
//$this->namespaces['ns1'] = $namespace;
|
7394 |
+
$nsPrefix = 'ns' . rand(1000, 9999);
|
7395 |
+
// serialize
|
7396 |
+
$payload = '';
|
7397 |
+
if (is_string($params)) {
|
7398 |
+
$this->debug("serializing param string for operation $operation");
|
7399 |
+
$payload = $params;
|
7400 |
+
} elseif (is_array($params)) {
|
7401 |
+
$this->debug("serializing param array for operation $operation");
|
7402 |
+
foreach($params as $k => $v){
|
7403 |
+
$payload .= $this->serialize_val($v,$k,false,false,false,false,$use);
|
7404 |
+
}
|
7405 |
+
} else {
|
7406 |
+
$this->debug('params must be array or string');
|
7407 |
+
$this->setError('params must be array or string');
|
7408 |
+
return false;
|
7409 |
+
}
|
7410 |
+
$usedNamespaces = array();
|
7411 |
+
if ($use == 'encoded') {
|
7412 |
+
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
|
7413 |
+
} else {
|
7414 |
+
$encodingStyle = '';
|
7415 |
+
}
|
7416 |
+
}
|
7417 |
+
// wrap RPC calls with method element
|
7418 |
+
if ($style == 'rpc') {
|
7419 |
+
if ($use == 'literal') {
|
7420 |
+
$this->debug("wrapping RPC request with literal method element");
|
7421 |
+
if ($namespace) {
|
7422 |
+
// 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
|
7423 |
+
$payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
|
7424 |
+
$payload .
|
7425 |
+
"</$nsPrefix:$operation>";
|
7426 |
+
} else {
|
7427 |
+
$payload = "<$operation>" . $payload . "</$operation>";
|
7428 |
+
}
|
7429 |
+
} else {
|
7430 |
+
$this->debug("wrapping RPC request with encoded method element");
|
7431 |
+
if ($namespace) {
|
7432 |
+
$payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
|
7433 |
+
$payload .
|
7434 |
+
"</$nsPrefix:$operation>";
|
7435 |
+
} else {
|
7436 |
+
$payload = "<$operation>" .
|
7437 |
+
$payload .
|
7438 |
+
"</$operation>";
|
7439 |
+
}
|
7440 |
+
}
|
7441 |
+
}
|
7442 |
+
// serialize envelope
|
7443 |
+
$soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders,$usedNamespaces,$style,$use,$encodingStyle);
|
7444 |
+
$this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
|
7445 |
+
$this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
|
7446 |
+
// send
|
7447 |
+
$return = $this->send($this->getHTTPBody($soapmsg),$soapAction,$this->timeout,$this->response_timeout);
|
7448 |
+
if($errstr = $this->getError()){
|
7449 |
+
$this->debug('Error: '.$errstr);
|
7450 |
+
return false;
|
7451 |
+
} else {
|
7452 |
+
$this->return = $return;
|
7453 |
+
$this->debug('sent message successfully and got a(n) '.gettype($return));
|
7454 |
+
$this->appendDebug('return=' . $this->varDump($return));
|
7455 |
+
|
7456 |
+
// fault?
|
7457 |
+
if(is_array($return) && isset($return['faultcode'])){
|
7458 |
+
$this->debug('got fault');
|
7459 |
+
$this->setError($return['faultcode'].': '.$return['faultstring']);
|
7460 |
+
$this->fault = true;
|
7461 |
+
foreach($return as $k => $v){
|
7462 |
+
$this->$k = $v;
|
7463 |
+
$this->debug("$k = $v<br>");
|
7464 |
+
}
|
7465 |
+
return $return;
|
7466 |
+
} elseif ($style == 'document') {
|
7467 |
+
// NOTE: if the response is defined to have multiple parts (i.e. unwrapped),
|
7468 |
+
// we are only going to return the first part here...sorry about that
|
7469 |
+
return $return;
|
7470 |
+
} else {
|
7471 |
+
// array of return values
|
7472 |
+
if(is_array($return)){
|
7473 |
+
// multiple 'out' parameters, which we return wrapped up
|
7474 |
+
// in the array
|
7475 |
+
if(sizeof($return) > 1){
|
7476 |
+
return $return;
|
7477 |
+
}
|
7478 |
+
// single 'out' parameter (normally the return value)
|
7479 |
+
$return = array_shift($return);
|
7480 |
+
$this->debug('return shifted value: ');
|
7481 |
+
$this->appendDebug($this->varDump($return));
|
7482 |
+
return $return;
|
7483 |
+
// nothing returned (ie, echoVoid)
|
7484 |
+
} else {
|
7485 |
+
return "";
|
7486 |
+
}
|
7487 |
+
}
|
7488 |
+
}
|
7489 |
+
}
|
7490 |
+
|
7491 |
+
/**
|
7492 |
+
* check WSDL passed as an instance or pulled from an endpoint
|
7493 |
+
*
|
7494 |
+
* @access private
|
7495 |
+
*/
|
7496 |
+
function checkWSDL() {
|
7497 |
+
$this->appendDebug($this->wsdl->getDebug());
|
7498 |
+
$this->wsdl->clearDebug();
|
7499 |
+
$this->debug('checkWSDL');
|
7500 |
+
// catch errors
|
7501 |
+
if ($errstr = $this->wsdl->getError()) {
|
7502 |
+
$this->appendDebug($this->wsdl->getDebug());
|
7503 |
+
$this->wsdl->clearDebug();
|
7504 |
+
$this->debug('got wsdl error: '.$errstr);
|
7505 |
+
$this->setError('wsdl error: '.$errstr);
|
7506 |
+
} elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap')) {
|
7507 |
+
$this->appendDebug($this->wsdl->getDebug());
|
7508 |
+
$this->wsdl->clearDebug();
|
7509 |
+
$this->bindingType = 'soap';
|
7510 |
+
$this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
|
7511 |
+
} elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap12')) {
|
7512 |
+
$this->appendDebug($this->wsdl->getDebug());
|
7513 |
+
$this->wsdl->clearDebug();
|
7514 |
+
$this->bindingType = 'soap12';
|
7515 |
+
$this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
|
7516 |
+
$this->debug('**************** WARNING: SOAP 1.2 BINDING *****************');
|
7517 |
+
} else {
|
7518 |
+
$this->appendDebug($this->wsdl->getDebug());
|
7519 |
+
$this->wsdl->clearDebug();
|
7520 |
+
$this->debug('getOperations returned false');
|
7521 |
+
$this->setError('no operations defined in the WSDL document!');
|
7522 |
+
}
|
7523 |
+
}
|
7524 |
+
|
7525 |
+
/**
|
7526 |
+
* instantiate wsdl object and parse wsdl file
|
7527 |
+
*
|
7528 |
+
* @access public
|
7529 |
+
*/
|
7530 |
+
function loadWSDL() {
|
7531 |
+
$this->debug('instantiating wsdl class with doc: '.$this->wsdlFile);
|
7532 |
+
$this->wsdl = new wsdl('',$this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeout,$this->response_timeout,$this->curl_options,$this->use_curl);
|
7533 |
+
$this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest);
|
7534 |
+
$this->wsdl->fetchWSDL($this->wsdlFile);
|
7535 |
+
$this->checkWSDL();
|
7536 |
+
}
|
7537 |
+
|
7538 |
+
/**
|
7539 |
+
* get available data pertaining to an operation
|
7540 |
+
*
|
7541 |
+
* @param string $operation operation name
|
7542 |
+
* @return array array of data pertaining to the operation
|
7543 |
+
* @access public
|
7544 |
+
*/
|
7545 |
+
function getOperationData($operation){
|
7546 |
+
if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
|
7547 |
+
$this->loadWSDL();
|
7548 |
+
if ($this->getError())
|
7549 |
+
return false;
|
7550 |
+
}
|
7551 |
+
if(isset($this->operations[$operation])){
|
7552 |
+
return $this->operations[$operation];
|
7553 |
+
}
|
7554 |
+
$this->debug("No data for operation: $operation");
|
7555 |
+
}
|
7556 |
+
|
7557 |
+
/**
|
7558 |
+
* send the SOAP message
|
7559 |
+
*
|
7560 |
+
* Note: if the operation has multiple return values
|
7561 |
+
* the return value of this method will be an array
|
7562 |
+
* of those values.
|
7563 |
+
*
|
7564 |
+
* @param string $msg a SOAPx4 soapmsg object
|
7565 |
+
* @param string $soapaction SOAPAction value
|
7566 |
+
* @param integer $timeout set connection timeout in seconds
|
7567 |
+
* @param integer $response_timeout set response timeout in seconds
|
7568 |
+
* @return mixed native PHP types.
|
7569 |
+
* @access private
|
7570 |
+
*/
|
7571 |
+
function send($msg, $soapaction = '', $timeout=0, $response_timeout=30) {
|
7572 |
+
$this->checkCookies();
|
7573 |
+
// detect transport
|
7574 |
+
switch(true){
|
7575 |
+
// http(s)
|
7576 |
+
case preg_match('/^http/',$this->endpoint):
|
7577 |
+
$this->debug('transporting via HTTP');
|
7578 |
+
if($this->persistentConnection == true && is_object($this->persistentConnection)){
|
7579 |
+
$http =& $this->persistentConnection;
|
7580 |
+
} else {
|
7581 |
+
$http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl);
|
7582 |
+
if ($this->persistentConnection) {
|
7583 |
+
$http->usePersistentConnection();
|
7584 |
+
}
|
7585 |
+
}
|
7586 |
+
$http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset());
|
7587 |
+
$http->setSOAPAction($soapaction);
|
7588 |
+
if($this->proxyhost && $this->proxyport){
|
7589 |
+
$http->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
|
7590 |
+
}
|
7591 |
+
if($this->authtype != '') {
|
7592 |
+
$http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
|
7593 |
+
}
|
7594 |
+
if($this->http_encoding != ''){
|
7595 |
+
$http->setEncoding($this->http_encoding);
|
7596 |
+
}
|
7597 |
+
$this->debug('sending message, length='.strlen($msg));
|
7598 |
+
if(preg_match('/^http:/',$this->endpoint)){
|
7599 |
+
//if(strpos($this->endpoint,'http:')){
|
7600 |
+
$this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies);
|
7601 |
+
} elseif(preg_match('/^https/',$this->endpoint)){
|
7602 |
+
//} elseif(strpos($this->endpoint,'https:')){
|
7603 |
+
//if(phpversion() == '4.3.0-dev'){
|
7604 |
+
//$response = $http->send($msg,$timeout,$response_timeout);
|
7605 |
+
//$this->request = $http->outgoing_payload;
|
7606 |
+
//$this->response = $http->incoming_payload;
|
7607 |
+
//} else
|
7608 |
+
$this->responseData = $http->sendHTTPS($msg,$timeout,$response_timeout,$this->cookies);
|
7609 |
+
} else {
|
7610 |
+
$this->setError('no http/s in endpoint url');
|
7611 |
+
}
|
7612 |
+
$this->request = $http->outgoing_payload;
|
7613 |
+
$this->response = $http->incoming_payload;
|
7614 |
+
$this->appendDebug($http->getDebug());
|
7615 |
+
$this->UpdateCookies($http->incoming_cookies);
|
7616 |
+
|
7617 |
+
// save transport object if using persistent connections
|
7618 |
+
if ($this->persistentConnection) {
|
7619 |
+
$http->clearDebug();
|
7620 |
+
if (!is_object($this->persistentConnection)) {
|
7621 |
+
$this->persistentConnection = $http;
|
7622 |
+
}
|
7623 |
+
}
|
7624 |
+
|
7625 |
+
if($err = $http->getError()){
|
7626 |
+
$this->setError('HTTP Error: '.$err);
|
7627 |
+
return false;
|
7628 |
+
} elseif($this->getError()){
|
7629 |
+
return false;
|
7630 |
+
} else {
|
7631 |
+
$this->debug('got response, length='. strlen($this->responseData).' type='.$http->incoming_headers['content-type']);
|
7632 |
+
return $this->parseResponse($http->incoming_headers, $this->responseData);
|
7633 |
+
}
|
7634 |
+
break;
|
7635 |
+
default:
|
7636 |
+
$this->setError('no transport found, or selected transport is not yet supported!');
|
7637 |
+
return false;
|
7638 |
+
break;
|
7639 |
+
}
|
7640 |
+
}
|
7641 |
+
|
7642 |
+
/**
|
7643 |
+
* processes SOAP message returned from server
|
7644 |
+
*
|
7645 |
+
* @param array $headers The HTTP headers
|
7646 |
+
* @param string $data unprocessed response data from server
|
7647 |
+
* @return mixed value of the message, decoded into a PHP type
|
7648 |
+
* @access private
|
7649 |
+
*/
|
7650 |
+
function parseResponse($headers, $data) {
|
7651 |
+
$this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:');
|
7652 |
+
$this->appendDebug($this->varDump($headers));
|
7653 |
+
if (!isset($headers['content-type'])) {
|
7654 |
+
$this->setError('Response not of type text/xml (no content-type header)');
|
7655 |
+
return false;
|
7656 |
+
}
|
7657 |
+
if (!strstr($headers['content-type'], 'text/xml')) {
|
7658 |
+
$this->setError('Response not of type text/xml: ' . $headers['content-type']);
|
7659 |
+
return false;
|
7660 |
+
}
|
7661 |
+
if (strpos($headers['content-type'], '=')) {
|
7662 |
+
$enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
|
7663 |
+
$this->debug('Got response encoding: ' . $enc);
|
7664 |
+
if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
|
7665 |
+
$this->xml_encoding = strtoupper($enc);
|
7666 |
+
} else {
|
7667 |
+
$this->xml_encoding = 'US-ASCII';
|
7668 |
+
}
|
7669 |
+
} else {
|
7670 |
+
// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
|
7671 |
+
$this->xml_encoding = 'ISO-8859-1';
|
7672 |
+
}
|
7673 |
+
$this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
|
7674 |
+
$parser = new nusoap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8);
|
7675 |
+
// add parser debug data to our debug
|
7676 |
+
$this->appendDebug($parser->getDebug());
|
7677 |
+
// if parse errors
|
7678 |
+
if($errstr = $parser->getError()){
|
7679 |
+
$this->setError( $errstr);
|
7680 |
+
// destroy the parser object
|
7681 |
+
unset($parser);
|
7682 |
+
return false;
|
7683 |
+
} else {
|
7684 |
+
// get SOAP headers
|
7685 |
+
$this->responseHeaders = $parser->getHeaders();
|
7686 |
+
// get SOAP headers
|
7687 |
+
$this->responseHeader = $parser->get_soapheader();
|
7688 |
+
// get decoded message
|
7689 |
+
$return = $parser->get_soapbody();
|
7690 |
+
// add document for doclit support
|
7691 |
+
$this->document = $parser->document;
|
7692 |
+
// destroy the parser object
|
7693 |
+
unset($parser);
|
7694 |
+
// return decode message
|
7695 |
+
return $return;
|
7696 |
+
}
|
7697 |
+
}
|
7698 |
+
|
7699 |
+
/**
|
7700 |
+
* sets user-specified cURL options
|
7701 |
+
*
|
7702 |
+
* @param mixed $option The cURL option (always integer?)
|
7703 |
+
* @param mixed $value The cURL option value
|
7704 |
+
* @access public
|
7705 |
+
*/
|
7706 |
+
function setCurlOption($option, $value) {
|
7707 |
+
$this->debug("setCurlOption option=$option, value=");
|
7708 |
+
$this->appendDebug($this->varDump($value));
|
7709 |
+
$this->curl_options[$option] = $value;
|
7710 |
+
}
|
7711 |
+
|
7712 |
+
/**
|
7713 |
+
* sets the SOAP endpoint, which can override WSDL
|
7714 |
+
*
|
7715 |
+
* @param string $endpoint The endpoint URL to use, or empty string or false to prevent override
|
7716 |
+
* @access public
|
7717 |
+
*/
|
7718 |
+
function setEndpoint($endpoint) {
|
7719 |
+
$this->debug("setEndpoint(\"$endpoint\")");
|
7720 |
+
$this->forceEndpoint = $endpoint;
|
7721 |
+
}
|
7722 |
+
|
7723 |
+
/**
|
7724 |
+
* set the SOAP headers
|
7725 |
+
*
|
7726 |
+
* @param mixed $headers String of XML with SOAP header content, or array of soapval objects for SOAP headers
|
7727 |
+
* @access public
|
7728 |
+
*/
|
7729 |
+
function setHeaders($headers){
|
7730 |
+
$this->debug("setHeaders headers=");
|
7731 |
+
$this->appendDebug($this->varDump($headers));
|
7732 |
+
$this->requestHeaders = $headers;
|
7733 |
+
}
|
7734 |
+
|
7735 |
+
/**
|
7736 |
+
* get the SOAP response headers (namespace resolution incomplete)
|
7737 |
+
*
|
7738 |
+
* @return string
|
7739 |
+
* @access public
|
7740 |
+
*/
|
7741 |
+
function getHeaders(){
|
7742 |
+
return $this->responseHeaders;
|
7743 |
+
}
|
7744 |
+
|
7745 |
+
/**
|
7746 |
+
* get the SOAP response Header (parsed)
|
7747 |
+
*
|
7748 |
+
* @return mixed
|
7749 |
+
* @access public
|
7750 |
+
*/
|
7751 |
+
function getHeader(){
|
7752 |
+
return $this->responseHeader;
|
7753 |
+
}
|
7754 |
+
|
7755 |
+
/**
|
7756 |
+
* set proxy info here
|
7757 |
+
*
|
7758 |
+
* @param string $proxyhost
|
7759 |
+
* @param string $proxyport
|
7760 |
+
* @param string $proxyusername
|
7761 |
+
* @param string $proxypassword
|
7762 |
+
* @access public
|
7763 |
+
*/
|
7764 |
+
function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') {
|
7765 |
+
$this->proxyhost = $proxyhost;
|
7766 |
+
$this->proxyport = $proxyport;
|
7767 |
+
$this->proxyusername = $proxyusername;
|
7768 |
+
$this->proxypassword = $proxypassword;
|
7769 |
+
}
|
7770 |
+
|
7771 |
+
/**
|
7772 |
+
* if authenticating, set user credentials here
|
7773 |
+
*
|
7774 |
+
* @param string $username
|
7775 |
+
* @param string $password
|
7776 |
+
* @param string $authtype (basic|digest|certificate|ntlm)
|
7777 |
+
* @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
|
7778 |
+
* @access public
|
7779 |
+
*/
|
7780 |
+
function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
|
7781 |
+
$this->debug("setCredentials username=$username authtype=$authtype certRequest=");
|
7782 |
+
$this->appendDebug($this->varDump($certRequest));
|
7783 |
+
$this->username = $username;
|
7784 |
+
$this->password = $password;
|
7785 |
+
$this->authtype = $authtype;
|
7786 |
+
$this->certRequest = $certRequest;
|
7787 |
+
}
|
7788 |
+
|
7789 |
+
/**
|
7790 |
+
* use HTTP encoding
|
7791 |
+
*
|
7792 |
+
* @param string $enc HTTP encoding
|
7793 |
+
* @access public
|
7794 |
+
*/
|
7795 |
+
function setHTTPEncoding($enc='gzip, deflate'){
|
7796 |
+
$this->debug("setHTTPEncoding(\"$enc\")");
|
7797 |
+
$this->http_encoding = $enc;
|
7798 |
+
}
|
7799 |
+
|
7800 |
+
/**
|
7801 |
+
* Set whether to try to use cURL connections if possible
|
7802 |
+
*
|
7803 |
+
* @param boolean $use Whether to try to use cURL
|
7804 |
+
* @access public
|
7805 |
+
*/
|
7806 |
+
function setUseCURL($use) {
|
7807 |
+
$this->debug("setUseCURL($use)");
|
7808 |
+
$this->use_curl = $use;
|
7809 |
+
}
|
7810 |
+
|
7811 |
+
/**
|
7812 |
+
* use HTTP persistent connections if possible
|
7813 |
+
*
|
7814 |
+
* @access public
|
7815 |
+
*/
|
7816 |
+
function useHTTPPersistentConnection(){
|
7817 |
+
$this->debug("useHTTPPersistentConnection");
|
7818 |
+
$this->persistentConnection = true;
|
7819 |
+
}
|
7820 |
+
|
7821 |
+
/**
|
7822 |
+
* gets the default RPC parameter setting.
|
7823 |
+
* If true, default is that call params are like RPC even for document style.
|
7824 |
+
* Each call() can override this value.
|
7825 |
+
*
|
7826 |
+
* This is no longer used.
|
7827 |
+
*
|
7828 |
+
* @return boolean
|
7829 |
+
* @access public
|
7830 |
+
* @deprecated
|
7831 |
+
*/
|
7832 |
+
function getDefaultRpcParams() {
|
7833 |
+
return $this->defaultRpcParams;
|
7834 |
+
}
|
7835 |
+
|
7836 |
+
/**
|
7837 |
+
* sets the default RPC parameter setting.
|
7838 |
+
* If true, default is that call params are like RPC even for document style
|
7839 |
+
* Each call() can override this value.
|
7840 |
+
*
|
7841 |
+
* This is no longer used.
|
7842 |
+
*
|
7843 |
+
* @param boolean $rpcParams
|
7844 |
+
* @access public
|
7845 |
+
* @deprecated
|
7846 |
+
*/
|
7847 |
+
function setDefaultRpcParams($rpcParams) {
|
7848 |
+
$this->defaultRpcParams = $rpcParams;
|
7849 |
+
}
|
7850 |
+
|
7851 |
+
/**
|
7852 |
+
* dynamically creates an instance of a proxy class,
|
7853 |
+
* allowing user to directly call methods from wsdl
|
7854 |
+
*
|
7855 |
+
* @return object soap_proxy object
|
7856 |
+
* @access public
|
7857 |
+
*/
|
7858 |
+
function getProxy() {
|
7859 |
+
$r = rand();
|
7860 |
+
$evalStr = $this->_getProxyClassCode($r);
|
7861 |
+
//$this->debug("proxy class: $evalStr");
|
7862 |
+
if ($this->getError()) {
|
7863 |
+
$this->debug("Error from _getProxyClassCode, so return NULL");
|
7864 |
+
return null;
|
7865 |
+
}
|
7866 |
+
// eval the class
|
7867 |
+
eval($evalStr);
|
7868 |
+
// instantiate proxy object
|
7869 |
+
eval("\$proxy = new nusoap_proxy_$r('');");
|
7870 |
+
// transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
|
7871 |
+
$proxy->endpointType = 'wsdl';
|
7872 |
+
$proxy->wsdlFile = $this->wsdlFile;
|
7873 |
+
$proxy->wsdl = $this->wsdl;
|
7874 |
+
$proxy->operations = $this->operations;
|
7875 |
+
$proxy->defaultRpcParams = $this->defaultRpcParams;
|
7876 |
+
// transfer other state
|
7877 |
+
$proxy->soap_defencoding = $this->soap_defencoding;
|
7878 |
+
$proxy->username = $this->username;
|
7879 |
+
$proxy->password = $this->password;
|
7880 |
+
$proxy->authtype = $this->authtype;
|
7881 |
+
$proxy->certRequest = $this->certRequest;
|
7882 |
+
$proxy->requestHeaders = $this->requestHeaders;
|
7883 |
+
$proxy->endpoint = $this->endpoint;
|
7884 |
+
$proxy->forceEndpoint = $this->forceEndpoint;
|
7885 |
+
$proxy->proxyhost = $this->proxyhost;
|
7886 |
+
$proxy->proxyport = $this->proxyport;
|
7887 |
+
$proxy->proxyusername = $this->proxyusername;
|
7888 |
+
$proxy->proxypassword = $this->proxypassword;
|
7889 |
+
$proxy->http_encoding = $this->http_encoding;
|
7890 |
+
$proxy->timeout = $this->timeout;
|
7891 |
+
$proxy->response_timeout = $this->response_timeout;
|
7892 |
+
$proxy->persistentConnection = &$this->persistentConnection;
|
7893 |
+
$proxy->decode_utf8 = $this->decode_utf8;
|
7894 |
+
$proxy->curl_options = $this->curl_options;
|
7895 |
+
$proxy->bindingType = $this->bindingType;
|
7896 |
+
$proxy->use_curl = $this->use_curl;
|
7897 |
+
return $proxy;
|
7898 |
+
}
|
7899 |
+
|
7900 |
+
/**
|
7901 |
+
* dynamically creates proxy class code
|
7902 |
+
*
|
7903 |
+
* @return string PHP/NuSOAP code for the proxy class
|
7904 |
+
* @access private
|
7905 |
+
*/
|
7906 |
+
function _getProxyClassCode($r) {
|
7907 |
+
$this->debug("in getProxy endpointType=$this->endpointType");
|
7908 |
+
$this->appendDebug("wsdl=" . $this->varDump($this->wsdl));
|
7909 |
+
if ($this->endpointType != 'wsdl') {
|
7910 |
+
$evalStr = 'A proxy can only be created for a WSDL client';
|
7911 |
+
$this->setError($evalStr);
|
7912 |
+
$evalStr = "echo \"$evalStr\";";
|
7913 |
+
return $evalStr;
|
7914 |
+
}
|
7915 |
+
if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
|
7916 |
+
$this->loadWSDL();
|
7917 |
+
if ($this->getError()) {
|
7918 |
+
return "echo \"" . $this->getError() . "\";";
|
7919 |
+
}
|
7920 |
+
}
|
7921 |
+
$evalStr = '';
|
7922 |
+
foreach ($this->operations as $operation => $opData) {
|
7923 |
+
if ($operation != '') {
|
7924 |
+
// create param string and param comment string
|
7925 |
+
if (sizeof($opData['input']['parts']) > 0) {
|
7926 |
+
$paramStr = '';
|
7927 |
+
$paramArrayStr = '';
|
7928 |
+
$paramCommentStr = '';
|
7929 |
+
foreach ($opData['input']['parts'] as $name => $type) {
|
7930 |
+
$paramStr .= "\$$name, ";
|
7931 |
+
$paramArrayStr .= "'$name' => \$$name, ";
|
7932 |
+
$paramCommentStr .= "$type \$$name, ";
|
7933 |
+
}
|
7934 |
+
$paramStr = substr($paramStr, 0, strlen($paramStr)-2);
|
7935 |
+
$paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr)-2);
|
7936 |
+
$paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2);
|
7937 |
+
} else {
|
7938 |
+
$paramStr = '';
|
7939 |
+
$paramArrayStr = '';
|
7940 |
+
$paramCommentStr = 'void';
|
7941 |
+
}
|
7942 |
+
$opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
|
7943 |
+
$evalStr .= "// $paramCommentStr
|
7944 |
+
function " . str_replace('.', '__', $operation) . "($paramStr) {
|
7945 |
+
\$params = array($paramArrayStr);
|
7946 |
+
return \$this->call('$operation', \$params, '".$opData['namespace']."', '".(isset($opData['soapAction']) ? $opData['soapAction'] : '')."');
|
7947 |
+
}
|
7948 |
+
";
|
7949 |
+
unset($paramStr);
|
7950 |
+
unset($paramCommentStr);
|
7951 |
+
}
|
7952 |
+
}
|
7953 |
+
$evalStr = 'class nusoap_proxy_'.$r.' extends nusoap_client {
|
7954 |
+
'.$evalStr.'
|
7955 |
+
}';
|
7956 |
+
return $evalStr;
|
7957 |
+
}
|
7958 |
+
|
7959 |
+
/**
|
7960 |
+
* dynamically creates proxy class code
|
7961 |
+
*
|
7962 |
+
* @return string PHP/NuSOAP code for the proxy class
|
7963 |
+
* @access public
|
7964 |
+
*/
|
7965 |
+
function getProxyClassCode() {
|
7966 |
+
$r = rand();
|
7967 |
+
return $this->_getProxyClassCode($r);
|
7968 |
+
}
|
7969 |
+
|
7970 |
+
/**
|
7971 |
+
* gets the HTTP body for the current request.
|
7972 |
+
*
|
7973 |
+
* @param string $soapmsg The SOAP payload
|
7974 |
+
* @return string The HTTP body, which includes the SOAP payload
|
7975 |
+
* @access private
|
7976 |
+
*/
|
7977 |
+
function getHTTPBody($soapmsg) {
|
7978 |
+
return $soapmsg;
|
7979 |
+
}
|
7980 |
+
|
7981 |
+
/**
|
7982 |
+
* gets the HTTP content type for the current request.
|
7983 |
+
*
|
7984 |
+
* Note: getHTTPBody must be called before this.
|
7985 |
+
*
|
7986 |
+
* @return string the HTTP content type for the current request.
|
7987 |
+
* @access private
|
7988 |
+
*/
|
7989 |
+
function getHTTPContentType() {
|
7990 |
+
return 'text/xml';
|
7991 |
+
}
|
7992 |
+
|
7993 |
+
/**
|
7994 |
+
* gets the HTTP content type charset for the current request.
|
7995 |
+
* returns false for non-text content types.
|
7996 |
+
*
|
7997 |
+
* Note: getHTTPBody must be called before this.
|
7998 |
+
*
|
7999 |
+
* @return string the HTTP content type charset for the current request.
|
8000 |
+
* @access private
|
8001 |
+
*/
|
8002 |
+
function getHTTPContentTypeCharset() {
|
8003 |
+
return $this->soap_defencoding;
|
8004 |
+
}
|
8005 |
+
|
8006 |
+
/*
|
8007 |
+
* whether or not parser should decode utf8 element content
|
8008 |
+
*
|
8009 |
+
* @return always returns true
|
8010 |
+
* @access public
|
8011 |
+
*/
|
8012 |
+
function decodeUTF8($bool){
|
8013 |
+
$this->decode_utf8 = $bool;
|
8014 |
+
return true;
|
8015 |
+
}
|
8016 |
+
|
8017 |
+
/**
|
8018 |
+
* adds a new Cookie into $this->cookies array
|
8019 |
+
*
|
8020 |
+
* @param string $name Cookie Name
|
8021 |
+
* @param string $value Cookie Value
|
8022 |
+
* @return boolean if cookie-set was successful returns true, else false
|
8023 |
+
* @access public
|
8024 |
+
*/
|
8025 |
+
function setCookie($name, $value) {
|
8026 |
+
if (strlen($name) == 0) {
|
8027 |
+
return false;
|
8028 |
+
}
|
8029 |
+
$this->cookies[] = array('name' => $name, 'value' => $value);
|
8030 |
+
return true;
|
8031 |
+
}
|
8032 |
+
|
8033 |
+
/**
|
8034 |
+
* gets all Cookies
|
8035 |
+
*
|
8036 |
+
* @return array with all internal cookies
|
8037 |
+
* @access public
|
8038 |
+
*/
|
8039 |
+
function getCookies() {
|
8040 |
+
return $this->cookies;
|
8041 |
+
}
|
8042 |
+
|
8043 |
+
/**
|
8044 |
+
* checks all Cookies and delete those which are expired
|
8045 |
+
*
|
8046 |
+
* @return boolean always return true
|
8047 |
+
* @access private
|
8048 |
+
*/
|
8049 |
+
function checkCookies() {
|
8050 |
+
if (sizeof($this->cookies) == 0) {
|
8051 |
+
return true;
|
8052 |
+
}
|
8053 |
+
$this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies');
|
8054 |
+
$curr_cookies = $this->cookies;
|
8055 |
+
$this->cookies = array();
|
8056 |
+
foreach ($curr_cookies as $cookie) {
|
8057 |
+
if (! is_array($cookie)) {
|
8058 |
+
$this->debug('Remove cookie that is not an array');
|
8059 |
+
continue;
|
8060 |
+
}
|
8061 |
+
if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
|
8062 |
+
if (strtotime($cookie['expires']) > time()) {
|
8063 |
+
$this->cookies[] = $cookie;
|
8064 |
+
} else {
|
8065 |
+
$this->debug('Remove expired cookie ' . $cookie['name']);
|
8066 |
+
}
|
8067 |
+
} else {
|
8068 |
+
$this->cookies[] = $cookie;
|
8069 |
+
}
|
8070 |
+
}
|
8071 |
+
$this->debug('checkCookie: '.sizeof($this->cookies).' cookies left in array');
|
8072 |
+
return true;
|
8073 |
+
}
|
8074 |
+
|
8075 |
+
/**
|
8076 |
+
* updates the current cookies with a new set
|
8077 |
+
*
|
8078 |
+
* @param array $cookies new cookies with which to update current ones
|
8079 |
+
* @return boolean always return true
|
8080 |
+
* @access private
|
8081 |
+
*/
|
8082 |
+
function UpdateCookies($cookies) {
|
8083 |
+
if (sizeof($this->cookies) == 0) {
|
8084 |
+
// no existing cookies: take whatever is new
|
8085 |
+
if (sizeof($cookies) > 0) {
|
8086 |
+
$this->debug('Setting new cookie(s)');
|
8087 |
+
$this->cookies = $cookies;
|
8088 |
+
}
|
8089 |
+
return true;
|
8090 |
+
}
|
8091 |
+
if (sizeof($cookies) == 0) {
|
8092 |
+
// no new cookies: keep what we've got
|
8093 |
+
return true;
|
8094 |
+
}
|
8095 |
+
// merge
|
8096 |
+
foreach ($cookies as $newCookie) {
|
8097 |
+
if (!is_array($newCookie)) {
|
8098 |
+
continue;
|
8099 |
+
}
|
8100 |
+
if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) {
|
8101 |
+
continue;
|
8102 |
+
}
|
8103 |
+
$newName = $newCookie['name'];
|
8104 |
+
|
8105 |
+
$found = false;
|
8106 |
+
for ($i = 0; $i < count($this->cookies); $i++) {
|
8107 |
+
$cookie = $this->cookies[$i];
|
8108 |
+
if (!is_array($cookie)) {
|
8109 |
+
continue;
|
8110 |
+
}
|
8111 |
+
if (!isset($cookie['name'])) {
|
8112 |
+
continue;
|
8113 |
+
}
|
8114 |
+
if ($newName != $cookie['name']) {
|
8115 |
+
continue;
|
8116 |
+
}
|
8117 |
+
$newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN';
|
8118 |
+
$domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN';
|
8119 |
+
if ($newDomain != $domain) {
|
8120 |
+
continue;
|
8121 |
+
}
|
8122 |
+
$newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH';
|
8123 |
+
$path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH';
|
8124 |
+
if ($newPath != $path) {
|
8125 |
+
continue;
|
8126 |
+
}
|
8127 |
+
$this->cookies[$i] = $newCookie;
|
8128 |
+
$found = true;
|
8129 |
+
$this->debug('Update cookie ' . $newName . '=' . $newCookie['value']);
|
8130 |
+
break;
|
8131 |
+
}
|
8132 |
+
if (! $found) {
|
8133 |
+
$this->debug('Add cookie ' . $newName . '=' . $newCookie['value']);
|
8134 |
+
$this->cookies[] = $newCookie;
|
8135 |
+
}
|
8136 |
+
}
|
8137 |
+
return true;
|
8138 |
+
}
|
8139 |
+
}
|
8140 |
+
|
8141 |
+
if (!extension_loaded('soap')) {
|
8142 |
+
/**
|
8143 |
+
* For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded.
|
8144 |
+
*/
|
8145 |
+
class soapclient extends nusoap_client {
|
8146 |
+
}
|
8147 |
+
}
|
8148 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/lib/nusoapmime.php
ADDED
@@ -0,0 +1,501 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
$Id: nusoapmime.php,v 1.13 2010/04/26 20:15:08 snichol Exp $
|
4 |
+
|
5 |
+
NuSOAP - Web Services Toolkit for PHP
|
6 |
+
|
7 |
+
Copyright (c) 2002 NuSphere Corporation
|
8 |
+
|
9 |
+
This library is free software; you can redistribute it and/or
|
10 |
+
modify it under the terms of the GNU Lesser General Public
|
11 |
+
License as published by the Free Software Foundation; either
|
12 |
+
version 2.1 of the License, or (at your option) any later version.
|
13 |
+
|
14 |
+
This library is distributed in the hope that it will be useful,
|
15 |
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
16 |
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
17 |
+
Lesser General Public License for more details.
|
18 |
+
|
19 |
+
You should have received a copy of the GNU Lesser General Public
|
20 |
+
License along with this library; if not, write to the Free Software
|
21 |
+
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
22 |
+
|
23 |
+
The NuSOAP project home is:
|
24 |
+
http://sourceforge.net/projects/nusoap/
|
25 |
+
|
26 |
+
The primary support for NuSOAP is the mailing list:
|
27 |
+
nusoap-general@lists.sourceforge.net
|
28 |
+
|
29 |
+
If you have any questions or comments, please email:
|
30 |
+
|
31 |
+
Dietrich Ayala
|
32 |
+
dietrich@ganx4.com
|
33 |
+
http://dietrich.ganx4.com/nusoap
|
34 |
+
|
35 |
+
NuSphere Corporation
|
36 |
+
http://www.nusphere.com
|
37 |
+
|
38 |
+
*/
|
39 |
+
|
40 |
+
/*require_once('nusoap.php');*/
|
41 |
+
/* PEAR Mail_MIME library */
|
42 |
+
require_once('Mail/mimeDecode.php');
|
43 |
+
require_once('Mail/mimePart.php');
|
44 |
+
|
45 |
+
/**
|
46 |
+
* nusoap_client_mime client supporting MIME attachments defined at
|
47 |
+
* http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library.
|
48 |
+
*
|
49 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
50 |
+
* @author Thanks to Guillaume and Henning Reich for posting great attachment code to the mail list
|
51 |
+
* @version $Id: nusoapmime.php,v 1.13 2010/04/26 20:15:08 snichol Exp $
|
52 |
+
* @access public
|
53 |
+
*/
|
54 |
+
class nusoap_client_mime extends nusoap_client {
|
55 |
+
/**
|
56 |
+
* @var array Each array element in the return is an associative array with keys
|
57 |
+
* data, filename, contenttype, cid
|
58 |
+
* @access private
|
59 |
+
*/
|
60 |
+
var $requestAttachments = array();
|
61 |
+
/**
|
62 |
+
* @var array Each array element in the return is an associative array with keys
|
63 |
+
* data, filename, contenttype, cid
|
64 |
+
* @access private
|
65 |
+
*/
|
66 |
+
var $responseAttachments;
|
67 |
+
/**
|
68 |
+
* @var string
|
69 |
+
* @access private
|
70 |
+
*/
|
71 |
+
var $mimeContentType;
|
72 |
+
|
73 |
+
/**
|
74 |
+
* adds a MIME attachment to the current request.
|
75 |
+
*
|
76 |
+
* If the $data parameter contains an empty string, this method will read
|
77 |
+
* the contents of the file named by the $filename parameter.
|
78 |
+
*
|
79 |
+
* If the $cid parameter is false, this method will generate the cid.
|
80 |
+
*
|
81 |
+
* @param string $data The data of the attachment
|
82 |
+
* @param string $filename The filename of the attachment (default is empty string)
|
83 |
+
* @param string $contenttype The MIME Content-Type of the attachment (default is application/octet-stream)
|
84 |
+
* @param string $cid The content-id (cid) of the attachment (default is false)
|
85 |
+
* @return string The content-id (cid) of the attachment
|
86 |
+
* @access public
|
87 |
+
*/
|
88 |
+
function addAttachment($data, $filename = '', $contenttype = 'application/octet-stream', $cid = false) {
|
89 |
+
if (! $cid) {
|
90 |
+
$cid = md5(uniqid(time()));
|
91 |
+
}
|
92 |
+
|
93 |
+
$info['data'] = $data;
|
94 |
+
$info['filename'] = $filename;
|
95 |
+
$info['contenttype'] = $contenttype;
|
96 |
+
$info['cid'] = $cid;
|
97 |
+
|
98 |
+
$this->requestAttachments[] = $info;
|
99 |
+
|
100 |
+
return $cid;
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* clears the MIME attachments for the current request.
|
105 |
+
*
|
106 |
+
* @access public
|
107 |
+
*/
|
108 |
+
function clearAttachments() {
|
109 |
+
$this->requestAttachments = array();
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* gets the MIME attachments from the current response.
|
114 |
+
*
|
115 |
+
* Each array element in the return is an associative array with keys
|
116 |
+
* data, filename, contenttype, cid. These keys correspond to the parameters
|
117 |
+
* for addAttachment.
|
118 |
+
*
|
119 |
+
* @return array The attachments.
|
120 |
+
* @access public
|
121 |
+
*/
|
122 |
+
function getAttachments() {
|
123 |
+
return $this->responseAttachments;
|
124 |
+
}
|
125 |
+
|
126 |
+
/**
|
127 |
+
* gets the HTTP body for the current request.
|
128 |
+
*
|
129 |
+
* @param string $soapmsg The SOAP payload
|
130 |
+
* @return string The HTTP body, which includes the SOAP payload
|
131 |
+
* @access private
|
132 |
+
*/
|
133 |
+
function getHTTPBody($soapmsg) {
|
134 |
+
if (count($this->requestAttachments) > 0) {
|
135 |
+
$params['content_type'] = 'multipart/related; type="text/xml"';
|
136 |
+
$mimeMessage = new Mail_mimePart('', $params);
|
137 |
+
unset($params);
|
138 |
+
|
139 |
+
$params['content_type'] = 'text/xml';
|
140 |
+
$params['encoding'] = '8bit';
|
141 |
+
$params['charset'] = $this->soap_defencoding;
|
142 |
+
$mimeMessage->addSubpart($soapmsg, $params);
|
143 |
+
|
144 |
+
foreach ($this->requestAttachments as $att) {
|
145 |
+
unset($params);
|
146 |
+
|
147 |
+
$params['content_type'] = $att['contenttype'];
|
148 |
+
$params['encoding'] = 'base64';
|
149 |
+
$params['disposition'] = 'attachment';
|
150 |
+
$params['dfilename'] = $att['filename'];
|
151 |
+
$params['cid'] = $att['cid'];
|
152 |
+
|
153 |
+
if ($att['data'] == '' && $att['filename'] <> '') {
|
154 |
+
if ($fd = fopen($att['filename'], 'rb')) {
|
155 |
+
$data = fread($fd, filesize($att['filename']));
|
156 |
+
fclose($fd);
|
157 |
+
} else {
|
158 |
+
$data = '';
|
159 |
+
}
|
160 |
+
$mimeMessage->addSubpart($data, $params);
|
161 |
+
} else {
|
162 |
+
$mimeMessage->addSubpart($att['data'], $params);
|
163 |
+
}
|
164 |
+
}
|
165 |
+
|
166 |
+
$output = $mimeMessage->encode();
|
167 |
+
$mimeHeaders = $output['headers'];
|
168 |
+
|
169 |
+
foreach ($mimeHeaders as $k => $v) {
|
170 |
+
$this->debug("MIME header $k: $v");
|
171 |
+
if (strtolower($k) == 'content-type') {
|
172 |
+
// PHP header() seems to strip leading whitespace starting
|
173 |
+
// the second line, so force everything to one line
|
174 |
+
$this->mimeContentType = str_replace("\r\n", " ", $v);
|
175 |
+
}
|
176 |
+
}
|
177 |
+
|
178 |
+
return $output['body'];
|
179 |
+
}
|
180 |
+
|
181 |
+
return parent::getHTTPBody($soapmsg);
|
182 |
+
}
|
183 |
+
|
184 |
+
/**
|
185 |
+
* gets the HTTP content type for the current request.
|
186 |
+
*
|
187 |
+
* Note: getHTTPBody must be called before this.
|
188 |
+
*
|
189 |
+
* @return string the HTTP content type for the current request.
|
190 |
+
* @access private
|
191 |
+
*/
|
192 |
+
function getHTTPContentType() {
|
193 |
+
if (count($this->requestAttachments) > 0) {
|
194 |
+
return $this->mimeContentType;
|
195 |
+
}
|
196 |
+
return parent::getHTTPContentType();
|
197 |
+
}
|
198 |
+
|
199 |
+
/**
|
200 |
+
* gets the HTTP content type charset for the current request.
|
201 |
+
* returns false for non-text content types.
|
202 |
+
*
|
203 |
+
* Note: getHTTPBody must be called before this.
|
204 |
+
*
|
205 |
+
* @return string the HTTP content type charset for the current request.
|
206 |
+
* @access private
|
207 |
+
*/
|
208 |
+
function getHTTPContentTypeCharset() {
|
209 |
+
if (count($this->requestAttachments) > 0) {
|
210 |
+
return false;
|
211 |
+
}
|
212 |
+
return parent::getHTTPContentTypeCharset();
|
213 |
+
}
|
214 |
+
|
215 |
+
/**
|
216 |
+
* processes SOAP message returned from server
|
217 |
+
*
|
218 |
+
* @param array $headers The HTTP headers
|
219 |
+
* @param string $data unprocessed response data from server
|
220 |
+
* @return mixed value of the message, decoded into a PHP type
|
221 |
+
* @access private
|
222 |
+
*/
|
223 |
+
function parseResponse($headers, $data) {
|
224 |
+
$this->debug('Entering parseResponse() for payload of length ' . strlen($data) . ' and type of ' . $headers['content-type']);
|
225 |
+
$this->responseAttachments = array();
|
226 |
+
if (strstr($headers['content-type'], 'multipart/related')) {
|
227 |
+
$this->debug('Decode multipart/related');
|
228 |
+
$input = '';
|
229 |
+
foreach ($headers as $k => $v) {
|
230 |
+
$input .= "$k: $v\r\n";
|
231 |
+
}
|
232 |
+
$params['input'] = $input . "\r\n" . $data;
|
233 |
+
$params['include_bodies'] = true;
|
234 |
+
$params['decode_bodies'] = true;
|
235 |
+
$params['decode_headers'] = true;
|
236 |
+
|
237 |
+
$structure = Mail_mimeDecode::decode($params);
|
238 |
+
|
239 |
+
foreach ($structure->parts as $part) {
|
240 |
+
if (!isset($part->disposition) && (strstr($part->headers['content-type'], 'text/xml'))) {
|
241 |
+
$this->debug('Have root part of type ' . $part->headers['content-type']);
|
242 |
+
$root = $part->body;
|
243 |
+
$return = parent::parseResponse($part->headers, $part->body);
|
244 |
+
} else {
|
245 |
+
$this->debug('Have an attachment of type ' . $part->headers['content-type']);
|
246 |
+
$info['data'] = $part->body;
|
247 |
+
$info['filename'] = isset($part->d_parameters['filename']) ? $part->d_parameters['filename'] : '';
|
248 |
+
$info['contenttype'] = $part->headers['content-type'];
|
249 |
+
$info['cid'] = $part->headers['content-id'];
|
250 |
+
$this->responseAttachments[] = $info;
|
251 |
+
}
|
252 |
+
}
|
253 |
+
|
254 |
+
if (isset($return)) {
|
255 |
+
$this->responseData = $root;
|
256 |
+
return $return;
|
257 |
+
}
|
258 |
+
|
259 |
+
$this->setError('No root part found in multipart/related content');
|
260 |
+
return '';
|
261 |
+
}
|
262 |
+
$this->debug('Not multipart/related');
|
263 |
+
return parent::parseResponse($headers, $data);
|
264 |
+
}
|
265 |
+
}
|
266 |
+
|
267 |
+
/*
|
268 |
+
* For backwards compatiblity, define soapclientmime unless the PHP SOAP extension is loaded.
|
269 |
+
*/
|
270 |
+
if (!extension_loaded('soap')) {
|
271 |
+
class soapclientmime extends nusoap_client_mime {
|
272 |
+
}
|
273 |
+
}
|
274 |
+
|
275 |
+
/**
|
276 |
+
* nusoap_server_mime server supporting MIME attachments defined at
|
277 |
+
* http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library.
|
278 |
+
*
|
279 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
280 |
+
* @author Thanks to Guillaume and Henning Reich for posting great attachment code to the mail list
|
281 |
+
* @version $Id: nusoapmime.php,v 1.13 2010/04/26 20:15:08 snichol Exp $
|
282 |
+
* @access public
|
283 |
+
*/
|
284 |
+
class nusoap_server_mime extends nusoap_server {
|
285 |
+
/**
|
286 |
+
* @var array Each array element in the return is an associative array with keys
|
287 |
+
* data, filename, contenttype, cid
|
288 |
+
* @access private
|
289 |
+
*/
|
290 |
+
var $requestAttachments = array();
|
291 |
+
/**
|
292 |
+
* @var array Each array element in the return is an associative array with keys
|
293 |
+
* data, filename, contenttype, cid
|
294 |
+
* @access private
|
295 |
+
*/
|
296 |
+
var $responseAttachments;
|
297 |
+
/**
|
298 |
+
* @var string
|
299 |
+
* @access private
|
300 |
+
*/
|
301 |
+
var $mimeContentType;
|
302 |
+
|
303 |
+
/**
|
304 |
+
* adds a MIME attachment to the current response.
|
305 |
+
*
|
306 |
+
* If the $data parameter contains an empty string, this method will read
|
307 |
+
* the contents of the file named by the $filename parameter.
|
308 |
+
*
|
309 |
+
* If the $cid parameter is false, this method will generate the cid.
|
310 |
+
*
|
311 |
+
* @param string $data The data of the attachment
|
312 |
+
* @param string $filename The filename of the attachment (default is empty string)
|
313 |
+
* @param string $contenttype The MIME Content-Type of the attachment (default is application/octet-stream)
|
314 |
+
* @param string $cid The content-id (cid) of the attachment (default is false)
|
315 |
+
* @return string The content-id (cid) of the attachment
|
316 |
+
* @access public
|
317 |
+
*/
|
318 |
+
function addAttachment($data, $filename = '', $contenttype = 'application/octet-stream', $cid = false) {
|
319 |
+
if (! $cid) {
|
320 |
+
$cid = md5(uniqid(time()));
|
321 |
+
}
|
322 |
+
|
323 |
+
$info['data'] = $data;
|
324 |
+
$info['filename'] = $filename;
|
325 |
+
$info['contenttype'] = $contenttype;
|
326 |
+
$info['cid'] = $cid;
|
327 |
+
|
328 |
+
$this->responseAttachments[] = $info;
|
329 |
+
|
330 |
+
return $cid;
|
331 |
+
}
|
332 |
+
|
333 |
+
/**
|
334 |
+
* clears the MIME attachments for the current response.
|
335 |
+
*
|
336 |
+
* @access public
|
337 |
+
*/
|
338 |
+
function clearAttachments() {
|
339 |
+
$this->responseAttachments = array();
|
340 |
+
}
|
341 |
+
|
342 |
+
/**
|
343 |
+
* gets the MIME attachments from the current request.
|
344 |
+
*
|
345 |
+
* Each array element in the return is an associative array with keys
|
346 |
+
* data, filename, contenttype, cid. These keys correspond to the parameters
|
347 |
+
* for addAttachment.
|
348 |
+
*
|
349 |
+
* @return array The attachments.
|
350 |
+
* @access public
|
351 |
+
*/
|
352 |
+
function getAttachments() {
|
353 |
+
return $this->requestAttachments;
|
354 |
+
}
|
355 |
+
|
356 |
+
/**
|
357 |
+
* gets the HTTP body for the current response.
|
358 |
+
*
|
359 |
+
* @param string $soapmsg The SOAP payload
|
360 |
+
* @return string The HTTP body, which includes the SOAP payload
|
361 |
+
* @access private
|
362 |
+
*/
|
363 |
+
function getHTTPBody($soapmsg) {
|
364 |
+
if (count($this->responseAttachments) > 0) {
|
365 |
+
$params['content_type'] = 'multipart/related; type="text/xml"';
|
366 |
+
$mimeMessage = new Mail_mimePart('', $params);
|
367 |
+
unset($params);
|
368 |
+
|
369 |
+
$params['content_type'] = 'text/xml';
|
370 |
+
$params['encoding'] = '8bit';
|
371 |
+
$params['charset'] = $this->soap_defencoding;
|
372 |
+
$mimeMessage->addSubpart($soapmsg, $params);
|
373 |
+
|
374 |
+
foreach ($this->responseAttachments as $att) {
|
375 |
+
unset($params);
|
376 |
+
|
377 |
+
$params['content_type'] = $att['contenttype'];
|
378 |
+
$params['encoding'] = 'base64';
|
379 |
+
$params['disposition'] = 'attachment';
|
380 |
+
$params['dfilename'] = $att['filename'];
|
381 |
+
$params['cid'] = $att['cid'];
|
382 |
+
|
383 |
+
if ($att['data'] == '' && $att['filename'] <> '') {
|
384 |
+
if ($fd = fopen($att['filename'], 'rb')) {
|
385 |
+
$data = fread($fd, filesize($att['filename']));
|
386 |
+
fclose($fd);
|
387 |
+
} else {
|
388 |
+
$data = '';
|
389 |
+
}
|
390 |
+
$mimeMessage->addSubpart($data, $params);
|
391 |
+
} else {
|
392 |
+
$mimeMessage->addSubpart($att['data'], $params);
|
393 |
+
}
|
394 |
+
}
|
395 |
+
|
396 |
+
$output = $mimeMessage->encode();
|
397 |
+
$mimeHeaders = $output['headers'];
|
398 |
+
|
399 |
+
foreach ($mimeHeaders as $k => $v) {
|
400 |
+
$this->debug("MIME header $k: $v");
|
401 |
+
if (strtolower($k) == 'content-type') {
|
402 |
+
// PHP header() seems to strip leading whitespace starting
|
403 |
+
// the second line, so force everything to one line
|
404 |
+
$this->mimeContentType = str_replace("\r\n", " ", $v);
|
405 |
+
}
|
406 |
+
}
|
407 |
+
|
408 |
+
return $output['body'];
|
409 |
+
}
|
410 |
+
|
411 |
+
return parent::getHTTPBody($soapmsg);
|
412 |
+
}
|
413 |
+
|
414 |
+
/**
|
415 |
+
* gets the HTTP content type for the current response.
|
416 |
+
*
|
417 |
+
* Note: getHTTPBody must be called before this.
|
418 |
+
*
|
419 |
+
* @return string the HTTP content type for the current response.
|
420 |
+
* @access private
|
421 |
+
*/
|
422 |
+
function getHTTPContentType() {
|
423 |
+
if (count($this->responseAttachments) > 0) {
|
424 |
+
return $this->mimeContentType;
|
425 |
+
}
|
426 |
+
return parent::getHTTPContentType();
|
427 |
+
}
|
428 |
+
|
429 |
+
/**
|
430 |
+
* gets the HTTP content type charset for the current response.
|
431 |
+
* returns false for non-text content types.
|
432 |
+
*
|
433 |
+
* Note: getHTTPBody must be called before this.
|
434 |
+
*
|
435 |
+
* @return string the HTTP content type charset for the current response.
|
436 |
+
* @access private
|
437 |
+
*/
|
438 |
+
function getHTTPContentTypeCharset() {
|
439 |
+
if (count($this->responseAttachments) > 0) {
|
440 |
+
return false;
|
441 |
+
}
|
442 |
+
return parent::getHTTPContentTypeCharset();
|
443 |
+
}
|
444 |
+
|
445 |
+
/**
|
446 |
+
* processes SOAP message received from client
|
447 |
+
*
|
448 |
+
* @param array $headers The HTTP headers
|
449 |
+
* @param string $data unprocessed request data from client
|
450 |
+
* @return mixed value of the message, decoded into a PHP type
|
451 |
+
* @access private
|
452 |
+
*/
|
453 |
+
function parseRequest($headers, $data) {
|
454 |
+
$this->debug('Entering parseRequest() for payload of length ' . strlen($data) . ' and type of ' . $headers['content-type']);
|
455 |
+
$this->requestAttachments = array();
|
456 |
+
if (strstr($headers['content-type'], 'multipart/related')) {
|
457 |
+
$this->debug('Decode multipart/related');
|
458 |
+
$input = '';
|
459 |
+
foreach ($headers as $k => $v) {
|
460 |
+
$input .= "$k: $v\r\n";
|
461 |
+
}
|
462 |
+
$params['input'] = $input . "\r\n" . $data;
|
463 |
+
$params['include_bodies'] = true;
|
464 |
+
$params['decode_bodies'] = true;
|
465 |
+
$params['decode_headers'] = true;
|
466 |
+
|
467 |
+
$structure = Mail_mimeDecode::decode($params);
|
468 |
+
|
469 |
+
foreach ($structure->parts as $part) {
|
470 |
+
if (!isset($part->disposition) && (strstr($part->headers['content-type'], 'text/xml'))) {
|
471 |
+
$this->debug('Have root part of type ' . $part->headers['content-type']);
|
472 |
+
$return = parent::parseRequest($part->headers, $part->body);
|
473 |
+
} else {
|
474 |
+
$this->debug('Have an attachment of type ' . $part->headers['content-type']);
|
475 |
+
$info['data'] = $part->body;
|
476 |
+
$info['filename'] = isset($part->d_parameters['filename']) ? $part->d_parameters['filename'] : '';
|
477 |
+
$info['contenttype'] = $part->headers['content-type'];
|
478 |
+
$info['cid'] = $part->headers['content-id'];
|
479 |
+
$this->requestAttachments[] = $info;
|
480 |
+
}
|
481 |
+
}
|
482 |
+
|
483 |
+
if (isset($return)) {
|
484 |
+
return $return;
|
485 |
+
}
|
486 |
+
|
487 |
+
$this->setError('No root part found in multipart/related content');
|
488 |
+
return;
|
489 |
+
}
|
490 |
+
$this->debug('Not multipart/related');
|
491 |
+
return parent::parseRequest($headers, $data);
|
492 |
+
}
|
493 |
+
}
|
494 |
+
|
495 |
+
/*
|
496 |
+
* For backwards compatiblity
|
497 |
+
*/
|
498 |
+
class nusoapservermime extends nusoap_server_mime {
|
499 |
+
}
|
500 |
+
|
501 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/samples/client1.php
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* $Id: client1.php,v 1.3 2007/11/06 14:48:24 snichol Exp $
|
4 |
+
*
|
5 |
+
* Client sample that should get a fault response.
|
6 |
+
*
|
7 |
+
* Service: SOAP endpoint
|
8 |
+
* Payload: rpc/encoded
|
9 |
+
* Transport: http
|
10 |
+
* Authentication: none
|
11 |
+
*/
|
12 |
+
require_once('../lib/nusoap.php');
|
13 |
+
$proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : '';
|
14 |
+
$proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : '';
|
15 |
+
$proxyusername = isset($_POST['proxyusername']) ? $_POST['proxyusername'] : '';
|
16 |
+
$proxypassword = isset($_POST['proxypassword']) ? $_POST['proxypassword'] : '';
|
17 |
+
$useCURL = isset($_POST['usecurl']) ? $_POST['usecurl'] : '0';
|
18 |
+
$client = new nusoap_client("http://soap.amazon.com/onca/soap2", false,
|
19 |
+
$proxyhost, $proxyport, $proxyusername, $proxypassword);
|
20 |
+
$err = $client->getError();
|
21 |
+
if ($err) {
|
22 |
+
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
|
23 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->getDebug(), ENT_QUOTES) . '</pre>';
|
24 |
+
exit();
|
25 |
+
}
|
26 |
+
$client->setUseCurl($useCURL);
|
27 |
+
// This is an archaic parameter list
|
28 |
+
$params = array(
|
29 |
+
'manufacturer' => "O'Reilly",
|
30 |
+
'page' => '1',
|
31 |
+
'mode' => 'books',
|
32 |
+
'tag' => 'trachtenberg-20',
|
33 |
+
'type' => 'lite',
|
34 |
+
'devtag' => 'Your tag here',
|
35 |
+
'sort' => '+title'
|
36 |
+
);
|
37 |
+
$result = $client->call('ManufacturerSearchRequest', $params, 'http://soap.amazon.com', 'http://soap.amazon.com');
|
38 |
+
if ($client->fault) {
|
39 |
+
echo '<h2>Fault (Expect - The request contains an invalid SOAP body)</h2><pre>'; print_r($result); echo '</pre>';
|
40 |
+
} else {
|
41 |
+
$err = $client->getError();
|
42 |
+
if ($err) {
|
43 |
+
echo '<h2>Error</h2><pre>' . $err . '</pre>';
|
44 |
+
} else {
|
45 |
+
echo '<h2>Result</h2><pre>'; print_r($result); echo '</pre>';
|
46 |
+
}
|
47 |
+
}
|
48 |
+
echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
|
49 |
+
echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
|
50 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->getDebug(), ENT_QUOTES) . '</pre>';
|
51 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/samples/client2.php
ADDED
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* $Id: client2.php,v 1.4 2007/11/06 14:48:24 snichol Exp $
|
4 |
+
*
|
5 |
+
* Client sample.
|
6 |
+
*
|
7 |
+
* Service: SOAP endpoint
|
8 |
+
* Payload: rpc/encoded
|
9 |
+
* Transport: http
|
10 |
+
* Authentication: none
|
11 |
+
*/
|
12 |
+
require_once('../lib/nusoap.php');
|
13 |
+
$proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : '';
|
14 |
+
$proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : '';
|
15 |
+
$proxyusername = isset($_POST['proxyusername']) ? $_POST['proxyusername'] : '';
|
16 |
+
$proxypassword = isset($_POST['proxypassword']) ? $_POST['proxypassword'] : '';
|
17 |
+
$useCURL = isset($_POST['usecurl']) ? $_POST['usecurl'] : '0';
|
18 |
+
$client = new nusoap_client("http://soap.amazon.com/onca/soap2", false,
|
19 |
+
$proxyhost, $proxyport, $proxyusername, $proxypassword);
|
20 |
+
$err = $client->getError();
|
21 |
+
if ($err) {
|
22 |
+
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
|
23 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->getDebug(), ENT_QUOTES) . '</pre>';
|
24 |
+
exit();
|
25 |
+
}
|
26 |
+
$client->setUseCurl($useCURL);
|
27 |
+
$client->useHTTPPersistentConnection();
|
28 |
+
$param = array(
|
29 |
+
'manufacturer' => "O'Reilly",
|
30 |
+
'page' => '1',
|
31 |
+
'mode' => 'books',
|
32 |
+
'tag' => 'trachtenberg-20',
|
33 |
+
'type' => 'lite',
|
34 |
+
'devtag' => 'Your tag here'
|
35 |
+
);
|
36 |
+
$params = array('ManufacturerSearchRequest' =>
|
37 |
+
new soapval('ManufacturerSearchRequest',
|
38 |
+
'ManufacturerRequest',
|
39 |
+
$param,
|
40 |
+
false,
|
41 |
+
'http://soap.amazon.com')
|
42 |
+
);
|
43 |
+
$result = $client->call('ManufacturerSearchRequest', $params, 'http://soap.amazon.com', 'http://soap.amazon.com');
|
44 |
+
if ($client->fault) {
|
45 |
+
echo '<h2>Fault</h2><pre>'; print_r($result); echo '</pre>';
|
46 |
+
} else {
|
47 |
+
$err = $client->getError();
|
48 |
+
if ($err) {
|
49 |
+
echo '<h2>Error</h2><pre>' . $err . '</pre>';
|
50 |
+
} else {
|
51 |
+
echo '<h2>Result</h2><pre>'; print_r($result); echo '</pre>';
|
52 |
+
}
|
53 |
+
}
|
54 |
+
echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
|
55 |
+
echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
|
56 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->getDebug(), ENT_QUOTES) . '</pre>';
|
57 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/samples/client3.php
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* $Id: client3.php,v 1.4 2007/11/06 14:48:24 snichol Exp $
|
4 |
+
*
|
5 |
+
* Client sample.
|
6 |
+
*
|
7 |
+
* Service: SOAP endpoint
|
8 |
+
* Payload: rpc/encoded
|
9 |
+
* Transport: http
|
10 |
+
* Authentication: none
|
11 |
+
*/
|
12 |
+
require_once('../lib/nusoap.php');
|
13 |
+
$proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : '';
|
14 |
+
$proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : '';
|
15 |
+
$proxyusername = isset($_POST['proxyusername']) ? $_POST['proxyusername'] : '';
|
16 |
+
$proxypassword = isset($_POST['proxypassword']) ? $_POST['proxypassword'] : '';
|
17 |
+
$useCURL = isset($_POST['usecurl']) ? $_POST['usecurl'] : '0';
|
18 |
+
$client = new nusoap_client("http://api.google.com/search/beta2", false,
|
19 |
+
$proxyhost, $proxyport, $proxyusername, $proxypassword);
|
20 |
+
$err = $client->getError();
|
21 |
+
if ($err) {
|
22 |
+
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
|
23 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->getDebug(), ENT_QUOTES) . '</pre>';
|
24 |
+
exit();
|
25 |
+
}
|
26 |
+
$client->setUseCurl($useCURL);
|
27 |
+
$client->soap_defencoding = 'UTF-8';
|
28 |
+
|
29 |
+
//echo 'You must set your own Google key in the source code to run this client!'; exit();
|
30 |
+
$params = array(
|
31 |
+
'Googlekey'=>'Your Google key',
|
32 |
+
'queryStr'=>'robotics',
|
33 |
+
'startFrom'=>0,
|
34 |
+
'maxResults'=>10,
|
35 |
+
'filter'=>true,
|
36 |
+
'restrict'=>'',
|
37 |
+
'adultContent'=>true,
|
38 |
+
'language'=>'',
|
39 |
+
'iencoding'=>'',
|
40 |
+
'oendcoding'=>''
|
41 |
+
);
|
42 |
+
$result = $client->call("doGoogleSearch", $params, "urn:GoogleSearch", "urn:GoogleSearch");
|
43 |
+
if ($client->fault) {
|
44 |
+
echo '<h2>Fault</h2><pre>'; print_r($result); echo '</pre>';
|
45 |
+
} else {
|
46 |
+
$err = $client->getError();
|
47 |
+
if ($err) {
|
48 |
+
echo '<h2>Error</h2><pre>' . $err . '</pre>';
|
49 |
+
} else {
|
50 |
+
echo '<h2>Result</h2><pre>'; print_r($result); echo '</pre>';
|
51 |
+
}
|
52 |
+
}
|
53 |
+
echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
|
54 |
+
echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
|
55 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->getDebug(), ENT_QUOTES) . '</pre>';
|
56 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/samples/getfile1client.php
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* $Id: getfile1client.php,v 1.1 2005/05/18 14:38:53 snichol Exp $
|
4 |
+
*
|
5 |
+
* Get file client sample.
|
6 |
+
*
|
7 |
+
* Service: SOAP endpoint
|
8 |
+
* Payload: rpc/encoded
|
9 |
+
* Transport: http
|
10 |
+
* Authentication: none
|
11 |
+
*/
|
12 |
+
require_once('../lib/nusoap.php');
|
13 |
+
$proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : '';
|
14 |
+
$proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : '';
|
15 |
+
$proxyusername = isset($_POST['proxyusername']) ? $_POST['proxyusername'] : '';
|
16 |
+
$proxypassword = isset($_POST['proxypassword']) ? $_POST['proxypassword'] : '';
|
17 |
+
$client = new soapclient('http://www.scottnichol.com/samples/getfile1.php?wsdl', true,
|
18 |
+
$proxyhost, $proxyport, $proxyusername, $proxypassword);
|
19 |
+
$err = $client->getError();
|
20 |
+
if ($err) {
|
21 |
+
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
|
22 |
+
}
|
23 |
+
$result = $client->call('getFile', array('filename' => 'getfile1.php'));
|
24 |
+
if ($client->fault) {
|
25 |
+
echo '<h2>Fault</h2><pre>'; print_r($result); echo '</pre>';
|
26 |
+
} else {
|
27 |
+
$err = $client->getError();
|
28 |
+
if ($err) {
|
29 |
+
echo '<h2>Error</h2><pre>' . $err . '</pre>';
|
30 |
+
} else {
|
31 |
+
echo '<h2>Result</h2><pre>' . htmlspecialchars($result, ENT_QUOTES) . '</pre>';
|
32 |
+
}
|
33 |
+
}
|
34 |
+
echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
|
35 |
+
echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
|
36 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->debug_str, ENT_QUOTES) . '</pre>';
|
37 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/samples/getfile2client.php
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* $Id: getfile2client.php,v 1.1 2005/05/18 14:38:53 snichol Exp $
|
4 |
+
*
|
5 |
+
* Get file client sample.
|
6 |
+
*
|
7 |
+
* Service: SOAP endpoint
|
8 |
+
* Payload: rpc/encoded
|
9 |
+
* Transport: http
|
10 |
+
* Authentication: none
|
11 |
+
*/
|
12 |
+
require_once('../lib/nusoap.php');
|
13 |
+
$proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : '';
|
14 |
+
$proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : '';
|
15 |
+
$proxyusername = isset($_POST['proxyusername']) ? $_POST['proxyusername'] : '';
|
16 |
+
$proxypassword = isset($_POST['proxypassword']) ? $_POST['proxypassword'] : '';
|
17 |
+
$client = new soapclient('http://www.scottnichol.com/samples/getfile2.php?wsdl', true,
|
18 |
+
$proxyhost, $proxyport, $proxyusername, $proxypassword);
|
19 |
+
$err = $client->getError();
|
20 |
+
if ($err) {
|
21 |
+
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
|
22 |
+
}
|
23 |
+
$result = $client->call('getFile', array('filename' => 'getfile2.php'));
|
24 |
+
if ($client->fault) {
|
25 |
+
echo '<h2>Fault</h2><pre>'; print_r($result); echo '</pre>';
|
26 |
+
} else {
|
27 |
+
$err = $client->getError();
|
28 |
+
if ($err) {
|
29 |
+
echo '<h2>Error</h2><pre>' . $err . '</pre>';
|
30 |
+
} else {
|
31 |
+
echo '<h2>Result</h2><pre>' . htmlspecialchars($result, ENT_QUOTES) . '</pre>';
|
32 |
+
}
|
33 |
+
}
|
34 |
+
echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
|
35 |
+
echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
|
36 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->debug_str, ENT_QUOTES) . '</pre>';
|
37 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/samples/index.html
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<html>
|
2 |
+
<!--
|
3 |
+
-- $Id: index.html,v 1.19 2010/04/26 15:31:48 snichol Exp $
|
4 |
+
-->
|
5 |
+
<head>
|
6 |
+
<title>NuSOAP Samples</title>
|
7 |
+
<script type="text/javascript">
|
8 |
+
function go(url) {
|
9 |
+
document.linkform.action = url;
|
10 |
+
document.linkform.submit();
|
11 |
+
}
|
12 |
+
</script>
|
13 |
+
</head>
|
14 |
+
<body>
|
15 |
+
<h2>NuSOAP Samples</h2>
|
16 |
+
<p>
|
17 |
+
These links allow you to launch sample clients. <b><i>As of 26 April 2010, most of the links to commercial services no longer work.</i></b>
|
18 |
+
</p>
|
19 |
+
<form name="linkform" method="POST" action="javascript:void();">
|
20 |
+
<a href="javascript:go('client1.php')">Amazon endpoint (Fault expected)</a><br>
|
21 |
+
<a href="javascript:go('client2.php')">Amazon endpoint</a><br>
|
22 |
+
<a href="javascript:go('client3.php')">Google endpoint (you must have a key)</a><br>
|
23 |
+
<a href="javascript:go('mimeclient.php')">MIME Attachment</a><br>
|
24 |
+
<a href="javascript:go('sslclient.php')">SSL endpoint</a><br>
|
25 |
+
<a href="javascript:go('wsdlclient1.php')">Stock quote WSDL</a><br>
|
26 |
+
<a href="javascript:go('wsdlclient2.php')">Amazon WSDL</a><br>
|
27 |
+
<a href="javascript:go('wsdlclient3.php?method=function')">Hello WSDL (PHP function)</a><br>
|
28 |
+
<a href="javascript:go('wsdlclient3.php?method=instance')">Hello WSDL (PHP instance method)</a><br>
|
29 |
+
<a href="javascript:go('wsdlclient3.php?method=class')">Hello WSDL (PHP class method)</a><br>
|
30 |
+
<a href="javascript:go('wsdlclient3b.php')">Hello WSDL with pre-formed parameter XML</a><br>
|
31 |
+
<a href="javascript:go('wsdlclient3c.php')">Hello WSDL (rpc/literal version)</a><br>
|
32 |
+
<a href="javascript:go('wsdlclient4.php')">Interop WSDL</a><br>
|
33 |
+
<a href="javascript:go('wsdlclient5.php')">Price quote WSDL (uses wsdlcache)</a><br>
|
34 |
+
<a href="javascript:go('wsdlclient6.php')">Google WSDL (you must have WSDL file local)</a><br>
|
35 |
+
<a href="javascript:go('wsdlclient7.php')">MapPoint WSDL #1 (you must have a username/password)</a><br>
|
36 |
+
<a href="javascript:go('wsdlclient8.php')">MapPoint WSDL #2 (you must have a username/password)</a><br>
|
37 |
+
<a href="javascript:go('wsdlclient9.php')">MapPoint WSDL #3 (you must have a username/password)</a><br>
|
38 |
+
<a href="javascript:go('wsdlclient10.php')">Country list WSDL</a><br>
|
39 |
+
<a href="javascript:go('wsdlclient11.php')">Hello WSDL (document/literal version)</a><br>
|
40 |
+
<a href="javascript:go('wsdlclient12.php?method=ItemLookup')">Amazon E-Commerce Service (ItemLookup by node)</a><br>
|
41 |
+
<a href="javascript:go('wsdlclient12.php?method=ItemSearch')">Amazon E-Commerce Service (ItemSearch by node)</a><br>
|
42 |
+
<a href="javascript:go('wsdlclient12.php?method=ItemSearch2')">Amazon E-Commerce Service (ItemSearch by keyword)</a><br>
|
43 |
+
<a href="javascript:go('wsdlclient12.php?method=ListLookup')">Amazon E-Commerce Service (ListLookup)</a><br>
|
44 |
+
<a href="javascript:go('wsdlclient12.php?method=ListSearch')">Amazon E-Commerce Service (ListSearch)</a><br>
|
45 |
+
<a href="javascript:go('wsdlclient12.php?method=CartCreate')">Amazon E-Commerce Service (CartCreate)</a><br>
|
46 |
+
<a href="javascript:go('wsdlclient13.php')">Maintain a Session</a><br>
|
47 |
+
<a href="javascript:go('wsdlclient14.php')">Via Michelin</a><br>
|
48 |
+
<a href="javascript:go('wsdlclient15.php')">UTF-8 Character Encoding</a><br>
|
49 |
+
<a href="javascript:go('getfile1client.php')">Get a file #1 (uses base64Binary)</a><br>
|
50 |
+
<a href="javascript:go('getfile2client.php')">Get a file #2 (uses base64Binary; service uses external WSDL file)</a><br>
|
51 |
+
<br>
|
52 |
+
<table border="0">
|
53 |
+
<tr><td>Use cURL?</td><td><input type="checkbox" name="usecurl" value="1"></td></tr>
|
54 |
+
</table>
|
55 |
+
<p>
|
56 |
+
If you access the Internet through a proxy, provide the proxy
|
57 |
+
information below.
|
58 |
+
</p>
|
59 |
+
<table border="0">
|
60 |
+
<tr><td>Proxy Host:</td><td><input type="text" name="proxyhost" value="" size="50" maxlength="256"></td></tr>
|
61 |
+
<tr><td>Proxy Port:</td><td><input type="text" name="proxyport" value="" size="5" maxlength="5"></td></tr>
|
62 |
+
<tr><td>Proxy Username:</td><td><input type="text" name="proxyusername" value="" size="50" maxlength="256"></td></tr>
|
63 |
+
<tr><td>Proxy Password:</td><td><input type="password" name="proxypassword" value="" size="50" maxlength="256"></td></tr>
|
64 |
+
</table>
|
65 |
+
</form>
|
66 |
+
</body>
|
67 |
+
</html>
|
app/code/local/Waterstone/winvoice/Model/nusoap/samples/mimeclient.php
ADDED
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* $Id: mimeclient.php,v 1.6 2007/04/16 22:08:17 snichol Exp $
|
4 |
+
*
|
5 |
+
* MIME client sample.
|
6 |
+
*
|
7 |
+
* Service: SOAP endpoint
|
8 |
+
* Payload: rpc/encoded
|
9 |
+
* Transport: http
|
10 |
+
* Authentication: none
|
11 |
+
*/
|
12 |
+
require_once('../lib/nusoap.php');
|
13 |
+
require_once('../lib/nusoapmime.php');
|
14 |
+
$proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : '';
|
15 |
+
$proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : '';
|
16 |
+
$proxyusername = isset($_POST['proxyusername']) ? $_POST['proxyusername'] : '';
|
17 |
+
$proxypassword = isset($_POST['proxypassword']) ? $_POST['proxypassword'] : '';
|
18 |
+
$useCURL = isset($_POST['usecurl']) ? $_POST['usecurl'] : '0';
|
19 |
+
$client = new nusoap_client_mime('http://www.scottnichol.com/samples/mimetest.php', false,
|
20 |
+
$proxyhost, $proxyport, $proxyusername, $proxypassword);
|
21 |
+
$err = $client->getError();
|
22 |
+
if ($err) {
|
23 |
+
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
|
24 |
+
}
|
25 |
+
$client->setUseCurl($useCURL);
|
26 |
+
$client->setHTTPEncoding('deflate, gzip');
|
27 |
+
$cid = $client->addAttachment('', 'mimeclient.php');
|
28 |
+
$result = $client->call('hello', array('name' => 'Scott'));
|
29 |
+
if ($client->fault) {
|
30 |
+
echo '<h2>Fault</h2><pre>'; print_r($result); echo '</pre>';
|
31 |
+
} else {
|
32 |
+
$err = $client->getError();
|
33 |
+
if ($err) {
|
34 |
+
echo '<h2>Error</h2><pre>' . $err . '</pre>';
|
35 |
+
} else {
|
36 |
+
echo '<h2>Result</h2><pre>'; print_r($result); echo '</pre>';
|
37 |
+
echo '<h2>Attachments</h2><pre>';
|
38 |
+
$attachments = $client->getAttachments();
|
39 |
+
foreach ($attachments as $a) {
|
40 |
+
echo 'Filename: ' . $a['filename'] . "\r\n";
|
41 |
+
echo 'Content-Type: ' . $a['contenttype'] . "\r\n";
|
42 |
+
echo 'cid: ' . htmlspecialchars($a['cid'], ENT_QUOTES) . "\r\n";
|
43 |
+
echo htmlspecialchars($a['data'], ENT_QUOTES);
|
44 |
+
echo "\r\n";
|
45 |
+
}
|
46 |
+
echo '</pre>';
|
47 |
+
}
|
48 |
+
}
|
49 |
+
echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
|
50 |
+
echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
|
51 |
+
echo '<h2>ResponseData</h2><pre>' . htmlspecialchars($client->responseData, ENT_QUOTES) . '</pre>';
|
52 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->debug_str, ENT_QUOTES) . '</pre>';
|
53 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/samples/sslclient.php
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* $Id: sslclient.php,v 1.1 2004/01/09 03:23:42 snichol Exp $
|
4 |
+
*
|
5 |
+
* SSL client sample.
|
6 |
+
*
|
7 |
+
* Service: SOAP endpoint
|
8 |
+
* Payload: rpc/encoded
|
9 |
+
* Transport: https
|
10 |
+
* Authentication: none
|
11 |
+
*/
|
12 |
+
require_once('../lib/nusoap.php');
|
13 |
+
$proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : '';
|
14 |
+
$proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : '';
|
15 |
+
$proxyusername = isset($_POST['proxyusername']) ? $_POST['proxyusername'] : '';
|
16 |
+
$proxypassword = isset($_POST['proxypassword']) ? $_POST['proxypassword'] : '';
|
17 |
+
$client = new soapclient('https://arcweb.esri.com/services/v2/AddressFinder', false,
|
18 |
+
$proxyhost, $proxyport, $proxyusername, $proxypassword);
|
19 |
+
$err = $client->getError();
|
20 |
+
if ($err) {
|
21 |
+
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
|
22 |
+
}
|
23 |
+
$result = $client->call('getVersion', array(), 'http://arcweb.esri.com/v2', 'getVersion');
|
24 |
+
if ($client->fault) {
|
25 |
+
echo '<h2>Fault</h2><pre>'; print_r($result); echo '</pre>';
|
26 |
+
} else {
|
27 |
+
$err = $client->getError();
|
28 |
+
if ($err) {
|
29 |
+
echo '<h2>Error</h2><pre>' . $err . '</pre>';
|
30 |
+
} else {
|
31 |
+
echo '<h2>Result</h2><pre>'; print_r($result); echo '</pre>';
|
32 |
+
}
|
33 |
+
}
|
34 |
+
echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
|
35 |
+
echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
|
36 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->debug_str, ENT_QUOTES) . '</pre>';
|
37 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient1.php
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* $Id: wsdlclient1.php,v 1.3 2007/11/06 14:48:48 snichol Exp $
|
4 |
+
*
|
5 |
+
* WSDL client sample.
|
6 |
+
*
|
7 |
+
* Service: WSDL
|
8 |
+
* Payload: document/literal
|
9 |
+
* Transport: http
|
10 |
+
* Authentication: none
|
11 |
+
*/
|
12 |
+
require_once('../lib/nusoap.php');
|
13 |
+
$proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : '';
|
14 |
+
$proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : '';
|
15 |
+
$proxyusername = isset($_POST['proxyusername']) ? $_POST['proxyusername'] : '';
|
16 |
+
$proxypassword = isset($_POST['proxypassword']) ? $_POST['proxypassword'] : '';
|
17 |
+
$client = new nusoap_client('http://www.xignite.com/xquotes.asmx?WSDL', 'wsdl',
|
18 |
+
$proxyhost, $proxyport, $proxyusername, $proxypassword);
|
19 |
+
$err = $client->getError();
|
20 |
+
if ($err) {
|
21 |
+
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
|
22 |
+
}
|
23 |
+
// Doc/lit parameters get wrapped
|
24 |
+
$param = array('Symbol' => 'IBM');
|
25 |
+
$result = $client->call('GetQuickQuotes', array('parameters' => $param), '', '', false, true);
|
26 |
+
// Check for a fault
|
27 |
+
if ($client->fault) {
|
28 |
+
echo '<h2>Fault</h2><pre>';
|
29 |
+
print_r($result);
|
30 |
+
echo '</pre>';
|
31 |
+
} else {
|
32 |
+
// Check for errors
|
33 |
+
$err = $client->getError();
|
34 |
+
if ($err) {
|
35 |
+
// Display the error
|
36 |
+
echo '<h2>Error</h2><pre>' . $err . '</pre>';
|
37 |
+
} else {
|
38 |
+
// Display the result
|
39 |
+
echo '<h2>Result</h2><pre>';
|
40 |
+
print_r($result);
|
41 |
+
echo '</pre>';
|
42 |
+
}
|
43 |
+
}
|
44 |
+
echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
|
45 |
+
echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
|
46 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->debug_str, ENT_QUOTES) . '</pre>';
|
47 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient10.php
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* $Id: wsdlclient10.php,v 1.2 2007/04/13 14:22:09 snichol Exp $
|
4 |
+
*
|
5 |
+
* WSDL client sample.
|
6 |
+
* Demonstrates de-serialization of a document/literal array (added nusoap.php 1.73).
|
7 |
+
*
|
8 |
+
* Service: WSDL
|
9 |
+
* Payload: document/literal
|
10 |
+
* Transport: http
|
11 |
+
* Authentication: none
|
12 |
+
*/
|
13 |
+
require_once('../lib/nusoap.php');
|
14 |
+
$proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : '';
|
15 |
+
$proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : '';
|
16 |
+
$proxyusername = isset($_POST['proxyusername']) ? $_POST['proxyusername'] : '';
|
17 |
+
$proxypassword = isset($_POST['proxypassword']) ? $_POST['proxypassword'] : '';
|
18 |
+
$useCURL = isset($_POST['usecurl']) ? $_POST['usecurl'] : '0';
|
19 |
+
$client = new soapclient('http://www.abundanttech.com/WebServices/Population/population.asmx?WSDL', true,
|
20 |
+
$proxyhost, $proxyport, $proxyusername, $proxypassword);
|
21 |
+
$err = $client->getError();
|
22 |
+
if ($err) {
|
23 |
+
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
|
24 |
+
}
|
25 |
+
$client->setUseCurl($useCURL);
|
26 |
+
$result = $client->call('getCountries', array(), '', '', false, true);
|
27 |
+
if ($client->fault) {
|
28 |
+
echo '<h2>Fault</h2><pre>';
|
29 |
+
print_r($result);
|
30 |
+
echo '</pre>';
|
31 |
+
} else {
|
32 |
+
$err = $client->getError();
|
33 |
+
if ($err) {
|
34 |
+
echo '<h2>Error</h2><pre>' . $err . '</pre>';
|
35 |
+
} else {
|
36 |
+
echo '<h2>Result</h2><pre>';
|
37 |
+
print_r($result);
|
38 |
+
echo '</pre>';
|
39 |
+
}
|
40 |
+
}
|
41 |
+
echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
|
42 |
+
echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
|
43 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->debug_str, ENT_QUOTES) . '</pre>';
|
44 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient11.php
ADDED
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* $Id: wsdlclient11.php,v 1.2 2007/04/13 16:52:32 snichol Exp $
|
4 |
+
*
|
5 |
+
* WSDL client sample.
|
6 |
+
* Exercises a document/literal NuSOAP service (added nusoap.php 1.73).
|
7 |
+
* Does not explicitly wrap parameters.
|
8 |
+
*
|
9 |
+
* Service: WSDL
|
10 |
+
* Payload: document/literal
|
11 |
+
* Transport: http
|
12 |
+
* Authentication: none
|
13 |
+
*/
|
14 |
+
require_once('../lib/nusoap.php');
|
15 |
+
$proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : '';
|
16 |
+
$proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : '';
|
17 |
+
$proxyusername = isset($_POST['proxyusername']) ? $_POST['proxyusername'] : '';
|
18 |
+
$proxypassword = isset($_POST['proxypassword']) ? $_POST['proxypassword'] : '';
|
19 |
+
$useCURL = isset($_POST['usecurl']) ? $_POST['usecurl'] : '0';
|
20 |
+
$client = new soapclient('http://www.scottnichol.com/samples/hellowsdl3.wsdl', true,
|
21 |
+
$proxyhost, $proxyport, $proxyusername, $proxypassword);
|
22 |
+
$err = $client->getError();
|
23 |
+
if ($err) {
|
24 |
+
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
|
25 |
+
}
|
26 |
+
$client->setUseCurl($useCURL);
|
27 |
+
$person = array('firstname' => 'Willi', 'age' => 22, 'gender' => 'male');
|
28 |
+
$name = array('name' => $person);
|
29 |
+
$result = $client->call('hello', $name);
|
30 |
+
if ($client->fault) {
|
31 |
+
echo '<h2>Fault</h2><pre>';
|
32 |
+
print_r($result);
|
33 |
+
echo '</pre>';
|
34 |
+
} else {
|
35 |
+
$err = $client->getError();
|
36 |
+
if ($err) {
|
37 |
+
echo '<h2>Error</h2><pre>' . $err . '</pre>';
|
38 |
+
} else {
|
39 |
+
echo '<h2>Result</h2><pre>';
|
40 |
+
print_r($result);
|
41 |
+
echo '</pre>';
|
42 |
+
}
|
43 |
+
}
|
44 |
+
echo '<h2>Request</h2>';
|
45 |
+
echo '<pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
|
46 |
+
echo '<h2>Response</h2>';
|
47 |
+
echo '<pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
|
48 |
+
echo '<h2>Debug</h2>';
|
49 |
+
echo '<pre>' . htmlspecialchars($client->debug_str, ENT_QUOTES) . '</pre>';
|
50 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient12.php
ADDED
@@ -0,0 +1,225 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* $Id: wsdlclient12.php,v 1.4 2007/11/06 14:50:07 snichol Exp $
|
4 |
+
*
|
5 |
+
* WSDL client sample.
|
6 |
+
*
|
7 |
+
* Service: WSDL
|
8 |
+
* Payload: document/literal
|
9 |
+
* Transport: http
|
10 |
+
* Authentication: none
|
11 |
+
*/
|
12 |
+
require_once('../lib/nusoap.php');
|
13 |
+
require_once('../lib/class.wsdlcache.php');
|
14 |
+
$proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : '';
|
15 |
+
$proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : '';
|
16 |
+
$proxyusername = isset($_POST['proxyusername']) ? $_POST['proxyusername'] : '';
|
17 |
+
$proxypassword = isset($_POST['proxypassword']) ? $_POST['proxypassword'] : '';
|
18 |
+
|
19 |
+
$method = isset($_GET['method']) ? $_GET['method'] : 'ItemSearch';
|
20 |
+
|
21 |
+
$SubscriptionId = 'Your AWS subscription id';
|
22 |
+
|
23 |
+
$wsdlurl = 'http://webservices.amazon.com/AWSECommerceService/US/AWSECommerceService.wsdl';
|
24 |
+
$cache = new wsdlcache('.', 120);
|
25 |
+
$wsdl = $cache->get($wsdlurl);
|
26 |
+
if (is_null($wsdl)) {
|
27 |
+
$wsdl = new wsdl($wsdlurl,
|
28 |
+
$proxyhost, $proxyport, $proxyusername, $proxypassword);
|
29 |
+
$cache->put($wsdl);
|
30 |
+
} else {
|
31 |
+
$wsdl->debug_str = '';
|
32 |
+
$wsdl->debug('Retrieved from cache');
|
33 |
+
}
|
34 |
+
$client = new nusoap_client($wsdl, true,
|
35 |
+
$proxyhost, $proxyport, $proxyusername, $proxypassword);
|
36 |
+
$err = $client->getError();
|
37 |
+
if ($err) {
|
38 |
+
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
|
39 |
+
}
|
40 |
+
|
41 |
+
$client->soap_defencoding = 'UTF-8';
|
42 |
+
|
43 |
+
function GetCartCreateParams() {
|
44 |
+
global $SubscriptionId;
|
45 |
+
|
46 |
+
// create items to be added to the cart
|
47 |
+
$item = array ();
|
48 |
+
$item[0] = array( "ASIN" => "0596004206",
|
49 |
+
"Quantity" => "1"
|
50 |
+
);
|
51 |
+
$item[1] = array( "ASIN" => "0596003277",
|
52 |
+
"Quantity" => "2"
|
53 |
+
);
|
54 |
+
|
55 |
+
// pack it to <Item> array
|
56 |
+
$items = array("Item" => $item);
|
57 |
+
// Construct request parameters
|
58 |
+
$request = array("Items" => $items, "ResponseGroup" => "CartSimilarities");
|
59 |
+
|
60 |
+
// Construct all parameters
|
61 |
+
$cartCreate = array( "SubscriptionId" => $SubscriptionId,
|
62 |
+
"Request" => $request
|
63 |
+
);
|
64 |
+
|
65 |
+
return $cartCreate;
|
66 |
+
}
|
67 |
+
|
68 |
+
function GetItemLookupParams() {
|
69 |
+
global $SubscriptionId;
|
70 |
+
|
71 |
+
$itemLookupRequest[] = array(
|
72 |
+
'ItemId' => 'B0002IQML6',
|
73 |
+
'IdType' => 'ASIN',
|
74 |
+
'Condition' => 'All',
|
75 |
+
'ResponseGroup' => 'Large'
|
76 |
+
);
|
77 |
+
|
78 |
+
$itemLookupRequest[] = array(
|
79 |
+
'ItemId' => '0486411214',
|
80 |
+
'IdType' => 'ASIN',
|
81 |
+
'Condition' => 'New',
|
82 |
+
'ResponseGroup' => 'Small'
|
83 |
+
);
|
84 |
+
|
85 |
+
$itemLookup = array(
|
86 |
+
'SubscriptionId' => $SubscriptionId,
|
87 |
+
// 'AssociateTag' => '',
|
88 |
+
'Request' => $itemLookupRequest,
|
89 |
+
);
|
90 |
+
|
91 |
+
return $itemLookup;
|
92 |
+
}
|
93 |
+
|
94 |
+
function GetItemSearchParams() {
|
95 |
+
global $SubscriptionId;
|
96 |
+
|
97 |
+
$itemSearchRequest = array(
|
98 |
+
'BrowseNode' => '53',
|
99 |
+
'ItemPage' => 1,
|
100 |
+
// 'ResponseGroup' => array('Request', 'Small'),
|
101 |
+
'SearchIndex' => 'Books',
|
102 |
+
'Sort' => 'salesrank'
|
103 |
+
);
|
104 |
+
|
105 |
+
$itemSearch = array(
|
106 |
+
'SubscriptionId' => $SubscriptionId,
|
107 |
+
// 'AssociateTag' => '',
|
108 |
+
// 'Validate' => '',
|
109 |
+
// 'XMLEscaping' => '',
|
110 |
+
// 'Shared' => $itemSearchRequest,
|
111 |
+
'Request' => array($itemSearchRequest)
|
112 |
+
);
|
113 |
+
|
114 |
+
return $itemSearch;
|
115 |
+
}
|
116 |
+
|
117 |
+
function GetItemSearchParams2() {
|
118 |
+
global $SubscriptionId;
|
119 |
+
|
120 |
+
$request = array(
|
121 |
+
"Keywords" => "postal stamps",
|
122 |
+
"SearchIndex" => "Books"
|
123 |
+
);
|
124 |
+
|
125 |
+
$itemSearch = array(
|
126 |
+
'SubscriptionId' => $SubscriptionId,
|
127 |
+
'Request' => $request
|
128 |
+
);
|
129 |
+
|
130 |
+
return $itemSearch;
|
131 |
+
}
|
132 |
+
|
133 |
+
function GetListLookupParams() {
|
134 |
+
global $SubscriptionId;
|
135 |
+
|
136 |
+
$listLookupRequest[] = array(
|
137 |
+
'ListId' => '1L0ZL7Y9FL4U0',
|
138 |
+
'ListType' => 'WishList',
|
139 |
+
'ProductPage' => 1,
|
140 |
+
'ResponseGroup' => 'ListFull',
|
141 |
+
'Sort' => 'LastUpdated'
|
142 |
+
);
|
143 |
+
|
144 |
+
$listLookupRequest[] = array(
|
145 |
+
'ListId' => '1L0ZL7Y9FL4U0',
|
146 |
+
'ListType' => 'WishList',
|
147 |
+
'ProductPage' => 2,
|
148 |
+
'ResponseGroup' => 'ListFull',
|
149 |
+
'Sort' => 'LastUpdated'
|
150 |
+
);
|
151 |
+
/*
|
152 |
+
// two lookup maximum
|
153 |
+
$listLookupRequest[] = array(
|
154 |
+
'ListId' => '1L0ZL7Y9FL4U0',
|
155 |
+
'ListType' => 'WishList',
|
156 |
+
'ProductPage' => 3,
|
157 |
+
'ResponseGroup' => 'ListFull',
|
158 |
+
'Sort' => 'LastUpdated'
|
159 |
+
);
|
160 |
+
*/
|
161 |
+
$listLookup = array(
|
162 |
+
'SubscriptionId' => $SubscriptionId,
|
163 |
+
// 'AssociateTag' => '',
|
164 |
+
'Request' => $listLookupRequest,
|
165 |
+
);
|
166 |
+
|
167 |
+
return $listLookup;
|
168 |
+
}
|
169 |
+
|
170 |
+
function GetListSearchParams() {
|
171 |
+
global $SubscriptionId;
|
172 |
+
|
173 |
+
$listSearchRequest[] = array(
|
174 |
+
'FirstName' => 'Scott',
|
175 |
+
'LastName' => 'Nichol',
|
176 |
+
'ListType' => 'WishList'
|
177 |
+
);
|
178 |
+
|
179 |
+
$listSearch = array(
|
180 |
+
'SubscriptionId' => $SubscriptionId,
|
181 |
+
// 'AssociateTag' => '',
|
182 |
+
'Request' => $listSearchRequest,
|
183 |
+
);
|
184 |
+
|
185 |
+
return $listSearch;
|
186 |
+
}
|
187 |
+
|
188 |
+
if ($method == 'ItemLookup') {
|
189 |
+
$result = $client->call('ItemLookup', array('body' => GetItemLookupParams()));
|
190 |
+
} elseif ($method == 'ItemSearch') {
|
191 |
+
$result = $client->call('ItemSearch', array('body' => GetItemSearchParams()));
|
192 |
+
} elseif ($method == 'ItemSearch2') {
|
193 |
+
$result = $client->call('ItemSearch', array('body' => GetItemSearchParams2()));
|
194 |
+
} elseif ($method == 'ListLookup') {
|
195 |
+
$result = $client->call('ListLookup', array('body' => GetListLookupParams()));
|
196 |
+
} elseif ($method == 'ListSearch') {
|
197 |
+
$result = $client->call('ListSearch', array('body' => GetListSearchParams()));
|
198 |
+
} elseif ($method == 'CartCreate') {
|
199 |
+
$result = $client->call('CartCreate', array('body' => GetCartCreateParams()));
|
200 |
+
} else {
|
201 |
+
echo "Unsupported method $method";
|
202 |
+
exit;
|
203 |
+
}
|
204 |
+
// Check for a fault
|
205 |
+
if ($client->fault) {
|
206 |
+
echo '<h2>Fault</h2><pre>';
|
207 |
+
print_r($result);
|
208 |
+
echo '</pre>';
|
209 |
+
} else {
|
210 |
+
// Check for errors
|
211 |
+
$err = $client->getError();
|
212 |
+
if ($err) {
|
213 |
+
// Display the error
|
214 |
+
echo '<h2>Error</h2><pre>' . $err . '</pre>';
|
215 |
+
} else {
|
216 |
+
// Display the result
|
217 |
+
echo '<h2>Result</h2><pre>';
|
218 |
+
print_r($result);
|
219 |
+
echo '</pre>';
|
220 |
+
}
|
221 |
+
}
|
222 |
+
echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
|
223 |
+
echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
|
224 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->debug_str, ENT_QUOTES) . '</pre>';
|
225 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient13.php
ADDED
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* $Id: wsdlclient13.php,v 1.2 2007/11/06 14:50:42 snichol Exp $
|
4 |
+
*
|
5 |
+
* WSDL client sample.
|
6 |
+
*
|
7 |
+
* Service: WSDL
|
8 |
+
* Payload: rpc/literal
|
9 |
+
* Transport: http
|
10 |
+
* Authentication: none
|
11 |
+
*/
|
12 |
+
require_once('../lib/nusoap.php');
|
13 |
+
$proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : '';
|
14 |
+
$proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : '';
|
15 |
+
$proxyusername = isset($_POST['proxyusername']) ? $_POST['proxyusername'] : '';
|
16 |
+
$proxypassword = isset($_POST['proxypassword']) ? $_POST['proxypassword'] : '';
|
17 |
+
echo '<h2>Constructor</h2>';
|
18 |
+
$client = new nusoap_client('http://www.scottnichol.com/samples/session.php?wsdl', true,
|
19 |
+
$proxyhost, $proxyport, $proxyusername, $proxypassword);
|
20 |
+
$err = $client->getError();
|
21 |
+
if ($err) {
|
22 |
+
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
|
23 |
+
}
|
24 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->getDebug(), ENT_QUOTES) . '</pre>';
|
25 |
+
$client->clearDebug();
|
26 |
+
// A persistent connection is *optional*, *not* necessary
|
27 |
+
$client->useHTTPPersistentConnection();
|
28 |
+
echo '<h2>GetSessionID</h2>';
|
29 |
+
$result = $client->call('GetSessionID', array());
|
30 |
+
// Check for a fault
|
31 |
+
if ($client->fault) {
|
32 |
+
echo '<h2>Fault</h2><pre>';
|
33 |
+
print_r($result);
|
34 |
+
echo '</pre>';
|
35 |
+
} else {
|
36 |
+
// Check for errors
|
37 |
+
$err = $client->getError();
|
38 |
+
if ($err) {
|
39 |
+
// Display the error
|
40 |
+
echo '<h2>Error</h2><pre>' . $err . '</pre>';
|
41 |
+
} else {
|
42 |
+
// Display the result
|
43 |
+
echo '<h2>Result</h2><pre>';
|
44 |
+
print_r($result);
|
45 |
+
echo '</pre>';
|
46 |
+
}
|
47 |
+
}
|
48 |
+
echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
|
49 |
+
echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
|
50 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->getDebug(), ENT_QUOTES) . '</pre>';
|
51 |
+
$client->clearDebug();
|
52 |
+
echo '<h2>SetSession</h2>';
|
53 |
+
$result = $client->call('SetSession', array('name' => 'testvalue', 'value' => 'it works'));
|
54 |
+
// Check for a fault
|
55 |
+
if ($client->fault) {
|
56 |
+
echo '<h2>Fault</h2><pre>';
|
57 |
+
print_r($result);
|
58 |
+
echo '</pre>';
|
59 |
+
} else {
|
60 |
+
// Check for errors
|
61 |
+
$err = $client->getError();
|
62 |
+
if ($err) {
|
63 |
+
// Display the error
|
64 |
+
echo '<h2>Error</h2><pre>' . $err . '</pre>';
|
65 |
+
} else {
|
66 |
+
// Display the result
|
67 |
+
echo '<h2>Result</h2><pre>';
|
68 |
+
print_r($result);
|
69 |
+
echo '</pre>';
|
70 |
+
}
|
71 |
+
}
|
72 |
+
echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
|
73 |
+
echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
|
74 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->getDebug(), ENT_QUOTES) . '</pre>';
|
75 |
+
$client->clearDebug();
|
76 |
+
echo '<h2>GetSession</h2>';
|
77 |
+
$result = $client->call('GetSession', array('name' => 'testvalue'));
|
78 |
+
// Check for a fault
|
79 |
+
if ($client->fault) {
|
80 |
+
echo '<h2>Fault</h2><pre>';
|
81 |
+
print_r($result);
|
82 |
+
echo '</pre>';
|
83 |
+
} else {
|
84 |
+
// Check for errors
|
85 |
+
$err = $client->getError();
|
86 |
+
if ($err) {
|
87 |
+
// Display the error
|
88 |
+
echo '<h2>Error</h2><pre>' . $err . '</pre>';
|
89 |
+
} else {
|
90 |
+
// Display the result
|
91 |
+
echo '<h2>Result</h2><pre>';
|
92 |
+
print_r($result);
|
93 |
+
echo '</pre>';
|
94 |
+
}
|
95 |
+
}
|
96 |
+
echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
|
97 |
+
echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
|
98 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->getDebug(), ENT_QUOTES) . '</pre>';
|
99 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient14.php
ADDED
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* $Id: wsdlclient14.php,v 1.2 2007/11/06 14:50:08 snichol Exp $
|
4 |
+
*
|
5 |
+
* WSDL client sample.
|
6 |
+
*
|
7 |
+
* Service: WSDL
|
8 |
+
* Payload: rpc/encoded
|
9 |
+
* Transport: http
|
10 |
+
* Authentication: none
|
11 |
+
*/
|
12 |
+
require_once('../lib/nusoap.php');
|
13 |
+
require_once('../lib/class.wsdlcache.php');
|
14 |
+
$proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : '';
|
15 |
+
$proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : '';
|
16 |
+
$proxyusername = isset($_POST['proxyusername']) ? $_POST['proxyusername'] : '';
|
17 |
+
$proxypassword = isset($_POST['proxypassword']) ? $_POST['proxypassword'] : '';
|
18 |
+
$useCURL = isset($_POST['usecurl']) ? $_POST['usecurl'] : '0';
|
19 |
+
|
20 |
+
//echo 'You must set your own Via Michelin login and password in the source code to run this client!'; exit();
|
21 |
+
$login = 'WSDEMO_01145';
|
22 |
+
$password = 'DckHXMMHj';
|
23 |
+
|
24 |
+
$wsdlurl = 'http://www.viamichelin.com/ws/services/Geocoding?wsdl';
|
25 |
+
$cache = new wsdlcache('.', 120);
|
26 |
+
$wsdl = $cache->get($wsdlurl);
|
27 |
+
if (is_null($wsdl)) {
|
28 |
+
$wsdl = new wsdl($wsdlurl,
|
29 |
+
$proxyhost, $proxyport, $proxyusername, $proxypassword,
|
30 |
+
0, 30, null, $useCURL);
|
31 |
+
$err = $wsdl->getError();
|
32 |
+
if ($err) {
|
33 |
+
echo '<h2>WSDL Constructor error</h2><pre>' . $err . '</pre>';
|
34 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($wsdl->getDebug(), ENT_QUOTES) . '</pre>';
|
35 |
+
exit();
|
36 |
+
}
|
37 |
+
$cache->put($wsdl);
|
38 |
+
} else {
|
39 |
+
$wsdl->debug_str = '';
|
40 |
+
$wsdl->debug('Retrieved from cache');
|
41 |
+
}
|
42 |
+
$client = new nusoap_client($wsdl, 'wsdl',
|
43 |
+
$proxyhost, $proxyport, $proxyusername, $proxypassword);
|
44 |
+
$err = $client->getError();
|
45 |
+
if ($err) {
|
46 |
+
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
|
47 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->getDebug(), ENT_QUOTES) . '</pre>';
|
48 |
+
exit();
|
49 |
+
}
|
50 |
+
|
51 |
+
$inputAddresses[] = array(
|
52 |
+
'address' => '45 Liberty Blvd.',
|
53 |
+
'cityName' => 'Malvern',
|
54 |
+
'countryCode' => 'USA',
|
55 |
+
'postalCode' => '19355',
|
56 |
+
'stateName' => 'PA'
|
57 |
+
);
|
58 |
+
$geocodingrequest = array('addressesList' => $inputAddresses);
|
59 |
+
$params = array('request' => $geocodingrequest, 'check' => "$login|$password");
|
60 |
+
$result = $client->call('getLocationsList', $params);
|
61 |
+
|
62 |
+
// Check for a fault
|
63 |
+
if ($client->fault) {
|
64 |
+
echo '<h2>Fault (Expect - AUTHENTIFICATION)</h2><pre>';
|
65 |
+
print_r($result);
|
66 |
+
echo '</pre>';
|
67 |
+
} else {
|
68 |
+
// Check for errors
|
69 |
+
$err = $client->getError();
|
70 |
+
if ($err) {
|
71 |
+
// Display the error
|
72 |
+
echo '<h2>Error</h2><pre>' . $err . '</pre>';
|
73 |
+
} else {
|
74 |
+
// Display the result
|
75 |
+
echo '<h2>Result</h2><pre>';
|
76 |
+
print_r($result);
|
77 |
+
echo '</pre>';
|
78 |
+
}
|
79 |
+
}
|
80 |
+
echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
|
81 |
+
echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
|
82 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->getDebug(), ENT_QUOTES) . '</pre>';
|
83 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient15.php
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* $Id: wsdlclient15.php,v 1.1 2008/02/12 00:13:50 snichol Exp $
|
4 |
+
*
|
5 |
+
* UTF-8 client sample that sends and receives data with characters UTF-8 encoded.
|
6 |
+
*
|
7 |
+
* Service: WSDL
|
8 |
+
* Payload: document/literal
|
9 |
+
* Transport: http
|
10 |
+
* Authentication: none
|
11 |
+
*/
|
12 |
+
require_once('../lib/nusoap.php');
|
13 |
+
$proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : '';
|
14 |
+
$proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : '';
|
15 |
+
$proxyusername = isset($_POST['proxyusername']) ? $_POST['proxyusername'] : '';
|
16 |
+
$proxypassword = isset($_POST['proxypassword']) ? $_POST['proxypassword'] : '';
|
17 |
+
$useCURL = isset($_POST['usecurl']) ? $_POST['usecurl'] : '0';
|
18 |
+
$client = new nusoap_client('http://www.scottnichol.com/samples/helloutf8.php?wsdl', 'wsdl',
|
19 |
+
$proxyhost, $proxyport, $proxyusername, $proxypassword);
|
20 |
+
$err = $client->getError();
|
21 |
+
if ($err) {
|
22 |
+
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
|
23 |
+
echo '<h2>Debug</h2>';
|
24 |
+
echo '<pre>' . htmlspecialchars($client->getDebug(), ENT_QUOTES) . '</pre>';
|
25 |
+
exit();
|
26 |
+
}
|
27 |
+
$client->setUseCurl($useCURL);
|
28 |
+
$client->soap_defencoding = 'UTF-8';
|
29 |
+
$client->decode_utf8 = false;
|
30 |
+
$utf8string = array('stuff' => "\xc2\xa9\xc2\xae\xc2\xbc\xc2\xbd\xc2\xbe");
|
31 |
+
$result = $client->call('echoback', $utf8string);
|
32 |
+
if ($client->fault) {
|
33 |
+
echo '<h2>Fault</h2><pre>';
|
34 |
+
print_r($result);
|
35 |
+
echo '</pre>';
|
36 |
+
} else {
|
37 |
+
$err = $client->getError();
|
38 |
+
if ($err) {
|
39 |
+
echo '<h2>Error</h2><pre>' . $err . '</pre>';
|
40 |
+
} else {
|
41 |
+
echo '<h2>Result</h2><pre>';
|
42 |
+
// Decode the result: it so happens we sent Latin-1 characters
|
43 |
+
if (isset($result['return'])) {
|
44 |
+
$result1 = utf8_decode($result['return']);
|
45 |
+
} elseif (!is_array($result)) {
|
46 |
+
$result1 = utf8_decode($result);
|
47 |
+
} else {
|
48 |
+
$result1 = $result;
|
49 |
+
}
|
50 |
+
print_r($result1);
|
51 |
+
echo '</pre>';
|
52 |
+
}
|
53 |
+
}
|
54 |
+
echo '<h2>Request</h2>';
|
55 |
+
echo '<pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
|
56 |
+
echo '<h2>Response</h2>';
|
57 |
+
echo '<pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
|
58 |
+
echo '<h2>Debug</h2>';
|
59 |
+
echo '<pre>' . htmlspecialchars($client->getDebug(), ENT_QUOTES) . '</pre>';
|
60 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient2.php
ADDED
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* $Id: wsdlclient2.php,v 1.3 2007/11/06 14:48:49 snichol Exp $
|
4 |
+
*
|
5 |
+
* WSDL client sample.
|
6 |
+
*
|
7 |
+
* Service: WSDL proxy
|
8 |
+
* Payload: rpc/encoded
|
9 |
+
* Transport: http
|
10 |
+
* Authentication: none
|
11 |
+
*/
|
12 |
+
require_once('../lib/nusoap.php');
|
13 |
+
$proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : '';
|
14 |
+
$proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : '';
|
15 |
+
$proxyusername = isset($_POST['proxyusername']) ? $_POST['proxyusername'] : '';
|
16 |
+
$proxypassword = isset($_POST['proxypassword']) ? $_POST['proxypassword'] : '';
|
17 |
+
$useCURL = isset($_POST['usecurl']) ? $_POST['usecurl'] : '0';
|
18 |
+
$client = new nusoap_client("http://soap.amazon.com/schemas2/AmazonWebServices.wsdl", 'wsdl',
|
19 |
+
$proxyhost, $proxyport, $proxyusername, $proxypassword);
|
20 |
+
$err = $client->getError();
|
21 |
+
if ($err) {
|
22 |
+
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
|
23 |
+
exit();
|
24 |
+
}
|
25 |
+
$client->setUseCurl($useCURL);
|
26 |
+
$proxy = $client->getProxy();
|
27 |
+
$param = array(
|
28 |
+
'browse_node' => 18,
|
29 |
+
'page' => 1,
|
30 |
+
'mode' => 'books',
|
31 |
+
'tag' =>'melonfire-20',
|
32 |
+
'type' => 'lite',
|
33 |
+
'devtag' => 'Your dev tag'
|
34 |
+
);
|
35 |
+
$result = $proxy->BrowseNodeSearchRequest($param);
|
36 |
+
// Check for a fault
|
37 |
+
if ($proxy->fault) {
|
38 |
+
echo '<h2>Fault</h2><pre>';
|
39 |
+
print_r($result);
|
40 |
+
echo '</pre>';
|
41 |
+
} else {
|
42 |
+
// Check for errors
|
43 |
+
$err = $proxy->getError();
|
44 |
+
if ($err) {
|
45 |
+
// Display the error
|
46 |
+
echo '<h2>Error</h2><pre>' . $err . '</pre>';
|
47 |
+
} else {
|
48 |
+
// Display the result
|
49 |
+
echo '<h2>Result</h2><pre>';
|
50 |
+
print_r($result);
|
51 |
+
echo '</pre>';
|
52 |
+
}
|
53 |
+
}
|
54 |
+
echo '<h2>Request</h2><pre>' . htmlspecialchars($proxy->request, ENT_QUOTES) . '</pre>';
|
55 |
+
echo '<h2>Response</h2><pre>' . htmlspecialchars($proxy->response, ENT_QUOTES) . '</pre>';
|
56 |
+
echo '<h2>Client Debug</h2><pre>' . htmlspecialchars($client->debug_str, ENT_QUOTES) . '</pre>';
|
57 |
+
echo '<h2>Proxy Debug</h2><pre>' . htmlspecialchars($proxy->debug_str, ENT_QUOTES) . '</pre>';
|
58 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient3.php
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* $Id: wsdlclient3.php,v 1.4 2007/11/06 14:48:49 snichol Exp $
|
4 |
+
*
|
5 |
+
* WSDL client sample.
|
6 |
+
*
|
7 |
+
* Service: WSDL
|
8 |
+
* Payload: rpc/encoded
|
9 |
+
* Transport: http
|
10 |
+
* Authentication: none
|
11 |
+
*/
|
12 |
+
require_once('../lib/nusoap.php');
|
13 |
+
$proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : '';
|
14 |
+
$proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : '';
|
15 |
+
$proxyusername = isset($_POST['proxyusername']) ? $_POST['proxyusername'] : '';
|
16 |
+
$proxypassword = isset($_POST['proxypassword']) ? $_POST['proxypassword'] : '';
|
17 |
+
$client = new nusoap_client('http://www.scottnichol.com/samples/hellowsdl2.php?wsdl&debug=1', 'wsdl',
|
18 |
+
$proxyhost, $proxyport, $proxyusername, $proxypassword);
|
19 |
+
$err = $client->getError();
|
20 |
+
if ($err) {
|
21 |
+
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
|
22 |
+
}
|
23 |
+
$person = array('firstname' => 'Willi', 'age' => 22, 'gender' => 'male');
|
24 |
+
$method = isset($_GET['method']) ? $_GET['method'] : 'function';
|
25 |
+
if ($method == 'function') {
|
26 |
+
$call = 'hello';
|
27 |
+
} elseif ($method == 'instance') {
|
28 |
+
$call = 'hellowsdl2.hello';
|
29 |
+
} elseif ($method == 'class') {
|
30 |
+
$call = 'hellowsdl2..hello';
|
31 |
+
} else {
|
32 |
+
$call = 'hello';
|
33 |
+
}
|
34 |
+
$result = $client->call($call, array('person' => $person));
|
35 |
+
// Check for a fault
|
36 |
+
if ($client->fault) {
|
37 |
+
echo '<h2>Fault</h2><pre>';
|
38 |
+
print_r($result);
|
39 |
+
echo '</pre>';
|
40 |
+
} else {
|
41 |
+
// Check for errors
|
42 |
+
$err = $client->getError();
|
43 |
+
if ($err) {
|
44 |
+
// Display the error
|
45 |
+
echo '<h2>Error</h2><pre>' . $err . '</pre>';
|
46 |
+
} else {
|
47 |
+
// Display the result
|
48 |
+
echo '<h2>Result</h2><pre>';
|
49 |
+
print_r($result);
|
50 |
+
echo '</pre>';
|
51 |
+
}
|
52 |
+
}
|
53 |
+
echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
|
54 |
+
echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
|
55 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->debug_str, ENT_QUOTES) . '</pre>';
|
56 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient3b.php
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* $Id: wsdlclient3b.php,v 1.1 2004/06/15 15:38:29 snichol Exp $
|
4 |
+
*
|
5 |
+
* WSDL client sample.
|
6 |
+
*
|
7 |
+
* Service: WSDL
|
8 |
+
* Payload: rpc/encoded (params as an XML string; cf. wsdlclient3.php)
|
9 |
+
* Transport: http
|
10 |
+
* Authentication: none
|
11 |
+
*/
|
12 |
+
require_once('../lib/nusoap.php');
|
13 |
+
$proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : '';
|
14 |
+
$proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : '';
|
15 |
+
$proxyusername = isset($_POST['proxyusername']) ? $_POST['proxyusername'] : '';
|
16 |
+
$proxypassword = isset($_POST['proxypassword']) ? $_POST['proxypassword'] : '';
|
17 |
+
$client = new soapclient('http://www.scottnichol.com/samples/hellowsdl2.php?wsdl', true,
|
18 |
+
$proxyhost, $proxyport, $proxyusername, $proxypassword);
|
19 |
+
$err = $client->getError();
|
20 |
+
if ($err) {
|
21 |
+
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
|
22 |
+
}
|
23 |
+
$params = '<person xsi:type="tns:Person"><firstname xsi:type="xsd:string">Willi</firstname><age xsi:type="xsd:int">22</age><gender xsi:type="xsd:string">male</gender></person>';
|
24 |
+
$result = $client->call('hello', $params);
|
25 |
+
// Check for a fault
|
26 |
+
if ($client->fault) {
|
27 |
+
echo '<h2>Fault</h2><pre>';
|
28 |
+
print_r($result);
|
29 |
+
echo '</pre>';
|
30 |
+
} else {
|
31 |
+
// Check for errors
|
32 |
+
$err = $client->getError();
|
33 |
+
if ($err) {
|
34 |
+
// Display the error
|
35 |
+
echo '<h2>Error</h2><pre>' . $err . '</pre>';
|
36 |
+
} else {
|
37 |
+
// Display the result
|
38 |
+
echo '<h2>Result</h2><pre>';
|
39 |
+
print_r($result);
|
40 |
+
echo '</pre>';
|
41 |
+
}
|
42 |
+
}
|
43 |
+
echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
|
44 |
+
echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
|
45 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->debug_str, ENT_QUOTES) . '</pre>';
|
46 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient3c.php
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* $Id: wsdlclient3c.php,v 1.2 2004/10/01 19:57:20 snichol Exp $
|
4 |
+
*
|
5 |
+
* WSDL client sample.
|
6 |
+
*
|
7 |
+
* Service: WSDL
|
8 |
+
* Payload: rpc/literal
|
9 |
+
* Transport: http
|
10 |
+
* Authentication: none
|
11 |
+
*/
|
12 |
+
require_once('../lib/nusoap.php');
|
13 |
+
$proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : '';
|
14 |
+
$proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : '';
|
15 |
+
$proxyusername = isset($_POST['proxyusername']) ? $_POST['proxyusername'] : '';
|
16 |
+
$proxypassword = isset($_POST['proxypassword']) ? $_POST['proxypassword'] : '';
|
17 |
+
$client = new soapclient('http://www.scottnichol.com/samples/hellowsdl4.php?wsdl&debug=1', true,
|
18 |
+
$proxyhost, $proxyport, $proxyusername, $proxypassword);
|
19 |
+
$err = $client->getError();
|
20 |
+
if ($err) {
|
21 |
+
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
|
22 |
+
}
|
23 |
+
$person = array('firstname' => 'Willi', 'age' => 22, 'gender' => 'male');
|
24 |
+
$result = $client->call('hello', array('person' => $person));
|
25 |
+
// Check for a fault
|
26 |
+
if ($client->fault) {
|
27 |
+
echo '<h2>Fault</h2><pre>';
|
28 |
+
print_r($result);
|
29 |
+
echo '</pre>';
|
30 |
+
} else {
|
31 |
+
// Check for errors
|
32 |
+
$err = $client->getError();
|
33 |
+
if ($err) {
|
34 |
+
// Display the error
|
35 |
+
echo '<h2>Error</h2><pre>' . $err . '</pre>';
|
36 |
+
} else {
|
37 |
+
// Display the result
|
38 |
+
echo '<h2>Result</h2><pre>';
|
39 |
+
print_r($result);
|
40 |
+
echo '</pre>';
|
41 |
+
}
|
42 |
+
}
|
43 |
+
echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
|
44 |
+
echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
|
45 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->debug_str, ENT_QUOTES) . '</pre>';
|
46 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient4.php
ADDED
@@ -0,0 +1,176 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* $Id: wsdlclient4.php,v 1.6 2005/05/12 21:42:06 snichol Exp $
|
4 |
+
*
|
5 |
+
* WSDL client sample, based on soap builders round 2 interop.
|
6 |
+
*
|
7 |
+
* Service: WSDL
|
8 |
+
* Payload: rpc/encoded
|
9 |
+
* Transport: http
|
10 |
+
* Authentication: none
|
11 |
+
*/
|
12 |
+
require_once('../lib/nusoap.php');
|
13 |
+
/*
|
14 |
+
* Grab post vars, if present
|
15 |
+
*/
|
16 |
+
$method = isset($_POST['method']) ? $_POST['method'] : '';
|
17 |
+
$null = isset($_POST['null']) ? $_POST['null'] : '';
|
18 |
+
$empty = isset($_POST['empty']) ? $_POST['empty'] : '';
|
19 |
+
$proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : '';
|
20 |
+
$proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : '';
|
21 |
+
$proxyusername = isset($_POST['proxyusername']) ? $_POST['proxyusername'] : '';
|
22 |
+
$proxypassword = isset($_POST['proxypassword']) ? $_POST['proxypassword'] : '';
|
23 |
+
/*
|
24 |
+
* When no method has been specified, give the user a choice
|
25 |
+
*/
|
26 |
+
if ($method == '') {
|
27 |
+
echo '<form name="MethodForm" method="POST">';
|
28 |
+
echo '<input type="hidden" name="proxyhost" value="' . $proxyhost .'">';
|
29 |
+
echo '<input type="hidden" name="proxyport" value="' . $proxyport .'">';
|
30 |
+
echo '<input type="hidden" name="proxyusername" value="' . $proxyusername .'">';
|
31 |
+
echo '<input type="hidden" name="proxypassword" value="' . $proxypassword .'">';
|
32 |
+
echo 'Method: <select name="method">';
|
33 |
+
echo '<option>echoString</option>';
|
34 |
+
echo '<option>echoStringArray</option>';
|
35 |
+
echo '<option>echoInteger</option>';
|
36 |
+
echo '<option>echoIntegerArray</option>';
|
37 |
+
echo '<option>echoFloat</option>';
|
38 |
+
echo '<option>echoFloatArray</option>';
|
39 |
+
echo '<option>echoStruct</option>';
|
40 |
+
echo '<option>echoStructArray</option>';
|
41 |
+
echo '<option>echoVoid</option>';
|
42 |
+
echo '<option>echoBoolean</option>';
|
43 |
+
echo '<option>echoBase64</option>';
|
44 |
+
echo '</select><br><br>';
|
45 |
+
echo 'Null parameter? <input type="checkbox" name="null" value="1"><br>';
|
46 |
+
echo 'Empty array? <input type="checkbox" name="empty" value="1"><br><br>';
|
47 |
+
echo '<input type="submit" value=" Execute ">';
|
48 |
+
echo '</form>';
|
49 |
+
exit();
|
50 |
+
}
|
51 |
+
/*
|
52 |
+
* Execute the specified method
|
53 |
+
*/
|
54 |
+
if ($method == 'echoString') {
|
55 |
+
if ($null != '1') {
|
56 |
+
$params = array('inputString' => 'If you cannot echo a string, you probably cannot do much');
|
57 |
+
} else {
|
58 |
+
$params = array('inputString' => null);
|
59 |
+
}
|
60 |
+
} elseif ($method == 'echoStringArray') {
|
61 |
+
if ($null != '1') {
|
62 |
+
if ($empty != '1') {
|
63 |
+
$params = array('inputStringArray' => array('String 1', 'String 2', 'String Three'));
|
64 |
+
} else {
|
65 |
+
$params = array('inputStringArray' => array());
|
66 |
+
}
|
67 |
+
} else {
|
68 |
+
$params = array('inputStringArray' => null);
|
69 |
+
}
|
70 |
+
} elseif ($method == 'echoInteger') {
|
71 |
+
if ($null != '1') {
|
72 |
+
$params = array('inputInteger' => 329);
|
73 |
+
} else {
|
74 |
+
$params = array('inputInteger' => null);
|
75 |
+
}
|
76 |
+
} elseif ($method == 'echoIntegerArray') {
|
77 |
+
if ($null != '1') {
|
78 |
+
if ($empty != '1') {
|
79 |
+
$params = array('inputIntegerArray' => array(451, 43, -392220011, 1, 1, 2, 3, 5, 8, 13, 21));
|
80 |
+
} else {
|
81 |
+
$params = array('inputIntegerArray' => array());
|
82 |
+
}
|
83 |
+
} else {
|
84 |
+
$params = array('inputIntegerArray' => null);
|
85 |
+
}
|
86 |
+
} elseif ($method == 'echoFloat') {
|
87 |
+
if ($null != '1') {
|
88 |
+
$params = array('inputFloat' => 3.14159265);
|
89 |
+
} else {
|
90 |
+
$params = array('inputFloat' => null);
|
91 |
+
}
|
92 |
+
} elseif ($method == 'echoFloatArray') {
|
93 |
+
if ($null != '1') {
|
94 |
+
if ($empty != '1') {
|
95 |
+
$params = array('inputFloatArray' => array(1.1, 2.2, 3.3, 1/4, -1/9));
|
96 |
+
} else {
|
97 |
+
$params = array('inputFloatArray' => array());
|
98 |
+
}
|
99 |
+
} else {
|
100 |
+
$params = array('inputFloatArray' => null);
|
101 |
+
}
|
102 |
+
} elseif ($method == 'echoStruct') {
|
103 |
+
if ($null != '1') {
|
104 |
+
$struct = array('varString' => 'who', 'varInt' => 2, 'varFloat' => 3.14159);
|
105 |
+
$params = array('inputStruct' => $struct);
|
106 |
+
} else {
|
107 |
+
$params = array('inputStruct' => null);
|
108 |
+
}
|
109 |
+
} elseif ($method == 'echoStructArray') {
|
110 |
+
if ($null != '1') {
|
111 |
+
if ($empty != '1') {
|
112 |
+
$structs[] = array('varString' => 'who', 'varInt' => 2, 'varFloat' => 3.14159);
|
113 |
+
$structs[] = array('varString' => 'when', 'varInt' => 4, 'varFloat' => 99.9876);
|
114 |
+
$params = array('inputStructArray' => $structs);
|
115 |
+
} else {
|
116 |
+
$params = array('inputStructArray' => array());
|
117 |
+
}
|
118 |
+
} else {
|
119 |
+
$params = array('inputStructArray' => null);
|
120 |
+
}
|
121 |
+
} elseif ($method == 'echoVoid') {
|
122 |
+
$params = array();
|
123 |
+
} elseif ($method == 'echoBoolean') {
|
124 |
+
if ($null != '1') {
|
125 |
+
$params = array('inputBoolean' => false);
|
126 |
+
} else {
|
127 |
+
$params = array('inputBoolean' => null);
|
128 |
+
}
|
129 |
+
} elseif ($method == 'echoBase64') {
|
130 |
+
if ($null != '1') {
|
131 |
+
$params = array('inputBase64' => base64_encode('You must encode the data you send; NuSOAP will automatically decode the data it receives'));
|
132 |
+
} else {
|
133 |
+
$params = array('inputBase64' => null);
|
134 |
+
}
|
135 |
+
} else {
|
136 |
+
echo 'Sorry, I do not know about method ' . $method;
|
137 |
+
exit();
|
138 |
+
}
|
139 |
+
$client = new soapclient('http://www.scottnichol.com/samples/round2_base_server.php?wsdl&debug=1', true,
|
140 |
+
$proxyhost, $proxyport, $proxyusername, $proxypassword);
|
141 |
+
$err = $client->getError();
|
142 |
+
if ($err) {
|
143 |
+
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
|
144 |
+
}
|
145 |
+
$client->useHTTPPersistentConnection();
|
146 |
+
echo '<h2>Execute ' . $method . '</h2>';
|
147 |
+
$result = $client->call($method, $params);
|
148 |
+
// Check for a fault
|
149 |
+
if ($client->fault) {
|
150 |
+
echo '<h2>Fault</h2><pre>';
|
151 |
+
print_r($result);
|
152 |
+
echo '</pre>';
|
153 |
+
} else {
|
154 |
+
// Check for errors
|
155 |
+
$err = $client->getError();
|
156 |
+
if ($err) {
|
157 |
+
// Display the error
|
158 |
+
echo '<h2>Error</h2><pre>' . $err . '</pre>';
|
159 |
+
} else {
|
160 |
+
// Display the result
|
161 |
+
echo '<h2>Result</h2><pre>';
|
162 |
+
print_r((!is_bool($result)) ? $result : ($result ? 'true' : 'false'));
|
163 |
+
echo '</pre>';
|
164 |
+
// And execute again to test persistent connection
|
165 |
+
echo '<h2>Execute ' . $method . ' again to test persistent connection (see debug)</h2>';
|
166 |
+
$client->debug("*** execute again to test persistent connection ***");
|
167 |
+
$result = $client->call($method, $params);
|
168 |
+
// And again...
|
169 |
+
$client->debug("*** execute again ... ***");
|
170 |
+
$result = $client->call($method, $params);
|
171 |
+
}
|
172 |
+
}
|
173 |
+
echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
|
174 |
+
echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
|
175 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->debug_str, ENT_QUOTES) . '</pre>';
|
176 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient5.php
ADDED
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* $Id: wsdlclient5.php,v 1.4 2007/11/06 14:49:10 snichol Exp $
|
4 |
+
*
|
5 |
+
* WSDL client sample.
|
6 |
+
*
|
7 |
+
* Service: WSDL
|
8 |
+
* Payload: rpc/encoded
|
9 |
+
* Transport: http
|
10 |
+
* Authentication: none
|
11 |
+
*/
|
12 |
+
require_once('../lib/nusoap.php');
|
13 |
+
require_once('../lib/class.wsdlcache.php');
|
14 |
+
$proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : '';
|
15 |
+
$proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : '';
|
16 |
+
$proxyusername = isset($_POST['proxyusername']) ? $_POST['proxyusername'] : '';
|
17 |
+
$proxypassword = isset($_POST['proxypassword']) ? $_POST['proxypassword'] : '';
|
18 |
+
$useCURL = isset($_POST['usecurl']) ? $_POST['usecurl'] : '0';
|
19 |
+
|
20 |
+
$cache = new wsdlcache('.', 60);
|
21 |
+
$wsdl = $cache->get('http://www.xmethods.net/sd/2001/BNQuoteService.wsdl');
|
22 |
+
if (is_null($wsdl)) {
|
23 |
+
$wsdl = new wsdl('http://www.xmethods.net/sd/2001/BNQuoteService.wsdl',
|
24 |
+
$proxyhost, $proxyport, $proxyusername, $proxypassword,
|
25 |
+
0, 30, null, $useCURL);
|
26 |
+
$err = $wsdl->getError();
|
27 |
+
if ($err) {
|
28 |
+
echo '<h2>WSDL Constructor error (Expect - 404 Not Found)</h2><pre>' . $err . '</pre>';
|
29 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($wsdl->getDebug(), ENT_QUOTES) . '</pre>';
|
30 |
+
exit();
|
31 |
+
}
|
32 |
+
$cache->put($wsdl);
|
33 |
+
} else {
|
34 |
+
$wsdl->clearDebug();
|
35 |
+
$wsdl->debug('Retrieved from cache');
|
36 |
+
}
|
37 |
+
$client = new nusoap_client($wsdl, 'wsdl',
|
38 |
+
$proxyhost, $proxyport, $proxyusername, $proxypassword);
|
39 |
+
$err = $client->getError();
|
40 |
+
if ($err) {
|
41 |
+
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
|
42 |
+
exit();
|
43 |
+
}
|
44 |
+
$client->setUseCurl($useCURL);
|
45 |
+
$params = array('isbn' => '0060188782');
|
46 |
+
$result = $client->call('getPrice', $params);
|
47 |
+
// Check for a fault
|
48 |
+
if ($client->fault) {
|
49 |
+
echo '<h2>Fault</h2><pre>';
|
50 |
+
print_r($result);
|
51 |
+
echo '</pre>';
|
52 |
+
} else {
|
53 |
+
// Check for errors
|
54 |
+
$err = $client->getError();
|
55 |
+
if ($err) {
|
56 |
+
// Display the error
|
57 |
+
echo '<h2>Error</h2><pre>' . $err . '</pre>';
|
58 |
+
} else {
|
59 |
+
// Display the result
|
60 |
+
echo '<h2>Result</h2><pre>';
|
61 |
+
print_r($result);
|
62 |
+
echo '</pre>';
|
63 |
+
}
|
64 |
+
}
|
65 |
+
echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
|
66 |
+
echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
|
67 |
+
echo '<h2>Cache Debug</h2><pre>' . htmlspecialchars($cache->getDebug(), ENT_QUOTES) . '</pre>';
|
68 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->getDebug(), ENT_QUOTES) . '</pre>';
|
69 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient6.php
ADDED
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* $Id: wsdlclient6.php,v 1.1 2004/01/26 07:15:20 snichol Exp $
|
4 |
+
*
|
5 |
+
* WSDL client sample.
|
6 |
+
*
|
7 |
+
* Service: WSDL
|
8 |
+
* Payload: rpc/encoded
|
9 |
+
* Transport: http
|
10 |
+
* Authentication: none
|
11 |
+
*/
|
12 |
+
require_once('../lib/nusoap.php');
|
13 |
+
$proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : '';
|
14 |
+
$proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : '';
|
15 |
+
$proxyusername = isset($_POST['proxyusername']) ? $_POST['proxyusername'] : '';
|
16 |
+
$proxypassword = isset($_POST['proxypassword']) ? $_POST['proxypassword'] : '';
|
17 |
+
echo 'You must change the source code to specify the location of the WSDL!'; exit();
|
18 |
+
$client = new soapclient('file://f:/googleapi/GoogleSearch.wsdl', true,
|
19 |
+
$proxyhost, $proxyport, $proxyusername, $proxypassword);
|
20 |
+
$err = $client->getError();
|
21 |
+
if ($err) {
|
22 |
+
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
|
23 |
+
}
|
24 |
+
$client->soap_defencoding = 'UTF-8';
|
25 |
+
|
26 |
+
echo 'You must set your own Google key in the source code to run this client!'; exit();
|
27 |
+
$key = 'set your own Google key';
|
28 |
+
$q = '"Lies and the Lying"';
|
29 |
+
$start = 1;
|
30 |
+
$maxResults = 10;
|
31 |
+
$filter = false;
|
32 |
+
$restrict = '';
|
33 |
+
$safeSearch = false;
|
34 |
+
$lr = '';
|
35 |
+
$ie = '';
|
36 |
+
$oe = '';
|
37 |
+
|
38 |
+
$params = array(
|
39 |
+
'key' => $key, 'q' => $q, 'start' => $start, 'maxResults' => $maxResults,
|
40 |
+
'filter' => $filter, 'restrict' => $restrict, 'safeSearch' => $safeSearch, 'lr' => $lr,
|
41 |
+
'ie' => $ie, 'oe' => $oe
|
42 |
+
);
|
43 |
+
|
44 |
+
$result = $client->call('doGoogleSearch', $params);
|
45 |
+
// Check for a fault
|
46 |
+
if ($client->fault) {
|
47 |
+
echo '<h2>Fault</h2><pre>';
|
48 |
+
print_r($result);
|
49 |
+
echo '</pre>';
|
50 |
+
} else {
|
51 |
+
// Check for errors
|
52 |
+
$err = $client->getError();
|
53 |
+
if ($err) {
|
54 |
+
// Display the error
|
55 |
+
echo '<h2>Error</h2><pre>' . $err . '</pre>';
|
56 |
+
} else {
|
57 |
+
// Display the result
|
58 |
+
echo '<h2>Result</h2><pre>';
|
59 |
+
print_r($result);
|
60 |
+
echo '</pre>';
|
61 |
+
}
|
62 |
+
}
|
63 |
+
echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
|
64 |
+
echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
|
65 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->debug_str, ENT_QUOTES) . '</pre>';
|
66 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient7.php
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* $Id: wsdlclient7.php,v 1.2 2007/11/06 14:49:10 snichol Exp $
|
4 |
+
*
|
5 |
+
* WSDL client sample.
|
6 |
+
*
|
7 |
+
* Service: WSDL
|
8 |
+
* Payload: document/literal
|
9 |
+
* Transport: http
|
10 |
+
* Authentication: digest
|
11 |
+
*/
|
12 |
+
require_once('../lib/nusoap.php');
|
13 |
+
$proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : '';
|
14 |
+
$proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : '';
|
15 |
+
$proxyusername = isset($_POST['proxyusername']) ? $_POST['proxyusername'] : '';
|
16 |
+
$proxypassword = isset($_POST['proxypassword']) ? $_POST['proxypassword'] : '';
|
17 |
+
$useCURL = isset($_POST['usecurl']) ? $_POST['usecurl'] : '0';
|
18 |
+
echo 'You must set your username and password in the source';
|
19 |
+
exit();
|
20 |
+
$client = new nusoap_client("http://staging.mappoint.net/standard-30/mappoint.wsdl", 'wsdl',
|
21 |
+
$proxyhost, $proxyport, $proxyusername, $proxypassword);
|
22 |
+
$err = $client->getError();
|
23 |
+
if ($err) {
|
24 |
+
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
|
25 |
+
}
|
26 |
+
$client->setUseCurl($useCURL);
|
27 |
+
$client->loadWSDL();
|
28 |
+
$client->setCredentials($username, $password, 'digest');
|
29 |
+
$result = $client->call('GetVersionInfo', array());
|
30 |
+
// Check for a fault
|
31 |
+
if ($client->fault) {
|
32 |
+
echo '<h2>Fault</h2><pre>';
|
33 |
+
print_r($result);
|
34 |
+
echo '</pre>';
|
35 |
+
} else {
|
36 |
+
// Check for errors
|
37 |
+
$err = $client->getError();
|
38 |
+
if ($err) {
|
39 |
+
// Display the error
|
40 |
+
echo '<h2>Error</h2><pre>' . $err . '</pre>';
|
41 |
+
} else {
|
42 |
+
// Display the result
|
43 |
+
echo '<h2>Result</h2><pre>';
|
44 |
+
print_r($result);
|
45 |
+
echo '</pre>';
|
46 |
+
}
|
47 |
+
}
|
48 |
+
echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
|
49 |
+
echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
|
50 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->debug_str, ENT_QUOTES) . '</pre>';
|
51 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient8.php
ADDED
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* $Id: wsdlclient8.php,v 1.2 2007/11/06 14:49:10 snichol Exp $
|
4 |
+
*
|
5 |
+
* WSDL client sample.
|
6 |
+
*
|
7 |
+
* Service: WSDL
|
8 |
+
* Payload: document/literal
|
9 |
+
* Transport: http
|
10 |
+
* Authentication: digest
|
11 |
+
*/
|
12 |
+
require_once('../lib/nusoap.php');
|
13 |
+
$proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : '';
|
14 |
+
$proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : '';
|
15 |
+
$proxyusername = isset($_POST['proxyusername']) ? $_POST['proxyusername'] : '';
|
16 |
+
$proxypassword = isset($_POST['proxypassword']) ? $_POST['proxypassword'] : '';
|
17 |
+
echo 'You must set your username and password in the source';
|
18 |
+
exit();
|
19 |
+
$client = new nusoap_client("http://staging.mappoint.net/standard-30/mappoint.wsdl", 'wsdl',
|
20 |
+
$proxyhost, $proxyport, $proxyusername, $proxypassword);
|
21 |
+
$err = $client->getError();
|
22 |
+
if ($err) {
|
23 |
+
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
|
24 |
+
}
|
25 |
+
$client->setCredentials($username, $password, 'digest');
|
26 |
+
$address = array(
|
27 |
+
'AddressLine' => '563 Park Avenue',
|
28 |
+
'PrimaryCity' => 'New York',
|
29 |
+
'SecondaryCity' => 'Brooklyn',
|
30 |
+
'Subdivision' => '',
|
31 |
+
'PostalCode' => '',
|
32 |
+
'CountryRegion' => 'US',
|
33 |
+
'FormattedAddress' => ''
|
34 |
+
);
|
35 |
+
$findRange = array(
|
36 |
+
'StartIndex' => 0,
|
37 |
+
'Count' => 10
|
38 |
+
);
|
39 |
+
$findResultMask = 'AddressFlag';
|
40 |
+
$findOptions = array(
|
41 |
+
'Range' => $findRange,
|
42 |
+
'SearchContext' => 1,
|
43 |
+
'ResultMask' => $findResultMask,
|
44 |
+
'ThresholdScore' => 0.85
|
45 |
+
);
|
46 |
+
$findAddressSpecification = array(
|
47 |
+
'DataSourceName' => 'MapPoint.NA',
|
48 |
+
'InputAddress' => $address,
|
49 |
+
'Options' => $findOptions
|
50 |
+
);
|
51 |
+
$findAddress = array('specification' => $findAddressSpecification);
|
52 |
+
$result = $client->call('FindAddress', array('parameters' => $findAddress));
|
53 |
+
// Check for a fault
|
54 |
+
if ($client->fault) {
|
55 |
+
echo '<h2>Fault</h2><pre>';
|
56 |
+
print_r($result);
|
57 |
+
echo '</pre>';
|
58 |
+
} else {
|
59 |
+
// Check for errors
|
60 |
+
$err = $client->getError();
|
61 |
+
if ($err) {
|
62 |
+
// Display the error
|
63 |
+
echo '<h2>Error</h2><pre>' . $err . '</pre>';
|
64 |
+
} else {
|
65 |
+
// Display the result
|
66 |
+
echo '<h2>Result</h2><pre>';
|
67 |
+
print_r($result);
|
68 |
+
echo '</pre>';
|
69 |
+
}
|
70 |
+
}
|
71 |
+
echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
|
72 |
+
echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
|
73 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->debug_str, ENT_QUOTES) . '</pre>';
|
74 |
+
?>
|
app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient9.php
ADDED
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* $Id: wsdlclient9.php,v 1.2 2007/11/06 14:50:06 snichol Exp $
|
4 |
+
*
|
5 |
+
* WSDL client sample.
|
6 |
+
*
|
7 |
+
* Service: WSDL
|
8 |
+
* Payload: document/literal
|
9 |
+
* Transport: http
|
10 |
+
* Authentication: digest
|
11 |
+
*/
|
12 |
+
require_once('../lib/nusoap.php');
|
13 |
+
$proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : '';
|
14 |
+
$proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : '';
|
15 |
+
$proxyusername = isset($_POST['proxyusername']) ? $_POST['proxyusername'] : '';
|
16 |
+
$proxypassword = isset($_POST['proxypassword']) ? $_POST['proxypassword'] : '';
|
17 |
+
echo 'You must set your username and password in the source';
|
18 |
+
exit();
|
19 |
+
$client = new nusoap_client("http://staging.mappoint.net/standard-30/mappoint.wsdl", 'wsdl',
|
20 |
+
$proxyhost, $proxyport, $proxyusername, $proxypassword);
|
21 |
+
$err = $client->getError();
|
22 |
+
if ($err) {
|
23 |
+
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
|
24 |
+
}
|
25 |
+
$client->setCredentials($username, $password, 'digest');
|
26 |
+
$client->useHTTPPersistentConnection();
|
27 |
+
$view = array(
|
28 |
+
'Height' => 200,
|
29 |
+
'Width' => 300,
|
30 |
+
'CenterPoint' => array(
|
31 |
+
'Latitude' => 40,
|
32 |
+
'Longitude' => -120
|
33 |
+
)
|
34 |
+
);
|
35 |
+
$myViews[] = new soapval('MapView', 'ViewByHeightWidth', $view, false, 'http://s.mappoint.net/mappoint-30/');
|
36 |
+
$mapSpec = array(
|
37 |
+
'DataSourceName' => "MapPoint.NA",
|
38 |
+
'Views' => array('MapView' => $myViews)
|
39 |
+
);
|
40 |
+
$map = array('specification' => $mapSpec);
|
41 |
+
$result = $client->call('GetMap', array('parameters' => $map));
|
42 |
+
// Check for a fault
|
43 |
+
if ($client->fault) {
|
44 |
+
echo '<h2>Fault</h2><pre>';
|
45 |
+
print_r($result);
|
46 |
+
echo '</pre>';
|
47 |
+
} else {
|
48 |
+
// Check for errors
|
49 |
+
$err = $client->getError();
|
50 |
+
if ($err) {
|
51 |
+
// Display the error
|
52 |
+
echo '<h2>Error</h2><pre>' . $err . '</pre>';
|
53 |
+
} else {
|
54 |
+
// Display the result
|
55 |
+
echo '<h2>Result</h2><pre>';
|
56 |
+
print_r($result);
|
57 |
+
echo '</pre>';
|
58 |
+
}
|
59 |
+
}
|
60 |
+
echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
|
61 |
+
echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
|
62 |
+
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->debug_str, ENT_QUOTES) . '</pre>';
|
63 |
+
?>
|
app/code/local/Waterstone/winvoice/controllers/Adminhtml/WinvoiceController.php
ADDED
@@ -0,0 +1,335 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* DISCLAIMER
|
4 |
+
*
|
5 |
+
* Do not edit or add to this file if you wish to upgrade the extension to newer
|
6 |
+
* versions in the future. If you need personal customization please contact us
|
7 |
+
* on http://www.waterstone.pt for more information.
|
8 |
+
*
|
9 |
+
* @category Waterstone
|
10 |
+
* @package Waterstone_Winvoice
|
11 |
+
* @copyright Copyright (c) 2014 Waterstone Consulting, Lda. (http://www.waterstone.pt)
|
12 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
13 |
+
*/
|
14 |
+
|
15 |
+
class Waterstone_Winvoice_Adminhtml_WinvoiceController extends Mage_Adminhtml_Controller_action
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* Initialization action.
|
19 |
+
* - Initializes the layout activating the menu and breadcrumbs.
|
20 |
+
*
|
21 |
+
* @since 1.0.0
|
22 |
+
*
|
23 |
+
* @return Waterstone_Winvoice_Adminhtml_WinvoiceController
|
24 |
+
*/
|
25 |
+
protected function _initAction()
|
26 |
+
{
|
27 |
+
$this->loadLayout()
|
28 |
+
->_setActiveMenu('winvoice/items')
|
29 |
+
->_addBreadcrumb(Mage::helper('adminhtml')->__('Items Manager'), Mage::helper('adminhtml')->__('Item Manager'));
|
30 |
+
|
31 |
+
return $this;
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Index action.
|
36 |
+
* - Renders the layout.
|
37 |
+
*
|
38 |
+
* @since 1.0.0
|
39 |
+
*
|
40 |
+
* @return void
|
41 |
+
*/
|
42 |
+
public function indexAction()
|
43 |
+
{
|
44 |
+
$this->_initAction()->renderLayout();
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Edit action.
|
49 |
+
* - Sets the breadcrumb items and layout blocks. Renders the layout.
|
50 |
+
* - On error redirect to previous url.
|
51 |
+
*
|
52 |
+
* @since 1.0.0
|
53 |
+
*
|
54 |
+
* @return void
|
55 |
+
*/
|
56 |
+
public function editAction()
|
57 |
+
{
|
58 |
+
$id = $this->getRequest()->getParam('id');
|
59 |
+
$model = Mage::getModel('winvoice/winvoice')->load($id);
|
60 |
+
|
61 |
+
if ($model->getId() || $id == 0) {
|
62 |
+
|
63 |
+
$data = Mage::getSingleton('adminhtml/session')->getFormData(true);
|
64 |
+
|
65 |
+
if (!empty($data)) {
|
66 |
+
$model->setData($data);
|
67 |
+
}
|
68 |
+
|
69 |
+
Mage::register('winvoice_data', $model);
|
70 |
+
|
71 |
+
$this->loadLayout();
|
72 |
+
$this->_setActiveMenu('winvoice/items');
|
73 |
+
|
74 |
+
$this->_addBreadcrumb(Mage::helper('adminhtml')->__('Item Manager'), Mage::helper('adminhtml')->__('Item Manager'));
|
75 |
+
$this->_addBreadcrumb(Mage::helper('adminhtml')->__('Item News'), Mage::helper('adminhtml')->__('Item News'));
|
76 |
+
|
77 |
+
$this->getLayout()->getBlock('head')->setCanLoadExtJs(true);
|
78 |
+
|
79 |
+
$this->_addContent($this->getLayout()->createBlock('winvoice/adminhtml_winvoice_edit'))
|
80 |
+
->_addLeft($this->getLayout()->createBlock('winvoice/adminhtml_winvoice_edit_tabs'));
|
81 |
+
|
82 |
+
$this->renderLayout();
|
83 |
+
} else {
|
84 |
+
Mage::getSingleton('adminhtml/session')->addError(Mage::helper('winvoice')->__('Item does not exist'));
|
85 |
+
$this->_redirect('*/*/');
|
86 |
+
}
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* New action.
|
91 |
+
* - Forwards to edit action.
|
92 |
+
*
|
93 |
+
* @since 1.0.0
|
94 |
+
*
|
95 |
+
* @return void
|
96 |
+
*/
|
97 |
+
public function newAction()
|
98 |
+
{
|
99 |
+
$this->_forward('edit');
|
100 |
+
}
|
101 |
+
|
102 |
+
/**
|
103 |
+
* Save action.
|
104 |
+
* - Adds image files to data and redirects to previous url
|
105 |
+
* - On error redirect to previous url.
|
106 |
+
*
|
107 |
+
* @since 1.0.0
|
108 |
+
*
|
109 |
+
* @return void
|
110 |
+
*/
|
111 |
+
public function saveAction()
|
112 |
+
{
|
113 |
+
if ($data = $this->getRequest()->getPost()) {
|
114 |
+
|
115 |
+
if (isset($_FILES['filename']['name']) && $_FILES['filename']['name'] != '') {
|
116 |
+
|
117 |
+
try {
|
118 |
+
|
119 |
+
/* Starting upload */
|
120 |
+
$uploader = new Varien_File_Uploader('filename');
|
121 |
+
|
122 |
+
// Any extention would work
|
123 |
+
$uploader->setAllowedExtensions(array('jpg','jpeg','gif','png'));
|
124 |
+
$uploader->setAllowRenameFiles(false);
|
125 |
+
|
126 |
+
// Set the file upload mode
|
127 |
+
// false -> get the file directly in the specified folder
|
128 |
+
// true -> get the file in the product like folders
|
129 |
+
// (file.jpg will go in something like /media/f/i/file.jpg)
|
130 |
+
$uploader->setFilesDispersion(false);
|
131 |
+
|
132 |
+
// We set media as the upload dir
|
133 |
+
$path = Mage::getBaseDir('media') . DS ;
|
134 |
+
|
135 |
+
$uploader->save($path, $_FILES['filename']['name']);
|
136 |
+
} catch (Exception $e) {
|
137 |
+
// Do nothing
|
138 |
+
}
|
139 |
+
|
140 |
+
// This way the name is saved in DB
|
141 |
+
$data['filename'] = $_FILES['filename']['name'];
|
142 |
+
}
|
143 |
+
|
144 |
+
$model = Mage::getModel('winvoice/winvoice');
|
145 |
+
$model->setData($data)->setId($this->getRequest()->getParam('id'));
|
146 |
+
|
147 |
+
try {
|
148 |
+
|
149 |
+
if ($model->getCreatedTime == NULL || $model->getUpdateTime() == NULL) {
|
150 |
+
$model->setCreatedTime(now())->setUpdateTime(now());
|
151 |
+
} else {
|
152 |
+
$model->setUpdateTime(now());
|
153 |
+
}
|
154 |
+
|
155 |
+
$model->save();
|
156 |
+
|
157 |
+
Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('winvoice')->__('Item was successfully saved'));
|
158 |
+
Mage::getSingleton('adminhtml/session')->setFormData(false);
|
159 |
+
|
160 |
+
if ($this->getRequest()->getParam('back')) {
|
161 |
+
$this->_redirect('*/*/edit', array('id' => $model->getId()));
|
162 |
+
return;
|
163 |
+
}
|
164 |
+
|
165 |
+
$this->_redirect('*/*/');
|
166 |
+
return;
|
167 |
+
|
168 |
+
} catch (Exception $e) {
|
169 |
+
|
170 |
+
Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
|
171 |
+
Mage::getSingleton('adminhtml/session')->setFormData($data);
|
172 |
+
|
173 |
+
$this->_redirect('*/*/edit', array('id' => $this->getRequest()->getParam('id')));
|
174 |
+
return;
|
175 |
+
}
|
176 |
+
}
|
177 |
+
|
178 |
+
Mage::getSingleton('adminhtml/session')->addError(Mage::helper('winvoice')->__('Unable to find item to save'));
|
179 |
+
$this->_redirect('*/*/');
|
180 |
+
}
|
181 |
+
|
182 |
+
/**
|
183 |
+
* Delete action.
|
184 |
+
*
|
185 |
+
* @since 1.0.0
|
186 |
+
*
|
187 |
+
* @return void
|
188 |
+
*/
|
189 |
+
public function deleteAction()
|
190 |
+
{
|
191 |
+
if( $this->getRequest()->getParam('id') > 0 ) {
|
192 |
+
|
193 |
+
try {
|
194 |
+
$model = Mage::getModel('winvoice/winvoice');
|
195 |
+
$model->setId($this->getRequest()->getParam('id'))->delete();
|
196 |
+
|
197 |
+
Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('adminhtml')->__('Item was successfully deleted'));
|
198 |
+
$this->_redirect('*/*/');
|
199 |
+
|
200 |
+
} catch (Exception $e) {
|
201 |
+
Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
|
202 |
+
$this->_redirect('*/*/edit', array('id' => $this->getRequest()->getParam('id')));
|
203 |
+
}
|
204 |
+
}
|
205 |
+
|
206 |
+
$this->_redirect('*/*/');
|
207 |
+
}
|
208 |
+
|
209 |
+
/**
|
210 |
+
* Mass delete action.
|
211 |
+
*
|
212 |
+
* @since 1.0.0
|
213 |
+
*
|
214 |
+
* @return void
|
215 |
+
*/
|
216 |
+
public function massDeleteAction()
|
217 |
+
{
|
218 |
+
$winvoiceIds = $this->getRequest()->getParam('winvoice');
|
219 |
+
|
220 |
+
if(!is_array($winvoiceIds)) {
|
221 |
+
Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__('Please select item(s)'));
|
222 |
+
} else {
|
223 |
+
try {
|
224 |
+
foreach ($winvoiceIds as $winvoiceId) {
|
225 |
+
$winvoice = Mage::getModel('winvoice/winvoice')->load($winvoiceId);
|
226 |
+
$winvoice->delete();
|
227 |
+
}
|
228 |
+
|
229 |
+
Mage::getSingleton('adminhtml/session')->addSuccess(
|
230 |
+
Mage::helper('adminhtml')->__(
|
231 |
+
'Total of %d record(s) were successfully deleted', count($winvoiceIds)
|
232 |
+
)
|
233 |
+
);
|
234 |
+
|
235 |
+
} catch (Exception $e) {
|
236 |
+
Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
|
237 |
+
}
|
238 |
+
}
|
239 |
+
|
240 |
+
$this->_redirect('*/*/index');
|
241 |
+
}
|
242 |
+
|
243 |
+
/**
|
244 |
+
* Mass status action.
|
245 |
+
*
|
246 |
+
* @since 1.0.0
|
247 |
+
*
|
248 |
+
* @return void
|
249 |
+
*/
|
250 |
+
public function massStatusAction()
|
251 |
+
{
|
252 |
+
$winvoiceIds = $this->getRequest()->getParam('winvoice');
|
253 |
+
|
254 |
+
if(!is_array($winvoiceIds)) {
|
255 |
+
Mage::getSingleton('adminhtml/session')->addError($this->__('Please select item(s)'));
|
256 |
+
} else {
|
257 |
+
try {
|
258 |
+
foreach ($winvoiceIds as $winvoiceId) {
|
259 |
+
$winvoice = Mage::getSingleton('winvoice/winvoice')
|
260 |
+
->load($winvoiceId)
|
261 |
+
->setStatus($this->getRequest()->getParam('status'))
|
262 |
+
->setIsMassupdate(true)
|
263 |
+
->save();
|
264 |
+
}
|
265 |
+
|
266 |
+
$this->_getSession()->addSuccess(
|
267 |
+
$this->__('Total of %d record(s) were successfully updated', count($winvoiceIds))
|
268 |
+
);
|
269 |
+
} catch (Exception $e) {
|
270 |
+
$this->_getSession()->addError($e->getMessage());
|
271 |
+
}
|
272 |
+
}
|
273 |
+
|
274 |
+
$this->_redirect('*/*/index');
|
275 |
+
}
|
276 |
+
|
277 |
+
/**
|
278 |
+
* Export CSV action.
|
279 |
+
*
|
280 |
+
* @since 1.0.0
|
281 |
+
*
|
282 |
+
* @return void
|
283 |
+
*/
|
284 |
+
public function exportCsvAction()
|
285 |
+
{
|
286 |
+
$fileName = 'winvoice.csv';
|
287 |
+
$content = $this->getLayout()->createBlock('winvoice/adminhtml_winvoice_grid')->getCsv();
|
288 |
+
|
289 |
+
$this->_sendUploadResponse($fileName, $content);
|
290 |
+
}
|
291 |
+
|
292 |
+
/**
|
293 |
+
* Export XML action.
|
294 |
+
*
|
295 |
+
* @since 1.0.0
|
296 |
+
*
|
297 |
+
* @return void
|
298 |
+
*/
|
299 |
+
public function exportXmlAction()
|
300 |
+
{
|
301 |
+
$fileName = 'winvoice.xml';
|
302 |
+
$content = $this->getLayout()->createBlock('winvoice/adminhtml_winvoice_grid')->getXml();
|
303 |
+
|
304 |
+
$this->_sendUploadResponse($fileName, $content);
|
305 |
+
}
|
306 |
+
|
307 |
+
/**
|
308 |
+
* Send upload response action.
|
309 |
+
* - Sets the document headers for file download.
|
310 |
+
*
|
311 |
+
* @since 1.0.0
|
312 |
+
*
|
313 |
+
* @param string $fileName
|
314 |
+
* @param string $content
|
315 |
+
* @param string $contentType
|
316 |
+
* @return void
|
317 |
+
*/
|
318 |
+
protected function _sendUploadResponse($fileName, $content, $contentType='application/octet-stream')
|
319 |
+
{
|
320 |
+
$response = $this->getResponse();
|
321 |
+
$response->setHeader('HTTP/1.1 200 OK','');
|
322 |
+
$response->setHeader('Pragma', 'public', true);
|
323 |
+
$response->setHeader('Cache-Control', 'must-revalidate, post-check=0, pre-check=0', true);
|
324 |
+
$response->setHeader('Content-Disposition', 'attachment; filename='.$fileName);
|
325 |
+
$response->setHeader('Last-Modified', date('r'));
|
326 |
+
$response->setHeader('Accept-Ranges', 'bytes');
|
327 |
+
$response->setHeader('Content-Length', strlen($content));
|
328 |
+
$response->setHeader('Content-type', $contentType);
|
329 |
+
$response->setBody($content);
|
330 |
+
$response->sendResponse();
|
331 |
+
|
332 |
+
die;
|
333 |
+
}
|
334 |
+
|
335 |
+
}
|
app/code/local/Waterstone/winvoice/etc/adminhtml.xml
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<!--
|
3 |
+
/**
|
4 |
+
* DISCLAIMER
|
5 |
+
*
|
6 |
+
* Do not edit or add to this file if you wish to upgrade the extension to newer
|
7 |
+
* versions in the future. If you need personal customization please contact us
|
8 |
+
* on http://www.waterstone.pt for more information.
|
9 |
+
*
|
10 |
+
* @category Waterstone
|
11 |
+
* @package Waterstone_Winvoice
|
12 |
+
* @copyright Copyright (c) 2014 Waterstone Consulting, Lda. (http://www.waterstone.pt)
|
13 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
14 |
+
*/
|
15 |
+
-->
|
16 |
+
|
17 |
+
<config>
|
18 |
+
<acl>
|
19 |
+
<resources>
|
20 |
+
<all>
|
21 |
+
<title>Allow Everything</title>
|
22 |
+
</all>
|
23 |
+
<admin>
|
24 |
+
<children>
|
25 |
+
<system>
|
26 |
+
<children>
|
27 |
+
<config>
|
28 |
+
<children>
|
29 |
+
<winvoice translate="title">
|
30 |
+
<title>Winvoice</title>
|
31 |
+
<sort_order>100</sort_order>
|
32 |
+
</winvoice>
|
33 |
+
</children>
|
34 |
+
</config>
|
35 |
+
</children>
|
36 |
+
</system>
|
37 |
+
</children>
|
38 |
+
</admin>
|
39 |
+
</resources>
|
40 |
+
</acl>
|
41 |
+
</config>
|
app/code/local/Waterstone/winvoice/etc/config.xml
ADDED
@@ -0,0 +1,138 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<!--
|
3 |
+
/**
|
4 |
+
* DISCLAIMER
|
5 |
+
*
|
6 |
+
* Do not edit or add to this file if you wish to upgrade the extension to newer
|
7 |
+
* versions in the future. If you need personal customization please contact us
|
8 |
+
* on http://www.waterstone.pt for more information.
|
9 |
+
*
|
10 |
+
* @category Waterstone
|
11 |
+
* @package Waterstone_Winvoice
|
12 |
+
* @copyright Copyright (c) 2014 Waterstone Consulting, Lda. (http://www.waterstone.pt)
|
13 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
14 |
+
*/
|
15 |
+
-->
|
16 |
+
|
17 |
+
<config>
|
18 |
+
<modules>
|
19 |
+
<Waterstone_Winvoice>
|
20 |
+
<version>1.0.0</version>
|
21 |
+
</Waterstone_Winvoice>
|
22 |
+
|
23 |
+
</modules>
|
24 |
+
<frontend>
|
25 |
+
<routers>
|
26 |
+
<winvoice>
|
27 |
+
<use>standard</use>
|
28 |
+
<args>
|
29 |
+
<module>Waterstone_Winvoice</module>
|
30 |
+
<frontName>winvoice</frontName>
|
31 |
+
</args>
|
32 |
+
</winvoice>
|
33 |
+
</routers>
|
34 |
+
<layout>
|
35 |
+
<updates>
|
36 |
+
<winvoice>
|
37 |
+
<file>winvoice.xml</file>
|
38 |
+
</winvoice>
|
39 |
+
</updates>
|
40 |
+
</layout>
|
41 |
+
</frontend>
|
42 |
+
<admin>
|
43 |
+
<routers>
|
44 |
+
<winvoice>
|
45 |
+
<use>admin</use>
|
46 |
+
<args>
|
47 |
+
<module>Waterstone_Winvoice</module>
|
48 |
+
<frontName>winvoice</frontName>
|
49 |
+
</args>
|
50 |
+
</winvoice>
|
51 |
+
</routers>
|
52 |
+
</admin>
|
53 |
+
<adminhtml>
|
54 |
+
<layout>
|
55 |
+
<updates>
|
56 |
+
<winvoice>
|
57 |
+
<file>winvoice.xml</file>
|
58 |
+
</winvoice>
|
59 |
+
</updates>
|
60 |
+
</layout>
|
61 |
+
</adminhtml>
|
62 |
+
<global>
|
63 |
+
<models>
|
64 |
+
<winvoice>
|
65 |
+
<class>Waterstone_Winvoice_Model</class>
|
66 |
+
<resourceModel>winvoice_mysql4</resourceModel>
|
67 |
+
</winvoice>
|
68 |
+
<winvoice_mysql4>
|
69 |
+
<class>Waterstone_Winvoice_Model_Mysql4</class>
|
70 |
+
<entities>
|
71 |
+
<winvoice>
|
72 |
+
<table>winvoice</table>
|
73 |
+
</winvoice>
|
74 |
+
</entities>
|
75 |
+
</winvoice_mysql4>
|
76 |
+
<core>
|
77 |
+
<rewrite>
|
78 |
+
<email_template_mailer>Waterstone_Winvoice_Model_Email_Template_Mailer</email_template_mailer>
|
79 |
+
</rewrite>
|
80 |
+
</core>
|
81 |
+
<sales>
|
82 |
+
<rewrite>
|
83 |
+
<order_invoice>Waterstone_Winvoice_Model_Order_Invoice</order_invoice>
|
84 |
+
</rewrite>
|
85 |
+
</sales>
|
86 |
+
</models>
|
87 |
+
<resources>
|
88 |
+
<winvoice_setup>
|
89 |
+
<setup>
|
90 |
+
<module>Waterstone_Winvoice</module>
|
91 |
+
</setup>
|
92 |
+
<connection>
|
93 |
+
<use>core_setup</use>
|
94 |
+
</connection>
|
95 |
+
</winvoice_setup>
|
96 |
+
<winvoice_write>
|
97 |
+
<connection>
|
98 |
+
<use>core_write</use>
|
99 |
+
</connection>
|
100 |
+
</winvoice_write>
|
101 |
+
<winvoice_read>
|
102 |
+
<connection>
|
103 |
+
<use>core_read</use>
|
104 |
+
</connection>
|
105 |
+
</winvoice_read>
|
106 |
+
</resources>
|
107 |
+
<blocks>
|
108 |
+
<winvoice>
|
109 |
+
<class>Waterstone_Winvoice_Block</class>
|
110 |
+
</winvoice>
|
111 |
+
</blocks>
|
112 |
+
<helpers>
|
113 |
+
<winvoice>
|
114 |
+
<class>Waterstone_Winvoice_Helper</class>
|
115 |
+
</winvoice>
|
116 |
+
</helpers>
|
117 |
+
<events>
|
118 |
+
<sales_order_invoice_save_before>
|
119 |
+
<observers>
|
120 |
+
<Waterstone_Winvoice_order_create>
|
121 |
+
<type>singleton</type>
|
122 |
+
<class>Waterstone_Winvoice_Model_AddInvoice</class>
|
123 |
+
<method>AddInvoice</method>
|
124 |
+
</Waterstone_Winvoice_order_create>
|
125 |
+
</observers>
|
126 |
+
</sales_order_invoice_save_before>
|
127 |
+
<sales_order_shipment_save_after>
|
128 |
+
<observers>
|
129 |
+
<Waterstone_Winvoice_order_pay>
|
130 |
+
<type>singleton</type>
|
131 |
+
<class>Waterstone_Winvoice_Model_AddInvoice</class>
|
132 |
+
<method>AutoInvoice</method>
|
133 |
+
</Waterstone_Winvoice_order_pay>
|
134 |
+
</observers>
|
135 |
+
</sales_order_shipment_save_after>
|
136 |
+
</events>
|
137 |
+
</global>
|
138 |
+
</config>
|
app/code/local/Waterstone/winvoice/etc/system.xml
ADDED
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<!--
|
3 |
+
/**
|
4 |
+
* DISCLAIMER
|
5 |
+
*
|
6 |
+
* Do not edit or add to this file if you wish to upgrade the extension to newer
|
7 |
+
* versions in the future. If you need personal customization please contact us
|
8 |
+
* on http://www.waterstone.pt for more information.
|
9 |
+
*
|
10 |
+
* @category Waterstone
|
11 |
+
* @package Waterstone_Winvoice
|
12 |
+
* @copyright Copyright (c) 2014 Waterstone Consulting, Lda. (http://www.waterstone.pt)
|
13 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
14 |
+
*/
|
15 |
+
-->
|
16 |
+
|
17 |
+
<config>
|
18 |
+
<sections>
|
19 |
+
<winvoice translate="label">
|
20 |
+
<label>Winvoice</label>
|
21 |
+
<tab>general</tab>
|
22 |
+
<frontend_type>text</frontend_type>
|
23 |
+
<sort_order>1000</sort_order>
|
24 |
+
<show_in_default>1</show_in_default>
|
25 |
+
<show_in_website>1</show_in_website>
|
26 |
+
<show_in_store>1</show_in_store>
|
27 |
+
<groups>
|
28 |
+
<wconfig translate="label">
|
29 |
+
<label>Configuração</label>
|
30 |
+
<frontend_type>text</frontend_type>
|
31 |
+
<sort_order>100</sort_order>
|
32 |
+
<show_in_default>1</show_in_default>
|
33 |
+
<show_in_website>1</show_in_website>
|
34 |
+
<show_in_store>1</show_in_store>
|
35 |
+
<fields>
|
36 |
+
<!-- New fields go here -->
|
37 |
+
<wapi translate="label comment">
|
38 |
+
<label>API weoInvoice</label>
|
39 |
+
<comment>API fornecida pelo weoInvoice</comment>
|
40 |
+
<frontend_type>text</frontend_type>
|
41 |
+
<sort_order>10</sort_order>
|
42 |
+
<show_in_default>1</show_in_default>
|
43 |
+
<show_in_website>1</show_in_website>
|
44 |
+
<show_in_store>1</show_in_store>
|
45 |
+
<validate>validate-url</validate>
|
46 |
+
</wapi>
|
47 |
+
<wpassword translate="label comment">
|
48 |
+
<label>Password weoInvoice</label>
|
49 |
+
<comment>Password da sua conta weoInvoice</comment>
|
50 |
+
<frontend_type>password</frontend_type>
|
51 |
+
<sort_order>20</sort_order>
|
52 |
+
<show_in_default>1</show_in_default>
|
53 |
+
<show_in_website>1</show_in_website>
|
54 |
+
<show_in_store>1</show_in_store>
|
55 |
+
</wpassword>
|
56 |
+
<wshiptax translate="label comment">
|
57 |
+
<label>Imposto a aplicar ao envio</label>
|
58 |
+
<comment>Introduza a taxa de IVA a aplicar aos envios</comment>
|
59 |
+
<frontend_type>text</frontend_type>
|
60 |
+
<sort_order>30</sort_order>
|
61 |
+
<show_in_default>1</show_in_default>
|
62 |
+
<show_in_website>1</show_in_website>
|
63 |
+
<show_in_store>1</show_in_store>
|
64 |
+
<validate>validate-digits</validate>
|
65 |
+
</wshiptax>
|
66 |
+
</fields>
|
67 |
+
</wconfig>
|
68 |
+
</groups>
|
69 |
+
</winvoice>
|
70 |
+
</sections>
|
71 |
+
</config>
|
app/code/local/Waterstone/winvoice/sql/winvoice_setup/mysql4-install-0.1.0.php
ADDED
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* DISCLAIMER
|
4 |
+
*
|
5 |
+
* Do not edit or add to this file if you wish to upgrade the extension to newer
|
6 |
+
* versions in the future. If you need personal customization please contact us
|
7 |
+
* on http://www.waterstone.pt for more information.
|
8 |
+
*
|
9 |
+
* @category Waterstone
|
10 |
+
* @package Waterstone_Winvoice
|
11 |
+
* @copyright Copyright (c) 2014 Waterstone Consulting, Lda. (http://www.waterstone.pt)
|
12 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
13 |
+
*/
|
14 |
+
|
15 |
+
$installer = $this;
|
16 |
+
|
17 |
+
// Set the setup class
|
18 |
+
$setup = new Mage_Customer_Model_Entity_Setup('core_setup');
|
19 |
+
$setup->startSetup();
|
20 |
+
|
21 |
+
// Get customer entity data
|
22 |
+
$vCustomerEntityType = $setup->getEntityTypeId('customer');
|
23 |
+
$vCustAttributeSetId = $setup->getDefaultAttributeSetId($vCustomerEntityType);
|
24 |
+
$vCustAttributeGroupId = $setup->getDefaultAttributeGroupId($vCustomerEntityType, $vCustAttributeSetId);
|
25 |
+
|
26 |
+
// Set new attribute for the customer entity
|
27 |
+
$setup->removeAttribute('customer','wsclient');
|
28 |
+
$setup->addAttribute('customer', 'wsclient', array(
|
29 |
+
'label' => 'Cliente Weo',
|
30 |
+
'input' => 'text',
|
31 |
+
'type' => 'varchar',
|
32 |
+
'forms' => array('customer_account_edit','customer_account_create','adminhtml_customer','checkout_register'),
|
33 |
+
'required' => 0,
|
34 |
+
'user_defined' => 1,
|
35 |
+
));
|
36 |
+
|
37 |
+
// Add the attribute to the attribute group
|
38 |
+
$setup->addAttributeToGroup($vCustomerEntityType, $vCustAttributeSetId, $vCustAttributeGroupId, 'wsclient', 0);
|
39 |
+
|
40 |
+
// Define the forms where the atribute should be used
|
41 |
+
$oAttribute = Mage::getSingleton('eav/config')->getAttribute('customer', 'wsclient');
|
42 |
+
$oAttribute->setData('used_in_forms', array('customer_account_edit','customer_account_create','adminhtml_customer','checkout_register'));
|
43 |
+
$oAttribute->save();
|
44 |
+
|
45 |
+
// Add a new attribute to the order entity
|
46 |
+
$setup->addAttribute('order', 'wsinvoiceurl', array(
|
47 |
+
'type' => 'varchar',
|
48 |
+
'label' => 'Factura certificada',
|
49 |
+
'visible' => true,
|
50 |
+
'required' => false,
|
51 |
+
'visible_on_front' => true,
|
52 |
+
'user_defined' => true
|
53 |
+
));
|
54 |
+
|
55 |
+
$setup->endSetup();
|
56 |
+
|
57 |
+
$installer->startSetup();
|
58 |
+
$installer->endSetup();
|
package.xml
CHANGED
@@ -1,82 +1,18 @@
|
|
1 |
<?xml version="1.0"?>
|
2 |
<package>
|
3 |
<name>Waterstone_Winvoice</name>
|
4 |
-
<version>1.0.1</version>
|
5 |
<stability>stable</stability>
|
6 |
-
<license
|
7 |
<channel>community</channel>
|
8 |
<extends/>
|
9 |
-
<summary>
|
10 |
-
<description
|
11 |
-
<p>This extension allows you to get a certified invoice when the Magento invoice is generated. It uses an external service (weoInvoice) that automatically generates your certified invoice which is sent to you in PDF, annexed to the Magento invoice email.</p>
|
12 |
-

|
13 |
-
<h3>Product Requirements</h3>
|
14 |
-

|
15 |
-
<p>For this to work you need to subscribe for a license in <a href="http://www.waterstone.pt/facturacao-certificada-magento/">Waterstone</a>.</p>
|
16 |
-

|
17 |
-
<h3>Configuration</h3>
|
18 |
-

|
19 |
-
<p>To configure the extension, navigate on the top main menu <strong>System -> Configuration</strong>. On the side menu click on <strong>General - > Winvoice</strong>. The configuration page has three fields (check the first screenshot):
|
20 |
-
<ul>
|
21 |
-
<li>API weoInvoice</li>
|
22 |
-
<li>Password weoInvoice</li>
|
23 |
-
<li>Imposto a aplicar ao envio</li>
|
24 |
-
</ul>
|
25 |
-
</p>
|
26 |
-

|
27 |
-
<p>On the "API weoInvoice" field insert the API hyperlink supplied with our license. 
|
28 |
-
On "Password weoInvoice" insert the API password supplied with our license. 
|
29 |
-
On "Imposto a aplicar ao envio" insert a tax value in percentage, if you desire to include an tax associated with product shipment.</p>
|
30 |
-

|
31 |
-
<p>All products should have an associated tax class compatible with the <a href="http://info.portaldasfinancas.gov.pt/pt/informacao_fiscal/codigos_tributarios/civa_rep/index_iva.htm">Portuguese IVA</a> taxes (eg. 23%).</p>
|
32 |
-

|
33 |
-
<p>If you want to test the extension first, please use the following account data:
|
34 |
-
<ul>
|
35 |
-
<li>API: <strong>http://www.weoinvoice.com/webservice/304e76cb321c57672915bf2b7be5b9d5e905dfc9/webservice.php</strong></li>
|
36 |
-
<li>Password: <strong>=$Z%5XJq</strong></li>
|
37 |
-
</ul>
|
38 |
-
The email associated with this account is <strong>info@waterstone.pt</strong>. To access the demo panel and check your invoice, go to <strong>www.weoinvoice.com</strong> and log in with the demo account.
|
39 |
-
</p>
|
40 |
-

|
41 |
-
<hr>
|
42 |
-

|
43 |
-
<h2>Winvoice</h2>
|
44 |
-

|
45 |
-
<p>Obtenha facturas certificadas na sua loja Magento (apenas requisitos legais Portugueses).</p>
|
46 |
-
<p>Ao gerar uma factura na sua conta Magento, a extensão Winvoice gera uma fatura certificada em simultâneo através de um serviço externo (weoInvoice), sendo esta posteriormente enviada para si em formato PDF, anexado ao email da factura Magento.</p>
|
47 |
-

|
48 |
-
<h3>Requisitos</h3>
|
49 |
-

|
50 |
-
<p>Para que esta extensão funcione deverá subscrever uma licença com a <a href="http://www.waterstone.pt/facturacao-certificada-magento/">Waterstone</a>.</p>
|
51 |
-

|
52 |
-
<h3>Configuração</h3>
|
53 |
-

|
54 |
-
<p>Para configurar a extensão aceda ao menu principal <strong>System -> Configuration</strong>. No menu lateral, deve aceder à secção <strong>General -> Winvoice</strong>. A página de configuração da extensão contém três campos (ver o primeiro screenshot):
|
55 |
-
<ul>
|
56 |
-
<li>API weoInvoice</li>
|
57 |
-
<li>Password weoInvoice</li>
|
58 |
-
<li>Imposto a aplicar ao envio</li>
|
59 |
-
</ul>
|
60 |
-
</p>
|
61 |
-

|
62 |
-
<p>No campo "API weoInvoice" deverá colocar a hiperligação fornecida na nossa licença. 
|
63 |
-
Em "Password weoInvoice" deverá colocar a palavra-chave fornecida na nossa licença.
|
64 |
-
Em "Imposto a aplicar ao envio" deve inserir um valor em percentagem, se desejar incluir uma taxa associada ao envio de produtos.</p>
|
65 |
-

|
66 |
-
<p>Todos os produtos devem ter uma classe de imposto associada compatível com as taxas de <a href="http://info.portaldasfinancas.gov.pt/pt/informacao_fiscal/codigos_tributarios/civa_rep/index_iva.htm">IVA Português</a> (ex. 23%).</p>
|
67 |
-

|
68 |
-
<p>Para efeitos de teste pode usar a seguinte conta:
|
69 |
-
<ul>
|
70 |
-
<li>API: <strong>http://www.weoinvoice.com/webservice/304e76cb321c57672915bf2b7be5b9d5e905dfc9/webservice.php</strong></li>
|
71 |
-
<li>Password: <strong>=$Z%5XJq</strong></li>
|
72 |
-
</ul>
|
73 |
-
A conta de email associada à conta de demonstração é <strong>info@waterstone.pt</strong>. Para aceder ao painel de demonstração e verificar a sua factura, aceda a <strong>www.weoinvoice.com</strong> e faça login com a conta demo.
|
74 |
-
</p></description>
|
75 |
<notes>.</notes>
|
76 |
-
<authors><author><name>Waterstone
|
77 |
-
<date>2014-
|
78 |
-
<time>
|
79 |
-
<contents><target name="magelocal"><dir name="Waterstone"><dir name="
|
80 |
<compatible/>
|
81 |
-
<dependencies><required><php><min>5.4.12</min><max>5.5.
|
82 |
</package>
|
1 |
<?xml version="1.0"?>
|
2 |
<package>
|
3 |
<name>Waterstone_Winvoice</name>
|
4 |
+
<version>1.0.1.1</version>
|
5 |
<stability>stable</stability>
|
6 |
+
<license>OSL</license>
|
7 |
<channel>community</channel>
|
8 |
<extends/>
|
9 |
+
<summary>Provides certified invoices for your store.</summary>
|
10 |
+
<description>Provides a certified invoice that is sent via email to the store user.</description>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
<notes>.</notes>
|
12 |
+
<authors><author><name>Waterstone</name><user>waterstone</user><email>info@waterstone.pt</email></author></authors>
|
13 |
+
<date>2014-06-03</date>
|
14 |
+
<time>18:31:47</time>
|
15 |
+
<contents><target name="magelocal"><dir><dir name="Waterstone"><dir name="winvoice"><dir name="Helper"><file name="Data.php" hash="793437e2a036dae3ab1097f5de91d27d"/></dir><dir name="Model"><file name="AddInvoice.php" hash="2819ed5adc413eb646a69ad5dbcaf62c"/><dir name="Email"><dir name="Template"><file name="Mailer.php" hash="d990fe62b70529b6fcdb2c3e72cb0480"/></dir></dir><file name="Log.php" hash="d9f0200dd7c95dbf9bf5953462932526"/><dir name="Mysql4"><dir name="Winvoice"><file name="Collection.php" hash="2dd253dfae89056b584de8524a329a27"/></dir><file name="Winvoice.php" hash="6c1c7b045b65bddc395c828edb60ebe0"/></dir><dir name="Order"><file name="Invoice.php" hash="3670cfdea82e27da66d32556760c7e22"/></dir><file name="Status.php" hash="0e33254db1775e85fdd95773d9612c5c"/><dir name="nusoap"><dir name="lib"><file name="changelog" hash="3919a6a82b4f75206da9feaf8ceec3ed"/><file name="class.nusoap_base.php" hash="926c4daafe38a19c5d8444c270714741"/><file name="class.soap_fault.php" hash="cfd584361ababce6337b99e5979d7c4d"/><file name="class.soap_parser.php" hash="99ebb296b20d61d0161a037904366759"/><file name="class.soap_server.php" hash="5fd364995957f5c38a535a04a4be4384"/><file name="class.soap_transport_http.php" hash="2fedc17e37799b06e489d6a89c66453e"/><file name="class.soap_val.php" hash="ddd9047b47c42e5cbb2a88897372cb4f"/><file name="class.soapclient.php" hash="682f206b6917a163bc085d5093817767"/><file name="class.wsdl.php" hash="cafbf5025785922c4b6ecb005fd9b387"/><file name="class.wsdlcache.php" hash="89e38c3a9b266bce6ce70953829e0b70"/><file name="class.xmlschema.php" hash="f2a76931ddbd07c85ec882e736c2b90d"/><file name="nusoap.php" hash="675597fb030e84c0a3041bbceff9a2de"/><file name="nusoapmime.php" hash="29d372d39482f75b12655a562a10b822"/></dir><dir name="samples"><file name="client1.php" hash="d409d0bae57e8d4c13fefd63bec70b84"/><file name="client2.php" hash="7b95031a64f7b5975610520385503c37"/><file name="client3.php" hash="c6f1a9a2c44fac36fadcd4631373a998"/><file name="getfile1client.php" hash="c8e9b2d47e157bea50cd4285d6989e3d"/><file name="getfile2client.php" hash="b1338a810f91d58973c95b9d12c579e3"/><file name="index.html" hash="b52de1d66171cade209a651328ac3f97"/><file name="mimeclient.php" hash="0b1196705730ee220b42f1197599dcfa"/><file name="sslclient.php" hash="b790bf099c5d983c848cdd3571ee05df"/><file name="wsdlclient1.php" hash="b114369ba77f166e02da529678f0e74b"/><file name="wsdlclient10.php" hash="b63c4edc9cdbe4fe0ef69ca2250538e8"/><file name="wsdlclient11.php" hash="f3bc441f4b1747612510c3644dd00367"/><file name="wsdlclient12.php" hash="b1413252ca52f96a01b6d30ad1dc341e"/><file name="wsdlclient13.php" hash="d93cbd256bffa0fc637012451466ff0d"/><file name="wsdlclient14.php" hash="496b7d67e53bf2573ca2a35c4f0e696e"/><file name="wsdlclient15.php" hash="7ef02ec40fb271b281a4dc698035ae25"/><file name="wsdlclient2.php" hash="9fd136cd8355714cf3780116d1cb6b2f"/><file name="wsdlclient3.php" hash="5cb748a2989ae8c6c151c43a9b16a51b"/><file name="wsdlclient3b.php" hash="d7eb5f646f946438b034b818098f941d"/><file name="wsdlclient3c.php" hash="22220ca28722857ff04a519b1a89280f"/><file name="wsdlclient4.php" hash="06160017a0748dc2e39d63150a17b869"/><file name="wsdlclient5.php" hash="4503ba03f13e5f75c7a69e09253c5ba9"/><file name="wsdlclient6.php" hash="9376d30095c9572d50cec1294914b51f"/><file name="wsdlclient7.php" hash="92640c4e76c3c024d57434d638fedd78"/><file name="wsdlclient8.php" hash="61fea89801914afc8c99119a5ea090ef"/><file name="wsdlclient9.php" hash="d2111b6ae75bb3fe104a51e845208e4b"/></dir></dir></dir><dir name="controllers"><dir name="Adminhtml"><file name="WinvoiceController.php" hash="cf1aa2e70e3343c8f173bf7bb56d867a"/></dir></dir><dir name="etc"><file name="adminhtml.xml" hash="28cda20f40db5efb00659ae4bd83f19e"/><file name="config.xml" hash="f65601d5139e6fd9cee454a847b437f6"/><file name="system.xml" hash="8b75637d21e01e24be2d4c61c7a23ebe"/></dir><dir name="sql"><dir name="winvoice_setup"><file name="mysql4-install-0.1.0.php" hash="92b059cb47ed001e285ff7b11e7311bd"/></dir></dir></dir></dir></dir></target></contents>
|
16 |
<compatible/>
|
17 |
+
<dependencies><required><php><min>5.4.12</min><max>5.5.12</max></php><package><name>Mage_Core_Modules</name><channel>community</channel><min>1.7</min><max>1.9</max></package></required></dependencies>
|
18 |
</package>
|