package eliom

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Source file eliommod_sersess.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
(* Ocsigen
 * http://www.ocsigen.org
 * 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:                                        *)

(** Service sessions                                                         *)

(*****************************************************************************)
(*****************************************************************************)

open Eliom_lib

let compute_cookie_info sitedata secure_o secure_ci cookie_info =
  let secure = Eliom_common.get_secure ~secure_o ~sitedata () in
  if secure
  then
    let c, _, _ = secure_ci in
    c, true
  else cookie_info, false

(*****************************************************************************)
let close_service_state ~scope ~secure_o ?sp () =
  let sp = Eliom_common.sp_of_option sp in
  try
    let cookie_level = Eliom_common.cookie_level_of_user_scope scope in
    let (cookie_info, _, _), secure_ci =
      Eliom_common.get_cookie_info sp cookie_level
    in
    let sitedata = Eliom_request_info.get_sitedata_sp ~sp in
    let cookie_info, secure =
      compute_cookie_info sitedata secure_o secure_ci cookie_info
    in
    let full_st_name = Eliom_common.make_full_state_name ~sp ~secure ~scope in
    let _, ior =
      Eliom_common.Full_state_name_table.find full_st_name !cookie_info
    in
    match !ior with
    | Eliom_common.SC c ->
        (* there is only one way to close a session:
             remove it from the session group table.
             It will remove the entry in the session table *)
        (match scope with
        | `Session_group _ -> (
          (* If we want to close all the group of browser sessions,
                   the node is found in the group table: *)
          match
            Eliommod_sessiongroups.Serv.find_node_in_group_of_groups
              !(c.Eliom_common.sc_session_group)
          with
          | None ->
              Lwt_log.ign_error ~section:Lwt_log.eliom
                "No group of groups. Please report this problem."
          | Some (_service_table, g) -> Eliommod_sessiongroups.Serv.remove g)
        | `Session _ | `Client_process _ ->
            Eliommod_sessiongroups.Serv.remove
              c.Eliom_common.sc_session_group_node);
        ior := Eliom_common.SCNo_data
    | _ -> ()
  with Not_found -> ()

let fullsessgrp ~cookie_level ~sp set_session_group =
  let sitedata = Eliom_request_info.get_sitedata_sp ~sp in
  Eliommod_sessiongroups.make_full_group_name ~cookie_level
    (Eliom_request_info.get_request_sp sp).Ocsigen_extensions.request_info
    (Eliom_common.get_site_dir_string sitedata)
    (Eliom_common.get_mask4 sitedata)
    (Eliom_common.get_mask6 sitedata)
    set_session_group

let rec find_or_create_service_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 *)
  let cookie_level = Eliom_common.cookie_level_of_user_scope cookie_scope in
  let new_service_cookie sitedata full_state_name table =
    let set_session_group =
      match cookie_scope with
      | `Client_process n ->
          (* We create a group whose name is the
                   browser session cookie
                   and put the tab session into it. *)
          let v =
            find_or_create_service_cookie_ ~cookie_scope:(`Session n) ~secure_o
              ~sp ()
          in
          Some Eliom_common.(Hashed_cookies.to_string v.sc_hvalue)
      | _ -> set_session_group
    in
    let fullsessgrp = fullsessgrp ~cookie_level ~sp set_session_group in
    let c = Eliommod_cookies.make_new_session_id () in
    let hc = Eliom_common.Hashed_cookies.hash c in
    let hc_string = Eliom_common.Hashed_cookies.to_string hc in
    let str = ref (Eliom_common.new_service_session_tables sitedata) in
    let timeout = ref Eliom_common.TGlobal (* See global table *) in
    let expiry =
      ref None
      (*Some 0.*)
      (* None = never. We'll change it later. *)
    in
    let session_group = ref fullsessgrp in
    let session_group_node =
      Eliommod_sessiongroups.Serv.add sitedata hc_string fullsessgrp
    in
    Eliom_common.SessionCookies.replace
      (* actually it will add the cookie *)
      table hc_string
      { Eliom_common.Service_cookie.full_state_name
      ; session_table = !str
      ; expiry
      ; timeout
      ; session_group
      ; session_group_node };
    { Eliom_common.sc_hvalue = hc
    ; Eliom_common.sc_set_value = Some c
    ; Eliom_common.sc_table = str
    ; Eliom_common.sc_timeout = timeout
    ; Eliom_common.sc_exp = expiry
    ; Eliom_common.sc_cookie_exp =
        ref (Eliom_common.default_client_cookie_exp ())
    ; Eliom_common.sc_session_group = session_group
    ; Eliom_common.sc_session_group_node = session_group_node }
  in
  let (cookie_info, _, _), secure_ci =
    Eliom_common.get_cookie_info sp cookie_level
  in
  let sitedata = Eliom_request_info.get_sitedata_sp ~sp in
  let cookie_info, secure =
    compute_cookie_info sitedata secure_o secure_ci cookie_info
  in
  let full_st_name =
    Eliom_common.make_full_state_name ~sp ~secure ~scope:cookie_scope
  in
  try
    let _old, ior =
      Eliom_common.Full_state_name_table.find full_st_name !cookie_info
    in
    match !ior with
    | Eliom_common.SCData_session_expired
      (* We do not trust the value sent by the client,
           for security reasons *)
    | Eliom_common.SCNo_data ->
        let v =
          new_service_cookie sitedata full_st_name
            sitedata.Eliom_common.session_services
        in
        ior := Eliom_common.SC v;
        v
    | Eliom_common.SC c ->
        (match set_session_group with
        | None -> ()
        | Some _session_group ->
            let fullsessgrp = fullsessgrp ~cookie_level ~sp set_session_group in
            let node =
              Eliommod_sessiongroups.Serv.move sitedata
                c.Eliom_common.sc_session_group_node fullsessgrp
            in
            c.Eliom_common.sc_session_group_node <- node;
            c.Eliom_common.sc_session_group := fullsessgrp);
        c
  with Not_found ->
    let v =
      new_service_cookie sitedata full_st_name
        sitedata.Eliom_common.session_services
    in
    cookie_info :=
      Eliom_common.Full_state_name_table.add full_st_name
        (None, ref (Eliom_common.SC v))
        !cookie_info;
    v

let find_or_create_service_cookie_ =
  (find_or_create_service_cookie_
    : ?set_session_group:string
      -> cookie_scope:Eliom_common.cookie_scope
      -> secure_o:bool option
      -> sp:Eliom_common.server_params
      -> unit
      -> Eliom_common.tables Eliom_common.one_service_cookie_info
    :> ?set_session_group:string
       -> cookie_scope:[< Eliom_common.cookie_scope]
       -> secure_o:bool option
       -> sp:Eliom_common.server_params
       -> unit
       -> Eliom_common.tables Eliom_common.one_service_cookie_info)

let find_or_create_service_cookie ?set_session_group ~cookie_scope ~secure_o ?sp
    ()
  =
  let sp = Eliom_common.sp_of_option sp in
  find_or_create_service_cookie_ ?set_session_group ~cookie_scope ~secure_o ~sp
    ()

let find_service_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 *)
  let sp = Eliom_common.sp_of_option sp in
  let (cookie_info, _, _), secure_ci =
    Eliom_common.get_cookie_info sp
      (Eliom_common.cookie_level_of_user_scope cookie_scope)
  in
  let sitedata = Eliom_request_info.get_sitedata_sp ~sp in
  let cookie_info, secure =
    compute_cookie_info sitedata secure_o secure_ci cookie_info
  in
  let full_st_name =
    Eliom_common.make_full_state_name ~sp ~secure ~scope:cookie_scope
  in
  let _, ior =
    Eliom_common.Full_state_name_table.find full_st_name !cookie_info
  in
  match !ior with
  | Eliom_common.SCNo_data -> raise Not_found
  | Eliom_common.SCData_session_expired ->
      raise Eliom_common.Eliom_Session_expired
  | Eliom_common.SC v -> v
OCaml

Innovation. Community. Security.