Subversion Repositories php-qbpwcf

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3 liveuser 1
<?php
2
 
3
namespace Guzzle\Parser\Cookie;
4
 
5
/**
6
 * Default Guzzle implementation of a Cookie parser
7
 */
8
class CookieParser implements CookieParserInterface
9
{
10
    /** @var array Cookie part names to snake_case array values */
11
    protected static $cookieParts = array(
12
        'domain'      => 'Domain',
13
        'path'        => 'Path',
14
        'max_age'     => 'Max-Age',
15
        'expires'     => 'Expires',
16
        'version'     => 'Version',
17
        'secure'      => 'Secure',
18
        'port'        => 'Port',
19
        'discard'     => 'Discard',
20
        'comment'     => 'Comment',
21
        'comment_url' => 'Comment-Url',
22
        'http_only'   => 'HttpOnly'
23
    );
24
 
25
    public function parseCookie($cookie, $host = null, $path = null, $decode = false)
26
    {
27
        // Explode the cookie string using a series of semicolons
28
        $pieces = array_filter(array_map('trim', explode(';', $cookie)));
29
 
30
        // The name of the cookie (first kvp) must include an equal sign.
31
        if (empty($pieces) || !strpos($pieces[0], '=')) {
32
            return false;
33
        }
34
 
35
        // Create the default return array
36
        $data = array_merge(array_fill_keys(array_keys(self::$cookieParts), null), array(
37
            'cookies'   => array(),
38
            'data'      => array(),
39
            'path'      => null,
40
            'http_only' => false,
41
            'discard'   => false,
42
            'domain'    => $host
43
        ));
44
        $foundNonCookies = 0;
45
 
46
        // Add the cookie pieces into the parsed data array
47
        foreach ($pieces as $part) {
48
 
49
            $cookieParts = explode('=', $part, 2);
50
            $key = trim($cookieParts[0]);
51
 
52
            if (count($cookieParts) == 1) {
53
                // Can be a single value (e.g. secure, httpOnly)
54
                $value = true;
55
            } else {
56
                // Be sure to strip wrapping quotes
57
                $value = trim($cookieParts[1], " \n\r\t\0\x0B\"");
58
                if ($decode) {
59
                    $value = urldecode($value);
60
                }
61
            }
62
 
63
            // Only check for non-cookies when cookies have been found
64
            if (!empty($data['cookies'])) {
65
                foreach (self::$cookieParts as $mapValue => $search) {
66
                    if (!strcasecmp($search, $key)) {
67
                        $data[$mapValue] = $mapValue == 'port' ? array_map('trim', explode(',', $value)) : $value;
68
                        $foundNonCookies++;
69
                        continue 2;
70
                    }
71
                }
72
            }
73
 
74
            // If cookies have not yet been retrieved, or this value was not found in the pieces array, treat it as a
75
            // cookie. IF non-cookies have been parsed, then this isn't a cookie, it's cookie data. Cookies then data.
76
            $data[$foundNonCookies ? 'data' : 'cookies'][$key] = $value;
77
        }
78
 
79
        // Calculate the expires date
80
        if (!$data['expires'] && $data['max_age']) {
81
            $data['expires'] = time() + (int) $data['max_age'];
82
        }
83
 
84
        // Check path attribute according RFC6265 http://tools.ietf.org/search/rfc6265#section-5.2.4
85
        // "If the attribute-value is empty or if the first character of the
86
        // attribute-value is not %x2F ("/"):
87
        //   Let cookie-path be the default-path.
88
        // Otherwise:
89
        //   Let cookie-path be the attribute-value."
90
        if (!$data['path'] || substr($data['path'], 0, 1) !== '/') {
91
            $data['path'] = $this->getDefaultPath($path);
92
        }
93
 
94
        return $data;
95
    }
96
 
97
    /**
98
     * Get default cookie path according to RFC 6265
99
     * http://tools.ietf.org/search/rfc6265#section-5.1.4 Paths and Path-Match
100
     *
101
     * @param string $path Request uri-path
102
     *
103
     * @return string
104
     */
105
    protected function getDefaultPath($path) {
106
        // "The user agent MUST use an algorithm equivalent to the following algorithm
107
        // to compute the default-path of a cookie:"
108
 
109
        // "2. If the uri-path is empty or if the first character of the uri-path is not
110
        // a %x2F ("/") character, output %x2F ("/") and skip the remaining steps.
111
        if (empty($path) || substr($path, 0, 1) !== '/') {
112
            return '/';
113
        }
114
 
115
        // "3. If the uri-path contains no more than one %x2F ("/") character, output
116
        // %x2F ("/") and skip the remaining step."
117
        if ($path === "/") {
118
            return $path;
119
        }
120
 
121
        $rightSlashPos = strrpos($path, '/');
122
        if ($rightSlashPos === 0) {
123
            return "/";
124
        }
125
 
126
        // "4. Output the characters of the uri-path from the first character up to,
127
        // but not including, the right-most %x2F ("/")."
128
        return substr($path, 0, $rightSlashPos);
129
 
130
    }
131
}