Browse Source

Fixed a problem with IE that does not support Cookie's max-age property

master
Artyom Beilis 11 years ago
parent
commit
c5a13d00d8
5 changed files with 90 additions and 17 deletions
  1. +6
    -1
      cppcms/http_cookie.h
  2. +24
    -0
      private/cached_settings.h
  3. +39
    -12
      src/http_cookie.cpp
  4. +20
    -4
      src/session_interface.cpp
  5. +1
    -0
      tests/session_interface_test.js

+ 6
- 1
cppcms/http_cookie.h View File

@@ -79,6 +79,10 @@ public:
void comment(std::string);

///
/// Set expiration date/time
///
void expires(time_t when);
///
/// Set max cookie's age
///
void max_age(unsigned a);
@@ -137,7 +141,8 @@ private:

uint32_t secure_ : 1;
uint32_t has_age_ : 1;
uint32_t reserved_ : 30;
uint32_t has_expiration_: 1;
uint32_t reserved_ : 29;
};




+ 24
- 0
private/cached_settings.h View File

@@ -9,6 +9,8 @@
#define CPPCMS_IMPL_CACHED_SETTINGS
#include <cppcms/json.h>
#include <booster/thread.h>
#include <cppcms/http_cookie.h>
#include <booster/log.h>
namespace cppcms {
namespace impl {
struct cached_settings {
@@ -129,6 +131,9 @@ namespace impl {
std::string prefix;
std::string domain;
std::string path;
int time_shift;
bool use_age;
bool use_exp;
bool secure;
} cookies;
cached_session(json::value const &v)
@@ -138,6 +143,25 @@ namespace impl {
cookies.prefix = v.get("session.cookies.prefix","cppcms_session");
cookies.domain = v.get("session.cookies.domain","");
cookies.path = v.get("session.cookies.path","/");
cookies.time_shift = v.get("session.cookies.time_shift",0);
std::string method = v.get("session.cookies.expiration_method","both");

if(method == "both") {
cookies.use_age = cookies.use_exp = true;
}
else if (method == "expires") {
cookies.use_age = false;
cookies.use_exp = true;
}
else if(method == "max-age") {
cookies.use_age = true;
cookies.use_exp = false;
}
else {
BOOSTER_WARNING("cppcms") << "Invalid session.cookies.expiration_method "
"should be one of 'max-age', 'expires' or 'both' assuming default 'both'";
cookies.use_age = cookies.use_exp = true;
}
cookies.secure = v.get("session.cookies.secure",false);
}
} session;


+ 39
- 12
src/http_cookie.cpp View File

@@ -9,13 +9,14 @@
#include <cppcms/http_cookie.h>
#include "http_protocol.h"
#include <cppcms/cppcms_error.h>
#include <booster/posix_time.h>

#include <sstream>
#include <locale>

namespace cppcms { namespace http {

struct cookie::_data { };
struct cookie::_data { time_t expires; };
bool cookie::empty() const
{
return name_.empty() && value_.empty();
@@ -31,6 +32,15 @@ std::string cookie::domain() const { return domain_; }
void cookie::domain(std::string v) { domain_=v; }
std::string cookie::comment() const { return comment_; }
void cookie::comment(std::string v) { comment_=v; }

void cookie::expires(time_t when)
{
if(!d.get()) {
d.reset(new _data());
}
has_expiration_=1;
d->expires = when;
}
void cookie::max_age(unsigned age)
{
has_age_=1;
@@ -39,6 +49,7 @@ void cookie::max_age(unsigned age)
void cookie::browser_age()
{
has_age_=0;
has_expiration_=0;
}
bool cookie::secure() const { return secure_; }
void cookie::secure(bool secure) { secure_ = secure ? 1: 0; }
@@ -60,11 +71,23 @@ void cookie::write(std::ostream &out) const
out<<"; Comment="<<protocol::quote(comment_);
if(!domain_.empty())
out<<"; Domain="<<domain_;
if(has_age_) {
std::ostringstream ss;
ss.imbue(std::locale("C"));
ss<<max_age_;
out<<"; Max-Age="<<ss.str();
if(has_age_ || has_expiration_) {
std::locale l=std::locale::classic();
std::stringstream ss;
ss.imbue(l);
if(has_age_)
ss<<"; Max-Age="<<max_age_;

if(has_expiration_ && d.get()) {
ss<<"; Expires=";
std::tm splitted = booster::ptime::universal_time(booster::ptime(d->expires));
static char const format[]="%a, %d %b %Y %H:%M:%S GMT";
char const *b=format;
char const *e=b+sizeof(format)-1;
std::use_facet<std::time_put<char> >(l).put(ss,ss,' ',&splitted,b,e);
}
out << ss.rdbuf();
}
if(!path_.empty())
out<<"; Path="<<path_;
@@ -80,25 +103,26 @@ std::ostream &operator<<(std::ostream &out,cookie const &c)
}

cookie::cookie(std::string name,std::string value) :
name_(name), value_(value), secure_(0), has_age_(0)
name_(name), value_(value), secure_(0), has_age_(0), has_expiration_(0)
{
}

cookie::cookie(std::string name,std::string value,unsigned age) :
name_(name), value_(value), max_age_(age), secure_(0), has_age_(1)
name_(name), value_(value), max_age_(age), secure_(0), has_age_(1), has_expiration_(0)
{
}
cookie::cookie(std::string name,std::string value,unsigned age,std::string path,std::string domain,std::string comment) :
name_(name), value_(value), path_(path),domain_(domain),comment_(comment),max_age_(age), secure_(0), has_age_(1)
name_(name), value_(value), path_(path),domain_(domain),comment_(comment),max_age_(age), secure_(0), has_age_(1), has_expiration_(0)
{
}

cookie::cookie(std::string name,std::string value,std::string path,std::string domain,std::string comment) :
name_(name), value_(value), path_(path),domain_(domain),comment_(comment), secure_(0), has_age_(0)
name_(name), value_(value), path_(path),domain_(domain),comment_(comment), secure_(0), has_age_(0), has_expiration_(0)
{
}

cookie::cookie(cookie const &other) :
d(other.d),
name_(other.name_),
value_(other.value_),
path_(other.path_),
@@ -106,12 +130,14 @@ cookie::cookie(cookie const &other) :
comment_(other.comment_),
max_age_(other.max_age_),
secure_(other.secure_),
has_age_(other.has_age_)
has_age_(other.has_age_),
has_expiration_(other.has_expiration_)
{
}

cookie const &cookie::operator=(cookie const &other)
{
d=other.d;
name_=other.name_;
value_=other.value_;
path_=other.path_;
@@ -120,10 +146,11 @@ cookie const &cookie::operator=(cookie const &other)
max_age_=other.max_age_;
secure_=other.secure_;
has_age_=other.has_age_;
has_expiration_ = other.has_expiration_;
return *this;
}

cookie::cookie() : secure_(0), has_age_(0) {}
cookie::cookie() : secure_(0), has_age_(0), has_expiration_(0) {}
cookie::~cookie() {}




+ 20
- 4
src/session_interface.cpp View File

@@ -394,18 +394,34 @@ void session_interface::set_session_cookie(int64_t age,string const &data,string
}
std::string const &domain = context_->service().cached_settings().session.cookies.domain;
std::string const &path = context_->service().cached_settings().session.cookies.path;
int time_shift = context_->service().cached_settings().session.cookies.time_shift;
bool use_age = context_->service().cached_settings().session.cookies.use_age;
bool use_exp = context_->service().cached_settings().session.cookies.use_exp;

bool secure = context_->service().cached_settings().session.cookies.secure;

http::cookie the_cookie(cookie_name,util::urlencode(data),path,domain);

if(age < 0) {
the_cookie.max_age(0);
if(use_age)
the_cookie.max_age(0);
if(use_exp)
the_cookie.expires(1);
}
else if(age == 0)
else if(age == 0) {
the_cookie.browser_age();
else
the_cookie.max_age(age);
}
else {
if(use_age)
the_cookie.max_age(age);
if(use_exp) {
the_cookie.expires(age + time(0) + time_shift);
}
}


the_cookie.secure(secure);

context_->response().set_cookie(the_cookie);
}



+ 1
- 0
tests/session_interface_test.js View File

@@ -13,6 +13,7 @@
"prefix" : "sc",
"domain" : "foo.bar",
"path" : "/foo",
"expiration_method" : "max-age"
},
"client" : {
"hmac" : "sha1",


Loading…
Cancel
Save