123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260(* Ocsigen
* http://www.ocsigen.org
* Module eliommod_datasess.ml
* Copyright (C) 2007 Vincent Balat
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, with linking exception;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*)(*****************************************************************************)(*****************************************************************************)(** Internal functions used by Eliom: *)(** Volatile data tables *)(*****************************************************************************)(*****************************************************************************)openEliom_libletcompute_cookie_infositedatasecure_osecure_cicookie_info=letsecure=Eliom_common.get_secure~secure_o~sitedata()inifsecurethenlet_,c,_=secure_ciinc,trueelsecookie_info,false(* to be called during a request *)letclose_data_state~scope~secure_o?sp()=letsp=Eliom_common.sp_of_optionspintryletcookie_level=Eliom_common.cookie_level_of_user_scopescopeinlet(_,cookie_info,_),secure_ci=Eliom_common.get_cookie_infospcookie_levelinletsitedata=Eliom_request_info.get_sitedata_sp~spinletcookie_info,secure=compute_cookie_infositedatasecure_osecure_cicookie_infoinletfull_st_name=Eliom_common.make_full_state_name~sp~secure~scopeinlet_,ior=Lazy.force(Eliom_common.Full_state_name_table.findfull_st_name!cookie_info)inmatch!iorwith|Eliom_common.SCc->(* There is only one way to close a session:
remove it from the session group table.
It will remove all the data table entries
and also the entry in the session table *)(matchscopewith|`Session_group_->((* If we want to close all the group of browser sessions,
the node is found in the group table: *)matchEliommod_sessiongroups.Data.find_node_in_group_of_groups!(c.Eliom_common.dc_session_group)with|None->Lwt_log.ign_error~section:Lwt_log.eliom"No group of groups. Please report this problem."|Someg->Eliommod_sessiongroups.Data.removeg)|`Session_|`Client_process_->(* If we want to close a (tab/browser) session, the node is found
in the cookie info: *)Eliommod_sessiongroups.Data.removec.Eliom_common.dc_session_group_node);ior:=Eliom_common.SCNo_data|_->()withNot_found->()letfullsessgrp~cookie_level~spset_session_group=Eliommod_sessiongroups.make_full_group_name~cookie_levelsp.Eliom_common.sp_request.Ocsigen_extensions.request_info(Eliom_common.get_site_dir_stringsp.Eliom_common.sp_sitedata)(Eliom_common.get_mask4sp.Eliom_common.sp_sitedata)(Eliom_common.get_mask6sp.Eliom_common.sp_sitedata)set_session_groupletrecfind_or_create_data_cookie?set_session_group~(cookie_scope:Eliom_common.cookie_scope)~secure_o?sp()=(* If the cookie does not exist, create it.
Returns the cookie info for the cookie *)letcookie_level=Eliom_common.cookie_level_of_user_scopecookie_scopeinletsp=Eliom_common.sp_of_optionspinletnew_data_cookiesitedatafull_st_nametable=letset_session_group=matchcookie_scopewith|`Client_processn->(* We create a group whose name is the
browser session cookie
and put the tab session into it. *)letv=find_or_create_data_cookie~cookie_scope:(`Sessionn)~secure_o~sp()inSomeEliom_common.(Hashed_cookies.to_stringv.dc_hvalue)|_->set_session_groupinletfullsessgrp=fullsessgrp~cookie_level~spset_session_groupinletc=Eliommod_cookies.make_new_session_id()inlethc=Eliom_common.Hashed_cookies.hashcinlethc_string=Eliom_common.Hashed_cookies.to_stringhcinletusertimeout=refEliom_common.TGlobal(* See global table *)inletserverexp=refNone(* Some 0. *)(* None = never. We'll change it later. *)inletfullsessgrpref=reffullsessgrpinletnode=Eliommod_sessiongroups.Data.addsitedatahc_stringfullsessgrpinEliom_common.SessionCookies.replace(* actually it will add the cookie *)tablehc_string{Eliom_common.Data_cookie.full_state_name=full_st_name;expiry=serverexp;timeout=usertimeout;session_group=fullsessgrpref;session_group_node=node};{Eliom_common.dc_hvalue=hc;Eliom_common.dc_set_value=Somec;Eliom_common.dc_timeout=usertimeout;Eliom_common.dc_exp=serverexp;Eliom_common.dc_cookie_exp=ref(Eliom_common.default_client_cookie_exp());Eliom_common.dc_session_group=fullsessgrpref;Eliom_common.dc_session_group_node=node}inlet(_,cookie_info,_),secure_ci=Eliom_common.get_cookie_infospcookie_levelinletsitedata=Eliom_request_info.get_sitedata_sp~spinletcookie_info,secure=compute_cookie_infositedatasecure_osecure_cicookie_infoinletfull_st_name=Eliom_common.make_full_state_name~sp~secure~scope:cookie_scopeintrylet_old,ior=Lazy.force(Eliom_common.Full_state_name_table.findfull_st_name!cookie_info)inmatch!iorwith|Eliom_common.SCData_session_expired(* We do not trust the value sent by the client,
for security reasons *)|Eliom_common.SCNo_data->letv=new_data_cookiesitedatafull_st_namesitedata.Eliom_common.session_datainior:=Eliom_common.SCv;v|Eliom_common.SCc->(matchset_session_groupwith|None->()|Some_session_group->letfullsessgrp=fullsessgrp~cookie_level~spset_session_groupinletnode=Eliommod_sessiongroups.Data.movesitedatac.Eliom_common.dc_session_group_nodefullsessgrpinc.Eliom_common.dc_session_group_node<-node;c.Eliom_common.dc_session_group:=fullsessgrp);cwithNot_found->letv=new_data_cookiesitedatafull_st_namesitedata.Eliom_common.session_dataincookie_info:=Eliom_common.Full_state_name_table.addfull_st_name(Lazy.from_val(None,ref(Eliom_common.SCv)))!cookie_info;vletfind_or_create_data_cookie=(find_or_create_data_cookie:?set_session_group:string->cookie_scope:Eliom_common.cookie_scope->secure_o:booloption->?sp:Eliom_common.server_params->unit->Eliom_common.one_data_cookie_info:>?set_session_group:string->cookie_scope:[<Eliom_common.cookie_scope]->secure_o:booloption->?sp:Eliom_common.server_params->unit->Eliom_common.one_data_cookie_info)letfind_data_cookie_only~cookie_scope~secure_o?sp()=(* If the cookie does not exist, do not create it, raise Not_found.
Returns the cookie info for the cookie *)letsp=Eliom_common.sp_of_optionspinletcookie_level=Eliom_common.cookie_level_of_user_scopecookie_scopeinlet(_,cookie_info,_),secure_ci=Eliom_common.get_cookie_infospcookie_levelinletsitedata=Eliom_request_info.get_sitedata_sp~spinletcookie_info,secure=compute_cookie_infositedatasecure_osecure_cicookie_infoinletfull_st_name=Eliom_common.make_full_state_name~sp~secure~scope:cookie_scopeinlet_,ior=Lazy.force(Eliom_common.Full_state_name_table.findfull_st_name!cookie_info)inmatch!iorwith|Eliom_common.SCNo_data->raiseNot_found|Eliom_common.SCData_session_expired->raiseEliom_common.Eliom_Session_expired|Eliom_common.SCv->v(*****************************************************************************)(** session data *)letcounttableelements=ref[](* Here only for exploration functions *)letcreate_volatile_table,create_volatile_table_during_session=letaux~scope~securesitedata=lett=Eliom_common.SessionCookies.create100inletold_remove_session_data=sitedata.Eliom_common.remove_session_datainsitedata.Eliom_common.remove_session_data<-(funcookie->(* cookie is actually either a cookie or a a group name *)(* In session group tables, keys may be either group names,
or a cookie values when no group name has been set. *)old_remove_session_datacookie;Eliom_common.SessionCookies.removetcookie);letold_not_bound_in_data_tables=sitedata.Eliom_common.not_bound_in_data_tablesinsitedata.Eliom_common.not_bound_in_data_tables<-(funcookie->old_not_bound_in_data_tablescookie&¬(Eliom_common.SessionCookies.memtcookie));counttableelements:=(fun()->Eliom_common.SessionCookies.lengtht)::!counttableelements;scope,secure,tin((fun~scope~secure->letsitedata=Eliom_common.get_current_sitedata()inaux~scope~securesitedata),fun~scope~securesitedata->aux~scope~securesitedata)