Lock Your Application From Prying Eyes

by Robert Picard

A client wanted to protect sensitive information from prying eyes when the computer was left unattended. It’s all very well to have access to certain areas of the application password protected. What happens when someone who has access privileges to sensitive information leaves his computer unattended? People would not only see this information but could conceivably have access to all restricted areas this access allowed.

So how do I monitor activity in the application and activate a locking mechanism either manually or automatically?

The answer: use a form's “OnTimer”, and “OnKey” events. First you will need to declare some variables to hold values. These can be declared in your “Autoexec” Script or using the method described in Dr. Wayne’s “A Better Way to Initialize Global Variables”.

DIM global last_form as c
DIM global Scrn_chck_time as c
DIM global Scrn_chck_time as c
DIM global Scrn_chck_time2 as c
DIM global Scrn_chck_diff as n
DIM global Scrn_chck_val as n
DIM global Scrn_chck_len as n

Now all forms need to be setup the following way. First the “OnActivate” and “OnInit” form events need to contain the following:

OPTION NOBREAK
F=parentform.this
'This sets the start time to compare against the elapsed time.
Scrn_chck_time=time()
'This variable will be used to store any keystroke activity on the form.
Scrn_chck=""
'This variable will measure the number of characters in the 
'Scrn_chck variable
Scrn_chck_len=0
'This variable contains the total number of characters from the last 
'keyboard activity and compare against any additional keyboard 
'activity recorded.
Scrn_chck_val=0
END

Next we need to monitor keyboard activity. The form's “OnKey” event needs to do the following:

option nobreak
if between(a_user.key.value,"0","z") then 
	'if any alphanumeric keys are pressed
	a_user.key.handled=.T.
	if a_user.key.event="down"
		Scrn_chck=Scrn_chck + a_user.key.value 'store the keystrokes
		Scrn_chck_len=len(scrn_chck) 'measure the number of keystrokes.
	end if
end if
end

Now that we are recording our keyboard activity we need to check for any activity. First the form's Timer property needs to be set to 1 second.

Set the form's Timer property

Fig. 1. Set the form's Timer interval to 1 second.

The forms “OnTimer” event needs to do the following:

option nobreak
' gets the elapsed time to compare against the time recorded when the form was opened (ie. Scrn_chck_time)
scrn_chck_time2=time() 
' converts time to seconds for subtraction
T_start=toseconds(Scrn_chck_time) 
T_end=toseconds(scrn_chck_time2)
' subtracts the two times and gets the amount of time elapsed
scrn_chck_diff=t_end - t_start
' Checks to see if 10 minutes has elapsed (10 X 60 seconds=600 seconds) 
'and if there was any keyboard activity. If the time is greater than 10
'minutes but there is keyboard activity then do nothing.
if scrn_chck_diff > 600 .and. Scrn_chck_val=Scrn_chck_len then
	script_play("close_all_forms")
end if
'Next check to see if previous keyboard activity (Scrn_chck_val) matches
'new keyboard activity (Scrn_chck_len). If there is activity it resets
' “Scrn_chck_val” to the same value as “Scrn_chck_len”. This
' way if there is no new key board activity then they will both have the same
'value and trigger the first “IF” statement that checks for time and
'keyboard inactivity (ie. Scrn_chck_val=Scrn_chck_len)
if Scrn_chck_val <> Scrn_chck_len then
	Scrn_chck_val=Scrn_chck_val + Scrn_chck_len
end if
'When the first “IF” statement evaluates to true the script “close_all_forms” executes. 
if scrn_chck_diff > 600 .and. Scrn_chck_val=Scrn_chck_len then
	script_play("close_all_forms")
end if

The script, close_all_forms, closes all open forms and loads the locking form. This script is not my creation but someone else’s. I only added two lines:

last_form=a_form_current

and

form.view("frm_blank_Scrn")

When I saved the original script for future use I neglected to record the author's name. My apologies to him / her!

Script “close_all_forms

dim formnme as c
dim count as n
dim formshort as c
dim result as c
dim type as c
dim p as p
dim frm as p
dim i as n
dim j as n
dim k as n
dim charcount as c
' This stores the name of the last form open to load later
last_form=a_form_current
charcount=""
for j=1 to 5 
formnme=""
formnme=:A5.form_enum("")
if formnme <> "" then 
while formnme <> ""
 count=at("@",formnme,1)-1
 formshort=":" + left(alltrim(formnme),count) + alltrim(charcount)
 p=obj(formshort)
 if is_object(p) then
 type=p.class()
 if type <> "form" then
 goto skip
 end if
 p.close()
 end if
 skip:
 formnme=:A5.form_enum(formnme)
end while
end if
charcount=alltrim(str(j-1))
next j
charcount=""
for k=1 to 5 
formnme=""
formnme=:A5.browse_enum("")
if formnme <> "" then
while formnme <> ""
 count=at("@",formnme,1)-1
 formshort=":" + left(alltrim(formnme),count) + alltrim(charcount)
 p=obj(formshort)
 if is_object(p) THEN
 type=p.class()
 if type <> "browse"
 goto skip2
 end if
 p.close()
 end if
 skip2:
 formnme=:A5.browse_enum(formnme) 
