1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
18:
19: App::uses('CakeSocket', 'Network');
20: App::uses('Router', 'Routing');
21: App::uses('Hash', 'Utility');
22:
23: 24: 25: 26: 27: 28: 29: 30:
31: class HttpSocket extends CakeSocket {
32:
33: 34: 35: 36: 37: 38: 39:
40: public $quirksMode = false;
41:
42: 43: 44: 45: 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: 73: 74: 75:
76: public $response = null;
77:
78: 79: 80: 81: 82:
83: public $responseClass = 'HttpSocketResponse';
84:
85: 86: 87: 88: 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: 113: 114: 115:
116: protected $_auth = array();
117:
118: 119: 120: 121: 122:
123: protected $_proxy = array();
124:
125: 126: 127: 128: 129:
130: protected $_contentResource = null;
131:
132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 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: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 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: 211: 212: 213: 214: 215: 216: 217: 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: 233: 234: 235: 236: 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: 251: 252: 253: 254: 255: 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: $this->_setProxy();
298: $this->request['proxy'] = $this->_proxy;
299:
300: $cookies = null;
301:
302: if (is_array($this->request['header'])) {
303: if (!empty($this->request['cookies'])) {
304: $cookies = $this->buildCookies($this->request['cookies']);
305: }
306: $scheme = '';
307: $port = 0;
308: if (isset($this->request['uri']['scheme'])) {
309: $scheme = $this->request['uri']['scheme'];
310: }
311: if (isset($this->request['uri']['port'])) {
312: $port = $this->request['uri']['port'];
313: }
314: if (
315: ($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: $this->_setAuth();
330: $this->request['auth'] = $this->_auth;
331:
332: if (is_array($this->request['body'])) {
333: $this->request['body'] = http_build_query($this->request['body'], '', '&');
334: }
335:
336: if (!empty($this->request['body']) && !isset($this->request['header']['Content-Type'])) {
337: $this->request['header']['Content-Type'] = 'application/x-www-form-urlencoded';
338: }
339:
340: if (!empty($this->request['body']) && !isset($this->request['header']['Content-Length'])) {
341: $this->request['header']['Content-Length'] = strlen($this->request['body']);
342: }
343:
344: $connectionType = null;
345: if (isset($this->request['header']['Connection'])) {
346: $connectionType = $this->request['header']['Connection'];
347: }
348: $this->request['header'] = $this->_buildHeader($this->request['header']) . $cookies;
349:
350: if (empty($this->request['line'])) {
351: $this->request['line'] = $this->_buildRequestLine($this->request);
352: }
353:
354: if ($this->quirksMode === false && $this->request['line'] === false) {
355: return false;
356: }
357:
358: $this->_configContext($this->request['uri']['host']);
359:
360: $this->request['raw'] = '';
361: if ($this->request['line'] !== false) {
362: $this->request['raw'] = $this->request['line'];
363: }
364:
365: if ($this->request['header'] !== false) {
366: $this->request['raw'] .= $this->request['header'];
367: }
368:
369: $this->request['raw'] .= "\r\n";
370: $this->request['raw'] .= $this->request['body'];
371: $this->write($this->request['raw']);
372:
373: $response = null;
374: $inHeader = true;
375: while ($data = $this->read()) {
376: if ($this->_contentResource) {
377: if ($inHeader) {
378: $response .= $data;
379: $pos = strpos($response, "\r\n\r\n");
380: if ($pos !== false) {
381: $pos += 4;
382: $data = substr($response, $pos);
383: fwrite($this->_contentResource, $data);
384:
385: $response = substr($response, 0, $pos);
386: $inHeader = false;
387: }
388: } else {
389: fwrite($this->_contentResource, $data);
390: fflush($this->_contentResource);
391: }
392: } else {
393: $response .= $data;
394: }
395: }
396:
397: if ($connectionType === 'close') {
398: $this->disconnect();
399: }
400:
401: list($plugin, $responseClass) = pluginSplit($this->responseClass, true);
402: App::uses($responseClass, $plugin . 'Network/Http');
403: if (!class_exists($responseClass)) {
404: throw new SocketException(__d('cake_dev', 'Class %s not found.', $this->responseClass));
405: }
406: $this->response = new $responseClass($response);
407:
408: if (!empty($this->response->cookies)) {
409: if (!isset($this->config['request']['cookies'][$Host])) {
410: $this->config['request']['cookies'][$Host] = array();
411: }
412: $this->config['request']['cookies'][$Host] = array_merge($this->config['request']['cookies'][$Host], $this->response->cookies);
413: }
414:
415: if ($this->request['redirect'] && $this->response->isRedirect()) {
416: $request['uri'] = trim(urldecode($this->response->getHeader('Location')), '=');
417: $request['redirect'] = is_int($this->request['redirect']) ? $this->request['redirect'] - 1 : $this->request['redirect'];
418: $this->response = $this->request($request);
419: }
420:
421: return $this->response;
422: }
423:
424: 425: 426: 427: 428: 429: 430: 431: 432: 433: 434: 435: 436: 437: 438: 439: 440: 441: 442: 443: 444: 445: 446:
447: public function get($uri = null, $query = array(), $request = array()) {
448: if (!empty($query)) {
449: $uri = $this->_parseUri($uri, $this->config['request']['uri']);
450: if (isset($uri['query'])) {
451: $uri['query'] = array_merge($uri['query'], $query);
452: } else {
453: $uri['query'] = $query;
454: }
455: $uri = $this->_buildUri($uri);
456: }
457:
458: $request = Hash::merge(array('method' => 'GET', 'uri' => $uri), $request);
459: return $this->request($request);
460: }
461:
462: 463: 464: 465: 466: 467: 468: 469: 470: 471: 472: 473: 474: 475: 476: 477: 478:
479: public function post($uri = null, $data = array(), $request = array()) {
480: $request = Hash::merge(array('method' => 'POST', 'uri' => $uri, 'body' => $data), $request);
481: return $this->request($request);
482: }
483:
484: 485: 486: 487: 488: 489: 490: 491:
492: public function put($uri = null, $data = array(), $request = array()) {
493: $request = Hash::merge(array('method' => 'PUT', 'uri' => $uri, 'body' => $data), $request);
494: return $this->request($request);
495: }
496:
497: 498: 499: 500: 501: 502: 503: 504:
505: public function patch($uri = null, $data = array(), $request = array()) {
506: $request = Hash::merge(array('method' => 'PATCH', 'uri' => $uri, 'body' => $data), $request);
507: return $this->request($request);
508: }
509:
510: 511: 512: 513: 514: 515: 516: 517:
518: public function delete($uri = null, $data = array(), $request = array()) {
519: $request = Hash::merge(array('method' => 'DELETE', 'uri' => $uri, 'body' => $data), $request);
520: return $this->request($request);
521: }
522:
523: 524: 525: 526: 527: 528: 529: 530: 531: 532: 533: 534: 535: 536: 537: 538: 539: 540: 541: 542: 543: 544: 545: 546: 547: 548: 549:
550: public function url($url = null, $uriTemplate = null) {
551: if ($url === null) {
552: $url = '/';
553: }
554: if (is_string($url)) {
555: $scheme = $this->config['request']['uri']['scheme'];
556: if (is_array($scheme)) {
557: $scheme = $scheme[0];
558: }
559: $port = $this->config['request']['uri']['port'];
560: if (is_array($port)) {
561: $port = $port[0];
562: }
563: if ($url{0} === '/') {
564: $url = $this->config['request']['uri']['host'] . ':' . $port . $url;
565: }
566: if (!preg_match('/^.+:\/\/|\*|^\//', $url)) {
567: $url = $scheme . '://' . $url;
568: }
569: } elseif (!is_array($url) && !empty($url)) {
570: return false;
571: }
572:
573: $base = array_merge($this->config['request']['uri'], array('scheme' => array('http', 'https'), 'port' => array(80, 443)));
574: $url = $this->_parseUri($url, $base);
575:
576: if (empty($url)) {
577: $url = $this->config['request']['uri'];
578: }
579:
580: if (!empty($uriTemplate)) {
581: return $this->_buildUri($url, $uriTemplate);
582: }
583: return $this->_buildUri($url);
584: }
585:
586: 587: 588: 589: 590: 591:
592: protected function _setAuth() {
593: if (empty($this->_auth)) {
594: return;
595: }
596: $method = key($this->_auth);
597: list($plugin, $authClass) = pluginSplit($method, true);
598: $authClass = Inflector::camelize($authClass) . 'Authentication';
599: App::uses($authClass, $plugin . 'Network/Http');
600:
601: if (!class_exists($authClass)) {
602: throw new SocketException(__d('cake_dev', 'Unknown authentication method.'));
603: }
604: if (!method_exists($authClass, 'authentication')) {
605: throw new SocketException(__d('cake_dev', 'The %s does not support authentication.', $authClass));
606: }
607: call_user_func_array("$authClass::authentication", array($this, &$this->_auth[$method]));
608: }
609:
610: 611: 612: 613: 614: 615:
616: protected function _setProxy() {
617: if (empty($this->_proxy) || !isset($this->_proxy['host'], $this->_proxy['port'])) {
618: return;
619: }
620: $this->config['host'] = $this->_proxy['host'];
621: $this->config['port'] = $this->_proxy['port'];
622:
623: if (empty($this->_proxy['method']) || !isset($this->_proxy['user'], $this->_proxy['pass'])) {
624: return;
625: }
626: list($plugin, $authClass) = pluginSplit($this->_proxy['method'], true);
627: $authClass = Inflector::camelize($authClass) . 'Authentication';
628: App::uses($authClass, $plugin . 'Network/Http');
629:
630: if (!class_exists($authClass)) {
631: throw new SocketException(__d('cake_dev', 'Unknown authentication method for proxy.'));
632: }
633: if (!method_exists($authClass, 'proxyAuthentication')) {
634: throw new SocketException(__d('cake_dev', 'The %s does not support proxy authentication.', $authClass));
635: }
636: call_user_func_array("$authClass::proxyAuthentication", array($this, &$this->_proxy));
637: }
638:
639: 640: 641: 642: 643: 644:
645: protected function _configUri($uri = null) {
646: if (empty($uri)) {
647: return false;
648: }
649:
650: if (is_array($uri)) {
651: $uri = $this->_parseUri($uri);
652: } else {
653: $uri = $this->_parseUri($uri, true);
654: }
655:
656: if (!isset($uri['host'])) {
657: return false;
658: }
659: $config = array(
660: 'request' => array(
661: 'uri' => array_intersect_key($uri, $this->config['request']['uri'])
662: )
663: );
664: $this->config = Hash::merge($this->config, $config);
665: $this->config = Hash::merge($this->config, array_intersect_key($this->config['request']['uri'], $this->config));
666: return true;
667: }
668:
669: 670: 671: 672: 673: 674: 675:
676: protected function _configContext($host) {
677: foreach ($this->config as $key => $value) {
678: if (substr($key, 0, 4) !== 'ssl_') {
679: continue;
680: }
681: $contextKey = substr($key, 4);
682: if (empty($this->config['context']['ssl'][$contextKey])) {
683: $this->config['context']['ssl'][$contextKey] = $value;
684: }
685: unset($this->config[$key]);
686: }
687: if (empty($this->config['context']['ssl']['cafile'])) {
688: $this->config['context']['ssl']['cafile'] = CAKE . 'Config' . DS . 'cacert.pem';
689: }
690: if (!empty($this->config['context']['ssl']['verify_host'])) {
691: $this->config['context']['ssl']['CN_match'] = $host;
692: }
693: unset($this->config['context']['ssl']['verify_host']);
694: }
695:
696: 697: 698: 699: 700: 701: 702:
703: protected function _buildUri($uri = array(), $uriTemplate = '%scheme://%user:%pass@%host:%port/%path?%query#%fragment') {
704: if (is_string($uri)) {
705: $uri = array('host' => $uri);
706: }
707: $uri = $this->_parseUri($uri, true);
708:
709: if (!is_array($uri) || empty($uri)) {
710: return false;
711: }
712:
713: $uri['path'] = preg_replace('/^\//', null, $uri['path']);
714: $uri['query'] = http_build_query($uri['query'], '', '&');
715: $uri['query'] = rtrim($uri['query'], '=');
716: $stripIfEmpty = array(
717: 'query' => '?%query',
718: 'fragment' => '#%fragment',
719: 'user' => '%user:%pass@',
720: 'host' => '%host:%port/'
721: );
722:
723: foreach ($stripIfEmpty as $key => $strip) {
724: if (empty($uri[$key])) {
725: $uriTemplate = str_replace($strip, null, $uriTemplate);
726: }
727: }
728:
729: $defaultPorts = array('http' => 80, 'https' => 443);
730: if (array_key_exists($uri['scheme'], $defaultPorts) && $defaultPorts[$uri['scheme']] == $uri['port']) {
731: $uriTemplate = str_replace(':%port', null, $uriTemplate);
732: }
733: foreach ($uri as $property => $value) {
734: $uriTemplate = str_replace('%' . $property, $value, $uriTemplate);
735: }
736:
737: if ($uriTemplate === '/*') {
738: $uriTemplate = '*';
739: }
740: return $uriTemplate;
741: }
742:
743: 744: 745: 746: 747: 748: 749: 750:
751: protected function _parseUri($uri = null, $base = array()) {
752: $uriBase = array(
753: 'scheme' => array('http', 'https'),
754: 'host' => null,
755: 'port' => array(80, 443),
756: 'user' => null,
757: 'pass' => null,
758: 'path' => '/',
759: 'query' => null,
760: 'fragment' => null
761: );
762:
763: if (is_string($uri)) {
764: $uri = parse_url($uri);
765: }
766: if (!is_array($uri) || empty($uri)) {
767: return false;
768: }
769: if ($base === true) {
770: $base = $uriBase;
771: }
772:
773: if (isset($base['port'], $base['scheme']) && is_array($base['port']) && is_array($base['scheme'])) {
774: if (isset($uri['scheme']) && !isset($uri['port'])) {
775: $base['port'] = $base['port'][array_search($uri['scheme'], $base['scheme'])];
776: } elseif (isset($uri['port']) && !isset($uri['scheme'])) {
777: $base['scheme'] = $base['scheme'][array_search($uri['port'], $base['port'])];
778: }
779: }
780:
781: if (is_array($base) && !empty($base)) {
782: $uri = array_merge($base, $uri);
783: }
784:
785: if (isset($uri['scheme']) && is_array($uri['scheme'])) {
786: $uri['scheme'] = array_shift($uri['scheme']);
787: }
788: if (isset($uri['port']) && is_array($uri['port'])) {
789: $uri['port'] = array_shift($uri['port']);
790: }
791:
792: if (array_key_exists('query', $uri)) {
793: $uri['query'] = $this->_parseQuery($uri['query']);
794: }
795:
796: if (!array_intersect_key($uriBase, $uri)) {
797: return false;
798: }
799: return $uri;
800: }
801:
802: 803: 804: 805: 806: 807: 808: 809: 810: 811: 812: 813: 814: 815:
816: protected function _parseQuery($query) {
817: if (is_array($query)) {
818: return $query;
819: }
820:
821: $parsedQuery = array();
822:
823: if (is_string($query) && !empty($query)) {
824: $query = preg_replace('/^\?/', '', $query);
825: $items = explode('&', $query);
826:
827: foreach ($items as $item) {
828: if (strpos($item, '=') !== false) {
829: list($key, $value) = explode('=', $item, 2);
830: } else {
831: $key = $item;
832: $value = null;
833: }
834:
835: $key = urldecode($key);
836: $value = urldecode($value);
837:
838: if (preg_match_all('/\[([^\[\]]*)\]/iUs', $key, $matches)) {
839: $subKeys = $matches[1];
840: $rootKey = substr($key, 0, strpos($key, '['));
841: if (!empty($rootKey)) {
842: array_unshift($subKeys, $rootKey);
843: }
844: $queryNode =& $parsedQuery;
845:
846: foreach ($subKeys as $subKey) {
847: if (!is_array($queryNode)) {
848: $queryNode = array();
849: }
850:
851: if ($subKey === '') {
852: $queryNode[] = array();
853: end($queryNode);
854: $subKey = key($queryNode);
855: }
856: $queryNode =& $queryNode[$subKey];
857: }
858: $queryNode = $value;
859: continue;
860: }
861: if (!isset($parsedQuery[$key])) {
862: $parsedQuery[$key] = $value;
863: } else {
864: $parsedQuery[$key] = (array)$parsedQuery[$key];
865: $parsedQuery[$key][] = $value;
866: }
867: }
868: }
869: return $parsedQuery;
870: }
871:
872: 873: 874: 875: 876: 877: 878: 879:
880: protected function _buildRequestLine($request = array(), $versionToken = 'HTTP/1.1') {
881: $asteriskMethods = array('OPTIONS');
882:
883: if (is_string($request)) {
884: $isValid = preg_match("/(.+) (.+) (.+)\r\n/U", $request, $match);
885: if (!$this->quirksMode && (!$isValid || ($match[2] === '*' && !in_array($match[3], $asteriskMethods)))) {
886: throw new SocketException(__d('cake_dev', 'HttpSocket::_buildRequestLine - Passed an invalid request line string. Activate quirks mode to do this.'));
887: }
888: return $request;
889: } elseif (!is_array($request)) {
890: return false;
891: } elseif (!array_key_exists('uri', $request)) {
892: return false;
893: }
894:
895: $request['uri'] = $this->_parseUri($request['uri']);
896: $request = array_merge(array('method' => 'GET'), $request);
897: if (!empty($this->_proxy['host'])) {
898: $request['uri'] = $this->_buildUri($request['uri'], '%scheme://%host:%port/%path?%query');
899: } else {
900: $request['uri'] = $this->_buildUri($request['uri'], '/%path?%query');
901: }
902:
903: if (!$this->quirksMode && $request['uri'] === '*' && !in_array($request['method'], $asteriskMethods)) {
904: 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)));
905: }
906: return $request['method'] . ' ' . $request['uri'] . ' ' . $versionToken . "\r\n";
907: }
908:
909: 910: 911: 912: 913: 914: 915:
916: protected function _buildHeader($header, $mode = 'standard') {
917: if (is_string($header)) {
918: return $header;
919: } elseif (!is_array($header)) {
920: return false;
921: }
922:
923: $fieldsInHeader = array();
924: foreach ($header as $key => $value) {
925: $lowKey = strtolower($key);
926: if (array_key_exists($lowKey, $fieldsInHeader)) {
927: $header[$fieldsInHeader[$lowKey]] = $value;
928: unset($header[$key]);
929: } else {
930: $fieldsInHeader[$lowKey] = $key;
931: }
932: }
933:
934: $returnHeader = '';
935: foreach ($header as $field => $contents) {
936: if (is_array($contents) && $mode === 'standard') {
937: $contents = implode(',', $contents);
938: }
939: foreach ((array)$contents as $content) {
940: $contents = preg_replace("/\r\n(?![\t ])/", "\r\n ", $content);
941: $field = $this->_escapeToken($field);
942:
943: $returnHeader .= $field . ': ' . $contents . "\r\n";
944: }
945: }
946: return $returnHeader;
947: }
948:
949: 950: 951: 952: 953: 954: 955: 956: 957:
958: public function buildCookies($cookies) {
959: $header = array();
960: foreach ($cookies as $name => $cookie) {
961: if (is_array($cookie)) {
962: $value = $this->_escapeToken($cookie['value'], array(';'));
963: } else {
964: $value = $this->_escapeToken($cookie, array(';'));
965: }
966: $header[] = $name . '=' . $value;
967: }
968: return $this->_buildHeader(array('Cookie' => implode('; ', $header)), 'pragmatic');
969: }
970:
971: 972: 973: 974: 975: 976: 977:
978: protected function _escapeToken($token, $chars = null) {
979: $regex = '/([' . implode('', $this->_tokenEscapeChars(true, $chars)) . '])/';
980: $token = preg_replace($regex, '"\\1"', $token);
981: return $token;
982: }
983:
984: 985: 986: 987: 988: 989: 990:
991: protected function _tokenEscapeChars($hex = true, $chars = null) {
992: if (!empty($chars)) {
993: $escape = $chars;
994: } else {
995: $escape = array('"', "(", ")", "<", ">", "@", ",", ";", ":", "\\", "/", "[", "]", "?", "=", "{", "}", " ");
996: for ($i = 0; $i <= 31; $i++) {
997: $escape[] = chr($i);
998: }
999: $escape[] = chr(127);
1000: }
1001:
1002: if (!$hex) {
1003: return $escape;
1004: }
1005: foreach ($escape as $key => $char) {
1006: $escape[$key] = '\\x' . str_pad(dechex(ord($char)), 2, '0', STR_PAD_LEFT);
1007: }
1008: return $escape;
1009: }
1010:
1011: 1012: 1013: 1014: 1015: 1016: 1017:
1018: public function reset($full = true) {
1019: static $initalState = array();
1020: if (empty($initalState)) {
1021: $initalState = get_class_vars(__CLASS__);
1022: }
1023: if (!$full) {
1024: $this->request = $initalState['request'];
1025: $this->response = $initalState['response'];
1026: return true;
1027: }
1028: parent::reset($initalState);
1029: return true;
1030: }
1031:
1032: }
1033: