1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23:
24: App::import('Core', array('Socket', 'Set', 'Router'));
25: 26: 27: 28: 29: 30: 31: 32:
33: class HttpSocket extends CakeSocket {
34: 35: 36: 37: 38: 39:
40: var $description = 'HTTP-based DataSource Interface';
41: 42: 43: 44: 45: 46: 47:
48: var $quirksMode = false;
49: 50: 51: 52: 53: 54:
55: var $request = array(
56: 'method' => 'GET',
57: 'uri' => array(
58: 'scheme' => 'http',
59: 'host' => null,
60: 'port' => 80,
61: 'user' => null,
62: 'pass' => null,
63: 'path' => null,
64: 'query' => null,
65: 'fragment' => null
66: ),
67: 'auth' => array(
68: 'method' => 'Basic',
69: 'user' => null,
70: 'pass' => null
71: ),
72: 'version' => '1.1',
73: 'body' => '',
74: 'line' => null,
75: 'header' => array(
76: 'Connection' => 'close',
77: 'User-Agent' => 'CakePHP'
78: ),
79: 'raw' => null,
80: 'cookies' => array()
81: );
82: 83: 84: 85: 86: 87:
88: var $response = array(
89: 'raw' => array(
90: 'status-line' => null,
91: 'header' => null,
92: 'body' => null,
93: 'response' => null
94: ),
95: 'status' => array(
96: 'http-version' => null,
97: 'code' => null,
98: 'reason-phrase' => null
99: ),
100: 'header' => array(),
101: 'body' => '',
102: 'cookies' => array()
103: );
104: 105: 106: 107: 108: 109:
110: var $config = array(
111: 'persistent' => false,
112: 'host' => 'localhost',
113: 'protocol' => 'tcp',
114: 'port' => 80,
115: 'timeout' => 30,
116: 'request' => array(
117: 'uri' => array(
118: 'scheme' => 'http',
119: 'host' => 'localhost',
120: 'port' => 80
121: ),
122: 'auth' => array(
123: 'method' => 'Basic',
124: 'user' => null,
125: 'pass' => null
126: ),
127: 'cookies' => array()
128: )
129: );
130: 131: 132: 133: 134: 135:
136: var $lineBreak = "\r\n";
137:
138: 139: 140: 141: 142:
143: function __construct($config = array()) {
144: if (is_string($config)) {
145: $this->configUri($config);
146: } elseif (is_array($config)) {
147: if (isset($config['request']['uri']) && is_string($config['request']['uri'])) {
148: $this->configUri($config['request']['uri']);
149: unset($config['request']['uri']);
150: }
151: $this->config = Set::merge($this->config, $config);
152: }
153: parent::__construct($this->config);
154: }
155: 156: 157: 158: 159: 160: 161:
162: function request($request = array()) {
163: $this->reset(false);
164:
165: if (is_string($request)) {
166: $request = array('uri' => $request);
167: } elseif (!is_array($request)) {
168: return false;
169: }
170:
171: if (!isset($request['uri'])) {
172: $request['uri'] = null;
173: }
174:
175: $uri = $this->parseUri($request['uri']);
176: $hadAuth = false;
177: if (is_array($uri) && array_key_exists('user', $uri)) {
178: $hadAuth = true;
179: }
180:
181: if (!isset($uri['host'])) {
182: $host = $this->config['host'];
183: }
184: if (isset($request['host'])) {
185: $host = $request['host'];
186: unset($request['host']);
187: }
188: $request['uri'] = $this->url($request['uri']);
189: $request['uri'] = $this->parseUri($request['uri'], true);
190: $this->request = Set::merge($this->request, $this->config['request'], $request);
191:
192: if (!$hadAuth && !empty($this->config['request']['auth']['user'])) {
193: $this->request['uri']['user'] = $this->config['request']['auth']['user'];
194: $this->request['uri']['pass'] = $this->config['request']['auth']['pass'];
195: }
196: $this->configUri($this->request['uri']);
197:
198: if (isset($host)) {
199: $this->config['host'] = $host;
200: }
201: $cookies = null;
202:
203: if (is_array($this->request['header'])) {
204: $this->request['header'] = $this->parseHeader($this->request['header']);
205: if (!empty($this->request['cookies'])) {
206: $cookies = $this->buildCookies($this->request['cookies']);
207: }
208: $Host = $this->request['uri']['host'];
209: $schema = '';
210: $port = 0;
211: if (isset($this->request['uri']['schema'])) {
212: $schema = $this->request['uri']['schema'];
213: }
214: if (isset($this->request['uri']['port'])) {
215: $port = $this->request['uri']['port'];
216: }
217: if (
218: ($schema === 'http' && $port != 80) ||
219: ($schema === 'https' && $port != 443) ||
220: ($port != 80 && $port != 443)
221: ) {
222: $Host .= ':' . $port;
223: }
224: $this->request['header'] = array_merge(compact('Host'), $this->request['header']);
225: }
226:
227: if (isset($this->request['auth']['user']) && isset($this->request['auth']['pass'])) {
228: $this->request['header']['Authorization'] = $this->request['auth']['method'] . " " . base64_encode($this->request['auth']['user'] . ":" . $this->request['auth']['pass']);
229: }
230: if (isset($this->request['uri']['user']) && isset($this->request['uri']['pass'])) {
231: $this->request['header']['Authorization'] = $this->request['auth']['method'] . " " . base64_encode($this->request['uri']['user'] . ":" . $this->request['uri']['pass']);
232: }
233:
234: if (is_array($this->request['body'])) {
235: $this->request['body'] = $this->httpSerialize($this->request['body']);
236: }
237:
238: if (!empty($this->request['body']) && !isset($this->request['header']['Content-Type'])) {
239: $this->request['header']['Content-Type'] = 'application/x-www-form-urlencoded';
240: }
241:
242: if (!empty($this->request['body']) && !isset($this->request['header']['Content-Length'])) {
243: $this->request['header']['Content-Length'] = strlen($this->request['body']);
244: }
245:
246: $connectionType = null;
247: if (isset($this->request['header']['Connection'])) {
248: $connectionType = $this->request['header']['Connection'];
249: }
250: $this->request['header'] = $this->buildHeader($this->request['header']).$cookies;
251:
252: if (empty($this->request['line'])) {
253: $this->request['line'] = $this->buildRequestLine($this->request);
254: }
255:
256: if ($this->quirksMode === false && $this->request['line'] === false) {
257: return $this->response = false;
258: }
259:
260: if ($this->request['line'] !== false) {
261: $this->request['raw'] = $this->request['line'];
262: }
263:
264: if ($this->request['header'] !== false) {
265: $this->request['raw'] .= $this->request['header'];
266: }
267:
268: $this->request['raw'] .= "\r\n";
269: $this->request['raw'] .= $this->request['body'];
270: $this->write($this->request['raw']);
271:
272: $response = null;
273: while ($data = $this->read()) {
274: $response .= $data;
275: }
276:
277: if ($connectionType == 'close') {
278: $this->disconnect();
279: }
280:
281: $this->response = $this->parseResponse($response);
282: if (!empty($this->response['cookies'])) {
283: $this->config['request']['cookies'] = array_merge($this->config['request']['cookies'], $this->response['cookies']);
284: }
285:
286: return $this->response['body'];
287: }
288: 289: 290: 291: 292: 293: 294: 295: 296:
297: function get($uri = null, $query = array(), $request = array()) {
298: if (!empty($query)) {
299: $uri =$this->parseUri($uri);
300: if (isset($uri['query'])) {
301: $uri['query'] = array_merge($uri['query'], $query);
302: } else {
303: $uri['query'] = $query;
304: }
305: $uri = $this->buildUri($uri);
306: }
307:
308: $request = Set::merge(array('method' => 'GET', 'uri' => $uri), $request);
309: return $this->request($request);
310: }
311:
312: 313: 314: 315: 316: 317: 318: 319: 320:
321: function post($uri = null, $data = array(), $request = array()) {
322: $request = Set::merge(array('method' => 'POST', 'uri' => $uri, 'body' => $data), $request);
323: return $this->request($request);
324: }
325: 326: 327: 328: 329: 330: 331: 332: 333:
334: function put($uri = null, $data = array(), $request = array()) {
335: $request = Set::merge(array('method' => 'PUT', 'uri' => $uri, 'body' => $data), $request);
336: return $this->request($request);
337: }
338: 339: 340: 341: 342: 343: 344: 345: 346:
347: function delete($uri = null, $data = array(), $request = array()) {
348: $request = Set::merge(array('method' => 'DELETE', 'uri' => $uri, 'body' => $data), $request);
349: return $this->request($request);
350: }
351: 352: 353: 354: 355: 356: 357: 358:
359: function url($url = null, $uriTemplate = null) {
360: if (is_null($url)) {
361: $url = '/';
362: }
363: if (is_string($url)) {
364: if ($url{0} == '/') {
365: $url = $this->config['request']['uri']['host'].':'.$this->config['request']['uri']['port'] . $url;
366: }
367: if (!preg_match('/^.+:\/\/|\*|^\//', $url)) {
368: $url = $this->config['request']['uri']['scheme'].'://'.$url;
369: }
370: } elseif (!is_array($url) && !empty($url)) {
371: return false;
372: }
373:
374: $base = array_merge($this->config['request']['uri'], array('scheme' => array('http', 'https'), 'port' => array(80, 443)));
375: $url = $this->parseUri($url, $base);
376:
377: if (empty($url)) {
378: $url = $this->config['request']['uri'];
379: }
380:
381: if (!empty($uriTemplate)) {
382: return $this->buildUri($url, $uriTemplate);
383: }
384: return $this->buildUri($url);
385: }
386: 387: 388: 389: 390: 391: 392:
393: function parseResponse($message) {
394: if (is_array($message)) {
395: return $message;
396: } elseif (!is_string($message)) {
397: return false;
398: }
399:
400: static $responseTemplate;
401:
402: if (empty($responseTemplate)) {
403: $classVars = get_class_vars(__CLASS__);
404: $responseTemplate = $classVars['response'];
405: }
406:
407: $response = $responseTemplate;
408:
409: if (!preg_match("/^(.+\r\n)(.*)(?<=\r\n)\r\n/Us", $message, $match)) {
410: return false;
411: }
412:
413: list($null, $response['raw']['status-line'], $response['raw']['header']) = $match;
414: $response['raw']['response'] = $message;
415: $response['raw']['body'] = substr($message, strlen($match[0]));
416:
417: if (preg_match("/(.+) ([0-9]{3}) (.+)\r\n/DU", $response['raw']['status-line'], $match)) {
418: $response['status']['http-version'] = $match[1];
419: $response['status']['code'] = (int)$match[2];
420: $response['status']['reason-phrase'] = $match[3];
421: }
422:
423: $response['header'] = $this->parseHeader($response['raw']['header']);
424: $transferEncoding = null;
425: if (isset($response['header']['Transfer-Encoding'])) {
426: $transferEncoding = $response['header']['Transfer-Encoding'];
427: }
428: $decoded = $this->decodeBody($response['raw']['body'], $transferEncoding);
429: $response['body'] = $decoded['body'];
430:
431: if (!empty($decoded['header'])) {
432: $response['header'] = $this->parseHeader($this->buildHeader($response['header']).$this->buildHeader($decoded['header']));
433: }
434:
435: if (!empty($response['header'])) {
436: $response['cookies'] = $this->parseCookies($response['header']);
437: }
438:
439: foreach ($response['raw'] as $field => $val) {
440: if ($val === '') {
441: $response['raw'][$field] = null;
442: }
443: }
444:
445: return $response;
446: }
447: 448: 449: 450: 451: 452: 453: 454: 455:
456: function decodeBody($body, $encoding = 'chunked') {
457: if (!is_string($body)) {
458: return false;
459: }
460: if (empty($encoding)) {
461: return array('body' => $body, 'header' => false);
462: }
463: $decodeMethod = 'decode'.Inflector::camelize(str_replace('-', '_', $encoding)).'Body';
464:
465: if (!is_callable(array(&$this, $decodeMethod))) {
466: if (!$this->quirksMode) {
467: trigger_error(sprintf(__('HttpSocket::decodeBody - Unknown encoding: %s. Activate quirks mode to surpress error.', true), h($encoding)), E_USER_WARNING);
468: }
469: return array('body' => $body, 'header' => false);
470: }
471: return $this->{$decodeMethod}($body);
472: }
473: 474: 475: 476: 477: 478: 479: 480:
481: function decodeChunkedBody($body) {
482: if (!is_string($body)) {
483: return false;
484: }
485:
486: $decodedBody = null;
487: $chunkLength = null;
488:
489: while ($chunkLength !== 0) {
490: if (!preg_match("/^([0-9a-f]+) *(?:;(.+)=(.+))?\r\n/iU", $body, $match)) {
491: if (!$this->quirksMode) {
492: trigger_error(__('HttpSocket::decodeChunkedBody - Could not parse malformed chunk. Activate quirks mode to do this.', true), E_USER_WARNING);
493: return false;
494: }
495: break;
496: }
497:
498: $chunkSize = 0;
499: $hexLength = 0;
500: $chunkExtensionName = '';
501: $chunkExtensionValue = '';
502: if (isset($match[0])) {
503: $chunkSize = $match[0];
504: }
505: if (isset($match[1])) {
506: $hexLength = $match[1];
507: }
508: if (isset($match[2])) {
509: $chunkExtensionName = $match[2];
510: }
511: if (isset($match[3])) {
512: $chunkExtensionValue = $match[3];
513: }
514:
515: $body = substr($body, strlen($chunkSize));
516: $chunkLength = hexdec($hexLength);
517: $chunk = substr($body, 0, $chunkLength);
518: if (!empty($chunkExtensionName)) {
519: 520: 521:
522: }
523: $decodedBody .= $chunk;
524: if ($chunkLength !== 0) {
525: $body = substr($body, $chunkLength+strlen("\r\n"));
526: }
527: }
528:
529: $entityHeader = false;
530: if (!empty($body)) {
531: $entityHeader = $this->parseHeader($body);
532: }
533: return array('body' => $decodedBody, 'header' => $entityHeader);
534: }
535: 536: 537: 538: 539: 540: 541:
542: function configUri($uri = null) {
543: if (empty($uri)) {
544: return false;
545: }
546:
547: if (is_array($uri)) {
548: $uri = $this->parseUri($uri);
549: } else {
550: $uri = $this->parseUri($uri, true);
551: }
552:
553: if (!isset($uri['host'])) {
554: return false;
555: }
556: $config = array(
557: 'request' => array(
558: 'uri' => array_intersect_key($uri, $this->config['request']['uri']),
559: 'auth' => array_intersect_key($uri, $this->config['request']['auth'])
560: )
561: );
562: $this->config = Set::merge($this->config, $config);
563: $this->config = Set::merge($this->config, array_intersect_key($this->config['request']['uri'], $this->config));
564: return $this->config;
565: }
566: 567: 568: 569: 570: 571: 572: 573:
574: function buildUri($uri = array(), $uriTemplate = '%scheme://%user:%pass@%host:%port/%path?%query#%fragment') {
575: if (is_string($uri)) {
576: $uri = array('host' => $uri);
577: }
578: $uri = $this->parseUri($uri, true);
579:
580: if (!is_array($uri) || empty($uri)) {
581: return false;
582: }
583:
584: $uri['path'] = preg_replace('/^\//', null, $uri['path']);
585: $uri['query'] = $this->httpSerialize($uri['query']);
586: $stripIfEmpty = array(
587: 'query' => '?%query',
588: 'fragment' => '#%fragment',
589: 'user' => '%user:%pass@',
590: 'host' => '%host:%port/'
591: );
592:
593: foreach ($stripIfEmpty as $key => $strip) {
594: if (empty($uri[$key])) {
595: $uriTemplate = str_replace($strip, null, $uriTemplate);
596: }
597: }
598:
599: $defaultPorts = array('http' => 80, 'https' => 443);
600: if (array_key_exists($uri['scheme'], $defaultPorts) && $defaultPorts[$uri['scheme']] == $uri['port']) {
601: $uriTemplate = str_replace(':%port', null, $uriTemplate);
602: }
603: foreach ($uri as $property => $value) {
604: $uriTemplate = str_replace('%'.$property, $value, $uriTemplate);
605: }
606:
607: if ($uriTemplate === '/*') {
608: $uriTemplate = '*';
609: }
610: return $uriTemplate;
611: }
612: 613: 614: 615: 616: 617: 618: 619: 620:
621: function parseUri($uri = null, $base = array()) {
622: $uriBase = array(
623: 'scheme' => array('http', 'https'),
624: 'host' => null,
625: 'port' => array(80, 443),
626: 'user' => null,
627: 'pass' => null,
628: 'path' => '/',
629: 'query' => null,
630: 'fragment' => null
631: );
632:
633: if (is_string($uri)) {
634: $uri = parse_url($uri);
635: }
636: if (!is_array($uri) || empty($uri)) {
637: return false;
638: }
639: if ($base === true) {
640: $base = $uriBase;
641: }
642:
643: if (isset($base['port'], $base['scheme']) && is_array($base['port']) && is_array($base['scheme'])) {
644: if (isset($uri['scheme']) && !isset($uri['port'])) {
645: $base['port'] = $base['port'][array_search($uri['scheme'], $base['scheme'])];
646: } elseif (isset($uri['port']) && !isset($uri['scheme'])) {
647: $base['scheme'] = $base['scheme'][array_search($uri['port'], $base['port'])];
648: }
649: }
650:
651: if (is_array($base) && !empty($base)) {
652: $uri = array_merge($base, $uri);
653: }
654:
655: if (isset($uri['scheme']) && is_array($uri['scheme'])) {
656: $uri['scheme'] = array_shift($uri['scheme']);
657: }
658: if (isset($uri['port']) && is_array($uri['port'])) {
659: $uri['port'] = array_shift($uri['port']);
660: }
661:
662: if (array_key_exists('query', $uri)) {
663: $uri['query'] = $this->parseQuery($uri['query']);
664: }
665:
666: if (!array_intersect_key($uriBase, $uri)) {
667: return false;
668: }
669: return $uri;
670: }
671: 672: 673: 674: 675: 676: 677: 678: 679: 680: 681: 682: 683: 684:
685: function parseQuery($query) {
686: if (is_array($query)) {
687: return $query;
688: }
689: $parsedQuery = array();
690:
691: if (is_string($query) && !empty($query)) {
692: $query = preg_replace('/^\?/', '', $query);
693: $items = explode('&', $query);
694:
695: foreach ($items as $item) {
696: if (strpos($item, '=') !== false) {
697: list($key, $value) = explode('=', $item, 2);
698: } else {
699: $key = $item;
700: $value = null;
701: }
702:
703: $key = urldecode($key);
704: $value = urldecode($value);
705:
706: if (preg_match_all('/\[([^\[\]]*)\]/iUs', $key, $matches)) {
707: $subKeys = $matches[1];
708: $rootKey = substr($key, 0, strpos($key, '['));
709: if (!empty($rootKey)) {
710: array_unshift($subKeys, $rootKey);
711: }
712: $queryNode =& $parsedQuery;
713:
714: foreach ($subKeys as $subKey) {
715: if (!is_array($queryNode)) {
716: $queryNode = array();
717: }
718:
719: if ($subKey === '') {
720: $queryNode[] = array();
721: end($queryNode);
722: $subKey = key($queryNode);
723: }
724: $queryNode =& $queryNode[$subKey];
725: }
726: $queryNode = $value;
727: } else {
728: $parsedQuery[$key] = $value;
729: }
730: }
731: }
732: return $parsedQuery;
733: }
734: 735: 736: 737: 738: 739: 740: 741:
742: function buildRequestLine($request = array(), $versionToken = 'HTTP/1.1') {
743: $asteriskMethods = array('OPTIONS');
744:
745: if (is_string($request)) {
746: $isValid = preg_match("/(.+) (.+) (.+)\r\n/U", $request, $match);
747: if (!$this->quirksMode && (!$isValid || ($match[2] == '*' && !in_array($match[3], $asteriskMethods)))) {
748: trigger_error(__('HttpSocket::buildRequestLine - Passed an invalid request line string. Activate quirks mode to do this.', true), E_USER_WARNING);
749: return false;
750: }
751: return $request;
752: } elseif (!is_array($request)) {
753: return false;
754: } elseif (!array_key_exists('uri', $request)) {
755: return false;
756: }
757:
758: $request['uri'] = $this->parseUri($request['uri']);
759: $request = array_merge(array('method' => 'GET'), $request);
760: $request['uri'] = $this->buildUri($request['uri'], '/%path?%query');
761:
762: if (!$this->quirksMode && $request['uri'] === '*' && !in_array($request['method'], $asteriskMethods)) {
763: trigger_error(sprintf(__('HttpSocket::buildRequestLine - The "*" asterisk character is only allowed for the following methods: %s. Activate quirks mode to work outside of HTTP/1.1 specs.', true), implode(',', $asteriskMethods)), E_USER_WARNING);
764: return false;
765: }
766: return $request['method'].' '.$request['uri'].' '.$versionToken.$this->lineBreak;
767: }
768: 769: 770: 771: 772: 773: 774:
775: function httpSerialize($data = array()) {
776: if (is_string($data)) {
777: return $data;
778: }
779: if (empty($data) || !is_array($data)) {
780: return false;
781: }
782: return substr(Router::queryString($data), 1);
783: }
784: 785: 786: 787: 788: 789: 790:
791: function buildHeader($header, $mode = 'standard') {
792: if (is_string($header)) {
793: return $header;
794: } elseif (!is_array($header)) {
795: return false;
796: }
797:
798: $returnHeader = '';
799: foreach ($header as $field => $contents) {
800: if (is_array($contents) && $mode == 'standard') {
801: $contents = implode(',', $contents);
802: }
803: foreach ((array)$contents as $content) {
804: $contents = preg_replace("/\r\n(?![\t ])/", "\r\n ", $content);
805: $field = $this->escapeToken($field);
806:
807: $returnHeader .= $field.': '.$contents.$this->lineBreak;
808: }
809: }
810: return $returnHeader;
811: }
812:
813: 814: 815: 816: 817: 818: 819:
820: function parseHeader($header) {
821: if (is_array($header)) {
822: foreach ($header as $field => $value) {
823: unset($header[$field]);
824: $field = strtolower($field);
825: preg_match_all('/(?:^|(?<=-))[a-z]/U', $field, $offsets, PREG_OFFSET_CAPTURE);
826:
827: foreach ($offsets[0] as $offset) {
828: $field = substr_replace($field, strtoupper($offset[0]), $offset[1], 1);
829: }
830: $header[$field] = $value;
831: }
832: return $header;
833: } elseif (!is_string($header)) {
834: return false;
835: }
836:
837: preg_match_all("/(.+):(.+)(?:(?<![\t ])" . $this->lineBreak . "|\$)/Uis", $header, $matches, PREG_SET_ORDER);
838:
839: $header = array();
840: foreach ($matches as $match) {
841: list(, $field, $value) = $match;
842:
843: $value = trim($value);
844: $value = preg_replace("/[\t ]\r\n/", "\r\n", $value);
845:
846: $field = $this->unescapeToken($field);
847:
848: $field = strtolower($field);
849: preg_match_all('/(?:^|(?<=-))[a-z]/U', $field, $offsets, PREG_OFFSET_CAPTURE);
850: foreach ($offsets[0] as $offset) {
851: $field = substr_replace($field, strtoupper($offset[0]), $offset[1], 1);
852: }
853:
854: if (!isset($header[$field])) {
855: $header[$field] = $value;
856: } else {
857: $header[$field] = array_merge((array)$header[$field], (array)$value);
858: }
859: }
860: return $header;
861: }
862: 863: 864: 865: 866: 867: 868: 869:
870: function parseCookies($header) {
871: if (!isset($header['Set-Cookie'])) {
872: return false;
873: }
874:
875: $cookies = array();
876: foreach ((array)$header['Set-Cookie'] as $cookie) {
877: if (strpos($cookie, '";"') !== false) {
878: $cookie = str_replace('";"', "{__cookie_replace__}", $cookie);
879: $parts = str_replace("{__cookie_replace__}", '";"', explode(';', $cookie));
880: } else {
881: $parts = preg_split('/\;[ \t]*/', $cookie);
882: }
883:
884: list($name, $value) = explode('=', array_shift($parts), 2);
885: $cookies[$name] = compact('value');
886:
887: foreach ($parts as $part) {
888: if (strpos($part, '=') !== false) {
889: list($key, $value) = explode('=', $part);
890: } else {
891: $key = $part;
892: $value = true;
893: }
894:
895: $key = strtolower($key);
896: if (!isset($cookies[$name][$key])) {
897: $cookies[$name][$key] = $value;
898: }
899: }
900: }
901: return $cookies;
902: }
903: 904: 905: 906: 907: 908: 909: 910:
911: function buildCookies($cookies) {
912: $header = array();
913: foreach ($cookies as $name => $cookie) {
914: $header[] = $name.'='.$this->escapeToken($cookie['value'], array(';'));
915: }
916: $header = $this->buildHeader(array('Cookie' => implode('; ', $header)), 'pragmatic');
917: return $header;
918: }
919: 920: 921: 922: 923: 924:
925: function saveCookies() {
926:
927: }
928: 929: 930: 931: 932: 933:
934: function loadCookies() {
935:
936: }
937: 938: 939: 940: 941: 942: 943: 944:
945: function unescapeToken($token, $chars = null) {
946: $regex = '/"(['.implode('', $this->__tokenEscapeChars(true, $chars)).'])"/';
947: $token = preg_replace($regex, '\\1', $token);
948: return $token;
949: }
950: 951: 952: 953: 954: 955: 956: 957:
958: function escapeToken($token, $chars = null) {
959: $regex = '/(['.implode('', $this->__tokenEscapeChars(true, $chars)).'])/';
960: $token = preg_replace($regex, '"\\1"', $token);
961: return $token;
962: }
963: 964: 965: 966: 967: 968: 969: 970:
971: function __tokenEscapeChars($hex = true, $chars = null) {
972: if (!empty($chars)) {
973: $escape = $chars;
974: } else {
975: $escape = array('"', "(", ")", "<", ">", "@", ",", ";", ":", "\\", "/", "[", "]", "?", "=", "{", "}", " ");
976: for ($i = 0; $i <= 31; $i++) {
977: $escape[] = chr($i);
978: }
979: $escape[] = chr(127);
980: }
981:
982: if ($hex == false) {
983: return $escape;
984: }
985: $regexChars = '';
986: foreach ($escape as $key => $char) {
987: $escape[$key] = '\\x'.str_pad(dechex(ord($char)), 2, '0', STR_PAD_LEFT);
988: }
989: return $escape;
990: }
991: 992: 993: 994: 995: 996: 997: 998:
999: function reset($full = true) {
1000: static $initalState = array();
1001: if (empty($initalState)) {
1002: $initalState = get_class_vars(__CLASS__);
1003: }
1004: if ($full == false) {
1005: $this->request = $initalState['request'];
1006: $this->response = $initalState['response'];
1007: return true;
1008: }
1009: parent::reset($initalState);
1010: return true;
1011: }
1012: }
1013: ?>