end while
end if
charcount=alltrim(str(k-1))
next k
' This opens the form which blanks the screen and locks the system.
form.view("frm_blank_Scrn")
end

The system can be manually locked, by placing a button on all your forms with the following code;

'Lock Button button
option nobreak
script_play("close_all_forms")
end

When form “frm_blank_screen” loads the user sees the following:

locking screen

What locks the system is the form properties set for “frm_blank_screen”.

In the “Form” tab all the “Restrictions” should be checked and “Hide status bar” should be checked.

Properties of locking form

The “Window” tab should have “Position”=0 and Size=100. All boxes in “Window Style” should be unchecked.

Window style for locking form

The “Menus / Toolbars” should have View=<None>, View right click=<None>, and Toolbars View=<None>.

no toolbars or menus, either

The Form's “CanExit” event should contain the following command to stop anyone from exiting the form;

Cancel() 

The form's OnAcivate” and “OnInit” events should contain the following;

option nobreak 
F=parentform.this 
:A5.Window_Title="Security Lock" 
'With window sizing disabled in form properties the A5 window can be 
' minimized and sized but not the form window. The form window will 
' always be maximized in the A5 window.
F.maximize() 
end 

The form event “OnKey” should contain the following:

' the password scheme that follows was taken from 
'Dr. Wayne’s book “Xbasic for Everyone”option nobreak 
f=parentform.this 
dim privileges as n 
dim shared your_password as c 
dim global Your_name as c 
dim global status as c 
dim advisor_new as c 
dim tbl_name as c 
dim shared a_db_current_path as c
' you need to trap the Escape key the first time it is used to
' avoid aborting the script and loading the “last_form”. Subsequent use
' of the Escape key will behave as it should.
if a_user.key.value="{ESC}" then 
	a_user.key.handled=.T. 
	end 
end if
' you need to trap the F1 key because it’s a system key and
'will call up the Help screen rather than starting the script.
if a_user.key.value="{f1}" then 
	a_user.key.handled=.T. 
	end 
end if 
if a_user.key.value <> "{ESC}" then
	a_user.key.handled=.T. 
	if a_user.key.event="down"
		tbl_name=a_db_current_path+"users.dbf" 
		tries=0 
		start: 
		ui_beep() 
		if tries=3 then 
			goto fail 
		end if
		your_password=ui_get_password("Authorization Required!","\
		Please enter your password to Enter!","","*")
		if your_password="" then 
			ui_beep() 
			ui_msg_box("No Password Entered!","\
			Access denied!",+ui_stop_symbol)
			tries=tries + 1 
			end 
		end if 
		if Your_password > "" then
			your_password=encrypt(your_password)
			privileges=lookupn("F",\
			Your_password,"privileges",tbl_name,"password")
			if privileges <2 then 
				ui_beep() 
				ui_msg_box("Authorization Denied!","\ 
				Your Security clearance does not allow Access!",\
				ui_stop_symbol)
				tries=tries + 1 
				goto start 
			end if 
		end if 
	end if
end if 
f.hide() 
f.close() 
' this loads the last form whose name was stored when
'the script “Close_all_forms” played 
form.view(last_form) 
end 
fail:
tries=3 
a5.close() 
end 

Some final points. If you like to have multiple forms loaded you will need to change that. My method only monitors activity in the current active form. Any forms running in the background will record no activity and lock the system.

Also, no provision has been made for mouse activity. I didn’t feel it was necessary as a snoop would very likely be using the mouse to move around the application and would be locked out after 10 minutes. There is an article on this web page that emulates mouse rollovers and could possibly be adapted to monitor mouse activity if wanted.

As to the time limit before the screen locks it does not have to be hard coded. If you use Dr. Wayne’s method mentioned above to initialize variables you could allow the user to set a different time.

Instead of the following:

if scrn_chck_diff > 600 .and. Scrn_chck_val=Scrn_chck_len then
 script_play("close_all_forms")
end if

You could use a numeric variable in place of a number.

if scrn_chck_diff > var->time_check .and.
Scrn_chck_val=Scrn_chck_len then
 script_play("close_all_forms")
end if
Editor's note: Robert has a clever idea to blank out a screen after a defined period of inactivity. If you study his code carefully you may see some ways to improve it. For example, I cannot see any reason to set the OnTimer interval to 1 second and then check to see if 10 minutes have elapsed. Why not just set the OnTimer interval to 600 seconds? I also do not think it is necessary to record the number of keystrokes posted in the 10-minute interval. Instead, create a global variable, "keystroke_activity", and set it to true at the initiation of the form. The OnKey event will also set "keystroke_activity" to true. Then the OnTimer event script will check to see if "keystroke_activity" is true. If it is true, the script will set the variable to false and then exit. The next time around, if no keystrokes have been recorded, the variable will still be false, and when OnKey detects this fact, it will call the close_all_forms script.
Care to modify Robert's scripts? If you do, send them to me and I'll post them.

9/7/02

Don't forget, we need your feedback to make this site better!

Return to home