pictcode / lib / Cake / Network / Http / HttpSocket.php @ 40928d1c
履歴 | 表示 | アノテート | ダウンロード (31.605 KB)
| 1 | 635eef61 | spyder1211 | <?php
|
|---|---|---|---|
| 2 | /**
|
||
| 3 | * HTTP Socket connection class.
|
||
| 4 | *
|
||
| 5 | * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||
| 6 | * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||
| 7 | *
|
||
| 8 | * Licensed under The MIT License
|
||
| 9 | * For full copyright and license information, please see the LICENSE.txt
|
||
| 10 | * Redistributions of files must retain the above copyright notice.
|
||
| 11 | *
|
||
| 12 | * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||
| 13 | * @link http://cakephp.org CakePHP(tm) Project
|
||
| 14 | * @package Cake.Network.Http
|
||
| 15 | * @since CakePHP(tm) v 1.2.0
|
||
| 16 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||
| 17 | */
|
||
| 18 | |||
| 19 | App::uses('CakeSocket', 'Network'); |
||
| 20 | App::uses('Router', 'Routing'); |
||
| 21 | App::uses('Hash', 'Utility'); |
||
| 22 | |||
| 23 | /**
|
||
| 24 | * CakePHP network socket connection class.
|
||
| 25 | *
|
||
| 26 | * Core base class for HTTP network communication. HttpSocket can be used as an
|
||
| 27 | * Object Oriented replacement for cURL in many places.
|
||
| 28 | *
|
||
| 29 | * @package Cake.Network.Http
|
||
| 30 | */
|
||
| 31 | class HttpSocket extends CakeSocket { |
||
| 32 | |||
| 33 | /**
|
||
| 34 | * When one activates the $quirksMode by setting it to true, all checks meant to
|
||
| 35 | * enforce RFC 2616 (HTTP/1.1 specs).
|
||
| 36 | * will be disabled and additional measures to deal with non-standard responses will be enabled.
|
||
| 37 | *
|
||
| 38 | * @var bool
|
||
| 39 | */
|
||
| 40 | public $quirksMode = false; |
||
| 41 | |||
| 42 | /**
|
||
| 43 | * Contain information about the last request (read only)
|
||
| 44 | *
|
||
| 45 | * @var array
|
||
| 46 | */
|
||
| 47 | public $request = array( |
||
| 48 | 'method' => 'GET', |
||
| 49 | 'uri' => array( |
||
| 50 | 'scheme' => 'http', |
||
| 51 | 'host' => null, |
||
| 52 | 'port' => 80, |
||
| 53 | 'user' => null, |
||
| 54 | 'pass' => null, |
||
| 55 | 'path' => null, |
||
| 56 | 'query' => null, |
||
| 57 | 'fragment' => null |
||
| 58 | ), |
||
| 59 | 'version' => '1.1', |
||
| 60 | 'body' => '', |
||
| 61 | 'line' => null, |
||
| 62 | 'header' => array( |
||
| 63 | 'Connection' => 'close', |
||
| 64 | 'User-Agent' => 'CakePHP' |
||
| 65 | ), |
||
| 66 | 'raw' => null, |
||
| 67 | 'redirect' => false, |
||
| 68 | 'cookies' => array(), |
||
| 69 | ); |
||
| 70 | |||
| 71 | /**
|
||
| 72 | * Contain information about the last response (read only)
|
||
| 73 | *
|
||
| 74 | * @var array
|
||
| 75 | */
|
||
| 76 | public $response = null; |
||
| 77 | |||
| 78 | /**
|
||
| 79 | * Response class name
|
||
| 80 | *
|
||
| 81 | * @var string
|
||
| 82 | */
|
||
| 83 | public $responseClass = 'HttpSocketResponse'; |
||
| 84 | |||
| 85 | /**
|
||
| 86 | * Configuration settings for the HttpSocket and the requests
|
||
| 87 | *
|
||
| 88 | * @var array
|
||
| 89 | */
|
||
| 90 | public $config = array( |
||
| 91 | 'persistent' => false, |
||
| 92 | 'host' => 'localhost', |
||
| 93 | 'protocol' => 'tcp', |
||
| 94 | 'port' => 80, |
||
| 95 | 'timeout' => 30, |
||
| 96 | 'ssl_verify_peer' => true, |
||
| 97 | 'ssl_allow_self_signed' => false, |
||
| 98 | 'ssl_verify_depth' => 5, |
||
| 99 | 'ssl_verify_host' => true, |
||
| 100 | 'request' => array( |
||
| 101 | 'uri' => array( |
||
| 102 | 'scheme' => array('http', 'https'), |
||
| 103 | 'host' => 'localhost', |
||
| 104 | 'port' => array(80, 443) |
||
| 105 | ), |
||
| 106 | 'redirect' => false, |
||
| 107 | 'cookies' => array(), |
||
| 108 | ) |
||
| 109 | ); |
||
| 110 | |||
| 111 | /**
|
||
| 112 | * Authentication settings
|
||
| 113 | *
|
||
| 114 | * @var array
|
||
| 115 | */
|
||
| 116 | protected $_auth = array(); |
||
| 117 | |||
| 118 | /**
|
||
| 119 | * Proxy settings
|
||
| 120 | *
|
||
| 121 | * @var array
|
||
| 122 | */
|
||
| 123 | protected $_proxy = array(); |
||
| 124 | |||
| 125 | /**
|
||
| 126 | * Resource to receive the content of request
|
||
| 127 | *
|
||
| 128 | * @var mixed
|
||
| 129 | */
|
||
| 130 | protected $_contentResource = null; |
||
| 131 | |||
| 132 | /**
|
||
| 133 | * Build an HTTP Socket using the specified configuration.
|
||
| 134 | *
|
||
| 135 | * You can use a URL string to set the URL and use default configurations for
|
||
| 136 | * all other options:
|
||
| 137 | *
|
||
| 138 | * `$http = new HttpSocket('http://cakephp.org/');`
|
||
| 139 | *
|
||
| 140 | * Or use an array to configure multiple options:
|
||
| 141 | *
|
||
| 142 | * ```
|
||
| 143 | * $http = new HttpSocket(array(
|
||
| 144 | * 'host' => 'cakephp.org',
|
||
| 145 | * 'timeout' => 20
|
||
| 146 | * ));
|
||
| 147 | * ```
|
||
| 148 | *
|
||
| 149 | * See HttpSocket::$config for options that can be used.
|
||
| 150 | *
|
||
| 151 | * @param string|array $config Configuration information, either a string URL or an array of options.
|
||
| 152 | */
|
||
| 153 | public function __construct($config = array()) { |
||
| 154 | if (is_string($config)) { |
||
| 155 | $this->_configUri($config); |
||
| 156 | } elseif (is_array($config)) { |
||
| 157 | if (isset($config['request']['uri']) && is_string($config['request']['uri'])) { |
||
| 158 | $this->_configUri($config['request']['uri']); |
||
| 159 | unset($config['request']['uri']); |
||
| 160 | } |
||
| 161 | $this->config = Hash::merge($this->config, $config); |
||
| 162 | } |
||
| 163 | parent::__construct($this->config); |
||
| 164 | } |
||
| 165 | |||
| 166 | /**
|
||
| 167 | * Set authentication settings.
|
||
| 168 | *
|
||
| 169 | * Accepts two forms of parameters. If all you need is a username + password, as with
|
||
| 170 | * Basic authentication you can do the following:
|
||
| 171 | *
|
||
| 172 | * ```
|
||
| 173 | * $http->configAuth('Basic', 'mark', 'secret');
|
||
| 174 | * ```
|
||
| 175 | *
|
||
| 176 | * If you are using an authentication strategy that requires more inputs, like Digest authentication
|
||
| 177 | * you can call `configAuth()` with an array of user information.
|
||
| 178 | *
|
||
| 179 | * ```
|
||
| 180 | * $http->configAuth('Digest', array(
|
||
| 181 | * 'user' => 'mark',
|
||
| 182 | * 'pass' => 'secret',
|
||
| 183 | * 'realm' => 'my-realm',
|
||
| 184 | * 'nonce' => 1235
|
||
| 185 | * ));
|
||
| 186 | * ```
|
||
| 187 | *
|
||
| 188 | * To remove any set authentication strategy, call `configAuth()` with no parameters:
|
||
| 189 | *
|
||
| 190 | * `$http->configAuth();`
|
||
| 191 | *
|
||
| 192 | * @param string $method Authentication method (ie. Basic, Digest). If empty, disable authentication
|
||
| 193 | * @param string|array $user Username for authentication. Can be an array with settings to authentication class
|
||
| 194 | * @param string $pass Password for authentication
|
||
| 195 | * @return void
|
||
| 196 | */
|
||
| 197 | public function configAuth($method, $user = null, $pass = null) { |
||
| 198 | if (empty($method)) { |
||
| 199 | $this->_auth = array(); |
||
| 200 | return;
|
||
| 201 | } |
||
| 202 | if (is_array($user)) { |
||
| 203 | $this->_auth = array($method => $user); |
||
| 204 | return;
|
||
| 205 | } |
||
| 206 | $this->_auth = array($method => compact('user', 'pass')); |
||
| 207 | } |
||
| 208 | |||
| 209 | /**
|
||
| 210 | * Set proxy settings
|
||
| 211 | *
|
||
| 212 | * @param string|array $host Proxy host. Can be an array with settings to authentication class
|
||
| 213 | * @param int $port Port. Default 3128.
|
||
| 214 | * @param string $method Proxy method (ie, Basic, Digest). If empty, disable proxy authentication
|
||
| 215 | * @param string $user Username if your proxy need authentication
|
||
| 216 | * @param string $pass Password to proxy authentication
|
||
| 217 | * @return void
|
||
| 218 | */
|
||
| 219 | public function configProxy($host, $port = 3128, $method = null, $user = null, $pass = null) { |
||
| 220 | if (empty($host)) { |
||
| 221 | $this->_proxy = array(); |
||
| 222 | return;
|
||
| 223 | } |
||
| 224 | if (is_array($host)) { |
||
| 225 | $this->_proxy = $host + array('host' => null); |
||
| 226 | return;
|
||
| 227 | } |
||
| 228 | $this->_proxy = compact('host', 'port', 'method', 'user', 'pass'); |
||
| 229 | } |
||
| 230 | |||
| 231 | /**
|
||
| 232 | * Set the resource to receive the request content. This resource must support fwrite.
|
||
| 233 | *
|
||
| 234 | * @param resource|bool $resource Resource or false to disable the resource use
|
||
| 235 | * @return void
|
||
| 236 | * @throws SocketException
|
||
| 237 | */
|
||
| 238 | public function setContentResource($resource) { |
||
| 239 | if ($resource === false) { |
||
| 240 | $this->_contentResource = null; |
||
| 241 | return;
|
||
| 242 | } |
||
| 243 | if (!is_resource($resource)) { |
||
| 244 | throw new SocketException(__d('cake_dev', 'Invalid resource.')); |
||
| 245 | } |
||
| 246 | $this->_contentResource = $resource; |
||
| 247 | } |
||
| 248 | |||
| 249 | /**
|
||
| 250 | * Issue the specified request. HttpSocket::get() and HttpSocket::post() wrap this
|
||
| 251 | * method and provide a more granular interface.
|
||
| 252 | *
|
||
| 253 | * @param string|array $request Either an URI string, or an array defining host/uri
|
||
| 254 | * @return mixed false on error, HttpSocketResponse on success
|
||
| 255 | * @throws SocketException
|
||
| 256 | */
|
||
| 257 | public function request($request = array()) { |
||
| 258 | $this->reset(false); |
||
| 259 | |||
| 260 | if (is_string($request)) { |
||
| 261 | $request = array('uri' => $request); |
||
| 262 | } elseif (!is_array($request)) { |
||
| 263 | return false; |
||
| 264 | } |
||
| 265 | |||
| 266 | if (!isset($request['uri'])) { |
||
| 267 | $request['uri'] = null; |
||
| 268 | } |
||
| 269 | $uri = $this->_parseUri($request['uri']); |
||
| 270 | if (!isset($uri['host'])) { |
||
| 271 | $host = $this->config['host']; |
||
| 272 | } |
||
| 273 | if (isset($request['host'])) { |
||
| 274 | $host = $request['host']; |
||
| 275 | unset($request['host']); |
||
| 276 | } |
||
| 277 | $request['uri'] = $this->url($request['uri']); |
||
| 278 | $request['uri'] = $this->_parseUri($request['uri'], true); |
||
| 279 | $this->request = Hash::merge($this->request, array_diff_key($this->config['request'], array('cookies' => true)), $request); |
||
| 280 | |||
| 281 | $this->_configUri($this->request['uri']); |
||
| 282 | |||
| 283 | $Host = $this->request['uri']['host']; |
||
| 284 | if (!empty($this->config['request']['cookies'][$Host])) { |
||
| 285 | if (!isset($this->request['cookies'])) { |
||
| 286 | $this->request['cookies'] = array(); |
||
| 287 | } |
||
| 288 | if (!isset($request['cookies'])) { |
||
| 289 | $request['cookies'] = array(); |
||
| 290 | } |
||
| 291 | $this->request['cookies'] = array_merge($this->request['cookies'], $this->config['request']['cookies'][$Host], $request['cookies']); |
||
| 292 | } |
||
| 293 | |||
| 294 | if (isset($host)) { |
||
| 295 | $this->config['host'] = $host; |
||
| 296 | } |
||
| 297 | |||
| 298 | $this->_setProxy();
|
||
| 299 | $this->request['proxy'] = $this->_proxy; |
||
| 300 | |||
| 301 | $cookies = null; |
||
| 302 | |||
| 303 | if (is_array($this->request['header'])) { |
||
| 304 | if (!empty($this->request['cookies'])) { |
||
| 305 | $cookies = $this->buildCookies($this->request['cookies']); |
||
| 306 | } |
||
| 307 | $scheme = ''; |
||
| 308 | $port = 0; |
||
| 309 | if (isset($this->request['uri']['scheme'])) { |
||
| 310 | $scheme = $this->request['uri']['scheme']; |
||
| 311 | } |
||
| 312 | if (isset($this->request['uri']['port'])) { |
||
| 313 | $port = $this->request['uri']['port']; |
||
| 314 | } |
||
| 315 | if (($scheme === 'http' && $port != 80) || |
||
| 316 | ($scheme === 'https' && $port != 443) || |
||
| 317 | ($port != 80 && $port != 443) |
||
| 318 | ) {
|
||
| 319 | $Host .= ':' . $port; |
||
| 320 | } |
||
| 321 | $this->request['header'] = array_merge(compact('Host'), $this->request['header']); |
||
| 322 | } |
||
| 323 | |||
| 324 | if (isset($this->request['uri']['user'], $this->request['uri']['pass'])) { |
||
| 325 | $this->configAuth('Basic', $this->request['uri']['user'], $this->request['uri']['pass']); |
||
| 326 | } elseif (isset($this->request['auth'], $this->request['auth']['method'], $this->request['auth']['user'], $this->request['auth']['pass'])) { |
||
| 327 | $this->configAuth($this->request['auth']['method'], $this->request['auth']['user'], $this->request['auth']['pass']); |
||
| 328 | } |
||
| 329 | $authHeader = Hash::get($this->request, 'header.Authorization'); |
||
| 330 | if (empty($authHeader)) { |
||
| 331 | $this->_setAuth();
|
||
| 332 | $this->request['auth'] = $this->_auth; |
||
| 333 | } |
||
| 334 | |||
| 335 | if (is_array($this->request['body'])) { |
||
| 336 | $this->request['body'] = http_build_query($this->request['body'], '', '&'); |
||
| 337 | } |
||
| 338 | |||
| 339 | if (!empty($this->request['body']) && !isset($this->request['header']['Content-Type'])) { |
||
| 340 | $this->request['header']['Content-Type'] = 'application/x-www-form-urlencoded'; |
||
| 341 | } |
||
| 342 | |||
| 343 | if (!empty($this->request['body']) && !isset($this->request['header']['Content-Length'])) { |
||
| 344 | $this->request['header']['Content-Length'] = strlen($this->request['body']); |
||
| 345 | } |
||
| 346 | if (isset($this->request['uri']['scheme']) && $this->request['uri']['scheme'] === 'https' && in_array($this->config['protocol'], array(false, 'tcp'))) { |
||
| 347 | $this->config['protocol'] = 'ssl'; |
||
| 348 | } |
||
| 349 | |||
| 350 | $connectionType = null; |
||
| 351 | if (isset($this->request['header']['Connection'])) { |
||
| 352 | $connectionType = $this->request['header']['Connection']; |
||
| 353 | } |
||
| 354 | $this->request['header'] = $this->_buildHeader($this->request['header']) . $cookies; |
||
| 355 | |||
| 356 | if (empty($this->request['line'])) { |
||
| 357 | $this->request['line'] = $this->_buildRequestLine($this->request); |
||
| 358 | } |
||
| 359 | |||
| 360 | if ($this->quirksMode === false && $this->request['line'] === false) { |
||
| 361 | return false; |
||
| 362 | } |
||
| 363 | |||
| 364 | $this->request['raw'] = ''; |
||
| 365 | if ($this->request['line'] !== false) { |
||
| 366 | $this->request['raw'] = $this->request['line']; |
||
| 367 | } |
||
| 368 | |||
| 369 | if ($this->request['header'] !== false) { |
||
| 370 | $this->request['raw'] .= $this->request['header']; |
||
| 371 | } |
||
| 372 | |||
| 373 | $this->request['raw'] .= "\r\n"; |
||
| 374 | $this->request['raw'] .= $this->request['body']; |
||
| 375 | |||
| 376 | // SSL context is set during the connect() method.
|
||
| 377 | $this->write($this->request['raw']); |
||
| 378 | |||
| 379 | $response = null; |
||
| 380 | $inHeader = true; |
||
| 381 | while (($data = $this->read()) !== false) { |
||
| 382 | if ($this->_contentResource) { |
||
| 383 | if ($inHeader) { |
||
| 384 | $response .= $data; |
||
| 385 | $pos = strpos($response, "\r\n\r\n"); |
||
| 386 | if ($pos !== false) { |
||
| 387 | $pos += 4; |
||
| 388 | $data = substr($response, $pos); |
||
| 389 | fwrite($this->_contentResource, $data); |
||
| 390 | |||
| 391 | $response = substr($response, 0, $pos); |
||
| 392 | $inHeader = false; |
||
| 393 | } |
||
| 394 | } else {
|
||
| 395 | fwrite($this->_contentResource, $data); |
||
| 396 | fflush($this->_contentResource); |
||
| 397 | } |
||
| 398 | } else {
|
||
| 399 | $response .= $data; |
||
| 400 | } |
||
| 401 | } |
||
| 402 | |||
| 403 | if ($connectionType === 'close') { |
||
| 404 | $this->disconnect();
|
||
| 405 | } |
||
| 406 | |||
| 407 | list($plugin, $responseClass) = pluginSplit($this->responseClass, true); |
||
| 408 | App::uses($responseClass, $plugin . 'Network/Http'); |
||
| 409 | if (!class_exists($responseClass)) { |
||
| 410 | throw new SocketException(__d('cake_dev', 'Class %s not found.', $this->responseClass)); |
||
| 411 | } |
||
| 412 | $this->response = new $responseClass($response); |
||
| 413 | |||
| 414 | if (!empty($this->response->cookies)) { |
||
| 415 | if (!isset($this->config['request']['cookies'][$Host])) { |
||
| 416 | $this->config['request']['cookies'][$Host] = array(); |
||
| 417 | } |
||
| 418 | $this->config['request']['cookies'][$Host] = array_merge($this->config['request']['cookies'][$Host], $this->response->cookies); |
||
| 419 | } |
||
| 420 | |||
| 421 | if ($this->request['redirect'] && $this->response->isRedirect()) { |
||
| 422 | $location = trim($this->response->getHeader('Location'), '='); |
||
| 423 | $request['uri'] = str_replace('%2F', '/', $location); |
||
| 424 | $request['redirect'] = is_int($this->request['redirect']) ? $this->request['redirect'] - 1 : $this->request['redirect']; |
||
| 425 | $this->response = $this->request($request); |
||
| 426 | } |
||
| 427 | |||
| 428 | return $this->response; |
||
| 429 | } |
||
| 430 | |||
| 431 | /**
|
||
| 432 | * Issues a GET request to the specified URI, query, and request.
|
||
| 433 | *
|
||
| 434 | * Using a string uri and an array of query string parameters:
|
||
| 435 | *
|
||
| 436 | * `$response = $http->get('http://google.com/search', array('q' => 'cakephp', 'client' => 'safari'));`
|
||
| 437 | *
|
||
| 438 | * Would do a GET request to `http://google.com/search?q=cakephp&client=safari`
|
||
| 439 | *
|
||
| 440 | * You could express the same thing using a uri array and query string parameters:
|
||
| 441 | *
|
||
| 442 | * ```
|
||
| 443 | * $response = $http->get(
|
||
| 444 | * array('host' => 'google.com', 'path' => '/search'),
|
||
| 445 | * array('q' => 'cakephp', 'client' => 'safari')
|
||
| 446 | * );
|
||
| 447 | * ```
|
||
| 448 | *
|
||
| 449 | * @param string|array $uri URI to request. Either a string uri, or a uri array, see HttpSocket::_parseUri()
|
||
| 450 | * @param array $query Querystring parameters to append to URI
|
||
| 451 | * @param array $request An indexed array with indexes such as 'method' or uri
|
||
| 452 | * @return mixed Result of request, either false on failure or the response to the request.
|
||
| 453 | */
|
||
| 454 | public function get($uri = null, $query = array(), $request = array()) { |
||
| 455 | if (!empty($query)) { |
||
| 456 | $uri = $this->_parseUri($uri, $this->config['request']['uri']); |
||
| 457 | if (isset($uri['query'])) { |
||
| 458 | $uri['query'] = array_merge($uri['query'], $query); |
||
| 459 | } else {
|
||
| 460 | $uri['query'] = $query; |
||
| 461 | } |
||
| 462 | $uri = $this->_buildUri($uri); |
||
| 463 | } |
||
| 464 | |||
| 465 | $request = Hash::merge(array('method' => 'GET', 'uri' => $uri), $request); |
||
| 466 | return $this->request($request); |
||
| 467 | } |
||
| 468 | |||
| 469 | /**
|
||
| 470 | * Issues a HEAD request to the specified URI, query, and request.
|
||
| 471 | *
|
||
| 472 | * By definition HEAD request are identical to GET request except they return no response body. This means that all
|
||
| 473 | * information and examples relevant to GET also applys to HEAD.
|
||
| 474 | *
|
||
| 475 | * @param string|array $uri URI to request. Either a string URI, or a URI array, see HttpSocket::_parseUri()
|
||
| 476 | * @param array $query Querystring parameters to append to URI
|
||
| 477 | * @param array $request An indexed array with indexes such as 'method' or uri
|
||
| 478 | * @return mixed Result of request, either false on failure or the response to the request.
|
||
| 479 | */
|
||
| 480 | public function head($uri = null, $query = array(), $request = array()) { |
||
| 481 | if (!empty($query)) { |
||
| 482 | $uri = $this->_parseUri($uri, $this->config['request']['uri']); |
||
| 483 | if (isset($uri['query'])) { |
||
| 484 | $uri['query'] = array_merge($uri['query'], $query); |
||
| 485 | } else {
|
||
| 486 | $uri['query'] = $query; |
||
| 487 | } |
||
| 488 | $uri = $this->_buildUri($uri); |
||
| 489 | } |
||
| 490 | |||
| 491 | $request = Hash::merge(array('method' => 'HEAD', 'uri' => $uri), $request); |
||
| 492 | return $this->request($request); |
||
| 493 | } |
||
| 494 | |||
| 495 | /**
|
||
| 496 | * Issues a POST request to the specified URI, query, and request.
|
||
| 497 | *
|
||
| 498 | * `post()` can be used to post simple data arrays to a URL:
|
||
| 499 | *
|
||
| 500 | * ```
|
||
| 501 | * $response = $http->post('http://example.com', array(
|
||
| 502 | * 'username' => 'batman',
|
||
| 503 | * 'password' => 'bruce_w4yne'
|
||
| 504 | * ));
|
||
| 505 | * ```
|
||
| 506 | *
|
||
| 507 | * @param string|array $uri URI to request. See HttpSocket::_parseUri()
|
||
| 508 | * @param array $data Array of request body data keys and values.
|
||
| 509 | * @param array $request An indexed array with indexes such as 'method' or uri
|
||
| 510 | * @return mixed Result of request, either false on failure or the response to the request.
|
||
| 511 | */
|
||
| 512 | public function post($uri = null, $data = array(), $request = array()) { |
||
| 513 | $request = Hash::merge(array('method' => 'POST', 'uri' => $uri, 'body' => $data), $request); |
||
| 514 | return $this->request($request); |
||
| 515 | } |
||
| 516 | |||
| 517 | /**
|
||
| 518 | * Issues a PUT request to the specified URI, query, and request.
|
||
| 519 | *
|
||
| 520 | * @param string|array $uri URI to request, See HttpSocket::_parseUri()
|
||
| 521 | * @param array $data Array of request body data keys and values.
|
||
| 522 | * @param array $request An indexed array with indexes such as 'method' or uri
|
||
| 523 | * @return mixed Result of request
|
||
| 524 | */
|
||
| 525 | public function put($uri = null, $data = array(), $request = array()) { |
||
| 526 | $request = Hash::merge(array('method' => 'PUT', 'uri' => $uri, 'body' => $data), $request); |
||
| 527 | return $this->request($request); |
||
| 528 | } |
||
| 529 | |||
| 530 | /**
|
||
| 531 | * Issues a PATCH request to the specified URI, query, and request.
|
||
| 532 | *
|
||
| 533 | * @param string|array $uri URI to request, See HttpSocket::_parseUri()
|
||
| 534 | * @param array $data Array of request body data keys and values.
|
||
| 535 | * @param array $request An indexed array with indexes such as 'method' or uri
|
||
| 536 | * @return mixed Result of request
|
||
| 537 | */
|
||
| 538 | public function patch($uri = null, $data = array(), $request = array()) { |
||
| 539 | $request = Hash::merge(array('method' => 'PATCH', 'uri' => $uri, 'body' => $data), $request); |
||
| 540 | return $this->request($request); |
||
| 541 | } |
||
| 542 | |||
| 543 | /**
|
||
| 544 | * Issues a DELETE request to the specified URI, query, and request.
|
||
| 545 | *
|
||
| 546 | * @param string|array $uri URI to request (see {@link _parseUri()})
|
||
| 547 | * @param array $data Array of request body data keys and values.
|
||
| 548 | * @param array $request An indexed array with indexes such as 'method' or uri
|
||
| 549 | * @return mixed Result of request
|
||
| 550 | */
|
||
| 551 | public function delete($uri = null, $data = array(), $request = array()) { |
||
| 552 | $request = Hash::merge(array('method' => 'DELETE', 'uri' => $uri, 'body' => $data), $request); |
||
| 553 | return $this->request($request); |
||
| 554 | } |
||
| 555 | |||
| 556 | /**
|
||
| 557 | * Normalizes URLs into a $uriTemplate. If no template is provided
|
||
| 558 | * a default one will be used. Will generate the URL using the
|
||
| 559 | * current config information.
|
||
| 560 | *
|
||
| 561 | * ### Usage:
|
||
| 562 | *
|
||
| 563 | * After configuring part of the request parameters, you can use url() to generate
|
||
| 564 | * URLs.
|
||
| 565 | *
|
||
| 566 | * ```
|
||
| 567 | * $http = new HttpSocket('http://www.cakephp.org');
|
||
| 568 | * $url = $http->url('/search?q=bar');
|
||
| 569 | * ```
|
||
| 570 | *
|
||
| 571 | * Would return `http://www.cakephp.org/search?q=bar`
|
||
| 572 | *
|
||
| 573 | * url() can also be used with custom templates:
|
||
| 574 | *
|
||
| 575 | * `$url = $http->url('http://www.cakephp/search?q=socket', '/%path?%query');`
|
||
| 576 | *
|
||
| 577 | * Would return `/search?q=socket`.
|
||
| 578 | *
|
||
| 579 | * @param string|array $url Either a string or array of URL options to create a URL with.
|
||
| 580 | * @param string $uriTemplate A template string to use for URL formatting.
|
||
| 581 | * @return mixed Either false on failure or a string containing the composed URL.
|
||
| 582 | */
|
||
| 583 | public function url($url = null, $uriTemplate = null) { |
||
| 584 | if ($url === null) { |
||
| 585 | $url = '/'; |
||
| 586 | } |
||
| 587 | if (is_string($url)) { |
||
| 588 | $scheme = $this->config['request']['uri']['scheme']; |
||
| 589 | if (is_array($scheme)) { |
||
| 590 | $scheme = $scheme[0]; |
||
| 591 | } |
||
| 592 | $port = $this->config['request']['uri']['port']; |
||
| 593 | if (is_array($port)) { |
||
| 594 | $port = $port[0]; |
||
| 595 | } |
||
| 596 | if ($url{0} === '/') { |
||
| 597 | $url = $this->config['request']['uri']['host'] . ':' . $port . $url; |
||
| 598 | } |
||
| 599 | if (!preg_match('/^.+:\/\/|\*|^\//', $url)) { |
||
| 600 | $url = $scheme . '://' . $url; |
||
| 601 | } |
||
| 602 | } elseif (!is_array($url) && !empty($url)) { |
||
| 603 | return false; |
||
| 604 | } |
||
| 605 | |||
| 606 | $base = array_merge($this->config['request']['uri'], array('scheme' => array('http', 'https'), 'port' => array(80, 443))); |
||
| 607 | $url = $this->_parseUri($url, $base); |
||
| 608 | |||
| 609 | if (empty($url)) { |
||
| 610 | $url = $this->config['request']['uri']; |
||
| 611 | } |
||
| 612 | |||
| 613 | if (!empty($uriTemplate)) { |
||
| 614 | return $this->_buildUri($url, $uriTemplate); |
||
| 615 | } |
||
| 616 | return $this->_buildUri($url); |
||
| 617 | } |
||
| 618 | |||
| 619 | /**
|
||
| 620 | * Set authentication in request
|
||
| 621 | *
|
||
| 622 | * @return void
|
||
| 623 | * @throws SocketException
|
||
| 624 | */
|
||
| 625 | protected function _setAuth() { |
||
| 626 | if (empty($this->_auth)) { |
||
| 627 | return;
|
||
| 628 | } |
||
| 629 | $method = key($this->_auth); |
||
| 630 | list($plugin, $authClass) = pluginSplit($method, true); |
||
| 631 | $authClass = Inflector::camelize($authClass) . 'Authentication'; |
||
| 632 | App::uses($authClass, $plugin . 'Network/Http'); |
||
| 633 | |||
| 634 | if (!class_exists($authClass)) { |
||
| 635 | throw new SocketException(__d('cake_dev', 'Unknown authentication method.')); |
||
| 636 | } |
||
| 637 | if (!method_exists($authClass, 'authentication')) { |
||
| 638 | throw new SocketException(__d('cake_dev', 'The %s does not support authentication.', $authClass)); |
||
| 639 | } |
||
| 640 | call_user_func_array("$authClass::authentication", array($this, &$this->_auth[$method])); |
||
| 641 | } |
||
| 642 | |||
| 643 | /**
|
||
| 644 | * Set the proxy configuration and authentication
|
||
| 645 | *
|
||
| 646 | * @return void
|
||
| 647 | * @throws SocketException
|
||
| 648 | */
|
||
| 649 | protected function _setProxy() { |
||
| 650 | if (empty($this->_proxy) || !isset($this->_proxy['host'], $this->_proxy['port'])) { |
||
| 651 | return;
|
||
| 652 | } |
||
| 653 | $this->config['host'] = $this->_proxy['host']; |
||
| 654 | $this->config['port'] = $this->_proxy['port']; |
||
| 655 | $this->config['proxy'] = true; |
||
| 656 | |||
| 657 | if (empty($this->_proxy['method']) || !isset($this->_proxy['user'], $this->_proxy['pass'])) { |
||
| 658 | return;
|
||
| 659 | } |
||
| 660 | list($plugin, $authClass) = pluginSplit($this->_proxy['method'], true); |
||
| 661 | $authClass = Inflector::camelize($authClass) . 'Authentication'; |
||
| 662 | App::uses($authClass, $plugin . 'Network/Http'); |
||
| 663 | |||
| 664 | if (!class_exists($authClass)) { |
||
| 665 | throw new SocketException(__d('cake_dev', 'Unknown authentication method for proxy.')); |
||
| 666 | } |
||
| 667 | if (!method_exists($authClass, 'proxyAuthentication')) { |
||
| 668 | throw new SocketException(__d('cake_dev', 'The %s does not support proxy authentication.', $authClass)); |
||
| 669 | } |
||
| 670 | call_user_func_array("$authClass::proxyAuthentication", array($this, &$this->_proxy)); |
||
| 671 | |||
| 672 | if (!empty($this->request['header']['Proxy-Authorization'])) { |
||
| 673 | $this->config['proxyauth'] = $this->request['header']['Proxy-Authorization']; |
||
| 674 | if ($this->request['uri']['scheme'] === 'https') { |
||
| 675 | $this->request['header'] = Hash::remove($this->request['header'], 'Proxy-Authorization'); |
||
| 676 | } |
||
| 677 | } |
||
| 678 | } |
||
| 679 | |||
| 680 | /**
|
||
| 681 | * Parses and sets the specified URI into current request configuration.
|
||
| 682 | *
|
||
| 683 | * @param string|array $uri URI, See HttpSocket::_parseUri()
|
||
| 684 | * @return bool If uri has merged in config
|
||
| 685 | */
|
||
| 686 | protected function _configUri($uri = null) { |
||
| 687 | if (empty($uri)) { |
||
| 688 | return false; |
||
| 689 | } |
||
| 690 | |||
| 691 | if (is_array($uri)) { |
||
| 692 | $uri = $this->_parseUri($uri); |
||
| 693 | } else {
|
||
| 694 | $uri = $this->_parseUri($uri, true); |
||
| 695 | } |
||
| 696 | |||
| 697 | if (!isset($uri['host'])) { |
||
| 698 | return false; |
||
| 699 | } |
||
| 700 | $config = array( |
||
| 701 | 'request' => array( |
||
| 702 | 'uri' => array_intersect_key($uri, $this->config['request']['uri']) |
||
| 703 | ) |
||
| 704 | ); |
||
| 705 | $this->config = Hash::merge($this->config, $config); |
||
| 706 | $this->config = Hash::merge($this->config, array_intersect_key($this->config['request']['uri'], $this->config)); |
||
| 707 | return true; |
||
| 708 | } |
||
| 709 | |||
| 710 | /**
|
||
| 711 | * Takes a $uri array and turns it into a fully qualified URL string
|
||
| 712 | *
|
||
| 713 | * @param string|array $uri Either A $uri array, or a request string. Will use $this->config if left empty.
|
||
| 714 | * @param string $uriTemplate The Uri template/format to use.
|
||
| 715 | * @return mixed A fully qualified URL formatted according to $uriTemplate, or false on failure
|
||
| 716 | */
|
||
| 717 | protected function _buildUri($uri = array(), $uriTemplate = '%scheme://%user:%pass@%host:%port/%path?%query#%fragment') { |
||
| 718 | if (is_string($uri)) { |
||
| 719 | $uri = array('host' => $uri); |
||
| 720 | } |
||
| 721 | $uri = $this->_parseUri($uri, true); |
||
| 722 | |||
| 723 | if (!is_array($uri) || empty($uri)) { |
||
| 724 | return false; |
||
| 725 | } |
||
| 726 | |||
| 727 | $uri['path'] = preg_replace('/^\//', null, $uri['path']); |
||
| 728 | $uri['query'] = http_build_query($uri['query'], '', '&'); |
||
| 729 | $uri['query'] = rtrim($uri['query'], '='); |
||
| 730 | $stripIfEmpty = array( |
||
| 731 | 'query' => '?%query', |
||
| 732 | 'fragment' => '#%fragment', |
||
| 733 | 'user' => '%user:%pass@', |
||
| 734 | 'host' => '%host:%port/' |
||
| 735 | ); |
||
| 736 | |||
| 737 | foreach ($stripIfEmpty as $key => $strip) { |
||
| 738 | if (empty($uri[$key])) { |
||
| 739 | $uriTemplate = str_replace($strip, null, $uriTemplate); |
||
| 740 | } |
||
| 741 | } |
||
| 742 | |||
| 743 | $defaultPorts = array('http' => 80, 'https' => 443); |
||
| 744 | if (array_key_exists($uri['scheme'], $defaultPorts) && $defaultPorts[$uri['scheme']] == $uri['port']) { |
||
| 745 | $uriTemplate = str_replace(':%port', null, $uriTemplate); |
||
| 746 | } |
||
| 747 | foreach ($uri as $property => $value) { |
||
| 748 | $uriTemplate = str_replace('%' . $property, $value, $uriTemplate); |
||
| 749 | } |
||
| 750 | |||
| 751 | if ($uriTemplate === '/*') { |
||
| 752 | $uriTemplate = '*'; |
||
| 753 | } |
||
| 754 | return $uriTemplate; |
||
| 755 | } |
||
| 756 | |||
| 757 | /**
|
||
| 758 | * Parses the given URI and breaks it down into pieces as an indexed array with elements
|
||
| 759 | * such as 'scheme', 'port', 'query'.
|
||
| 760 | *
|
||
| 761 | * @param string|array $uri URI to parse
|
||
| 762 | * @param bool|array $base If true use default URI config, otherwise indexed array to set 'scheme', 'host', 'port', etc.
|
||
| 763 | * @return array Parsed URI
|
||
| 764 | */
|
||
| 765 | protected function _parseUri($uri = null, $base = array()) { |
||
| 766 | $uriBase = array( |
||
| 767 | 'scheme' => array('http', 'https'), |
||
| 768 | 'host' => null, |
||
| 769 | 'port' => array(80, 443), |
||
| 770 | 'user' => null, |
||
| 771 | 'pass' => null, |
||
| 772 | 'path' => '/', |
||
| 773 | 'query' => null, |
||
| 774 | 'fragment' => null |
||
| 775 | ); |
||
| 776 | |||
| 777 | if (is_string($uri)) { |
||
| 778 | $uri = parse_url($uri); |
||
| 779 | } |
||
| 780 | if (!is_array($uri) || empty($uri)) { |
||
| 781 | return false; |
||
| 782 | } |
||
| 783 | if ($base === true) { |
||
| 784 | $base = $uriBase; |
||
| 785 | } |
||
| 786 | |||
| 787 | if (isset($base['port'], $base['scheme']) && is_array($base['port']) && is_array($base['scheme'])) { |
||
| 788 | if (isset($uri['scheme']) && !isset($uri['port'])) { |
||
| 789 | $base['port'] = $base['port'][array_search($uri['scheme'], $base['scheme'])]; |
||
| 790 | } elseif (isset($uri['port']) && !isset($uri['scheme'])) { |
||
| 791 | $base['scheme'] = $base['scheme'][array_search($uri['port'], $base['port'])]; |
||
| 792 | } |
||
| 793 | } |
||
| 794 | |||
| 795 | if (is_array($base) && !empty($base)) { |
||
| 796 | $uri = array_merge($base, $uri); |
||
| 797 | } |
||
| 798 | |||
| 799 | if (isset($uri['scheme']) && is_array($uri['scheme'])) { |
||
| 800 | $uri['scheme'] = array_shift($uri['scheme']); |
||
| 801 | } |
||
| 802 | if (isset($uri['port']) && is_array($uri['port'])) { |
||
| 803 | $uri['port'] = array_shift($uri['port']); |
||
| 804 | } |
||
| 805 | |||
| 806 | if (array_key_exists('query', $uri)) { |
||
| 807 | $uri['query'] = $this->_parseQuery($uri['query']); |
||
| 808 | } |
||
| 809 | |||
| 810 | if (!array_intersect_key($uriBase, $uri)) { |
||
| 811 | return false; |
||
| 812 | } |
||
| 813 | return $uri; |
||
| 814 | } |
||
| 815 | |||
| 816 | /**
|
||
| 817 | * This function can be thought of as a reverse to PHP5's http_build_query(). It takes a given query string and turns it into an array and
|
||
| 818 | * supports nesting by using the php bracket syntax. So this means you can parse queries like:
|
||
| 819 | *
|
||
| 820 | * - ?key[subKey]=value
|
||
| 821 | * - ?key[]=value1&key[]=value2
|
||
| 822 | *
|
||
| 823 | * A leading '?' mark in $query is optional and does not effect the outcome of this function.
|
||
| 824 | * For the complete capabilities of this implementation take a look at HttpSocketTest::testparseQuery()
|
||
| 825 | *
|
||
| 826 | * @param string|array $query A query string to parse into an array or an array to return directly "as is"
|
||
| 827 | * @return array The $query parsed into a possibly multi-level array. If an empty $query is
|
||
| 828 | * given, an empty array is returned.
|
||
| 829 | */
|
||
| 830 | protected function _parseQuery($query) { |
||
| 831 | if (is_array($query)) { |
||
| 832 | return $query; |
||
| 833 | } |
||
| 834 | |||
| 835 | $parsedQuery = array(); |
||
| 836 | |||
| 837 | if (is_string($query) && !empty($query)) { |
||
| 838 | $query = preg_replace('/^\?/', '', $query); |
||
| 839 | $items = explode('&', $query); |
||
| 840 | |||
| 841 | foreach ($items as $item) { |
||
| 842 | if (strpos($item, '=') !== false) { |
||
| 843 | list($key, $value) = explode('=', $item, 2); |
||
| 844 | } else {
|
||
| 845 | $key = $item; |
||
| 846 | $value = null; |
||
| 847 | } |
||
| 848 | |||
| 849 | $key = urldecode($key); |
||
| 850 | $value = urldecode($value); |
||
| 851 | |||
| 852 | if (preg_match_all('/\[([^\[\]]*)\]/iUs', $key, $matches)) { |
||
| 853 | $subKeys = $matches[1]; |
||
| 854 | $rootKey = substr($key, 0, strpos($key, '[')); |
||
| 855 | if (!empty($rootKey)) { |
||
| 856 | array_unshift($subKeys, $rootKey); |
||
| 857 | } |
||
| 858 | $queryNode =& $parsedQuery; |
||
| 859 | |||
| 860 | foreach ($subKeys as $subKey) { |
||
| 861 | if (!is_array($queryNode)) { |
||
| 862 | $queryNode = array(); |
||
| 863 | } |
||
| 864 | |||
| 865 | if ($subKey === '') { |
||
| 866 | $queryNode[] = array(); |
||
| 867 | end($queryNode); |
||
| 868 | $subKey = key($queryNode); |
||
| 869 | } |
||
| 870 | $queryNode =& $queryNode[$subKey]; |
||
| 871 | } |
||
| 872 | $queryNode = $value; |
||
| 873 | continue;
|
||
| 874 | } |
||
| 875 | if (!isset($parsedQuery[$key])) { |
||
| 876 | $parsedQuery[$key] = $value; |
||
| 877 | } else {
|
||
| 878 | $parsedQuery[$key] = (array)$parsedQuery[$key]; |
||
| 879 | $parsedQuery[$key][] = $value; |
||
| 880 | } |
||
| 881 | } |
||
| 882 | } |
||
| 883 | return $parsedQuery; |
||
| 884 | } |
||
| 885 | |||
| 886 | /**
|
||
| 887 | * Builds a request line according to HTTP/1.1 specs. Activate quirks mode to work outside specs.
|
||
| 888 | *
|
||
| 889 | * @param array $request Needs to contain a 'uri' key. Should also contain a 'method' key, otherwise defaults to GET.
|
||
| 890 | * @return string Request line
|
||
| 891 | * @throws SocketException
|
||
| 892 | */
|
||
| 893 | protected function _buildRequestLine($request = array()) { |
||
| 894 | $asteriskMethods = array('OPTIONS'); |
||
| 895 | |||
| 896 | if (is_string($request)) { |
||
| 897 | $isValid = preg_match("/(.+) (.+) (.+)\r\n/U", $request, $match); |
||
| 898 | if (!$this->quirksMode && (!$isValid || ($match[2] === '*' && !in_array($match[3], $asteriskMethods)))) { |
||
| 899 | throw new SocketException(__d('cake_dev', 'HttpSocket::_buildRequestLine - Passed an invalid request line string. Activate quirks mode to do this.')); |
||
| 900 | } |
||
| 901 | return $request; |
||
| 902 | } elseif (!is_array($request)) { |
||
| 903 | return false; |
||
| 904 | } elseif (!array_key_exists('uri', $request)) { |
||
| 905 | return false; |
||
| 906 | } |
||
| 907 | |||
| 908 | $request['uri'] = $this->_parseUri($request['uri']); |
||
| 909 | $request += array('method' => 'GET'); |
||
| 910 | if (!empty($this->_proxy['host']) && $request['uri']['scheme'] !== 'https') { |
||
| 911 | $request['uri'] = $this->_buildUri($request['uri'], '%scheme://%host:%port/%path?%query'); |
||
| 912 | } else {
|
||
| 913 | $request['uri'] = $this->_buildUri($request['uri'], '/%path?%query'); |
||
| 914 | } |
||
| 915 | |||
| 916 | if (!$this->quirksMode && $request['uri'] === '*' && !in_array($request['method'], $asteriskMethods)) { |
||
| 917 | throw new SocketException(__d('cake_dev', 'HttpSocket::_buildRequestLine - The "*" asterisk character is only allowed for the following methods: %s. Activate quirks mode to work outside of HTTP/1.1 specs.', implode(',', $asteriskMethods))); |
||
| 918 | } |
||
| 919 | $version = isset($request['version']) ? $request['version'] : '1.1'; |
||
| 920 | return $request['method'] . ' ' . $request['uri'] . ' HTTP/' . $version . "\r\n"; |
||
| 921 | } |
||
| 922 | |||
| 923 | /**
|
||
| 924 | * Builds the header.
|
||
| 925 | *
|
||
| 926 | * @param array $header Header to build
|
||
| 927 | * @param string $mode Mode
|
||
| 928 | * @return string Header built from array
|
||
| 929 | */
|
||
| 930 | protected function _buildHeader($header, $mode = 'standard') { |
||
| 931 | if (is_string($header)) { |
||
| 932 | return $header; |
||
| 933 | } elseif (!is_array($header)) { |
||
| 934 | return false; |
||
| 935 | } |
||
| 936 | |||
| 937 | $fieldsInHeader = array(); |
||
| 938 | foreach ($header as $key => $value) { |
||
| 939 | $lowKey = strtolower($key); |
||
| 940 | if (array_key_exists($lowKey, $fieldsInHeader)) { |
||
| 941 | $header[$fieldsInHeader[$lowKey]] = $value; |
||
| 942 | unset($header[$key]); |
||
| 943 | } else {
|
||
| 944 | $fieldsInHeader[$lowKey] = $key; |
||
| 945 | } |
||
| 946 | } |
||
| 947 | |||
| 948 | $returnHeader = ''; |
||
| 949 | foreach ($header as $field => $contents) { |
||
| 950 | if (is_array($contents) && $mode === 'standard') { |
||
| 951 | $contents = implode(',', $contents); |
||
| 952 | } |
||
| 953 | foreach ((array)$contents as $content) { |
||
| 954 | $contents = preg_replace("/\r\n(?![\t ])/", "\r\n ", $content); |
||
| 955 | $field = $this->_escapeToken($field); |
||
| 956 | |||
| 957 | $returnHeader .= $field . ': ' . $contents . "\r\n"; |
||
| 958 | } |
||
| 959 | } |
||
| 960 | return $returnHeader; |
||
| 961 | } |
||
| 962 | |||
| 963 | /**
|
||
| 964 | * Builds cookie headers for a request.
|
||
| 965 | *
|
||
| 966 | * Cookies can either be in the format returned in responses, or
|
||
| 967 | * a simple key => value pair.
|
||
| 968 | *
|
||
| 969 | * @param array $cookies Array of cookies to send with the request.
|
||
| 970 | * @return string Cookie header string to be sent with the request.
|
||
| 971 | */
|
||
| 972 | public function buildCookies($cookies) { |
||
| 973 | $header = array(); |
||
| 974 | foreach ($cookies as $name => $cookie) { |
||
| 975 | if (is_array($cookie)) { |
||
| 976 | $value = $this->_escapeToken($cookie['value'], array(';')); |
||
| 977 | } else {
|
||
| 978 | $value = $this->_escapeToken($cookie, array(';')); |
||
| 979 | } |
||
| 980 | $header[] = $name . '=' . $value; |
||
| 981 | } |
||
| 982 | return $this->_buildHeader(array('Cookie' => implode('; ', $header)), 'pragmatic'); |
||
| 983 | } |
||
| 984 | |||
| 985 | /**
|
||
| 986 | * Escapes a given $token according to RFC 2616 (HTTP 1.1 specs)
|
||
| 987 | *
|
||
| 988 | * @param string $token Token to escape
|
||
| 989 | * @param array $chars Characters to escape
|
||
| 990 | * @return string Escaped token
|
||
| 991 | */
|
||
| 992 | protected function _escapeToken($token, $chars = null) { |
||
| 993 | $regex = '/([' . implode('', $this->_tokenEscapeChars(true, $chars)) . '])/'; |
||
| 994 | $token = preg_replace($regex, '"\\1"', $token); |
||
| 995 | return $token; |
||
| 996 | } |
||
| 997 | |||
| 998 | /**
|
||
| 999 | * Gets escape chars according to RFC 2616 (HTTP 1.1 specs).
|
||
| 1000 | *
|
||
| 1001 | * @param bool $hex true to get them as HEX values, false otherwise
|
||
| 1002 | * @param array $chars Characters to escape
|
||
| 1003 | * @return array Escape chars
|
||
| 1004 | */
|
||
| 1005 | protected function _tokenEscapeChars($hex = true, $chars = null) { |
||
| 1006 | if (!empty($chars)) { |
||
| 1007 | $escape = $chars; |
||
| 1008 | } else {
|
||
| 1009 | $escape = array('"', "(", ")", "<", ">", "@", ",", ";", ":", "\\", "/", "[", "]", "?", "=", "{", "}", " "); |
||
| 1010 | for ($i = 0; $i <= 31; $i++) { |
||
| 1011 | $escape[] = chr($i); |
||
| 1012 | } |
||
| 1013 | $escape[] = chr(127); |
||
| 1014 | } |
||
| 1015 | |||
| 1016 | if (!$hex) { |
||
| 1017 | return $escape; |
||
| 1018 | } |
||
| 1019 | foreach ($escape as $key => $char) { |
||
| 1020 | $escape[$key] = '\\x' . str_pad(dechex(ord($char)), 2, '0', STR_PAD_LEFT); |
||
| 1021 | } |
||
| 1022 | return $escape; |
||
| 1023 | } |
||
| 1024 | |||
| 1025 | /**
|
||
| 1026 | * Resets the state of this HttpSocket instance to it's initial state (before Object::__construct got executed) or does
|
||
| 1027 | * the same thing partially for the request and the response property only.
|
||
| 1028 | *
|
||
| 1029 | * @param bool $full If set to false only HttpSocket::response and HttpSocket::request are reset
|
||
| 1030 | * @return bool True on success
|
||
| 1031 | */
|
||
| 1032 | public function reset($full = true) { |
||
| 1033 | static $initalState = array(); |
||
| 1034 | if (empty($initalState)) { |
||
| 1035 | $initalState = get_class_vars(__CLASS__); |
||
| 1036 | } |
||
| 1037 | if (!$full) { |
||
| 1038 | $this->request = $initalState['request']; |
||
| 1039 | $this->response = $initalState['response']; |
||
| 1040 | return true; |
||
| 1041 | } |
||
| 1042 | parent::reset($initalState); |
||
| 1043 | return true; |
||
| 1044 | } |
||
| 1045 | |||
| 1046 | } |