File: n_ds_session.sru
Size: 8135
Date: Sat, 08 Dec 2007 15:38:29 +0100
$PBExportHeader$n_ds_session.sru
$PBExportComments$Session
forward
global type n_ds_session from datastore
end type
end forward

global type n_ds_session from datastore
string dataobject = "d_session"
end type
global n_ds_session n_ds_session

type variables
string is_SessionDir
long il_SecondsUntilInvalid
long  il_ErrorCode
string is_ErrorMsg

constant string SID_NAME = "SID"
constant string COL_SESSIONID = "sessionid"
constant string COL_USERNAME = "username"
constant string SUPERUID = "pweadmin"



end variables
forward prototypes
public function string of_new ()
public function long of_load (string as_sessionid)
public function string of_getsessionid ()
public function long of_getvarvalue (string as_sessionvarname, ref string as_sessionvarvalue)
public function string of_invokemethod (string as_method)
public function string of_logonuser ()
public function string of_generatesessionid ()
public function string of_printsession ()
public function long of_save ()
public function string of_getusername ()
public function long of_cleanupsessions ()
public function string of_logoffuser ()
end prototypes

public function string of_new ();// Create Session and Return SessionID that can be used as a Cookie
// Empty String or Null means that there could not be generated a new
// session id.
string ls_sessionid
ls_sessionid = This.of_generatesessionid( )
if FileExists ( is_sessiondir + "/" + ls_sessionid + ".pbs" ) then
   ls_sessionid = String ( Long ( ls_sessionid ) + 1 )
   if FileExists ( is_sessiondir + "/" + ls_sessionid + ".pbs" ) then
      ls_sessionid = ""
   end if
end if
if Len (ls_sessionid) > 0 then
   This.Reset ()
   if This.InsertRow (0) = 1 Then
      This.SetItem ( 1 , COL_SESSIONID , ls_sessionid )
      return ls_sessionid
   End if
End if
Return ""

end function

public function long of_load (string as_sessionid);if This.ImportFile( Text!, is_sessiondir + as_sessionid + ".pbs" ) = 1 Then
   If as_sessionid = GetItemString ( 1 ,COL_SESSIONID) then
         return 1
   End if
End if

return -1

end function

public function string of_getsessionid ();
if This.RowCount() = 1 then Return This.GetItemString ( 1 , COL_SESSIONID )

return ""
end function

public function long of_getvarvalue (string as_sessionvarname, ref string as_sessionvarvalue);if This.RowCount() = 1 then
   as_sessionvarvalue = This.GetItemString ( 1 , as_sessionvarname )
   return 1
end if
return -1
end function

public function string of_invokemethod (string as_method);
choose case as_method
   case "of_logonuser"
      return This.of_logonuser () 
   case "of_logoffuser"
      return This.of_logoffuser () 
   case "of_printsession"
      return This.of_printsession () 
   case "of_cleanupsessions"
      if of_getusername () = SUPERUID then 
         return String(This.of_cleanupsessions( ))+ " sessions cleaned up<br />"
      else
         return "<h1>Sorry only SUPERUSER can invoke method from outside!</h1>"
      end if
end choose

return "Error in '" + Classname  ( This ) + "'<br />Method '" + as_method +"' unknown.<br />" 
end function

public function string of_logonuser ();string ls_username
string ls_password

string ls_supperpwd

boolean lb_authentified=FALSE

ls_username    = cgienv.of_getParam( "username" )
ls_password    = cgienv.of_getParam( "password" )

// Check for valid login...
log.of_addmessage( 1," Login: " + ls_username + ";" + ls_password)

// A better way might be to call an auth module here...
choose case TRUE
   case  ( ls_username = "admin" and ls_password = "test") ; lb_authentified = TRUE
   case  ( ls_username = "guest" ) ; lb_authentified = TRUE
   case  ( ls_username = "gast" ) ; lb_authentified = TRUE
end choose

if NOT lb_authentified then
   if ls_username = SUPERUID then 
      // Try to get super user password
      ls_supperpwd = ProfileString(cgienv.of_getINIFileName(), "config", "superpwd" , "" )
      lb_authentified = ( Len ( ls_supperpwd ) > 0  and ls_password = ls_supperpwd )
   end if
end if

if lb_authentified then
   This.of_new ()
   This.SetItem ( 1, "username" , ls_username )
   if This.of_save () = 1 then 
      httpheader.of_setcookie( SID_NAME , This.of_getsessionid () )
      httpheader.of_setredirect( WEBPATH + "Index.html")
   else

   End if
