IdleLogout.rbbas 21.9 KB
Newer Older
1
#tag Class
Protected Class IdleLogout
Inherits Application
	#tag Event
		Sub Open()
		  Dim debugFileName as string
		  Dim theDate as date
		  dim mXMLtreeToFollow(-1) as string
		  dim mPrefKeyFoundData(-1) as string
		  dim mTempFoundPlistData as string = "" // Local variable to use for gathering plist settings
		  theDate = new Date
		  
		  Globals.gAppFolderItem = GetFolderItem("/Users/Shared/", FolderItem.PathTypeShell)
		  if Globals.gAppFolderItem.Exists = false then
		    Globals.gAppFolderItem = GetFolderItem("/tmp/", FolderItem.PathTypeShell)
		    MsgBox "Can't find /Users/Shared! Using /tmp/ for logs"
		  end
		  
		  
		  // Set the name of the log
		  debugFileName = "psuIdleLogout.RUN" + MiscMethods.PadData("0",2,str(theDate.Year),Globals.kLogToFileDisable) _
		  + "-" + MiscMethods.PadData("0",2,str(theDate.Month),Globals.kLogToFileDisable) + "-"
		  debugFileName = debugFileName + MiscMethods.PadData("0",2,str(theDate.Day),Globals.kLogToFileDisable) + _
		  "-" + MiscMethods.PadData("0",2,str(theDate.Hour),Globals.kLogToFileDisable) + "-"
		  debugFileName = debugFileName + MiscMethods.PadData("0",2,str(theDate.Minute),Globals.kLogToFileDisable) + _
		  "-" + MiscMethods.PadData("0",2,str(theDate.Second),Globals.kLogToFileDisable) + ".log"
		  
		  // Initilize the log, quit if we can't create the log
		  if not (LogToFile.Initialize(debugFileName,Globals.gAppFolderItem)) then
		    beep
		    MsgBox "Error creating run log file! Exiting..."
		    quit
		  end if
		  
		  // Keep only the last 5 logs
		  if ( LogToFile.DeleteOldLogs(5) ) then
		    LogToFile("Deleted Old Logs")
		  end if
		  
		  // Get App Prefs
		  Prefs = new TTsSmartPreferences("edu.psu.idlelogout")
		  // Check for the user to ignore
		  pIgnoreUser = Prefs.Value("IgnoreUser", "macadmin")
		  
		  // Check the group to ignore
		  pIgnoreGroup = Prefs.Value ("IgnoreGroup", "admin")
		  
		  // How long should we wait before considering the Mac is idle too long?
		  pComputerIdleAfterNumSeconds = Prefs.Value("ComputerIdleAfterNumSeconds", 600)
		  
		  // How often should we check to see how long the Mac has been idle?
		  pIdleLoopDelaySeconds = Prefs.Value("IdleLoopDelaySeconds", 30)
		  
		  // How long should we wait for the user to respond for More Time or to Log Out?
		  pWaitForUserPromptSeconds = Prefs.Value("WaitForUserPromptSeconds",90)
		  
		  // What should we display on the popup window text
		  pWindowMessage = Prefs.Value("WindowMessage",pWindowMessage)
		  
		  // Should we skip the RemoteControlCheck when running idle thread? Default is false
		  pRemoteControlBool = Prefs.Value("SkipRemoteControlCheck",pWindowMessage)
		  
		  // Script to run at LogOut
		  pLogOutScriptPath = Prefs.Value("LogOutScriptPath",pLogOutScriptPath)
		  
		  // Create temp string with new line char
		  Dim cr As String
		  cr = EndOfLine.Unix
		  
		  // Replace \n with new line chars
		  pWindowMessage = ReplaceAllB(pWindowMessage, "\n", EndOfLine)
		  
		  // Update Window Message
		  LogoutWarning.WarningMessage.setString(pWindowMessage)
		  
		  // What should the Title Be in the Popup Window
		  pWindowTitle = Prefs.Value("WindowTitle","Idle Logout Alert")
		  
		  // Update Window Title
		  LogoutWarning.WarningTitle.setString(pWindowTitle)
		  
		  // Set Values in the Plist - Probably don't need to touch the disk
		  'Prefs.Value("IgnoreUser") = pIgnoreUser
		  'Prefs.Value ("IgnoreGroup") = pIgnoreGroup
		  'Prefs.Value("ComputerIdleAfterNumSeconds") = pComputerIdleAfterNumSeconds
		  'Prefs.Value("IdleLoopDelaySeconds") = pIdleLoopDelaySeconds
		  'Prefs.Value("WaitForUserPromptSeconds") = pWaitForUserPromptSeconds
		  'Prefs.Value("WindowMessage") = pWindowMessage
		  'Prefs.Value("WindowTitle") =  pWindowTitle
		  'Prefs.Sync
		  
		  LogToFile(CurrentMethodName + ": Received user exception = " + str(pIgnoreUser) )
		  LogToFile(CurrentMethodName + ": Received group exception = " + str(pIgnoreGroup) )
		  LogToFile(CurrentMethodName + ": Received ComputerIdleAfterNumSeconds = " + str(pComputerIdleAfterNumSeconds) )
		  LogToFile(CurrentMethodName + ": Received IdleLoopDelaySecond, = " + str(pIdleLoopDelaySeconds) )
		  LogToFile(CurrentMethodName + ": Received WaitForUserPromptSeconds = " + str(pWaitForUserPromptSeconds) )
		  LogToFile(CurrentMethodName + ": Received SkipRemoteControlCheck = " + str(pRemoteControlBool) )
		  LogToFile(CurrentMethodName + ": Received LogOutScriptPath = " + str(pLogOutScriptPath) )
		  
		  // Is this user macadmin?
		  if ( MiscMethods.CurrentUsername(pIgnoreUser) ) then
		    // It is macadmin, quit the app
		    LogToFile("Current user is " + pIgnoreUser + ", quiting app")
		    quit
		  else
		    LogToFile("User is not " + pIgnoreUser + ", continuing")
		  end if
		  
		  // Is this user an admin?
		  if ( MiscMethods.CurrentGroup(pIgnoreGroup) ) then
		    // It is macadmin, quit the app
		    LogToFile("Current user is an " + pIgnoreGroup + ", quiting app")
		    quit
		  else
		    LogToFile("User is not an " + pIgnoreGroup + ", continuing")
		  end if
		  
		  // Hide window from view at start
		  LogoutWarning.Hide()
		  // Start IdleThread
		  LogToFile(CurrentMethodName + ": Running IdleThread")
		  // start thread to watch for idle
		  StartIdleWatch()
		  
		  // exit app now
		  LogToFile(CurrentMethodName + ": <---")
		End Sub
	#tag EndEvent


	#tag Method, Flags = &h0
		Sub forceLogout()
		  LogToFile(CurrentMethodName + ": --->")
		  
		  // Testing mode, use say instead of logout
		  Dim s As Shell
		  s=New Shell
		  dim ShellResults as string
		  s.Mode = 0
		  
		  // Log 
		  LogToFile(CurrentMethodName + ": START Killing Apps")
		  
		  // Graceful quit of apps
		  LogToFile(CurrentMethodName + ": Quiting all launched from /Applications")
		  s.Execute("ps axxx -o comm | grep ""/Applications"" | grep -v grep | awk -F'.app' '{print $1"".app""}'")
		  Dim runningapps as string
		  runningapps = s.Result
		  
		  // Create New Array for running apps
		  Dim appArray() as String
		  // Place each line in new array
		  appArray=SPLIT(runningapps,EndOfLine)
		  // For each app in the array try to graceful quit
		  For Each appPath as string in appArray
		    if appPath = "" then
		      Continue
		    end
		    LogToFile("Quiting: " + appPath)
		    s.Execute("osascript -e 'quit app ""appPath""'")
		    LogToFile("    Exit Code: " + str(s.ErrorCode))
		  Next
		  
		  // kill the apps that are open from /Apps
		  LogToFile(CurrentMethodName + ": Killing all launched from /Applications")
		  s.Execute("kill -9 `ps axxx | grep ""/Applications"" | awk '{print $1}'`")
		  LogToFile(CurrentMethodName + ": App Kill Results: " + s.Result)
		  
		  s.Execute("/bin/bash " + "" + pLogOutScriptPath + "")
		  // Run Script after Logout
		  if (pLogOutScriptPath <> "") then
		    LogToFile(CurrentMethodName + ": Running Shell Script: " + pLogOutScriptPath)
		    // Get script type from extension
		    'Dim scriptArray() as String
		    'scriptArray=SPLIT(pLogOutScriptPath,".")
		    'Dim scriptType As String
		    'scriptType = scriptArray.Pop
		    'LogToFile(CurrentMethodName + ": Shell Script Type: " + scriptType)
		    // Execute script based on extension
		    's.Execute("/bin/bash " + "" + pLogOutScriptPath + "")
		    
		    // Nevermind, just run the script..
		    s.Execute(pLogOutScriptPath)
		    LogToFile(CurrentMethodName + ": Shell Script Results: " + s.Result)
		  end if
		  
		  // Log out our user with force
		  LogToFile(CurrentMethodName + ": Tell AppleScript to log it out")
		  // New method to logout with osascript.
		  s.Execute("osascript -e 'tell application ""System Events"" to keystroke ""q"" using {command down, shift down, option down}'")
		  LogToFile(CurrentMethodName + ": LogOut AS Results: " + s.Result)
		  
		  // Log and quit
		  LogToFile(CurrentMethodName + ": <---")
		  
		  
		End Sub
	#tag EndMethod

	#tag Method, Flags = &h0
		Function IdleSeconds() As Integer
		  // Set up variables for idle time
		  // Shell result
		  Dim mIdleSecs As String
		  // Shell exit code
		  Dim merrCode As  Integer
		  // Set up shell
		  Dim s As Shell
		  s=New Shell
		  s.Mode = 0
		  
		  // Check idle time
		  //s.Execute code to check idle time from USB input devices
		  s.Execute "/bin/echo $((`/usr/sbin/ioreg -c IOHIDSystem | /usr/bin/sed -e '/HIDIdleTime/ !{ d' -e 't' -e '}' -e 's/.* = //g' -e 'q'` / 1000000000))"
		  // Set results to mIdleResult
		  mIdleSecs = s.Result
		  // Set error code to mIdleError
		  merrCode = s.ErrorCode
		  // Log mIdleResult for debugging
		  // System.Log(System.LogLevelError, "Method: " + midleSecs)
		  // LogToFile("mIdleSeconds: " + str(mIdleSecs))
		  Return val(mIdleSecs)
		End Function
	#tag EndMethod

	#tag Method, Flags = &h0
		Function makeFolder(mkdirPath As string) As Boolean
		  // Set up variables for idle time
		  // Shell result = mkdirPath
		  // Shell exit code
		  Dim merrCode As  Integer
		  // Set up shell
		  Dim s As Shell
		  s=New Shell
		  s.Mode = 0
		  
		  // Check idle time
		  //s.Execute code to check idle time from USB input devices
		  s.Execute "mkdir -p /Users/Shared"
		  // Set results to mIdleResult
		  mkdirPath = s.Result
		  // Set error code to mIdleError
		  merrCode = s.ErrorCode
		  // Log mIdleResult for debugging
		  // System.Log(System.LogLevelError, "Method: " + midleSecs)
		  // LogToFile("mIdleSeconds: " + str(mIdleSecs))
		  if mkdirPath = "0" then
		    return true
		  else
		    return false
		  end
		End Function
	#tag EndMethod

	#tag Method, Flags = &h0
		Function RemoteControlCheck() As Boolean
		  // Set up variables for idle time
		  Dim stablished as String = "ESTABLISHED"
		  
		  // Shell result
		  Dim rccheck As String
		  // Shell exit code
		  Dim merrCode As  Integer
		  // Set up shell
		  Dim s As Shell
		  s=New Shell
		  s.Mode = 0
		  
		  
		  // Check idle time
		  //s.Execute code to check for connection
		  s.Execute "/usr/sbin/netstat -n | /usr/bin/grep '.5900'| /usr/bin/awk '{print $6}'"
		  
		  // Set results to rccheck
		  // Make the entire returned text uppercase in case Apple ever changes the case to CaMeL CaSe, which would break our code:
		  rccheck = Uppercase(s.Result)
		  
		  //LogToFile("rccheck: " + rccheck)
		  // Set error code to merrCode
		  merrCode = s.ErrorCode
		  
		  // LogToFile("rccheck: "+ rccheck)
		  // LogToFile("stablished: "+ stablished)
		  
		  If ( InStr( rccheck, stablished ) > 0 ) then
		    return true
		  else
		    //LogToFile("rccheck: false")
		    return false
		  End if
		  
		  // System.Log(System.LogLevelError, "Method: " + midleSecs)
		  // LogToFile("mIdleSeconds: " + str(mIdleSecs))
		  
		  
		  
		End Function
	#tag EndMethod

	#tag Method, Flags = &h0
		Sub StartIdleWatch()
		  // if the new WatchForIdleThread is not created, do it now
		  if ( pWatchForIdleThread = nil ) then
		    // instatiate new thread with enumerated type
		    pWatchForIdleThread = _
		    new WatchForIdleThread(Int32(eTaskType.StartIdleWatch ))
		    // add custom methods for run and finished handlers
		    AddHandler pWatchForIdleThread.Run, WeakAddressOf Thread_WaitForIdleTime
		    AddHandler pWatchForIdleThread.Finished, WeakAddressOf Thread_Finished
		  end if
		  // Run the thread if it's not already running:
		  if ( pWatchForIdleThread.State <> Thread.Running ) then
		    // Hide window during idle watch
		    LogoutWarning.Hide()
		    // Set label to default countdown time
		    LogoutWarning.TimeLabel.setString(str(pWaitForUserPromptSeconds))
		    // run the new thread
		    pWatchForIdleThread.Run
		  end if
		End Sub
	#tag EndMethod

	#tag Method, Flags = &h0
		Sub StartUserCountDown()
		  // if the new WatchForIdleThread is not created, do it now
		  if ( pIdleCountDownThread = nil ) then
		    // instatiate new thread with enumerated type
		    pIdleCountDownThread = _
		    new WatchForIdleThread(Int32(eTaskType.StartUserCountDown ))
		    // add custom methods for run and finished handlers
		    AddHandler pIdleCountDownThread.Run, WeakAddressOf Thread_WaitForUserInput
		    AddHandler pIdleCountDownThread.Finished, WeakAddressOf Thread_Finished
		  end if
		  // Run the thread if it's not already running
		  if ( pIdleCountDownThread.State <> Thread.Running ) then
		    // run the new thread
		    pIdleCountDownThread.Run
		  end if
		End Sub
	#tag EndMethod

	#tag Method, Flags = &h21
		Private Sub Thread_Finished(paramThread as WatchForIdleThread)
		  LogToFile(CurrentMethodName + ": --->")
		  
		  // Kill the thread that was used to get here
		  paramThread.Kill
		  // Found out which thread just finished
		  select case Int32 ( paramThread.pTaskType )
		    // If the StartIdleWatch thread just finished
		  case int32( eTaskType.StartIdleWatch )
		    
		    // LogToFile(CurrentMethodName + ": Idle time has expired.")
		    // Show Login Window
		    LogoutWarning.Show()
		    // start logout countdown window
		    StartUserCountDown()
		    
		  case int32 ( eTaskType.StartUserCountDown )
		    
		    // LogToFile(CurrentMethodName + ": No user response from countdown.")
		    // LogToFile(CurrentMethodName + ": LogoutWarning.pMoreTimeAskedFor = " +str(pMoreTimeAskedFor))
		    
		    // If the user (or anyone) asked for more time
		    if (pMoreTimeAskedFor) then
		      // if the user asks for more time, start the idle watch thread again
		      // Restart Idle Watch 
		      StartIdleWatch()
		    else
		      // if the user ran out of time, start the logout
		      // kill user logins
		      forceLogout()
		    end if
		  else
		    
		  end select
		  
		End Sub
	#tag EndMethod

	#tag Method, Flags = &h21
		Private Sub Thread_WaitForIdleTime(paramThread as WatchForIdleThread)
		  // Set up new integer to store idle seconds
		  Dim mIdleResult As Integer
		  // get current idle seconds
		  mIdleResult = IdleSeconds()
		  
		  // LogToFile(CurrentMethodName + " Idle Seconds: " + str(mIdleResult))
		  // LogToFile(CurrentMethodName + " waiting for " + str(LogoutWarning.pComputerIdleAfterNumSeconds))
		  
		  // While our idle result is less than max time
		  while ( mIdleResult < pComputerIdleAfterNumSeconds )
		    // Wait pIdleLoopDelaySeconds each loop
		    App.SleepCurrentThread( pIdleLoopDelaySeconds * 1000 )
		    // Check idle time:
		    mIdleResult = IdleSeconds()
		    // Log our time idle
		    LogToFile(CurrentMethodName + ": Idle Seconds: " + str(mIdleResult))
		  wend
		  
		  // while there is a ARD/VNC session, don't idle out  (netstat -n | grep '.5900')
		  If (pRemoteControlBool) then
		    // while there is a ARD/VNC session, don't idle out  (netstat -n | grep '.5900')
		    while (RemoteControlCheck() )
		      // Wait pIdleLoopDelaySeconds each loop
		      App.SleepCurrentThread( pIdleLoopDelaySeconds * 1000 )
		      // Log
		      LogToFile(CurrentMethodName + ": Someone is controlling via ARD/VNC, waiting...")
		    wend
		  end if
		  // When there is not remote control
		  LogToFile(CurrentMethodName + ": No one is controlling via ARD/VNC, continuing...")
		  
		  
		End Sub
	#tag EndMethod

	#tag Method, Flags = &h21
		Private Sub Thread_WaitForUserInput(paramThread as WatchForIdleThread)
		  LogToFile(CurrentMethodName + ": --->")
		  
		  // Set how long to wait before logging out user, set from global variable for LogOutDelay
		  Dim pLogoutDelay as Integer = pWaitForUserPromptSeconds
		  
		  // While we're waiting for the countdown to finish...
		  While pLogoutDelay >= 0
		    // LogToFile(CurrentMethodName + "Time Left: " + str(pLogoutDelay))
		    // Set global variable to the time left
		    pCountDownTime = pLogoutDelay
		    // call updateUI to set countdown label
		    pIdleCountDownThread.UpdateUI()
		    // take a second away from the time left
		    pLogoutDelay = pLogoutDelay - 1
		    // do nothing for 1 second
		    App.SleepCurrentThread( 1000 ) // sleep 1 second
		  Wend
		  
		  // If we're here, the user didn't cancel or log out manaully
		  // user did not ask for more time
		  pMoreTimeAskedFor = false
		  // Log
		  LogToFile(CurrentMethodName + ": Time Out for Response. Log User Out...")
		  // Done here
		  LogToFile(CurrentMethodName + ": <---")
		  // Return to Thread_Finished
		End Sub
	#tag EndMethod


	#tag Note, Name = Icon
		Application Icon use with CC license:
		From http://www.flickr.com/photos/23453447@N02/5107438855/sizes/o/in/photostream/
		By zyrquel
		http://www.flickr.com/photos/23453447@N02/
	#tag EndNote

	#tag Note, Name = Tests
		
		New builds should be tested for:
		
		Launching
		Hiding Dock Icon
		Logging to File
		Reading Preferences
		Reading Idle Time
		Countdown Timer starts when idle time reached
		Countdown Window Shows
		More Time button resets the clock
		Log Out Button quits open apps and logs out
		Timer Runs out and Auto-Logs Out
		Remove Control Blocks logout
		Custom Name
		Custom Text
		
		
		defaults write /Library/Preferences/edu.psu.idlelogout.plist IgnoreUser -string clcclmadmin
		defaults write /Library/Preferences/edu.psu.idlelogout.plist IgnoreGroup -string user
		defaults write /Library/Preferences/edu.psu.idlelogout.plist ComputerIdleAfterNumSeconds -string 10
		defaults write /Library/Preferences/edu.psu.idlelogout.plist IdleLoopDelaySeconds -string 5
		defaults write /Library/Preferences/edu.psu.idlelogout.plist WaitForUserPromptSeconds -string 120
		defaults write /Library/Preferences/edu.psu.idlelogout.plist WindowTitle -string "Our Idle Logout"
		defaults write /Library/Preferences/edu.psu.idlelogout.plist WindowMessage "You're going to be logged out\n\n\nDude\!"
	#tag EndNote


	#tag Property, Flags = &h0
		pAppVersion As String = "2.1"
	#tag EndProperty

	#tag Property, Flags = &h0
		pComputerIdleAfterNumSeconds As Integer = 900
	#tag EndProperty

	#tag Property, Flags = &h0
		pCountDownTime As Integer
	#tag EndProperty

	#tag Property, Flags = &h0
		pDefaultPrefsFileName As String = "edu.psu.its.clc.IdleLogoutSettings.plist"
	#tag EndProperty

	#tag Property, Flags = &h0
		pDefaultPrefsFSPath As String = "/Library/CLMadmin/Config/"
	#tag EndProperty

	#tag Property, Flags = &h0
		pIdleCountDownThread As WatchForIdleThread
	#tag EndProperty

	#tag Property, Flags = &h0
		pIdleLoopDelaySeconds As Integer = 60
	#tag EndProperty

	#tag Property, Flags = &h0
		pIgnoreGroup As String = "admin"
	#tag EndProperty

	#tag Property, Flags = &h0
		pIgnoreUser As String = "clmadmin"
	#tag EndProperty

	#tag Property, Flags = &h0
		pLogOutScriptPath As String
	#tag EndProperty

	#tag Property, Flags = &h0
		pMoreTimeAskedFor As Boolean = true
	#tag EndProperty

	#tag Property, Flags = &h0
		Prefs As TTsSmartPreferences
	#tag EndProperty

	#tag Property, Flags = &h0
		pRemoteControlBool As Boolean
	#tag EndProperty

	#tag Property, Flags = &h0
		pWaitForUserPromptSeconds As Integer = 90
	#tag EndProperty

	#tag Property, Flags = &h0
		pWatchForIdleThread As WatchForIdleThread
	#tag EndProperty

	#tag Property, Flags = &h0
		pWindowMessage As String = "This Mac is now Idle.\n\nClick the ""More Time"" button to continue using the Mac.\n\nOtherwise, an automatic logout will occur and all unsaved documents will be LOST!"
	#tag EndProperty

	#tag Property, Flags = &h0
		pWindowTitle As String
	#tag EndProperty


	#tag Constant, Name = kEditClear, Type = String, Dynamic = False, Default = \"&Delete", Scope = Public
		#Tag Instance, Platform = Windows, Language = Default, Definition  = \"&Delete"
		#Tag Instance, Platform = Linux, Language = Default, Definition  = \"&Delete"
	#tag EndConstant

	#tag Constant, Name = kFileQuit, Type = String, Dynamic = False, Default = \"&Quit", Scope = Public
		#Tag Instance, Platform = Windows, Language = Default, Definition  = \"E&xit"
	#tag EndConstant

	#tag Constant, Name = kFileQuitShortcut, Type = String, Dynamic = False, Default = \"", Scope = Public
		#Tag Instance, Platform = Mac OS, Language = Default, Definition  = \"Cmd+Q"
		#Tag Instance, Platform = Linux, Language = Default, Definition  = \"Ctrl+Q"
	#tag EndConstant


	#tag Enum, Name = eTaskType, Type = Int32, Flags = &h0
		StartIdleWatch
		StartUserCountDown
	#tag EndEnum


	#tag ViewBehavior
		#tag ViewProperty
			Name="pAppVersion"
			Group="Behavior"
			InitialValue="1.1"
			Type="String"
			EditorType="MultiLineEditor"
		#tag EndViewProperty
		#tag ViewProperty
			Name="pComputerIdleAfterNumSeconds"
			Group="Behavior"
			InitialValue="900"
			Type="Integer"
		#tag EndViewProperty
		#tag ViewProperty
			Name="pCountDownTime"
			Group="Behavior"
			Type="Integer"
		#tag EndViewProperty
		#tag ViewProperty
			Name="pDefaultPrefsFileName"
			Group="Behavior"
			InitialValue="edu.psu.its.clc.IdleLogoutSettings.plist"
			Type="String"
			EditorType="MultiLineEditor"
		#tag EndViewProperty
		#tag ViewProperty
			Name="pDefaultPrefsFSPath"
			Group="Behavior"
			InitialValue="/Library/CLMadmin/Config/"
			Type="String"
			EditorType="MultiLineEditor"
		#tag EndViewProperty
		#tag ViewProperty
			Name="pIdleLoopDelaySeconds"
			Group="Behavior"
			InitialValue="60"
			Type="Integer"
		#tag EndViewProperty
		#tag ViewProperty
			Name="pIgnoreGroup"
			Group="Behavior"
			InitialValue="admin"
			Type="String"
			EditorType="MultiLineEditor"
		#tag EndViewProperty
		#tag ViewProperty
			Name="pIgnoreUser"
			Group="Behavior"
			InitialValue="macadmin"
			Type="String"
			EditorType="MultiLineEditor"
		#tag EndViewProperty
		#tag ViewProperty
			Name="pLogOutScriptPath"
			Group="Behavior"
			Type="String"
			EditorType="MultiLineEditor"
		#tag EndViewProperty
		#tag ViewProperty
			Name="pMoreTimeAskedFor"
			Group="Behavior"
			InitialValue="true"
			Type="Boolean"
		#tag EndViewProperty
		#tag ViewProperty
			Name="pRemoteControlBool"
			Group="Behavior"
			Type="Boolean"
		#tag EndViewProperty
		#tag ViewProperty
			Name="pWaitForUserPromptSeconds"
			Group="Behavior"
			InitialValue="90"
			Type="Integer"
		#tag EndViewProperty
		#tag ViewProperty
			Name="pWindowMessage"
			Group="Behavior"
			InitialValue="'This Mac is idle.       Click the """"More Time"""" button to continue using the Mac.      Otherwise, an automatic logout will occur and all unsaved documents will be LOST!"
			Type="String"
			EditorType="MultiLineEditor"
		#tag EndViewProperty
		#tag ViewProperty
			Name="pWindowTitle"
			Group="Behavior"
			Type="String"
			EditorType="MultiLineEditor"
		#tag EndViewProperty
	#tag EndViewBehavior
End Class
#tag EndClass