123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224(* Ocsigen
* http://www.ocsigen.org
* Module eliommod_persess.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: *)(** Persistent data tables *)(*****************************************************************************)(*****************************************************************************)(*****************************************************************************)(* Persistent sessions: *)openLwtletcompute_cookie_infositedatasecure_osecure_cicookie_info=letsecure=Eliom_common.get_secure~secure_o~sitedata()inifsecurethenlet_,_,c=secure_ciinc,trueelsecookie_info,falseletclose_persistent_state2~(scope:[<Eliom_common.user_scope])sitedatasgv=(* check *)matchscopewith|`Session_group_->Eliommod_sessiongroups.Pers.remove_group~cookie_level:`Sessionsitedatasg|_->Eliommod_sessiongroups.Pers.close_persistent_session2~cookie_level:(Eliom_common.cookie_level_of_user_scopescope)sitedatasgv(* close current persistent session *)letclose_persistent_state~scope~secure_o?sp()=letsp=Eliom_common.sp_of_optionspincatch(fun()->letcookie_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~scopeinLazy.force(Eliom_common.Full_state_name_table.findfull_st_name!cookie_info)>>=fun(_,ior)->match!iorwith|Eliom_common.SCc->close_persistent_state2~scope:(scope:>Eliom_common.user_scope)sp.Eliom_common.sp_sitedata!(c.Eliom_common.pc_session_group)Eliom_common.(Hashed_cookies.to_stringc.pc_hvalue)>>=fun()->ior:=Eliom_common.SCNo_data;return_unit|_->return_unit)(functionNot_found->return_unit|e->faile)letfullsessgrp~cookie_level~spsession_group=Eliommod_sessiongroups.make_persistent_full_group_name~cookie_level(Eliom_common.get_site_dir_stringsp.Eliom_common.sp_sitedata)session_groupletrecfind_or_create_persistent_cookie_?set_max_in_group?set_session_group~cookie_scope~secure_o~sp()=(* if it exists, do not create it, but returns its value *)letcookie_level=Eliom_common.cookie_level_of_user_scopecookie_scopeinletnew_persistent_cookiesitedatafull_state_name=let%lwtset_session_group=matchcookie_scopewith|`Client_processn->(* We create a group whose name is the
browser session cookie
and put the tab session into it. *)let%lwtr=find_or_create_persistent_cookie_~set_max_in_group:(fstsitedata.Eliom_common.max_persistent_data_tab_sessions_per_group)~cookie_scope:(`Sessionn)~secure_o~sp()inLwt.return_someEliom_common.(Hashed_cookies.to_stringr.pc_hvalue)|_->Lwt.returnset_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_stringhcin(* We do not need to verify if it already exists.
make_new_session_id does never generate twice the same cookie. *)letusertimeout=refEliom_common.TGlobal(* See global table *)inlet%lwt()=Eliommod_cookies.Persistent_cookies.addhc_string{Eliommod_cookies.full_state_name;expiry=None;(* exp on server - We'll change it later *)timeout=Eliom_common.TGlobal;session_group=fullsessgrp}inEliommod_sessiongroups.Pers.add?set_max:set_max_in_group(fstsitedata.Eliom_common.max_persistent_data_sessions_per_group)hc_stringfullsessgrp>>=funl->Lwt_list.iter_p(close_persistent_state2~scope:(cookie_scope:>Eliom_common.user_scope)sitedataNone)l>>=fun()->Lwt.return{Eliom_common.pc_hvalue=hc;Eliom_common.pc_set_value=Somec;Eliom_common.pc_timeout=usertimeout;Eliom_common.pc_cookie_exp=ref(Eliom_common.default_client_cookie_exp())(* exp on client *);Eliom_common.pc_session_group=reffullsessgrp}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_scopeincatch(fun()->Lazy.force(Eliom_common.Full_state_name_table.findfull_st_name!cookie_info)>>=fun(_old,ior)->match!iorwith|Eliom_common.SCData_session_expired(* We do not trust the value sent by the client,
for security reasons *)|Eliom_common.SCNo_data->new_persistent_cookiesitedatafull_st_name>>=funv->ior:=Eliom_common.SCv;returnv|Eliom_common.SCv->returnv)(function|Not_found->new_persistent_cookiesitedatafull_st_name>>=funv->cookie_info:=Eliom_common.Full_state_name_table.addfull_st_name(Lazy.from_val(return(None,ref(Eliom_common.SCv))))!cookie_info;returnv|e->faile)letfind_or_create_persistent_cookie?set_session_group~cookie_scope~secure_o?sp()=letsp=Eliom_common.sp_of_optionspinfind_or_create_persistent_cookie_?set_session_group~cookie_scope~secure_o~sp()letfind_or_create_persistent_cookie=(find_or_create_persistent_cookie:?set_session_group:string->cookie_scope:Eliom_common.cookie_scope->secure_o:booloption->?sp:Eliom_common.server_params->unit->Eliom_common.one_persistent_cookie_infoLwt.t:>?set_session_group:string->cookie_scope:[<Eliom_common.cookie_scope]->secure_o:booloption->?sp:Eliom_common.server_params->unit->Eliom_common.one_persistent_cookie_infoLwt.t)letfind_persistent_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_scopeinLazy.force(Eliom_common.Full_state_name_table.findfull_st_name!cookie_info)>>=fun(_,ior)->match!iorwith|Eliom_common.SCNo_data->raiseNot_found|Eliom_common.SCData_session_expired->raiseEliom_common.Eliom_Session_expired|Eliom_common.SCv->returnv