Else // Authentifizierung fehlgeschlagen, aber gibt es bereits eine Session?
   if Len ( This.of_getsessionid( )  ) > 0 Then
      // Session deaktivieren!
      This.SetItem ( 1, "username" , "" )
      This.of_save () 
      httpheader.of_setredirect( webpath + "LoginFailed.html")
      return ""
   End if
End if
// Return Simple Error .. to relogin
Return '<strong>Something wunderful had happened.</strong><br/><a href="'+WEBPATH+'Login.html" >Login</a>'
end function

public function string of_generatesessionid ();// Generate Session ID
return String ( Long ( Long( String (Randomize ( 0 )) + String ( Now() , "hhmmffff")) * 13 / 7 ))

end function

public function string of_printsession ();// Print current session data

/* Generate HTML page to return */
return  "<html><body>" +&
   This.Object.DataWindow.data.HTML +&
   "</body></html>"

end function

public function long of_save ();string ls_sessionid
ls_sessionid = This.of_getSessionID () 
if Len ( ls_sessionid ) > 0 then
   This.SetItem ( 1, "lastaccess" , DateTime ( Today () , Now ()))
   Return This.Saveas( is_sessiondir + ls_sessionid + ".pbs" ,Text!, FALSE  )
end if

return -1
end function

public function string of_getusername ();if This.RowCount() = 1 then
    return  This.GetItemString ( 1 , COL_USERNAME )
end if
return ""
end function

public function long of_cleanupsessions ();long ll_idx 
long ll_cnt
long ll_deleted
string ls_directory
string ls_filename []
n_cst_filesrv lnv_filesrv
lnv_filesrv = CREATE n_cst_filesrv
ll_deleted = 0
ls_directory =  This.is_sessiondir 
datetime ldt_cleanup 
time lt_now
date ld_today
//Cleanup sessions older than 1 beforhours
long ll_beforehours = 1 

ld_today = Today()
lt_now = Now ()

if Secondsafter ( Time (  "00:00:00 ") , lt_now )> 3600 * ll_beforehours then
   ldt_cleanup = Datetime ( Today ()  , RelativeTime ( lt_now , -3600 *ll_beforehours) )
else
   ldt_cleanup = Datetime (  RelativeDate (Today (), - 1 ) , RelativeTime ( lt_now , 3600 * (24 - ll_beforehours ) ) )
end if

log.of_addmessage( 2,"Searching for sessions older than " + String ( ldt_cleanup) )

lnv_filesrv.of_findolderfiles( ls_directory + "*.pbs" , ldt_cleanup, ls_filename[])

ll_cnt = UpperBound ( ls_filename )

for ll_idx = 1 to ll_cnt 
   if Len ( ls_filename [ll_idx ] ) > 0 then 
      log.of_addmessage( 2,"Deleting:" + ls_directory +   ls_filename [ll_idx ])
      ll_deleted ++
      FileDelete ( ls_directory +   ls_filename [ll_idx ] )
   end if         
next  

return ll_deleted
end function

public function string of_logoffuser ();// if current Session exists... set to Username to space
if Len ( This.of_getsessionid( ) ) > 0 Then
   // Session deaktivieren!
   This.SetItem ( 1, "username" , "" )
   This.of_save () 
   httpheader.of_setredirect( webpath + "LoggedOff.html")
   RETURN ""
End if
// Return Simple Error .. to relogin
Return '<strong>Something wunderful had happened.</strong><br/><a href="'+WEBPATH+'Login.html" >Login</a>'
end function

on n_ds_session.create
call super::create
TriggerEvent( this, "constructor" )
end on

on n_ds_session.destroy
TriggerEvent( this, "destructor" )
call super::destroy
end on

event constructor;
/* Generic Session Handling - filesystem based approach */
/* Override this event when using another approach */
is_SessionDir = ProfileString(cgienv.of_getINIFileName(), getApplication().AppName , "sessiondir", "unset" )
if is_SessionDir = "unset" then
   SignalError ( 1 , "'sessiondir' in application section '[" + getApplication().AppName + "]' of file '"+ cgienv.of_getINIFileName() + "' not found in "+ cgienv.of_getINIFileName() )
End if

choose case Right ( is_SessionDir , 1 )
   case  "\" , "/"
   case else
      if Pos ( is_SessionDir , "/" ) > 0 then 
         is_SessionDir += "/"
      else
         is_SessionDir += "\"
      end if
end choose     

end event