Waterstone_Winvoice - Version 1.0.1.1

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

Files changed (53) hide show
  1. app/code/local/Waterstone/Winvoice +0 -1
  2. app/code/local/Waterstone/winvoice/Helper/Data.php +18 -0
  3. app/code/local/Waterstone/winvoice/Model/AddInvoice.php +390 -0
  4. app/code/local/Waterstone/winvoice/Model/Email/Template/Mailer.php +228 -0
  5. app/code/local/Waterstone/winvoice/Model/Log.php +65 -0
  6. app/code/local/Waterstone/winvoice/Model/Mysql4/Winvoice.php +31 -0
  7. app/code/local/Waterstone/winvoice/Model/Mysql4/Winvoice/Collection.php +31 -0
  8. app/code/local/Waterstone/winvoice/Model/Order/Invoice.php +1142 -0
  9. app/code/local/Waterstone/winvoice/Model/Status.php +37 -0
  10. app/code/local/Waterstone/winvoice/Model/nusoap/lib/changelog +648 -0
  11. app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.nusoap_base.php +996 -0
  12. app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.soap_fault.php +90 -0
  13. app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.soap_parser.php +643 -0
  14. app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.soap_server.php +1127 -0
  15. app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.soap_transport_http.php +1307 -0
  16. app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.soap_val.php +107 -0
  17. app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.soapclient.php +991 -0
  18. app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.wsdl.php +1938 -0
  19. app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.wsdlcache.php +209 -0
  20. app/code/local/Waterstone/winvoice/Model/nusoap/lib/class.xmlschema.php +973 -0
  21. app/code/local/Waterstone/winvoice/Model/nusoap/lib/nusoap.php +8148 -0
  22. app/code/local/Waterstone/winvoice/Model/nusoap/lib/nusoapmime.php +501 -0
  23. app/code/local/Waterstone/winvoice/Model/nusoap/samples/client1.php +51 -0
  24. app/code/local/Waterstone/winvoice/Model/nusoap/samples/client2.php +57 -0
  25. app/code/local/Waterstone/winvoice/Model/nusoap/samples/client3.php +56 -0
  26. app/code/local/Waterstone/winvoice/Model/nusoap/samples/getfile1client.php +37 -0
  27. app/code/local/Waterstone/winvoice/Model/nusoap/samples/getfile2client.php +37 -0
  28. app/code/local/Waterstone/winvoice/Model/nusoap/samples/index.html +67 -0
  29. app/code/local/Waterstone/winvoice/Model/nusoap/samples/mimeclient.php +53 -0
  30. app/code/local/Waterstone/winvoice/Model/nusoap/samples/sslclient.php +37 -0
  31. app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient1.php +47 -0
  32. app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient10.php +44 -0
  33. app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient11.php +50 -0
  34. app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient12.php +225 -0
  35. app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient13.php +99 -0
  36. app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient14.php +83 -0
  37. app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient15.php +60 -0
  38. app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient2.php +58 -0
  39. app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient3.php +56 -0
  40. app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient3b.php +46 -0
  41. app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient3c.php +46 -0
  42. app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient4.php +176 -0
  43. app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient5.php +69 -0
  44. app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient6.php +66 -0
  45. app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient7.php +51 -0
  46. app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient8.php +74 -0
  47. app/code/local/Waterstone/winvoice/Model/nusoap/samples/wsdlclient9.php +63 -0
  48. app/code/local/Waterstone/winvoice/controllers/Adminhtml/WinvoiceController.php +335 -0
  49. app/code/local/Waterstone/winvoice/etc/adminhtml.xml +41 -0
  50. app/code/local/Waterstone/winvoice/etc/config.xml +138 -0
  51. app/code/local/Waterstone/winvoice/etc/system.xml +71 -0
  52. app/code/local/Waterstone/winvoice/sql/winvoice_setup/mysql4-install-0.1.0.php +58 -0
  53. 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 '&lt;'.
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('&', '&amp;', $val);
344
+ $val = str_replace("'", '&apos;', $val);
345
+ $val = str_replace('"', '&quot;', $val);
346
+ $val = str_replace('<', '&lt;', $val);
347
+ $val = str_replace('>', '&gt;', $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&apos;s details.</p>
849
+ <ul>';
850
+ foreach($this->getOperations() as $op => $data){
851
+ $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
852
+ // create hidden div
853
+ $b .= "<div id='$op' class='hidden'>
854
+ <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
855
+ foreach($data as $donnie => $marie){ // loop through opdata
856
+ if($donnie == 'input' || $donnie == 'output'){ // show input/output data
857
+ $b .= "<font color='white'>".ucfirst($donnie).':</font><br>';
858
+ foreach($marie as $captain => $tenille){ // loop through data
859
+ if($captain == 'parts'){ // loop thru parts
860
+ $b .= "&nbsp;&nbsp;$captain:<br>";
861
+ //if(is_array($tenille)){
862
+ foreach($tenille as $joanie => $chachi){
863
+ $b .= "&nbsp;&nbsp;&nbsp;&nbsp;$joanie: $chachi<br>";
864
+ }
865
+ //}
866
+ } else {
867
+ $b .= "&nbsp;&nbsp;$captain: $tenille<br>";
868
+ }
869
+ }
870
+ } else {
871
+ $b .= "<font color='white'>".ucfirst($donnie).":</font> $marie<br>";
872
+ }
873
+ }
874
+ $b .= '</div>';
875
+ }
876
+ $b .= '
877
+ <ul>
878
+ </div>
879
+ </div></body></html>';
880
+ return $b;
881
+ }
882
+
883
+ /**
884
+ * serialize the parsed wsdl
885
+ *
886
+ * @param mixed $debug whether to put debug=1 in endpoint URL
887
+ * @return string serialization of WSDL
888
+ * @access public
889
+ */
890
+ function serialize($debug = 0)
891
+ {
892
+ $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
893
+ $xml .= "\n<definitions";
894
+ foreach($this->namespaces as $k => $v) {
895
+ $xml .= " xmlns:$k=\"$v\"";
896
+ }
897
+ // 10.9.02 - add poulter fix for wsdl and tns declarations
898
+ if (isset($this->namespaces['wsdl'])) {
899
+ $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
900
+ }
901
+ if (isset($this->namespaces['tns'])) {
902
+ $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
903
+ }
904
+ $xml .= '>';
905
+ // imports
906
+ if (sizeof($this->import) > 0) {
907
+ foreach($this->import as $ns => $list) {
908
+ foreach ($list as $ii) {
909
+ if ($ii['location'] != '') {
910
+ $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
911
+ } else {
912
+ $xml .= '<import namespace="' . $ns . '" />';
913
+ }
914
+ }
915
+ }
916
+ }
917
+ // types
918
+ if (count($this->schemas)>=1) {
919
+ $xml .= "\n<types>\n";
920
+ foreach ($this->schemas as $ns => $list) {
921
+ foreach ($list as $xs) {
922
+ $xml .= $xs->serializeSchema();
923
+ }
924
+ }
925
+ $xml .= '</types>';
926
+ }
927
+ // messages
928
+ if (count($this->messages) >= 1) {
929
+ foreach($this->messages as $msgName => $msgParts) {
930
+ $xml .= "\n<message name=\"" . $msgName . '">';
931
+ if(is_array($msgParts)){
932
+ foreach($msgParts as $partName => $partType) {
933
+ // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
934
+ if (strpos($partType, ':')) {
935
+ $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
936
+ } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
937
+ // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
938
+ $typePrefix = 'xsd';
939
+ } else {
940
+ foreach($this->typemap as $ns => $types) {
941
+ if (isset($types[$partType])) {
942
+ $typePrefix = $this->getPrefixFromNamespace($ns);
943
+ }
944
+ }
945
+ if (!isset($typePrefix)) {
946
+ die("$partType has no namespace!");
947
+ }
948
+ }
949
+ $ns = $this->getNamespaceFromPrefix($typePrefix);
950
+ $localPart = $this->getLocalPart($partType);
951
+ $typeDef = $this->getTypeDef($localPart, $ns);
952
+ if ($typeDef['typeClass'] == 'element') {
953
+ $elementortype = 'element';
954
+ if (substr($localPart, -1) == '^') {
955
+ $localPart = substr($localPart, 0, -1);
956
+ }
957
+ } else {
958
+ $elementortype = 'type';
959
+ }
960
+ $xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
961
+ }
962
+ }
963
+ $xml .= '</message>';
964
+ }
965
+ }
966
+ // bindings & porttypes
967
+ if (count($this->bindings) >= 1) {
968
+ $binding_xml = '';
969
+ $portType_xml = '';
970
+ foreach($this->bindings as $bindingName => $attrs) {
971
+ $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
972
+ $binding_xml .= "\n" . ' <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
973
+ $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
974
+ foreach($attrs['operations'] as $opName => $opParts) {
975
+ $binding_xml .= "\n" . ' <operation name="' . $opName . '">';
976
+ $binding_xml .= "\n" . ' <soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $opParts['style'] . '"/>';
977
+ if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
978
+ $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
979
+ } else {
980
+ $enc_style = '';
981
+ }
982
+ $binding_xml .= "\n" . ' <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
983
+ if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
984
+ $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
985
+ } else {
986
+ $enc_style = '';
987
+ }
988
+ $binding_xml .= "\n" . ' <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
989
+ $binding_xml .= "\n" . ' </operation>';
990
+ $portType_xml .= "\n" . ' <operation name="' . $opParts['name'] . '"';
991
+ if (isset($opParts['parameterOrder'])) {
992
+ $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
993
+ }
994
+ $portType_xml .= '>';
995
+ if(isset($opParts['documentation']) && $opParts['documentation'] != '') {
996
+ $portType_xml .= "\n" . ' <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
997
+ }
998
+ $portType_xml .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>';
999
+ $portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>';
1000
+ $portType_xml .= "\n" . ' </operation>';
1001
+ }
1002
+ $portType_xml .= "\n" . '</portType>';
1003
+ $binding_xml .= "\n" . '</binding>';
1004
+ }
1005
+ $xml .= $portType_xml . $binding_xml;
1006
+ }
1007
+ // services
1008
+ $xml .= "\n<service name=\"" . $this->serviceName . '">';
1009
+ if (count($this->ports) >= 1) {
1010
+ foreach($this->ports as $pName => $attrs) {
1011
+ $xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
1012
+ $xml .= "\n" . ' <soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>';
1013
+ $xml .= "\n" . ' </port>';
1014
+ }
1015
+ }
1016
+ $xml .= "\n" . '</service>';
1017
+ return $xml . "\n</definitions>";
1018
+ }
1019
+
1020
+ /**
1021
+ * determine whether a set of parameters are unwrapped
1022
+ * when they are expect to be wrapped, Microsoft-style.
1023
+ *
1024
+ * @param string $type the type (element name) of the wrapper
1025
+ * @param array $parameters the parameter values for the SOAP call
1026
+ * @return boolean whether they parameters are unwrapped (and should be wrapped)
1027
+ * @access private
1028
+ */
1029
+ function parametersMatchWrapped($type, &$parameters) {
1030
+ $this->debug("in parametersMatchWrapped type=$type, parameters=");
1031
+ $this->appendDebug($this->varDump($parameters));
1032
+
1033
+ // split type into namespace:unqualified-type
1034
+ if (strpos($type, ':')) {
1035
+ $uqType = substr($type, strrpos($type, ':') + 1);
1036
+ $ns = substr($type, 0, strrpos($type, ':'));
1037
+ $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns");
1038
+ if ($this->getNamespaceFromPrefix($ns)) {
1039
+ $ns = $this->getNamespaceFromPrefix($ns);
1040
+ $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns");
1041
+ }
1042
+ } else {
1043
+ // TODO: should the type be compared to types in XSD, and the namespace
1044
+ // set to XSD if the type matches?
1045
+ $this->debug("in parametersMatchWrapped: No namespace for type $type");
1046
+ $ns = '';
1047
+ $uqType = $type;
1048
+ }
1049
+
1050
+ // get the type information
1051
+ if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
1052
+ $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type.");
1053
+ return false;
1054
+ }
1055
+ $this->debug("in parametersMatchWrapped: found typeDef=");
1056
+ $this->appendDebug($this->varDump($typeDef));
1057
+ if (substr($uqType, -1) == '^') {
1058
+ $uqType = substr($uqType, 0, -1);
1059
+ }
1060
+ $phpType = $typeDef['phpType'];
1061
+ $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '');
1062
+ $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType");
1063
+
1064
+ // we expect a complexType or element of complexType
1065
+ if ($phpType != 'struct') {
1066
+ $this->debug("in parametersMatchWrapped: not a struct");
1067
+ return false;
1068
+ }
1069
+
1070
+ // see whether the parameter names match the elements
1071
+ if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
1072
+ $elements = 0;
1073
+ $matches = 0;
1074
+ 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 '&lt;'.
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('&', '&amp;', $val);
344
+ $val = str_replace("'", '&apos;', $val);
345
+ $val = str_replace('"', '&quot;', $val);
346
+ $val = str_replace('<', '&lt;', $val);
347
+ $val = str_replace('>', '&gt;', $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&apos;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 .= "&nbsp;&nbsp;$captain:<br>";
5443
+ //if(is_array($tenille)){
5444
+ foreach($tenille as $joanie => $chachi){
5445
+ $b .= "&nbsp;&nbsp;&nbsp;&nbsp;$joanie: $chachi<br>";
5446
+ }
5447
+ //}
5448
+ } else {
5449
+ $b .= "&nbsp;&nbsp;$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="&#160;Execute&#160;">';
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 uri="http://opensource.org/licenses/osl-3.0.php">Open Software License (OSL)</license>
7
  <channel>community</channel>
8
  <extends/>
9
- <summary>Automatically generates and sends Portuguese certified invoices for your Magento store clients.</summary>
10
- <description>&lt;p&gt;Get certified invoices in your Magento store (Portuguese legal requirements only).&lt;/p&gt;&#xD;
11
- &lt;p&gt;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.&lt;/p&gt;&#xD;
12
- &#xD;
13
- &lt;h3&gt;Product Requirements&lt;/h3&gt;&#xD;
14
- &#xD;
15
- &lt;p&gt;For this to work you need to subscribe for a license in &lt;a href="http://www.waterstone.pt/facturacao-certificada-magento/"&gt;Waterstone&lt;/a&gt;.&lt;/p&gt;&#xD;
16
- &#xD;
17
- &lt;h3&gt;Configuration&lt;/h3&gt;&#xD;
18
- &#xD;
19
- &lt;p&gt;To configure the extension, navigate on the top main menu &lt;strong&gt;System -&gt; Configuration&lt;/strong&gt;. On the side menu click on &lt;strong&gt;General - &gt; Winvoice&lt;/strong&gt;. The configuration page has three fields (check the first screenshot):&#xD;
20
- &lt;ul&gt;&#xD;
21
- &lt;li&gt;API weoInvoice&lt;/li&gt;&#xD;
22
- &lt;li&gt;Password weoInvoice&lt;/li&gt;&#xD;
23
- &lt;li&gt;Imposto a aplicar ao envio&lt;/li&gt;&#xD;
24
- &lt;/ul&gt;&#xD;
25
- &lt;/p&gt;&#xD;
26
- &#xD;
27
- &lt;p&gt;On the "API weoInvoice" field insert the API hyperlink supplied with our license. &#xD;
28
- On "Password weoInvoice" insert the API password supplied with our license. &#xD;
29
- On "Imposto a aplicar ao envio" insert a tax value in percentage, if you desire to include an tax associated with product shipment.&lt;/p&gt;&#xD;
30
- &#xD;
31
- &lt;p&gt;All products should have an associated tax class compatible with the &lt;a href="http://info.portaldasfinancas.gov.pt/pt/informacao_fiscal/codigos_tributarios/civa_rep/index_iva.htm"&gt;Portuguese IVA&lt;/a&gt; taxes (eg. 23%).&lt;/p&gt;&#xD;
32
- &#xD;
33
- &lt;p&gt;If you want to test the extension first, please use the following account data:&#xD;
34
- &lt;ul&gt;&#xD;
35
- &lt;li&gt;API: &lt;strong&gt;http://www.weoinvoice.com/webservice/304e76cb321c57672915bf2b7be5b9d5e905dfc9/webservice.php&lt;/strong&gt;&lt;/li&gt;&#xD;
36
- &lt;li&gt;Password: &lt;strong&gt;=$Z%5XJq&lt;/strong&gt;&lt;/li&gt;&#xD;
37
- &lt;/ul&gt;&#xD;
38
- The email associated with this account is &lt;strong&gt;info@waterstone.pt&lt;/strong&gt;. To access the demo panel and check your invoice, go to &lt;strong&gt;www.weoinvoice.com&lt;/strong&gt; and log in with the demo account.&#xD;
39
- &lt;/p&gt;&#xD;
40
- &#xD;
41
- &lt;hr&gt;&#xD;
42
- &#xD;
43
- &lt;h2&gt;Winvoice&lt;/h2&gt;&#xD;
44
- &#xD;
45
- &lt;p&gt;Obtenha facturas certificadas na sua loja Magento (apenas requisitos legais Portugueses).&lt;/p&gt;&#xD;
46
- &lt;p&gt;Ao gerar uma factura na sua conta Magento, a extens&#xE3;o Winvoice gera uma fatura certificada em simult&#xE2;neo atrav&#xE9;s de um servi&#xE7;o externo (weoInvoice), sendo esta posteriormente enviada para si em formato PDF, anexado ao email da factura Magento.&lt;/p&gt;&#xD;
47
- &#xD;
48
- &lt;h3&gt;Requisitos&lt;/h3&gt;&#xD;
49
- &#xD;
50
- &lt;p&gt;Para que esta extens&#xE3;o funcione dever&#xE1; subscrever uma licen&#xE7;a com a &lt;a href="http://www.waterstone.pt/facturacao-certificada-magento/"&gt;Waterstone&lt;/a&gt;.&lt;/p&gt;&#xD;
51
- &#xD;
52
- &lt;h3&gt;Configura&#xE7;&#xE3;o&lt;/h3&gt;&#xD;
53
- &#xD;
54
- &lt;p&gt;Para configurar a extens&#xE3;o aceda ao menu principal &lt;strong&gt;System -&gt; Configuration&lt;/strong&gt;. No menu lateral, deve aceder &#xE0; sec&#xE7;&#xE3;o &lt;strong&gt;General -&gt; Winvoice&lt;/strong&gt;. A p&#xE1;gina de configura&#xE7;&#xE3;o da extens&#xE3;o cont&#xE9;m tr&#xEA;s campos (ver o primeiro screenshot):&#xD;
55
- &lt;ul&gt;&#xD;
56
- &lt;li&gt;API weoInvoice&lt;/li&gt;&#xD;
57
- &lt;li&gt;Password weoInvoice&lt;/li&gt;&#xD;
58
- &lt;li&gt;Imposto a aplicar ao envio&lt;/li&gt;&#xD;
59
- &lt;/ul&gt;&#xD;
60
- &lt;/p&gt;&#xD;
61
- &#xD;
62
- &lt;p&gt;No campo "API weoInvoice" dever&#xE1; colocar a hiperliga&#xE7;&#xE3;o fornecida na nossa licen&#xE7;a. &#xD;
63
- Em "Password weoInvoice" dever&#xE1; colocar a palavra-chave fornecida na nossa licen&#xE7;a.&#xD;
64
- Em "Imposto a aplicar ao envio" deve inserir um valor em percentagem, se desejar incluir uma taxa associada ao envio de produtos.&lt;/p&gt;&#xD;
65
- &#xD;
66
- &lt;p&gt;Todos os produtos devem ter uma classe de imposto associada compat&#xED;vel com as taxas de &lt;a href="http://info.portaldasfinancas.gov.pt/pt/informacao_fiscal/codigos_tributarios/civa_rep/index_iva.htm"&gt;IVA Portugu&#xEA;s&lt;/a&gt; (ex. 23%).&lt;/p&gt;&#xD;
67
- &#xD;
68
- &lt;p&gt;Para efeitos de teste pode usar a seguinte conta:&#xD;
69
- &lt;ul&gt;&#xD;
70
- &lt;li&gt;API: &lt;strong&gt;http://www.weoinvoice.com/webservice/304e76cb321c57672915bf2b7be5b9d5e905dfc9/webservice.php&lt;/strong&gt;&lt;/li&gt;&#xD;
71
- &lt;li&gt;Password: &lt;strong&gt;=$Z%5XJq&lt;/strong&gt;&lt;/li&gt;&#xD;
72
- &lt;/ul&gt;&#xD;
73
- A conta de email associada &#xE0; conta de demonstra&#xE7;&#xE3;o &#xE9; &lt;strong&gt;info@waterstone.pt&lt;/strong&gt;. Para aceder ao painel de demonstra&#xE7;&#xE3;o e verificar a sua factura, aceda a &lt;strong&gt;www.weoinvoice.com&lt;/strong&gt; e fa&#xE7;a login com a conta demo.&#xD;
74
- &lt;/p&gt;</description>
75
  <notes>.</notes>
76
- <authors><author><name>Waterstone Consulting</name><user>waterstone</user><email>info@waterstone.pt</email></author></authors>
77
- <date>2014-04-21</date>
78
- <time>16:45:58</time>
79
- <contents><target name="magelocal"><dir name="Waterstone"><dir name="Winvoice"><dir name="Helper"><file name="Data.php" hash="793437e2a036dae3ab1097f5de91d27d"/></dir><dir name="Model"><file name="AddClient.php" hash="65285989fb817ff498aec5487803345c"/><file name="AddInvoice.php" hash="e30543520e72ff4d100d24812074f23b"/><dir name="Email"><dir name="Template"><file name="Mailer.php" hash="d990fe62b70529b6fcdb2c3e72cb0480"/></dir></dir><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"/><file name="Winvoice.php" hash="d5a6fdb503721f7a27e12d310a1933cd"/><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><file name="IndexController.php" hash="ff30218eeb3beeff7b9216c31c579336"/></dir><dir name="etc"><file name="adminhtml.xml" hash="28cda20f40db5efb00659ae4bd83f19e"/><file name="config.xml" hash="4788829c77abd244f6ab2c8a7a0ea2b3"/><file name="system.xml" hash="31538e5eb3e9d48bc708d22a60998838"/></dir><file name="manual_magento_winvoice.pdf" hash="2eb912a823c32fec977eb1a5d2ae1b13"/><dir name="sql"><dir name="winvoice_setup"><file name="mysql4-install-0.1.0.php" hash="92b059cb47ed001e285ff7b11e7311bd"/></dir></dir></dir></dir></target></contents>
80
  <compatible/>
81
- <dependencies><required><php><min>5.4.12</min><max>5.5.11</max></php><package><name>Mage_Core_Modules</name><channel>community</channel><min>1.5.0.0</min><max>1.8.1.0</max></package></required></dependencies>
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>