summaryrefslogtreecommitdiffabout
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--include/kingate/cgi_gateway.h1
-rw-r--r--include/kingate/cookies.h4
-rw-r--r--src/cookies.cc7
3 files changed, 7 insertions, 5 deletions
diff --git a/include/kingate/cgi_gateway.h b/include/kingate/cgi_gateway.h
index a26b0ae..087f7d0 100644
--- a/include/kingate/cgi_gateway.h
+++ b/include/kingate/cgi_gateway.h
@@ -118,208 +118,207 @@ namespace kingate {
*/
istream& in() { return iface.in(); }
/**
* fetch reference to the 'stdout' stream.
* @return the reference to the corresponding ostream object.
* @see cgi_interface::out()
*/
ostream& out() { return iface.out(); }
/**
* fetch reference to the 'stderr' stream.
* @return the reference to the corresponding ostream object.
* @see cgi_interface::err()
*/
ostream& err() { return iface.err(); }
/**
* cast to the ostream -- fetches the reference to the 'stdout'
* stream.
* @see out()
*/
operator ostream& (void) { return out(); }
/**
* Check to see whether the parameter was passed via GET.
* @param n the parameter name.
* @return true if yes.
*/
bool has_GET(const string& n) const;
/**
* Retrieve the parameter passed via GET.
* @param n the parameter name.
* @return the parameter contents.
* @see exception_notfound
*/
const string& get_GET(const string& n) const;
/**
* Check to see whether the parameter was passed via POST.
* @param n the parameter name.
* @return true if yes.
*/
bool has_POST(const string& n) const;
/**
* Retrieve the POST-parameter.
* @param n the parameter name.
* @return the parameter contents.
* @see exception_notfound
*/
const string& get_POST(const string& n) const;
/**
* Check to see whether the parameter was passed either via POST or
* GET.
* @param n the parameter name.
* @return true if yes.
*/
bool has_param(const string& n) const;
/**
* Retrieve the parameter passed either via POST or GET
* (GET-parameter takes precedence).
* @param n the parameter name.
* @return the parameter contents.
* @see exception_notfound.
*/
const string& get_param(const string& n) const;
/**
* Check to see whether the file was uploaded in the request body.
* @param n the parameter name.
* @return true if yes.
*/
bool has_file(const string& n) const;
/**
* Retrieve the file uploaded in the request body.
* @param n the parameter name.
* @return the file.
* @see exception_notfound.
*/
const file_t get_file(const string& n) const;
file_t get_file(const string& n);
/**
* Retrieve the POST content-type (as passed via CONTENT_TYPE
* environment variable).
* @return the content type.
*/
const string& __deprecated get_content_type() const;
/**
* Retrieve the POST content length (as passed via the
* CONTENT_LENGTH environment variable).
* @return the content length.
*/
unsigned long __deprecated get_content_length() const;
/**
* Check to see whether the content from stdin stream was parsed.
* @return true if yes.
*/
bool is_content_parsed() const { return b_parsed_content; }
/**
* Retrieve the HTTP header value from the HTTP_ meta-variable.
* (see RFC3875)
* @param hn header field name.
* @return the HTTP header value.
*/
const string& http_request_header(const string& hn) const;
/**
* Retrieve the AUTH_TYPE meta-variable (see RFC3875)
* @return authentication type.
*/
const string& auth_type() const;
/**
* Retrieve the CONTENT_LENGTH meta-variable (see RFC3875)
* @return size of the request message body.
*/
unsigned long content_length() const;
/**
* Retrieve the CONTENT_TYPE meta-variable (see RFC3875)
* @return media type of the request message body.
*/
const string& content_type() const;
/**
* Retrieve the GATEWAY_INTERFACE meta-variable (see RFC3875)
* @return the gateway interface dialect.
*/
const string& gateway_interface() const;
/**
* Retrieve the PATH_INFO meta-variable (see RFC3875)
* @return path to be interpreted by the script.
*/
const string& path_info() const;
/**
* Retrieve the PATH_TRANSLATED meta-variable (see RFC3875)
* @return the translated path to the document.
*/
const string& path_translated() const;
/**
* Retrieve the QUERY_STRING meta-variable (see RFC3875)
* @return the query string.
*/
const string& query_string() const;
/**
* Retrieve the REMOTE_ADDR meta-variable (see RFC3875)
* @return the network address of the remote host.
*/
const string& remote_addr() const;
/**
* Retrieve the REMOTE_HOST meta-variable (see RFC3875)
* @return the fully qualified domain name of the client if
* available. REMOTE_ADDR otherwise.
* @see remote_addr()
*/
const string& remote_host() const;
/**
* Retrieve the REMOTE_IDENT meta-variable (see RFC3875)
* @return remote user identity (see RFC1413).
*/
const string& remote_ident() const;
/**
* Retrieve the REMOTE_USER meta-variable (see RFC3875)
* @return the authenticated user name.
*/
const string& remote_user() const;
/**
* Retrieve the REQUEST_METHOD meta-variable (see RFC3875)
* @return the http request method.
*/
const string& request_method() const;
/**
* Retrieve the SCRIPT_NAME meta-variable (see RFC3875)
* @return the uri path identifying the script.
*/
const string& script_name() const;
/**
* Retrieve the SERVER_NAME meta-variable (see RFC3875)
* @return the server name of the script.
*/
const string& server_name() const;
/**
* Retrieve the SERVER_PORT meta-variable (see RFC3875)
* @return the port on which request was received.
*/
unsigned int server_port() const;
/**
* Retrieve the SERVER_PROTOCOL meta-variable (see RFC3875)
* @return the protocol used for the request.
*/
const string& server_protocol() const;
/**
* Retrieve the SERVER_SOFTWARE meta-variable (see RFC3875)
* @return the name and version of server software.
*/
const string& server_software() const;
- private:
/**
* Parse the query string, putting the parameters into the map
* specified.
* @param q the query string.
* @param p destination parameters map.
*/
static void parse_query(string& q,params_t& p);
};
}
#endif /* __KINGATE_CGI_GATEWAY_H */
/*
* vim:set ft=cpp:
*/
diff --git a/include/kingate/cookies.h b/include/kingate/cookies.h
index 83ef0c6..a1e813c 100644
--- a/include/kingate/cookies.h
+++ b/include/kingate/cookies.h
@@ -66,235 +66,235 @@ namespace kingate {
* @see has_domain()
* @see unset_domain()
*/
void set_domain(const string& d);
/**
* @param ma max-age.
* @see get_max_age()
* @see has_max_age()
* @see unset_max_age()
*/
void set_max_age(const string& ma);
/**
* @param p path.
* @see get_path()
* @see has_path()
* @see unset_path()
*/
void set_path(const string& p);
/**
* set cookie security.
* @param s true if secure.
* @see get_secure()
* @see is_secure()
*/
void set_secure(bool s);
/**
* @param e expiration time.
* @see get_expires()
* @see has_expires()
* @see unset_expires()
*/
void set_expires(const string& e);
/**
* get cookie parameter.
* @param p parameter name.
* @return parameter value.
* @see _set_string()
*/
const string& _get_string(const string& p) const;
/**
* @return cookie name.
* @see set_name()
*/
const string& get_name() const { return name; }
/**
* @return cookie value.
* @see set_value()
*/
const string& get_value() const { return value; }
/**
* @return cookie comment.
* @see set_comment()
* @see has_comment()
* @see unset_comment()
*/
const string& get_comment() const;
/**
* @return cookie domain.
* @see set_domain()
* @see has_domain()
* @see unset_domain()
*/
const string& get_domain() const;
/**
* @return cookie max-age.
* @see set_max_age()
* @see has_max_age()
* @see unset_max_age()
*/
const string& get_max_age() const;
/**
* @return cookie path.
* @see set_path()
* @see has_path()
* @see unset_path()
*/
const string& get_path() const;
/**
* @return cookie security.
* @see is_secure()
* @see set_secure()
*/
bool get_secure() const;
/**
* @return cookie security.
* @see get_secure()
* @see set_secure()
*/
bool is_secure() const { return get_secure(); }
/**
* @return cookie expiration time.
* @see set_expires()
* @see has_expires()
* @see unset_expires()
*/
const string& get_expires() const;
/**
* @return true if cookie has comment.
* @see set_comment()
* @see get_comment()
* @see unset_comment()
*/
bool has_comment() const;
/**
* @return true if cookie has domain.
* @see set_domain()
* @see get_domain()
* @see unset_domain()
*/
bool has_domain() const;
/**
* @return true if cookie has max-age.
* @see set_max_age()
* @see get_max_age()
* @see unset_max_age()
*/
bool has_max_age() const;
/**
* @return true if cookie has path.
* @see set_path()
* @see get_path()
* @see unset_path()
*/
bool has_path() const;
/**
* @return true if cookie has expiration time.
* @see set_expires()
* @see get_expires()
* @see unset_expires()
*/
bool has_expires() const;
/**
* rid cookie of comment.
* @see set_comment()
* @see get_comment()
* @see has_comment()
*/
void unset_comment();
/**
* rid cookie of domain.
* @see set_domain()
* @see get_domain()
* @see has_domain()
*/
void unset_domain();
/**
* rid cookie of max-age.
* @see set_max_age()
* @see get_max_age()
* @see has_max_age()
*/
void unset_max_age();
/**
* rid cookie of path.
* @see set_path()
* @see get_path()
* @see has_path()
*/
void unset_path();
/**
* rid cookie of expiration time.
* @see set_expires()
* @see get_expires()
* @see has_expires()
*/
void unset_expires();
/**
* render the 'Set-Cookie' HTTP header according to RFC2109.
* Absolutely useless, only works with lynx.
* @return the rendered header content.
*/
string set_cookie_header_rfc2109() const;
/**
* render the 'Set-Cookie' header according to the early vague
* netscape specs and common practice.
* @return the rendered header content.
*/
string set_cookie_header() const;
};
/**
* Cookies container class.
*/
- class cookies_t : public map<string,cookie> {
+ class cookies_t : public multimap<string,cookie> {
public:
cookies_t() { }
/**
* @param s 'Cookie:' HTTP header contents to parse.
*/
cookies_t(const string& s) { parse_cookies(s); }
/**
* @param c cookie to set.
*/
- void set_cookie(const cookie& c) { (*this)[c.get_name()]=c; }
+ void set_cookie(const cookie& c);
/**
* @param n cookie name to remove.
*/
void unset_cookie(const key_type& n) { erase(n); }
/**
* @param n cookie name.
* @return true if exists.
*/
bool has_cookie(const key_type& n) const;
/**
* Return the named cookie if one exists.
* @param n cookie name.
* @return const reference to cookie object.
*/
const cookie& get_cookie(const key_type& n) const;
/**
* Return the named cookie if one exists.
* @param n cookie name.
* @return reference to cookie object.
*/
cookie& get_cookie(const key_type& n);
/**
* @param s HTTP 'Cookie' header content.
*/
void parse_cookies(const string& s);
};
}
#endif /* __KINGATE_COOKIES_H */
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));
}
}
}