ChipMaster's trial hacks on C++CMS starting with v1.2.1. Not sure I'll follow on with the v2 since it looks to be breaking and mostly frivolous.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

155 lines
2.9 KiB

  1. #include "session_sid.h"
  2. #include "md5.h"
  3. #include "session_storage.h"
  4. #include "session_interface.h"
  5. #include <fstream>
  6. #include "cppcms_error.h"
  7. #include "archive.h"
  8. #include "worker_thread.h"
  9. using namespace std;
  10. namespace cppcms {
  11. namespace details {
  12. sid_generator::sid_generator()
  13. {
  14. hashed.session_counter=0;
  15. ifstream urandom("/dev/urandom");
  16. if(!urandom.good() || urandom.get(hashed.uid,16).fail()) {
  17. throw cppcms_error("Failed to read /dev/urandom");
  18. }
  19. }
  20. std::string sid_generator::operator()()
  21. {
  22. hashed.session_counter++;
  23. gettimeofday(&hashed.tv,NULL);
  24. md5_byte_t md5[16];
  25. char res[33];
  26. md5_state_t st;
  27. md5_init(&st);
  28. md5_append(&st,(md5_byte_t*)&hashed,sizeof(hashed));
  29. md5_finish(&st,md5);
  30. for(int i=0;i<16;i++) {
  31. snprintf(res+i*2,3,"%02x",md5[i]);
  32. }
  33. return std::string(res);
  34. }
  35. } // namespace details
  36. namespace {
  37. struct cached_data : public serializable {
  38. time_t timeout;
  39. std::string data;
  40. virtual void load(archive &a)
  41. {
  42. a>>timeout>>data;
  43. }
  44. virtual void save(archive &a) const
  45. {
  46. a<<timeout<<data;
  47. }
  48. };
  49. }
  50. bool session_sid::valid_sid(std::string const &id)
  51. {
  52. if(id.size()!=32)
  53. return false;
  54. for(int i=0;i<32;i++) {
  55. char c=id[i];
  56. bool is_low_x_digit=('0'<=c && c<='9') || ('a'<=c && c<='f');
  57. if(!is_low_x_digit)
  58. return false;
  59. }
  60. return true;
  61. }
  62. string session_sid::key(std::string sid)
  63. {
  64. return "_cppcms_session_"+sid;
  65. }
  66. void session_sid::save(session_interface *session,std::string const &data,time_t timeout,bool new_data)
  67. {
  68. string id;
  69. if(!new_data) {
  70. id=session->get_session_cookie();
  71. if(!valid_sid(id)) {
  72. id=sid(); // if id not valid create new one
  73. }
  74. }
  75. else {
  76. id=sid();
  77. }
  78. if(cache){
  79. session->get_worker().cache.rise(key(id));
  80. }
  81. storage->save(id,timeout,data);
  82. session->set_session_cookie(id); // Renew cookie or set new one
  83. if(cache) {
  84. cached_data cdata;
  85. cdata.timeout=timeout;
  86. cdata.data=data;
  87. session->get_worker().cache.store_data(
  88. key(id),
  89. cdata,
  90. timeout - time(NULL),
  91. true);
  92. // Store entry without triggers
  93. }
  94. }
  95. bool session_sid::load(session_interface *session,std::string &data,time_t &timeout)
  96. {
  97. string id=session->get_session_cookie();
  98. if(!valid_sid(id))
  99. return false;
  100. if(cache){
  101. cached_data cdata;
  102. if(session->get_worker().cache.fetch_data(key(id),cdata,true)) {
  103. // fetch data without triggers
  104. data.swap(cdata.data);
  105. timeout=cdata.timeout;
  106. return true;
  107. }
  108. }
  109. if(!storage->load(id,&timeout,data)) {
  110. return false;
  111. }
  112. if(!cache)
  113. return true;
  114. cached_data cdata;
  115. cdata.timeout=timeout;
  116. cdata.data=data;
  117. session->get_worker().cache.store_data(
  118. key(id),
  119. cdata,
  120. timeout-time(NULL),
  121. true
  122. ); // store entry without triggers
  123. return true;
  124. }
  125. void session_sid::clear(session_interface *session)
  126. {
  127. string id=session->get_session_cookie();
  128. if(valid_sid(id)) {
  129. storage->remove(id);
  130. if(cache)
  131. session->get_worker().cache.rise(key(id));
  132. }
  133. }
  134. } // namespace cppcms