summaryrefslogtreecommitdiffstats
path: root/library/Icinga/Web/Cookie.php
blob: 283f07a2218699d46535fbd21a2992c3e9ad86fd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
<?php
/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */

namespace Icinga\Web;

use Icinga\Application\Config;
use Icinga\Application\Icinga;
use InvalidArgumentException;

/**
 * A HTTP cookie
 */
class Cookie
{
    /**
     * Domain of the cookie
     *
     * @var string
     */
    protected $domain;

    /**
     * The timestamp at which the cookie expires
     *
     * @var int
     */
    protected $expire;

    /**
     * Whether to protect the cookie against client side script code attempts to read the cookie
     *
     * Defaults to true.
     *
     * @var bool
     */
    protected $httpOnly = true;

    /**
     * Name of the cookie
     *
     * @var string
     */
    protected $name;

    /**
     * The path on the web server where the cookie is available
     *
     * Defaults to the base URL.
     *
     * @var string
     */
    protected $path;

    /**
     * Whether to send the cookie only over a secure connection
     *
     * Defaults to auto-detection so that if the current request was sent over a secure connection the secure flag will
     * be set to true.
     *
     * @var bool
     */
    protected $secure;

    /**
     * Value of the cookie
     *
     * @var string
     */
    protected $value;

    /**
     * Create a new cookie
     *
     * @param   string  $name
     * @param   string  $value
     */
    public function __construct($name, $value = null)
    {
        if (preg_match("/[=,; \t\r\n\013\014]/", $name)) {
            throw new InvalidArgumentException(sprintf(
                'Cookie name can\'t contain these characters: =,; \t\r\n\013\014 (%s)',
                $name
            ));
        }
        if (empty($name)) {
            throw new InvalidArgumentException('The cookie name can\'t be empty');
        }
        $this->name = $name;
        $this->value = $value;
    }

    /**
     * Get the domain of the cookie
     *
     * @return  string
     */
    public function getDomain()
    {
        if ($this->domain === null) {
            $this->domain = Config::app()->get('cookie', 'domain');
        }
        return $this->domain;
    }

    /**
     * Set the domain of the cookie
     *
     * @param   string  $domain
     *
     * @return  $this
     */
    public function setDomain($domain)
    {
        $this->domain = $domain;
        return $this;
    }

    /**
     * Get the timestamp at which the cookie expires
     *
     * @return  int
     */
    public function getExpire()
    {
        return $this->expire;
    }

    /**
     * Set the timestamp at which the cookie expires
     *
     * @param   int $expire
     *
     * @return  $this
     */
    public function setExpire($expire)
    {
        $this->expire = $expire;
        return $this;
    }

    /**
     * Get whether to protect the cookie against client side script code attempts to read the cookie
     *
     * @return  bool
     */
    public function isHttpOnly()
    {
        return $this->httpOnly;
    }

    /**
     * Set whether to protect the cookie against client side script code attempts to read the cookie
     *
     * @param   bool    $httpOnly
     *
     * @return  $this
     */
    public function setHttpOnly($httpOnly)
    {
        $this->httpOnly = $httpOnly;
        return $this;
    }

    /**
     * Get the name of the cookie
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Get the path on the web server where the cookie is available
     *
     * If the path has not been set either via {@link setPath()} or via config, the base URL will be returned.
     *
     * @return  string
     */
    public function getPath()
    {
        if ($this->path === null) {
            $path = Config::app()->get('cookie', 'path');
            if ($path === null) {
                // The following call could be used as default for ConfigObject::get(), but we prevent unnecessary
                // function calls here, if the path is set in the config
                $path = Icinga::app()->getRequest()->getBaseUrl() . '/'; // Zend has rtrim($baseUrl, '/')
            }
            $this->path = $path;
        }
        return $this->path;
    }

    /**
     * Set the path on the web server where the cookie is available
     *
     * @param   string  $path
     *
     * @return  $this
     */
    public function setPath($path)
    {
        $this->path = $path;
        return $this;
    }

    /**
     * Get whether to send the cookie only over a secure connection
     *
     * If the secure flag has not been set either via {@link setSecure()} or via config and if the current request was
     * sent over a secure connection, true will be returned.
     *
     * @return bool
     */
    public function isSecure()
    {
        if ($this->secure === null) {
            $secure = Config::app()->get('cookie', 'secure');
            if ($secure === null) {
                // The following call could be used as default for ConfigObject::get(), but we prevent unnecessary
                // function calls here, if the secure flag is set in the config
                $secure = Icinga::app()->getRequest()->isSecure();
            }
            $this->secure = $secure;
        }
        return $this->secure;
    }

    /**
     * Set whether to send the cookie only over a secure connection
     *
     * @param   bool    $secure
     *
     * @return  $this
     */
    public function setSecure($secure)
    {
        $this->secure = $secure;
        return $this;
    }

    /**
     * Get the value of the cookie
     *
     * @return  string
     */
    public function getValue()
    {
        return $this->value;
    }

    /**
     * Set the value of the cookie
     *
     * @param   string  $value
     *
     * @return  $this
     */
    public function setValue($value)
    {
        $this->value = $value;
        return $this;
    }

    /**
     * Create invalidation cookie
     *
     * This method clones the current cookie and sets its value to null and expire time to 1.
     * That way, the cookie removes itself when it has been sent to and processed by the client.
     *
     * We're cloning the current cookie in order to meet the [RFC6265 spec](https://tools.ietf.org/search/rfc6265)
     * regarding the `Path` and `Domain` attribute:
     *
     * > Finally, to remove a cookie, the server returns a Set-Cookie header with an expiration date in the past.
     * > The server will be successful in removing the cookie only if the Path and the Domain attribute in the
     * > Set-Cookie header match the values used when the cookie was created.
     *
     * Note that the cookie has to be sent to the client.
     *
     * # Example Usage
     *
     * ```php
     * $response->setCookie(
     *     $cookie->forgetMe()
     * );
     * ```
     *
     * @return static
     */
    public function forgetMe()
    {
        $forgetMe = clone $this;

        return $forgetMe
            ->setValue(null)
            ->setExpire(1);
    }
}