1 | <?php |
---|
2 | /** |
---|
3 | * This file contains the code for a HTTP transport layer. |
---|
4 | * |
---|
5 | * PHP versions 4 and 5 |
---|
6 | * |
---|
7 | * LICENSE: This source file is subject to version 2.02 of the PHP license, |
---|
8 | * that is bundled with this package in the file LICENSE, and is available at |
---|
9 | * through the world-wide-web at http://www.php.net/license/2_02.txt. If you |
---|
10 | * did not receive a copy of the PHP license and are unable to obtain it |
---|
11 | * through the world-wide-web, please send a note to license@php.net so we can |
---|
12 | * mail you a copy immediately. |
---|
13 | * |
---|
14 | * @category Web Services |
---|
15 | * @package SOAP |
---|
16 | * @author Shane Caraveo <Shane@Caraveo.com> |
---|
17 | * @author Jan Schneider <jan@horde.org> |
---|
18 | * @copyright 2003-2006 The PHP Group |
---|
19 | * @license http://www.php.net/license/2_02.txt PHP License 2.02 |
---|
20 | * @link http://pear.php.net/package/SOAP |
---|
21 | */ |
---|
22 | |
---|
23 | /** |
---|
24 | * HTTP Transport class |
---|
25 | * |
---|
26 | * @package SOAP |
---|
27 | * @category Web Services |
---|
28 | */ |
---|
29 | |
---|
30 | /** |
---|
31 | * Needed Classes |
---|
32 | */ |
---|
33 | require_once 'SOAP/Transport.php'; |
---|
34 | |
---|
35 | /** |
---|
36 | * HTTP Transport for SOAP |
---|
37 | * |
---|
38 | * @access public |
---|
39 | * @package SOAP |
---|
40 | * @author Shane Caraveo <shane@php.net> |
---|
41 | * @author Jan Schneider <jan@horde.org> |
---|
42 | */ |
---|
43 | class SOAP_Transport_HTTP extends SOAP_Transport |
---|
44 | { |
---|
45 | /** |
---|
46 | * Basic Auth string. |
---|
47 | * |
---|
48 | * @var array |
---|
49 | */ |
---|
50 | var $headers = array(); |
---|
51 | |
---|
52 | /** |
---|
53 | * Cookies. |
---|
54 | * |
---|
55 | * @var array |
---|
56 | */ |
---|
57 | var $cookies; |
---|
58 | |
---|
59 | /** |
---|
60 | * Connection timeout in seconds. 0 = none. |
---|
61 | * |
---|
62 | * @var integer |
---|
63 | */ |
---|
64 | var $timeout = 4; |
---|
65 | |
---|
66 | /** |
---|
67 | * HTTP-Response Content-Type. |
---|
68 | */ |
---|
69 | var $result_content_type; |
---|
70 | |
---|
71 | var $result_headers = array(); |
---|
72 | |
---|
73 | var $result_cookies = array(); |
---|
74 | |
---|
75 | /** |
---|
76 | * SOAP_Transport_HTTP Constructor |
---|
77 | * |
---|
78 | * @access public |
---|
79 | * |
---|
80 | * @param string $url HTTP url to SOAP endpoint. |
---|
81 | * @param string $encoding Encoding to use. |
---|
82 | */ |
---|
83 | function SOAP_Transport_HTTP($url, $encoding = SOAP_DEFAULT_ENCODING) |
---|
84 | { |
---|
85 | parent::SOAP_Base('HTTP'); |
---|
86 | $this->urlparts = @parse_url($url); |
---|
87 | $this->url = $url; |
---|
88 | $this->encoding = $encoding; |
---|
89 | } |
---|
90 | |
---|
91 | /** |
---|
92 | * Sends and receives SOAP data. |
---|
93 | * |
---|
94 | * @access public |
---|
95 | * |
---|
96 | * @param string Outgoing SOAP data. |
---|
97 | * @param array Options. |
---|
98 | * |
---|
99 | * @return string|SOAP_Fault |
---|
100 | */ |
---|
101 | function send($msg, $options = array()) |
---|
102 | { |
---|
103 | $this->fault = null; |
---|
104 | |
---|
105 | if (!$this->_validateUrl()) { |
---|
106 | return $this->fault; |
---|
107 | } |
---|
108 | |
---|
109 | if (isset($options['timeout'])) { |
---|
110 | $this->timeout = (int)$options['timeout']; |
---|
111 | } |
---|
112 | |
---|
113 | if (strcasecmp($this->urlparts['scheme'], 'HTTP') == 0) { |
---|
114 | return $this->_sendHTTP($msg, $options); |
---|
115 | } elseif (strcasecmp($this->urlparts['scheme'], 'HTTPS') == 0) { |
---|
116 | return $this->_sendHTTPS($msg, $options); |
---|
117 | } |
---|
118 | |
---|
119 | return $this->_raiseSoapFault('Invalid url scheme ' . $this->url); |
---|
120 | } |
---|
121 | |
---|
122 | /** |
---|
123 | * Sets data for HTTP authentication, creates authorization header. |
---|
124 | * |
---|
125 | * @param string $username Username. |
---|
126 | * @param string $password Response data, minus HTTP headers. |
---|
127 | * |
---|
128 | * @access public |
---|
129 | */ |
---|
130 | function setCredentials($username, $password) |
---|
131 | { |
---|
132 | $this->headers['Authorization'] = 'Basic ' . base64_encode($username . ':' . $password); |
---|
133 | } |
---|
134 | |
---|
135 | /** |
---|
136 | * Adds a cookie. |
---|
137 | * |
---|
138 | * @access public |
---|
139 | * @param string $name Cookie name. |
---|
140 | * @param mixed $value Cookie value. |
---|
141 | */ |
---|
142 | function addCookie($name, $value) |
---|
143 | { |
---|
144 | $this->cookies[$name] = $value; |
---|
145 | } |
---|
146 | |
---|
147 | /** |
---|
148 | * Generates the correct headers for the cookies. |
---|
149 | * |
---|
150 | * @access private |
---|
151 | * |
---|
152 | * @param array $options Cookie options. If 'nocookies' is set and true |
---|
153 | * the cookies from the last response are added |
---|
154 | * automatically. 'cookies' is name-value-hash with |
---|
155 | * a list of cookies to add. |
---|
156 | * |
---|
157 | * @return string The cookie header value. |
---|
158 | */ |
---|
159 | function _generateCookieHeader($options) |
---|
160 | { |
---|
161 | $this->cookies = array(); |
---|
162 | |
---|
163 | if (empty($options['nocookies']) && |
---|
164 | isset($this->result_cookies)) { |
---|
165 | // Add the cookies we got from the last request. |
---|
166 | foreach ($this->result_cookies as $cookie) { |
---|
167 | if ($cookie['domain'] == $this->urlparts['host']) { |
---|
168 | $this->cookies[$cookie['name']] = $cookie['value']; |
---|
169 | } |
---|
170 | } |
---|
171 | } |
---|
172 | |
---|
173 | // Add cookies the user wants to set. |
---|
174 | if (isset($options['cookies'])) { |
---|
175 | foreach ($options['cookies'] as $cookie) { |
---|
176 | if ($cookie['domain'] == $this->urlparts['host']) { |
---|
177 | $this->cookies[$cookie['name']] = $cookie['value']; |
---|
178 | } |
---|
179 | } |
---|
180 | } |
---|
181 | |
---|
182 | $cookies = ''; |
---|
183 | foreach ($this->cookies as $name => $value) { |
---|
184 | if (!empty($cookies)) { |
---|
185 | $cookies .= '; '; |
---|
186 | } |
---|
187 | $cookies .= urlencode($name) . '=' . urlencode($value); |
---|
188 | } |
---|
189 | |
---|
190 | return $cookies; |
---|
191 | } |
---|
192 | |
---|
193 | /** |
---|
194 | * Validate url data passed to constructor. |
---|
195 | * |
---|
196 | * @access private |
---|
197 | * @return boolean |
---|
198 | */ |
---|
199 | function _validateUrl() |
---|
200 | { |
---|
201 | if (!is_array($this->urlparts) ) { |
---|
202 | $this->_raiseSoapFault('Unable to parse URL ' . $this->url); |
---|
203 | return false; |
---|
204 | } |
---|
205 | if (!isset($this->urlparts['host'])) { |
---|
206 | $this->_raiseSoapFault('No host in URL ' . $this->url); |
---|
207 | return false; |
---|
208 | } |
---|
209 | if (!isset($this->urlparts['port'])) { |
---|
210 | if (strcasecmp($this->urlparts['scheme'], 'HTTP') == 0) { |
---|
211 | $this->urlparts['port'] = 80; |
---|
212 | } elseif (strcasecmp($this->urlparts['scheme'], 'HTTPS') == 0) { |
---|
213 | $this->urlparts['port'] = 443; |
---|
214 | } |
---|
215 | |
---|
216 | } |
---|
217 | if (isset($this->urlparts['user'])) { |
---|
218 | $this->setCredentials(urldecode($this->urlparts['user']), |
---|
219 | urldecode($this->urlparts['pass'])); |
---|
220 | } |
---|
221 | if (!isset($this->urlparts['path']) || !$this->urlparts['path']) { |
---|
222 | $this->urlparts['path'] = '/'; |
---|
223 | } |
---|
224 | |
---|
225 | return true; |
---|
226 | } |
---|
227 | |
---|
228 | /** |
---|
229 | * Finds out what the encoding is. |
---|
230 | * Sets the object property accordingly. |
---|
231 | * |
---|
232 | * @access private |
---|
233 | * @param array $headers Headers. |
---|
234 | */ |
---|
235 | function _parseEncoding($headers) |
---|
236 | { |
---|
237 | $h = stristr($headers, 'Content-Type'); |
---|
238 | preg_match_all('/^Content-Type:\s*(.*)$/im', $h, $ct, PREG_SET_ORDER); |
---|
239 | $n = count($ct); |
---|
240 | $ct = $ct[$n - 1]; |
---|
241 | |
---|
242 | // Strip the string of \r. |
---|
243 | $this->result_content_type = str_replace("\r", '', $ct[1]); |
---|
244 | |
---|
245 | if (preg_match('/(.*?)(?:;\s?charset=)(.*)/i', |
---|
246 | $this->result_content_type, |
---|
247 | $m)) { |
---|
248 | $this->result_content_type = $m[1]; |
---|
249 | if (count($m) > 2) { |
---|
250 | $enc = strtoupper(str_replace('"', '', $m[2])); |
---|
251 | if (in_array($enc, $this->_encodings)) { |
---|
252 | $this->result_encoding = $enc; |
---|
253 | } |
---|
254 | } |
---|
255 | } |
---|
256 | |
---|
257 | // Deal with broken servers that don't set content type on faults. |
---|
258 | if (!$this->result_content_type) { |
---|
259 | $this->result_content_type = 'text/xml'; |
---|
260 | } |
---|
261 | } |
---|
262 | |
---|
263 | /** |
---|
264 | * Parses the headers. |
---|
265 | * |
---|
266 | * @param array $headers The headers. |
---|
267 | */ |
---|
268 | function _parseHeaders($headers) |
---|
269 | { |
---|
270 | /* Largely borrowed from HTTP_Request. */ |
---|
271 | $this->result_headers = array(); |
---|
272 | $headers = split("\r?\n", $headers); |
---|
273 | foreach ($headers as $value) { |
---|
274 | if (strpos($value,':') === false) { |
---|
275 | $this->result_headers[0] = $value; |
---|
276 | continue; |
---|
277 | } |
---|
278 | list($name, $value) = split(':', $value); |
---|
279 | $headername = strtolower($name); |
---|
280 | $headervalue = trim($value); |
---|
281 | $this->result_headers[$headername] = $headervalue; |
---|
282 | |
---|
283 | if ($headername == 'set-cookie') { |
---|
284 | // Parse a SetCookie header to fill _cookies array. |
---|
285 | $cookie = array('expires' => null, |
---|
286 | 'domain' => $this->urlparts['host'], |
---|
287 | 'path' => null, |
---|
288 | 'secure' => false); |
---|
289 | |
---|
290 | if (!strpos($headervalue, ';')) { |
---|
291 | // Only a name=value pair. |
---|
292 | list($cookie['name'], $cookie['value']) = array_map('trim', explode('=', $headervalue)); |
---|
293 | $cookie['name'] = urldecode($cookie['name']); |
---|
294 | $cookie['value'] = urldecode($cookie['value']); |
---|
295 | |
---|
296 | } else { |
---|
297 | // Some optional parameters are supplied. |
---|
298 | $elements = explode(';', $headervalue); |
---|
299 | list($cookie['name'], $cookie['value']) = array_map('trim', explode('=', $elements[0])); |
---|
300 | $cookie['name'] = urldecode($cookie['name']); |
---|
301 | $cookie['value'] = urldecode($cookie['value']); |
---|
302 | |
---|
303 | for ($i = 1; $i < count($elements);$i++) { |
---|
304 | list($elName, $elValue) = array_map('trim', explode('=', $elements[$i])); |
---|
305 | if ('secure' == $elName) { |
---|
306 | $cookie['secure'] = true; |
---|
307 | } elseif ('expires' == $elName) { |
---|
308 | $cookie['expires'] = str_replace('"', '', $elValue); |
---|
309 | } elseif ('path' == $elName OR 'domain' == $elName) { |
---|
310 | $cookie[$elName] = urldecode($elValue); |
---|
311 | } else { |
---|
312 | $cookie[$elName] = $elValue; |
---|
313 | } |
---|
314 | } |
---|
315 | } |
---|
316 | $this->result_cookies[] = $cookie; |
---|
317 | } |
---|
318 | } |
---|
319 | } |
---|
320 | |
---|
321 | /** |
---|
322 | * Removes HTTP headers from response. |
---|
323 | * |
---|
324 | * @return boolean |
---|
325 | * @access private |
---|
326 | */ |
---|
327 | function _parseResponse() |
---|
328 | { |
---|
329 | if (!preg_match("/^(.*?)\r?\n\r?\n(.*)/s", |
---|
330 | $this->incoming_payload, |
---|
331 | $match)) { |
---|
332 | $this->_raiseSoapFault('Invalid HTTP Response'); |
---|
333 | return false; |
---|
334 | } |
---|
335 | |
---|
336 | $this->response = $match[2]; |
---|
337 | // Find the response error, some servers response with 500 for |
---|
338 | // SOAP faults. |
---|
339 | $this->_parseHeaders($match[1]); |
---|
340 | |
---|
341 | list(, $code, $msg) = sscanf($this->result_headers[0], '%s %s %s'); |
---|
342 | unset($this->result_headers[0]); |
---|
343 | |
---|
344 | switch($code) { |
---|
345 | case 100: // Continue |
---|
346 | $this->incoming_payload = $match[2]; |
---|
347 | return $this->_parseResponse(); |
---|
348 | case 200: |
---|
349 | case 202: |
---|
350 | $this->incoming_payload = trim($match[2]); |
---|
351 | if (!strlen($this->incoming_payload)) { |
---|
352 | /* Valid one-way message response. */ |
---|
353 | return true; |
---|
354 | } |
---|
355 | break; |
---|
356 | case 400: |
---|
357 | $this->_raiseSoapFault("HTTP Response $code Bad Request"); |
---|
358 | return false; |
---|
359 | case 401: |
---|
360 | $this->_raiseSoapFault("HTTP Response $code Authentication Failed"); |
---|
361 | return false; |
---|
362 | case 403: |
---|
363 | $this->_raiseSoapFault("HTTP Response $code Forbidden"); |
---|
364 | return false; |
---|
365 | case 404: |
---|
366 | $this->_raiseSoapFault("HTTP Response $code Not Found"); |
---|
367 | return false; |
---|
368 | case 407: |
---|
369 | $this->_raiseSoapFault("HTTP Response $code Proxy Authentication Required"); |
---|
370 | return false; |
---|
371 | case 408: |
---|
372 | $this->_raiseSoapFault("HTTP Response $code Request Timeout"); |
---|
373 | return false; |
---|
374 | case 410: |
---|
375 | $this->_raiseSoapFault("HTTP Response $code Gone"); |
---|
376 | return false; |
---|
377 | default: |
---|
378 | if ($code >= 400 && $code < 500) { |
---|
379 | $this->_raiseSoapFault("HTTP Response $code Not Found, Server message: $msg"); |
---|
380 | return false; |
---|
381 | } |
---|
382 | break; |
---|
383 | } |
---|
384 | |
---|
385 | $this->_parseEncoding($match[1]); |
---|
386 | |
---|
387 | if ($this->result_content_type == 'application/dime') { |
---|
388 | // XXX quick hack insertion of DIME |
---|
389 | if (PEAR::isError($this->_decodeDIMEMessage($this->response, $this->headers, $this->attachments))) { |
---|
390 | // _decodeDIMEMessage already raised $this->fault |
---|
391 | return false; |
---|
392 | } |
---|
393 | $this->result_content_type = $this->headers['content-type']; |
---|
394 | } elseif (stristr($this->result_content_type, 'multipart/related')) { |
---|
395 | $this->response = $this->incoming_payload; |
---|
396 | if (PEAR::isError($this->_decodeMimeMessage($this->response, $this->headers, $this->attachments))) { |
---|
397 | // _decodeMimeMessage already raised $this->fault |
---|
398 | return false; |
---|
399 | } |
---|
400 | } elseif ($this->result_content_type != 'text/xml') { |
---|
401 | $this->_raiseSoapFault($this->response); |
---|
402 | return false; |
---|
403 | } |
---|
404 | |
---|
405 | // if no content, return false |
---|
406 | return strlen($this->response) > 0; |
---|
407 | } |
---|
408 | |
---|
409 | /** |
---|
410 | * Creates an HTTP request, including headers, for the outgoing request. |
---|
411 | * |
---|
412 | * @access private |
---|
413 | * |
---|
414 | * @param string $msg Outgoing SOAP package. |
---|
415 | * @param array $options Options. |
---|
416 | * |
---|
417 | * @return string Outgoing payload. |
---|
418 | */ |
---|
419 | function _getRequest($msg, $options) |
---|
420 | { |
---|
421 | $this->headers = array(); |
---|
422 | |
---|
423 | $action = isset($options['soapaction']) ? $options['soapaction'] : ''; |
---|
424 | $fullpath = $this->urlparts['path']; |
---|
425 | if (isset($this->urlparts['query'])) { |
---|
426 | $fullpath .= '?' . $this->urlparts['query']; |
---|
427 | } |
---|
428 | if (isset($this->urlparts['fragment'])) { |
---|
429 | $fullpath .= '#' . $this->urlparts['fragment']; |
---|
430 | } |
---|
431 | |
---|
432 | if (isset($options['proxy_host'])) { |
---|
433 | $fullpath = 'http://' . $this->urlparts['host'] . ':' . |
---|
434 | $this->urlparts['port'] . $fullpath; |
---|
435 | } |
---|
436 | |
---|
437 | if (isset($options['proxy_user'])) { |
---|
438 | $this->headers['Proxy-Authorization'] = 'Basic ' . |
---|
439 | base64_encode($options['proxy_user'] . ':' . |
---|
440 | $options['proxy_pass']); |
---|
441 | } |
---|
442 | |
---|
443 | if (isset($options['user'])) { |
---|
444 | $this->setCredentials($options['user'], $options['pass']); |
---|
445 | } |
---|
446 | |
---|
447 | $this->headers['User-Agent'] = $this->_userAgent; |
---|
448 | $this->headers['Host'] = $this->urlparts['host']; |
---|
449 | $this->headers['Content-Type'] = "text/xml; charset=$this->encoding"; |
---|
450 | $this->headers['Content-Length'] = strlen($msg); |
---|
451 | $this->headers['SOAPAction'] = '"' . $action . '"'; |
---|
452 | $this->headers['Connection'] = 'close'; |
---|
453 | |
---|
454 | if (isset($options['headers'])) { |
---|
455 | $this->headers = array_merge($this->headers, $options['headers']); |
---|
456 | } |
---|
457 | |
---|
458 | $cookies = $this->_generateCookieHeader($options); |
---|
459 | if ($cookies) { |
---|
460 | $this->headers['Cookie'] = $cookies; |
---|
461 | } |
---|
462 | |
---|
463 | $headers = ''; |
---|
464 | foreach ($this->headers as $k => $v) { |
---|
465 | $headers .= "$k: $v\r\n"; |
---|
466 | } |
---|
467 | $this->outgoing_payload = "POST $fullpath HTTP/1.0\r\n" . $headers . |
---|
468 | "\r\n" . $msg; |
---|
469 | |
---|
470 | return $this->outgoing_payload; |
---|
471 | } |
---|
472 | |
---|
473 | /** |
---|
474 | * Sends the outgoing HTTP request and reads and parses the response. |
---|
475 | * |
---|
476 | * @access private |
---|
477 | * |
---|
478 | * @param string $msg Outgoing SOAP package. |
---|
479 | * @param array $options Options. |
---|
480 | * |
---|
481 | * @return string Response data without HTTP headers. |
---|
482 | */ |
---|
483 | function _sendHTTP($msg, $options) |
---|
484 | { |
---|
485 | $this->incoming_payload = ''; |
---|
486 | $this->_getRequest($msg, $options); |
---|
487 | $host = $this->urlparts['host']; |
---|
488 | $port = $this->urlparts['port']; |
---|
489 | if (isset($options['proxy_host'])) { |
---|
490 | $host = $options['proxy_host']; |
---|
491 | $port = isset($options['proxy_port']) ? $options['proxy_port'] : 8080; |
---|
492 | } |
---|
493 | // Send. |
---|
494 | if ($this->timeout > 0) { |
---|
495 | $fp = @fsockopen($host, $port, $this->errno, $this->errmsg, $this->timeout); |
---|
496 | } else { |
---|
497 | $fp = @fsockopen($host, $port, $this->errno, $this->errmsg); |
---|
498 | } |
---|
499 | if (!$fp) { |
---|
500 | return $this->_raiseSoapFault("Connect Error to $host:$port"); |
---|
501 | } |
---|
502 | if ($this->timeout > 0) { |
---|
503 | // some builds of PHP do not support this, silence the warning |
---|
504 | @socket_set_timeout($fp, $this->timeout); |
---|
505 | } |
---|
506 | if (!fputs($fp, $this->outgoing_payload, strlen($this->outgoing_payload))) { |
---|
507 | return $this->_raiseSoapFault("Error POSTing Data to $host"); |
---|
508 | } |
---|
509 | |
---|
510 | // get reponse |
---|
511 | // XXX time consumer |
---|
512 | do { |
---|
513 | $data = fread($fp, 4096); |
---|
514 | $_tmp_status = socket_get_status($fp); |
---|
515 | if ($_tmp_status['timed_out']) { |
---|
516 | return $this->_raiseSoapFault("Timed out read from $host"); |
---|
517 | } else { |
---|
518 | $this->incoming_payload .= $data; |
---|
519 | } |
---|
520 | } while (!$_tmp_status['eof']); |
---|
521 | |
---|
522 | fclose($fp); |
---|
523 | |
---|
524 | if (!$this->_parseResponse()) { |
---|
525 | return $this->fault; |
---|
526 | } |
---|
527 | return $this->response; |
---|
528 | } |
---|
529 | |
---|
530 | /** |
---|
531 | * Sends the outgoing HTTPS request and reads and parses the response. |
---|
532 | * |
---|
533 | * @access private |
---|
534 | * |
---|
535 | * @param string $msg Outgoing SOAP package. |
---|
536 | * @param array $options Options. |
---|
537 | * |
---|
538 | * @return string Response data without HTTP headers. |
---|
539 | */ |
---|
540 | function _sendHTTPS($msg, $options) |
---|
541 | { |
---|
542 | /* Check if the required curl extension is installed. */ |
---|
543 | if (!extension_loaded('curl')) { |
---|
544 | return $this->_raiseSoapFault('CURL Extension is required for HTTPS'); |
---|
545 | } |
---|
546 | |
---|
547 | $ch = curl_init(); |
---|
548 | |
---|
549 | if (isset($options['proxy_host'])) { |
---|
550 | $port = isset($options['proxy_port']) ? $options['proxy_port'] : 8080; |
---|
551 | curl_setopt($ch, CURLOPT_PROXY, |
---|
552 | $options['proxy_host'] . ':' . $port); |
---|
553 | } |
---|
554 | if (isset($options['proxy_user'])) { |
---|
555 | curl_setopt($ch, CURLOPT_PROXYUSERPWD, |
---|
556 | $options['proxy_user'] . ':' . $options['proxy_pass']); |
---|
557 | } |
---|
558 | |
---|
559 | if (isset($options['user'])) { |
---|
560 | curl_setopt($ch, CURLOPT_USERPWD, |
---|
561 | $options['user'] . ':' . $options['pass']); |
---|
562 | } |
---|
563 | |
---|
564 | $headers = array(); |
---|
565 | $action = isset($options['soapaction']) ? $options['soapaction'] : ''; |
---|
566 | $headers['Content-Type'] = "text/xml; charset=$this->encoding"; |
---|
567 | $headers['SOAPAction'] = '"' . $action . '"'; |
---|
568 | if (isset($options['headers'])) { |
---|
569 | $headers = array_merge($headers, $options['headers']); |
---|
570 | } |
---|
571 | foreach ($headers as $header => $value) { |
---|
572 | $headers[$header] = $header . ': ' . $value; |
---|
573 | } |
---|
574 | curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); |
---|
575 | curl_setopt($ch, CURLOPT_USERAGENT, $this->_userAgent); |
---|
576 | |
---|
577 | if ($this->timeout) { |
---|
578 | curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout); |
---|
579 | } |
---|
580 | |
---|
581 | curl_setopt($ch, CURLOPT_POSTFIELDS, $msg); |
---|
582 | curl_setopt($ch, CURLOPT_URL, $this->url); |
---|
583 | curl_setopt($ch, CURLOPT_POST, 1); |
---|
584 | curl_setopt($ch, CURLOPT_FAILONERROR, 0); |
---|
585 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); |
---|
586 | curl_setopt($ch, CURLOPT_HEADER, 1); |
---|
587 | if (defined('CURLOPT_HTTP_VERSION')) { |
---|
588 | curl_setopt($ch, CURLOPT_HTTP_VERSION, 1); |
---|
589 | } |
---|
590 | if (!ini_get('safe_mode') && !ini_get('open_basedir')) { |
---|
591 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); |
---|
592 | } |
---|
593 | $cookies = $this->_generateCookieHeader($options); |
---|
594 | if ($cookies) { |
---|
595 | curl_setopt($ch, CURLOPT_COOKIE, $cookies); |
---|
596 | } |
---|
597 | |
---|
598 | if (isset($options['curl'])) { |
---|
599 | foreach ($options['curl'] as $key => $val) { |
---|
600 | curl_setopt($ch, $key, $val); |
---|
601 | } |
---|
602 | } |
---|
603 | |
---|
604 | // Save the outgoing XML. This doesn't quite match _sendHTTP as CURL |
---|
605 | // generates the headers, but having the XML is usually the most |
---|
606 | // important part for tracing/debugging. |
---|
607 | $this->outgoing_payload = $msg; |
---|
608 | |
---|
609 | $this->incoming_payload = curl_exec($ch); |
---|
610 | if (!$this->incoming_payload) { |
---|
611 | $m = 'curl_exec error ' . curl_errno($ch) . ' ' . curl_error($ch); |
---|
612 | curl_close($ch); |
---|
613 | return $this->_raiseSoapFault($m); |
---|
614 | } |
---|
615 | curl_close($ch); |
---|
616 | |
---|
617 | if (!$this->_parseResponse()) { |
---|
618 | return $this->fault; |
---|
619 | } |
---|
620 | |
---|
621 | return $this->response; |
---|
622 | } |
---|
623 | |
---|
624 | } |
---|