blob: e3247f33f72607d2527711a6a60f4c5b9bbffbe4 [file] [log] [blame]
/*
** Copyright 2003-2004 The Apache Software Foundation
**
** Licensed 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_tables.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
*
*/
/** @brief This is the container class for libapreq cookies. */
typedef struct apreq_jar_t {
apr_table_t *cookies; /**< cookie table */
void *env; /**< environment */
apr_status_t status; /**< status of "Cookie" header parse */
} apreq_jar_t;
/**
* Cookie Version. libapreq does not distinguish between
* rfc2109 and its successor rfc2965; both are referred to
* as APREQ_COOKIE_VERSION_RFC. Users can distinguish between
* them in their outgoing cookies by using apreq_cookie_bake()
* for sending rfc2109 cookies, or apreq_cookie_bake2() for rfc2965.
* The original Netscape cookie spec is still preferred for its
* greater portability, it is named APREQ_COOKIE_VERSION_NETSCAPE.
*
*/
typedef enum { APREQ_COOKIE_VERSION_NETSCAPE,
APREQ_COOKIE_VERSION_RFC } apreq_cookie_version_t;
/** Default version, used when creating a new cookie. See apreq_cookie_make().*/
#define APREQ_COOKIE_VERSION_DEFAULT APREQ_COOKIE_VERSION_NETSCAPE
/** 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 {
apreq_cookie_version_t version; /**< RFC or Netscape compliant cookie */
char *path; /**< Restricts url path */
char *domain; /**< Restricts server domain */
char *port; /**< Restricts server port */
unsigned secure; /**< Notify browser of "https" requirement */
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 */
apreq_value_t v; /**< "raw" cookie value */
} apreq_cookie_t;
#define apreq_value_to_cookie(ptr) apreq_attr_to_type(apreq_cookie_t, \
v, ptr)
#define apreq_cookie_name(c) ((c)->v.name)
#define apreq_cookie_value(c) ((c)->v.data)
#define apreq_jar_items(j) apr_table_elts(j->cookies)->nelts
#define apreq_jar_nelts(j) apr_table_elts(j->cookies)->nelts
/**
* Fetches a cookie from the jar
*
* @param jar The cookie jar.
* @param name The name of the desired cookie.
*/
APREQ_DECLARE(apreq_cookie_t *)apreq_cookie(const apreq_jar_t *jar,
const char *name);
/**
* Adds a cookie by pushing it to the bottom of the jar.
*
* @param jar The cookie jar.
* @param c The cookie to add.
*/
APREQ_DECLARE(void) apreq_jar_add(apreq_jar_t *jar,
const apreq_cookie_t *c);
#define apreq_add_cookie(j,c) apreq_jar_add(j,c)
/**
* Parse the incoming "Cookie:" headers into a cookie jar.
*
* @param env The current environment.
* @param hdr String to parse as a HTTP-merged "Cookie" header.
* @remark "data = NULL" has special behavior. In this case,
* apreq_jar(env,NULL) will attempt to fetch a cached object from the
* environment via apreq_env_jar. Failing that, it will replace
* "hdr" with the result of apreq_env_cookie(env), parse that,
* and store the resulting object back within the environment.
* This maneuver is designed to mimimize parsing work,
* since generating the cookie jar is relatively expensive.
*
*/
APREQ_DECLARE(apreq_jar_t *) apreq_jar(void *env, const char *hdr);
/**
* 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.
*/
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);
#define apreq_make_cookie(p,n,nl,v,vl) apreq_cookie_make(p,n,nl,v,vl)
/**
* Sets the associated cookie attribute.
* @param p Pool for allocating the new attribute.
* @param c Cookie.
* @param attr Name of attribute- leading '-' or '$' characters
* are ignored.
* @param alen Length of attr.
* @param val Value of new attribute.
* @param vlen Length of new attribute.
* @remarks Ensures cookie version & time are kept in sync.
*/
APREQ_DECLARE(apr_status_t)
apreq_cookie_attr(apr_pool_t *p, apreq_cookie_t *c,
const char *attr, apr_size_t alen,
const char *val, apr_size_t vlen);
/**
* Returns a string that represents the cookie as it would appear
* in a valid "Set-Cookie*" header.
*
* @param c The cookie.
* @param p The pool.
*/
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 The cookie.
* @param buf Storage location for the result.
* @param len Size of buf's storage area.
*/
APREQ_DECLARE(int) apreq_cookie_serialize(const apreq_cookie_t *c,
char *buf, apr_size_t len);
#define apreq_serialize_cookie(buf,len,c) apreq_cookie_serialize(c,buf,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]/.
*/
APREQ_DECLARE(void) apreq_cookie_expires(apreq_cookie_t *c,
const char *time_str);
/**
* Add the cookie to the outgoing "Set-Cookie" headers.
*
* @param c The cookie.
* @param env Environment.
*/
APREQ_DECLARE(apr_status_t) apreq_cookie_bake(const apreq_cookie_t *c,
void *env);
/**
* Add the cookie to the outgoing "Set-Cookie2" headers.
*
* @param c The cookie.
* @param env Environment.
*/
APREQ_DECLARE(apr_status_t) apreq_cookie_bake2(const apreq_cookie_t *c,
void *env);
/**
* Looks for the presence of a "Cookie2" header to determine whether
* or not the current User-Agent supports rfc2965.
* @param env The current environment.
* @return APREQ_COOKIE_VERSION_RFC if rfc2965 is supported,
* APREQ_COOKIE_VERSION_NETSCAPE otherwise.
*/
APREQ_DECLARE(apreq_cookie_version_t) apreq_ua_cookie_version(void *env);
#ifdef __cplusplus
}
#endif
#endif /*APREQ_COOKIE_H*/