summaryrefslogtreecommitdiffstats
path: root/include/apreq_cookie.h
blob: ee887a181d9acf6f020f9cc8cfab4276e4fc08eb (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
/*
**  Licensed to the Apache Software Foundation (ASF) under one or more
** contributor license agreements.  See the NOTICE file distributed with
** this work for additional information regarding copyright ownership.
** The ASF licenses this file to You under the Apache License, Version 2.0
** (the "License"); you may not use this file except in compliance with
** the License.  You may obtain a copy of the License at
**
**      http://www.apache.org/licenses/LICENSE-2.0
**
**  Unless required by applicable law or agreed to in writing, software
**  distributed under the License is distributed on an "AS IS" BASIS,
**  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
**  See the License for the specific language governing permissions and
**  limitations under the License.
*/

#ifndef APREQ_COOKIE_H
#define APREQ_COOKIE_H

#include "apreq.h"
#include "apr_time.h"

#ifdef  __cplusplus
extern "C" {
#endif

/**
 * @file apreq_cookie.h
 * @brief Cookies and Jars.
 * @ingroup libapreq2
 *
 * apreq_cookie.h describes a common server-side API for request (incoming)
 * and response (outgoing) cookies.  It aims towards compliance with the
 * standard cookie specifications listed below.
 *
 * @see http://wp.netscape.com/newsref/std/cookie_spec.html
 * @see http://www.ietf.org/rfc/rfc2109.txt
 * @see http://www.ietf.org/rfc/rfc2964.txt
 * @see http://www.ietf.org/rfc/rfc2965.txt
 *
 */

/** This macro is deprecated.
 *
 * Maximum length of a single Set-Cookie(2) header. 
 */
#define APREQ_COOKIE_MAX_LENGTH            4096

/** @brief Cookie type, supporting both Netscape and RFC cookie specifications.
 */

typedef struct apreq_cookie_t {

    char           *path;        /**< Restricts url path */
    char           *domain;      /**< Restricts server domain */
    char           *port;        /**< Restricts server port */
    char           *comment;     /**< RFC cookies may send a comment */
    char           *commentURL;  /**< RFC cookies may place an URL here */
    apr_time_t      max_age;     /**< total duration of cookie: -1 == session */
    unsigned        flags;       /**< charsets, taint marks, app-specific bits */
    const apreq_value_t   v;     /**< "raw" cookie value */

} apreq_cookie_t;


/** Upgrades a jar's table values to apreq_cookie_t structs. */
static APR_INLINE
apreq_cookie_t *apreq_value_to_cookie(const char *val)
{
    union { const char *in; char *out; } deconst;

    deconst.in = val;
    return apreq_attr_to_type(apreq_cookie_t, v,
           apreq_attr_to_type(apreq_value_t, data, deconst.out));
}

/**@return 1 if this is an RFC cookie, 0 if its a Netscape cookie. */
static APR_INLINE
unsigned apreq_cookie_version(const apreq_cookie_t *c) {
    return APREQ_FLAGS_GET(c->flags, APREQ_COOKIE_VERSION);
}

/** Sets the cookie's protocol version. */
static APR_INLINE
void apreq_cookie_version_set(apreq_cookie_t *c, unsigned v) {
    APREQ_FLAGS_SET(c->flags, APREQ_COOKIE_VERSION, v);
}

/** @return 1 if the secure flag is set, 0 otherwise. */
static APR_INLINE
unsigned apreq_cookie_is_secure(const apreq_cookie_t *c) {
    return APREQ_FLAGS_GET(c->flags, APREQ_COOKIE_SECURE);
}

/** Sets the cookie's secure flag, meaning it only
 *  comes back over an SSL-encrypted connction.
 */
static APR_INLINE
void apreq_cookie_secure_on(apreq_cookie_t *c) {
    APREQ_FLAGS_ON(c->flags, APREQ_COOKIE_SECURE);
}

/** Turns off the cookie's secure flag. */
static APR_INLINE
void apreq_cookie_secure_off(apreq_cookie_t *c) {
    APREQ_FLAGS_OFF(c->flags, APREQ_COOKIE_SECURE);
}

/** @return 1 if the HttpOnly flag is set, 0 otherwise. */
static APR_INLINE
unsigned apreq_cookie_is_httponly(const apreq_cookie_t *c) {
    return APREQ_FLAGS_GET(c->flags, APREQ_COOKIE_HTTPONLY);
}

/** Sets the cookie's HttpOnly flag, meaning it is not
 *  accessible through client-side script in supported
 *  browsers.
 */
static APR_INLINE
void apreq_cookie_httponly_on(apreq_cookie_t *c) {
    APREQ_FLAGS_ON(c->flags, APREQ_COOKIE_HTTPONLY);
}

/** Turns off the cookie's HttpOnly flag. */
static APR_INLINE
void apreq_cookie_httponly_off(apreq_cookie_t *c) {
    APREQ_FLAGS_OFF(c->flags, APREQ_COOKIE_HTTPONLY);
}


/** @return 1 if the taint flag is set, 0 otherwise. */
static APR_INLINE
unsigned apreq_cookie_is_tainted(const apreq_cookie_t *c) {
    return APREQ_FLAGS_GET(c->flags, APREQ_TAINTED);
}

/** Sets the cookie's tainted flag. */
static APR_INLINE
void apreq_cookie_tainted_on(apreq_cookie_t *c) {
    APREQ_FLAGS_ON(c->flags, APREQ_TAINTED);
}

/** Turns off the cookie's tainted flag. */
static APR_INLINE
void apreq_cookie_tainted_off(apreq_cookie_t *c) {
    APREQ_FLAGS_OFF(c->flags, APREQ_TAINTED);
}

/**
 * Parse a cookie header and store the cookies in an apr_table_t.
 *
 * @param pool pool which allocates the cookies
 * @param jar table where parsed cookies are stored
 * @param header the header value
 *
 * @return APR_SUCCESS.
 * @return ::APREQ_ERROR_BADSEQ if an unparseable character sequence appears.
 * @return ::APREQ_ERROR_MISMATCH if an rfc-cookie attribute appears in a
 *         netscape cookie header.
 * @return ::APR_ENOTIMPL if an unrecognized rfc-cookie attribute appears.
 * @return ::APREQ_ERROR_NOTOKEN if a required token was not present.
 * @return ::APREQ_ERROR_BADCHAR if an unexpected token was present.
 */
APREQ_DECLARE(apr_status_t) apreq_parse_cookie_header(apr_pool_t *pool,
                                                      apr_table_t *jar,
                                                      const char *header);

/**
 * Returns a new cookie, made from the argument list.
 *
 * @param pool  Pool which allocates the cookie.
 * @param name  The cookie's name.
 * @param nlen  Length of name.
 * @param value The cookie's value.
 * @param vlen  Length of value.
 *
 * @return the new cookie
 */
APREQ_DECLARE(apreq_cookie_t *) apreq_cookie_make(apr_pool_t *pool,
                                                  const char *name,
                                                  const apr_size_t nlen,
                                                  const char *value,
                                                  const apr_size_t vlen);

/**
 * Returns a string that represents the cookie as it would appear
 * in a valid "Set-Cookie*" header.
 *
 * @param c cookie.
 * @param p pool which allocates the returned string.
 *
 * @return header string.
 */
APREQ_DECLARE(char*) apreq_cookie_as_string(const apreq_cookie_t *c,
                                            apr_pool_t *p);


/**
 * Same functionality as apreq_cookie_as_string.  Stores the string
 * representation in buf, using up to len bytes in buf as storage.
 * The return value has the same semantics as that of apr_snprintf,
 * including the special behavior for a "len = 0" argument.
 *
 * @param c   cookie.
 * @param buf storage location for the result.
 * @param len size of buf's storage area.
 *
 * @return size of resulting header string.
 */
APREQ_DECLARE(int) apreq_cookie_serialize(const apreq_cookie_t *c,
                                          char *buf, apr_size_t len);

/**
 * Set the Cookie's expiration date.
 *
 * @param c The cookie.
 * @param time_str If NULL, the Cookie's expiration date is unset,
 * making it a session cookie.  This means no "expires" or "max-age"
 * attribute will appear in the cookie's serialized form. If time_str
 * is not NULL, the expiration date will be reset to the offset (from now)
 * represented by time_str.  The time_str should be in a format that
 * apreq_atoi64t() can understand, namely /[+-]?\\d+\\s*[YMDhms]/.
 *
 * @remarks Now time_str may also be a fixed date; see apr_date_parse_rfc()
 * for admissible formats.
 */
APREQ_DECLARE(void) apreq_cookie_expires(apreq_cookie_t *c,
                                         const char *time_str);

#ifdef __cplusplus
 }
#endif

#endif /*APREQ_COOKIE_H*/