summaryrefslogtreecommitdiffabout
path: root/src/cookies.cc
Side-by-side diff
Diffstat (limited to 'src/cookies.cc') (more/less context) (show whitespace changes)
-rw-r--r--src/cookies.cc7
1 files changed, 5 insertions, 2 deletions
diff --git a/src/cookies.cc b/src/cookies.cc
index 40a0c8b..1ee4f7c 100644
--- a/src/cookies.cc
+++ b/src/cookies.cc
@@ -1,242 +1,245 @@
#include "kingate/cookies.h"
#include "kingate/util.h"
#include "kingate/exception.h"
namespace kingate {
/*
* RFC 2109:
* av-pairs = av-pair *(";" av-pair)
* av-pair = attr ["=" value] ; optional value
* attr = token
* value = word
* word = token | quoted-string
*/
/* RFC 2109:
*
* The origin server effectively ends a session by sending the client a
* Set-Cookie header with Max-Age=0.
*
* An origin server may include multiple Set-Cookie headers in a response.
* Note that an intervening gateway could fold multiple such headers into a
* single header.
*
*
* set-cookie = "Set-Cookie:" cookies
* cookies = 1#cookie
* cookie = NAME "=" VALUE *(";" cookie-av)
* NAME = attr
* VALUE = value
* cookie-av = "Comment" "=" value
* | "Domain" "=" value
* | "Max-Age" "=" value
* | "Path" "=" value
* | "Secure"
* | "Version" "=" 1*DIGIT
*
*
* The origin server should send the following additional HTTP/1.1
* response headers, depending on circumstances:
*
* * To suppress caching of the Set-Cookie header: Cache-control: no-
* cache="set-cookie".
*
* and one of the following:
*
* * To suppress caching of a private document in shared caches: Cache-
* control: private.
*
* * To allow caching of a document and require that it be validated
* before returning it to the client: Cache-control: must-revalidate.
*
* * To allow caching of a document, but to require that proxy caches
* (not user agent caches) validate it before returning it to the
* client: Cache-control: proxy-revalidate.
*
* * To allow caching of a document and request that it be validated
* before returning it to the client (by "pre-expiring" it):
* Cache-control: max-age=0. Not all caches will revalidate the
* document in every case.
*
* HTTP/1.1 servers must send Expires: old-date (where old-date is a
* date long in the past) on responses containing Set-Cookie response
* headers unless they know for certain (by out of band means) that
* there are no downsteam HTTP/1.0 proxies. HTTP/1.1 servers may send
* other Cache-Control directives that permit caching by HTTP/1.1
* proxies in addition to the Expires: old-date directive; the Cache-
* Control directive will override the Expires: old-date for HTTP/1.1
* proxies.
*
*/
void cookie::_set_string(const string& p,const string& v) {
(*this)[p]=v;
}
void cookie::set_comment(const string& c) {
_set_string("comment",c);
}
void cookie::set_domain(const string& d) {
_set_string("domain",d);
}
void cookie::set_max_age(const string& ma) {
_set_string("max-age",ma);
}
void cookie::set_path(const string& p) {
_set_string("path",p);
}
void cookie::set_secure(bool s) {
if(s)
_set_string("secure","");
else
erase("secure");
}
void cookie::set_expires(const string& e) {
(*this)["expires"] = e;
}
const string& cookie::_get_string(const string& s) const {
const_iterator i = find(s);
if(i==end())
throw exception_notfound(CODEPOINT,"No parameter set");
return i->second;
}
const string& cookie::get_comment() const {
return _get_string("comment");
}
const string& cookie::get_domain() const {
return _get_string("domain");
}
const string& cookie::get_max_age() const {
return _get_string("max-age");
}
const string& cookie::get_path() const {
return _get_string("path");
}
bool cookie::get_secure() const {
return find("secure")!=end();
}
const string& cookie::get_expires() const {
return _get_string("expires");
}
bool cookie::has_comment() const {
return find("comment")!=end();
}
bool cookie::has_domain() const {
return find("domain")!=end();
}
bool cookie::has_max_age() const {
return find("max-age")!=end();
}
bool cookie::has_path() const {
return find("path")!=end();
}
bool cookie::has_expires() const {
return find("expires")!=end();
}
void cookie::unset_comment() {
erase("comment");
}
void cookie::unset_domain() {
erase("domain");
}
void cookie::unset_max_age() {
erase("max-age");
}
void cookie::unset_path() {
erase("path");
}
void cookie::unset_expires() {
erase("expires");
}
string cookie::set_cookie_header_rfc2109() const {
string rv = name + "=" + http_quoted_string(value);
for(const_iterator i=begin();i!=end();++i) {
if(i->first=="secure") {
rv += "; secure";
}else{
rv += "; "+i->first+"="+http_quote(i->second);
}
}
rv += "; Version=1";
return rv;
}
string cookie::set_cookie_header() const {
string rv = name + "=" + value;
for(const_iterator i=begin();i!=end();++i) {
if(i->first=="secure") {
rv += "; secure";
}else{
rv += "; "+i->first+"="+i->second;
}
}
return rv;
}
+ void cookies_t::set_cookie(const cookie& c) {
+ insert(value_type(c.get_name(),c));
+ }
+
bool cookies_t::has_cookie(const key_type& n) const {
return find(n)!=end();
}
const cookie& cookies_t::get_cookie(const key_type& n) const {
const_iterator i=find(n);
if(i==end())
throw exception_notfound(CODEPOINT,"No cookie with such name found");
return i->second;
}
cookie& cookies_t::get_cookie(const key_type& n) {
iterator i=find(n);
if(i==end())
throw exception_notfound(CODEPOINT,"No cookie with such name found");
return i->second;
}
void cookies_t::parse_cookies(const string& s) {
string str = s;
while(!str.empty()) {
string::size_type sc = str.find(';');
string s;
if(sc==string::npos) {
s = str;
str.erase();
}else{
s = str.substr(0,sc);
str.erase(0,sc+1);
}
string::size_type nsp=s.find_first_not_of(" \t");
if((nsp!=string::npos) && nsp)
s.erase(0,nsp);
string::size_type eq=s.find('=');
if(eq==string::npos)
continue;
string n = s.substr(0,eq);
s.erase(0,eq+1);
nsp = n.find_last_not_of(" \t");
n.erase(nsp+1);
nsp = s.find_first_not_of(" \t");
string v;
if(nsp!=string::npos)
v = s.substr(nsp);
else
v = s;
nsp = v.find_last_not_of(" \t");
if(nsp==string::npos)
v.erase();
else
v.erase(nsp+1);
- cookie& c = (*this)[n];
- c.set_name(n); c.set_value(v);
+ set_cookie(cookie(n,v));
}
}
}