Plasma GitLab Archive
Projects Blog Knowledge

(*
 * <COPYRIGHT>
 * Copyright 2003 Gerd Stolpmann
 *
 * <GPL>
 * This file is part of WTimer.
 *
 * WTimer is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * WTimer 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with WDialog; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * </>
 *)

(* $Id: startpage.ml,v 1.7 2003/03/23 20:03:50 gerd Exp $
 * ----------------------------------------------------------------------
 *
 *)

open Wd_dialog
open Wd_run_cgi
open Wd_types
open Netcgi_types

open Db.Types

let gecko_re = Netstring_pcre.regexp ".*Gecko/";;
let mozold_re = Netstring_pcre.regexp ".*Mozilla/[1234]";;
let msie_re = Netstring_pcre.regexp ".*MSIE";;  (* but MSIE is also mozold! *)
let msie_old_re = Netstring_pcre.regexp ".*MSIE [1234]";;
let msie_50_re = Netstring_pcre.regexp ".*MSIE 5.0";;
let opera_re = Netstring_pcre.regexp ".*Opera";; (* normally also MSIE *)


class startpage db universe name env =
object (self)
  inherit dialog universe name env
    
  method prepare_page() =
    (* Create a new session (empty by default): *)
    let session = !Registry.new_session universe env in
    (* Check whether there is a cookie containing the browser capabilities: *)
    let cgi = (self # environment).cgi in
    let cgienv = cgi # environment in
    let cookies = cgienv # cookies in
    let grid = 
      try
	List.assoc "wtimer-browser-cap" cookies 
      with
	  Not_found ->
	    (* No cookie: Browser sniffing as fallback method *)
	    let user_agent = cgienv # user_agent in
	    if Netstring_pcre.string_match gecko_re user_agent 0 <> None then
	      "dynamic"    (* for Gecko-based browsers *)
	    else
	      if Netstring_pcre.string_match opera_re user_agent 0 <> None then
		"fixed"    (* Operas work best with "fixed" *)
	      else
		if Netstring_pcre.string_match msie_re user_agent 0 <> None 
		then (
		  if Netstring_pcre.string_match msie_50_re user_agent 0 <>
		     None &&
		     Netstring_pcre.string_match msie_old_re user_agent 0 <>
		     None then
		       "legacy" (* for older Internet Explorers *)
		  else
		    "960"      (* for modern Internet Explorers *)
		)
	      else
		if Netstring_pcre.string_match mozold_re user_agent 0 <> None
		then       (* for Netscapes until 4.XX *)
		  "legacy"
		else
		  "960"    (* default *)
    in
    session # set_variable "grid" (Enum_value [grid]);
    (* Save the session: *)
    self # set_variable "session" (Dialog_value (Some session));
    self # set_variable "version" (String_value Const.version);


  method handle() =
    if self # event <> No_event then begin

      let grid = self # enum_variable "session.grid" in

      (* If demanded, store a new cookie: *)
      let grid_cookie = self # enum_variable "session.grid-cookie" in
      if grid_cookie = [ "yes" ] then begin
	(* The CGI activation object has already set the header, but we
	 * can modify it by calling the cgienv methods. Not very elegant,
	 * and to be improved.
	 *)
	let year = 86400.0 *. 365.0 in
	let cgi = (self # environment).cgi in
	let rh  = (self # environment).response_header in
	rh.rh_set_cookie <- [ { cookie_name = "wtimer-browser-cap";
				cookie_value = String.concat "" grid;
				cookie_expires = Some (Unix.time() +. year);
				cookie_domain = None;
				cookie_path = None;
				cookie_secure = cgi#environment#cgi_https;
			      } ];
      end;

      (* Set the button implementation from the grid: *)
      if grid = [ "dynamic" ] then
	self # set_variable "session.button-impl" (String_value "richbutton");
      
      (* Handle the event: *)
      
      match self#event with
	  Button("start") ->
	    (* Login by REMOTE_USER and trust the web server *)
	    let session = 
	      match self # dialog_variable "session" with
		  None -> assert false
		| Some s -> s in
	    let cgi = (self # environment).cgi in
	    let cgienv = cgi # environment in
	    let user = cgienv # cgi_remote_user in
	    let user_passes =
	      ( try
		  let urec = Db.User.get db (User user) in
		  urec.u_login
		with
		    No_such_user _ -> false
		  | Not_found -> false
	      ) in
	    if user_passes then begin
	      let now = Unix.localtime(Unix.time()) in
	      let now_str = Printf.sprintf "%04d-%02d-01"
			      (now.Unix.tm_year + 1900)
			      (now.Unix.tm_mon + 1) in
	      session # set_variable "login-user" (String_value user);
	      session # set_variable "passwd-hash" (String_value "n/a");
	      session # set_variable "current-sheet" (String_value user);
	      session # set_variable "current-date" (String_value now_str);
	      let next_dlg = 
		!Registry.new_editor universe env (Some session) in
	      raise(Change_dialog next_dlg)
	    end 
	    else
	      raise Definitions.Login_not_permitted
		
	| Button("login") ->
	    (* Login by entered user and password *)
	    let session = 
	      match self # dialog_variable "session" with
		  None -> assert false
		| Some s -> s in
	    let user = self # string_variable "entered-user" in
	    let pw = self # string_variable "entered-password" in
	    (* Check password: *)
	    let user_passes =
	      ( try
		  let urec = Db.User.get db (User user) in
		  match urec.u_password with
		      None -> raise Not_found
		    | Some upw ->
			if Db.User.encrypt_password pw <> upw then
			  raise Not_found;
			urec.u_login
		  with
		      No_such_user _ -> false
		    | Not_found -> false
	      ) in
	    if user_passes then begin
	      let now = Unix.localtime(Unix.time()) in
	      let now_str = Printf.sprintf "%04d-%02d-01"
			      (now.Unix.tm_year + 1900)
			      (now.Unix.tm_mon + 1) in
	      session # set_variable "login-user" (String_value user);
	      session # set_variable "passwd-hash" 
	        (String_value (Digest.string pw));
	      session # set_variable "current-sheet" (String_value user);
	      session # set_variable "current-date" (String_value now_str);
	      let next_dlg = 
		!Registry.new_editor universe env (Some session) in
	      raise(Change_dialog next_dlg)
	    end 
	    else
	      self # set_variable "bad-password" (String_value "yes")
	| _ ->
	    ()
    end

end
;;

Registry.new_startpage := 
  fun universe env ->
    let dlg = universe # create env "startpage" in
    dlg
;;

(* ======================================================================
 * History:
 * 
 * $Log: startpage.ml,v $
 * Revision 1.7  2003/03/23 20:03:50  gerd
 * 	Updates
 *
 * Revision 1.6  2003/03/23 11:59:14  gerd
 * 	GPL
 *
 * Revision 1.5  2003/02/16 21:35:15  gerd
 * 	Renamed ui:longbutton into ui:richbutton
 *
 * Revision 1.4  2003/02/07 16:18:10  gerd
 * 	wd-onstartup-call-handle activated
 * 	startpage: case No_event explicitly handled
 *
 * Revision 1.3  2003/02/03 01:28:59  gerd
 * 	Continued.
 *
 * Revision 1.2  2003/01/16 00:39:25  gerd
 * 	Continued.
 *
 * Revision 1.1  2002/11/16 12:34:51  gerd
 * 	Initial revision
 *
 * 
 *)

This web site is published by Informatikbüro Gerd Stolpmann
Powered by Caml