|
- #include "session_sid.h"
- #include "md5.h"
- #include "session_storage.h"
- #include "session_interface.h"
- #include <fstream>
- #include "cppcms_error.h"
- #include "archive.h"
- #include "worker_thread.h"
-
- using namespace std;
-
- namespace cppcms {
- namespace details {
-
- sid_generator::sid_generator()
- {
- hashed.session_counter=0;
- ifstream urandom("/dev/urandom");
- if(!urandom.good() || urandom.get(hashed.uid,16).fail()) {
- throw cppcms_error("Failed to read /dev/urandom");
- }
- }
-
- std::string sid_generator::operator()()
- {
- hashed.session_counter++;
- gettimeofday(&hashed.tv,NULL);
-
- md5_byte_t md5[16];
- char res[33];
- md5_state_t st;
- md5_init(&st);
- md5_append(&st,(md5_byte_t*)&hashed,sizeof(hashed));
- md5_finish(&st,md5);
- for(int i=0;i<16;i++) {
- snprintf(res+i*2,3,"%02x",md5[i]);
- }
- return std::string(res);
- }
-
-
- } // namespace details
-
- namespace {
- struct cached_data : public serializable {
- time_t timeout;
- std::string data;
- virtual void load(archive &a)
- {
- a>>timeout>>data;
- }
- virtual void save(archive &a) const
- {
- a<<timeout<<data;
- }
-
- };
- }
-
-
- bool session_sid::valid_sid(std::string const &id)
- {
- if(id.size()!=32)
- return false;
- for(int i=0;i<32;i++) {
- char c=id[i];
- bool is_low_x_digit=('0'<=c && c<='9') || ('a'<=c && c<='f');
- if(!is_low_x_digit)
- return false;
- }
- return true;
- }
-
- string session_sid::key(std::string sid)
- {
- return "_cppcms_session_"+sid;
- }
-
- void session_sid::save(session_interface *session,std::string const &data,time_t timeout,bool new_data)
- {
- string id;
- if(!new_data) {
- id=session->get_session_cookie();
- if(!valid_sid(id)) {
- id=sid(); // if id not valid create new one
- }
- }
- else {
- id=sid();
- }
-
- if(cache){
- session->get_worker().cache.rise(key(id));
- }
- storage->save(id,timeout,data);
- session->set_session_cookie(id); // Renew cookie or set new one
- if(cache) {
- cached_data cdata;
- cdata.timeout=timeout;
- cdata.data=data;
- session->get_worker().cache.store_data(
- key(id),
- cdata,
- timeout - time(NULL),
- true);
- // Store entry without triggers
- }
- }
-
- bool session_sid::load(session_interface *session,std::string &data,time_t &timeout)
- {
- string id=session->get_session_cookie();
- if(!valid_sid(id))
- return false;
- if(cache){
- cached_data cdata;
- if(session->get_worker().cache.fetch_data(key(id),cdata,true)) {
- // fetch data without triggers
- data.swap(cdata.data);
- timeout=cdata.timeout;
- return true;
- }
- }
- if(!storage->load(id,&timeout,data)) {
- return false;
- }
- if(!cache)
- return true;
-
- cached_data cdata;
- cdata.timeout=timeout;
- cdata.data=data;
-
- session->get_worker().cache.store_data(
- key(id),
- cdata,
- timeout-time(NULL),
- true
- ); // store entry without triggers
- return true;
- }
-
- void session_sid::clear(session_interface *session)
- {
- string id=session->get_session_cookie();
- if(valid_sid(id)) {
- storage->remove(id);
- if(cache)
- session->get_worker().cache.rise(key(id));
- }
- }
-
-
- } // namespace cppcms
|