Listing 1: index.cfm
<head>
<title>Instant Messaging</title>
<frameset rows="*,170">
<frame name="frameMain" src="welcome.cfm">
<frame name="frameBottom" src="Login.cfm">
</frameset>
</head>
Listing 2: welcome.cfm
<!--- /// welcome.cfm /// --->
<cfset tmpNickname = "">
<cfif IsDefined("SESSION.nickname")>
<cflock name="#SESSION.sessionID#"
type="ReadOnly" timeout="20" throwontimeout="Yes">
<cfset tmpNickname = SESSION.nickname>
</cflock>
</cfif>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Welcome</title>
</head>
<body><basefont face="Arial">
<cfoutput>
Welcome <b>#tmpNickname#</b>,<p>
Just browse our site here...
<p>
<a href="something_a.cfm">Some category</a>
<p>
<a href="something_b.cfm">Some other
category</a>
</cfoutput>
</body>
</html>
Listing 3: Login.cfm
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML
4.0 Transitional//EN">
<html>
<head>
<title>Login</title>
</head>
<body><basefont face="Arial">
<form name="formLogin" action="makeLogin.cfm"
method="post">
Nickname: <input type="Text" name="nickname">
<input type="Submit" value="Go">
</form>
</body>
</html>
Listing 4: makeLogin.cfm
<cflock name="#APPLICATION.applicationName#"
type="Exclusive" timeout="20" throwontimeout="Yes">
<!--- Set up Nickname-Structure
for mapping IPs to Nicknames --->
<cfparam name="APPLICATION.NickNames"
default=#StructNew()#>
<!--- Insert submitted Nickname
into Nickname-Structure --->
<cfset dummy = StructInsert(APPLICATION.NickNames,
CGI.REMOTE_ADDR, FORM.nickname, true)>
</cflock>
<cflock name="#SESSION.sessionID#" type="Exclusive"
timeout="20" throwontimeout="Yes">
<!--- Insert submitted Nickname
into Session-Scope (just for remembering the user's nickname) --->
<cfset SESSION.nickname = FORM.nickname>
</cflock>
<cflocation url="listUsers.cfm">
Listing 5: listUsers.cfm
<cflock name="#SESSION.sessionID#" type="ReadOnly"
timeout="20" throwontimeout="Yes">
<cfset tmpNickname = SESSION.nickname>
</cflock>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML
4.0 Transitional//EN">
<html>
<head>
<title>Currently Active Users</title>
<style type="text/css">
body {
font-family: Arial, Helvetica,
Verdana;
}
td {
font-size: 8pt;
}
input {
font-size: 9pt;
}
</style>
</head>
<body onLoad="window.setTimeout('location.reload()', 30000);">
<cfoutput>
Currently #StructCount(APPLICATION.SessionTracker)# active Users online
<cflock name="#APPLICATION.applicationName#" type="Exclusive" timeout="20" throwontimeout="Yes">
<form name="formUsers" action="sendMessage.cfm"
method="post">
<input type="Hidden" name="from"
value="#tmpNickname#">
<input type="Hidden" name="sender"
value="#CGI.REMOTE_ADDR#">
<table border="1" cellspacing="0"
cellpadding="1" width="40%">
<tr bgcolor="##eeeeee">
<td width="20"> </td>
<td width="*"><b>User</b></td>
<td width="*"><b>Online-Status</b></td>
</tr>
<!--- Loop through Session-Tracker
and list current online users --->
<CFLOOP collection=#APPLICATION.SessionTracker#
item="aUser">
<cfset onlineSince = StructFind(APPLICATION.SessionTracker,
aUser)>
<!--- Check for time-outs
--->
<CFIF DateCompare(onlineSince+theTimeout,
Now()) EQ 1>
<!--- User's last activity
lies within session-timeout, so his session is active --->
<cfset inactiveSince
= DateDiff("n", onlineSince, Now())>
<!--- The threshold
for coloring the report may be set individually --->
<cfif inactiveSince
LTE 2>
<cfset theColor
= "Red">
<cfelseif inactiveSince
LTE 5>
<cfset theColor
= "Yellow">
<cfelse>
<cfset theColor
= "Cyan">
</cfif>
<!--- Output of current
user in list --->
<tr>
<td><input
type="Checkbox" name="Users" value="#aUser#"></td>
<td><cfif
StructKeyExists(APPLICATION.NickNames,aUser)>#StructFind(AP-PLICATION.NickNames,
aUser)#<cfelse>#aUser#</cfif></td>
<td bgcolor="#theColor#">inactive
since <b>#inactiveSince#</b> mins</td>
</tr>
<CFELSE>
<!--- User's session
has timed-out, so we can delete his IP from the Session-Tracker and Nickname-Structure,
as well as the Message-Queue --->
<cfscript>
StructDelete(APPLICATION.SessionTracker,
aUser);
StructDelete(APPLICATION.NickNames,
aUser);
StructDelete(APPLICATION.MessageQueue,
aUser);
</cfscript>
</CFIF>
</CFLOOP>
</table>
<input type="Text" name="message"
size="70" maxlength="200">
<input type="Submit" value="Send
Instant Message">
</form>
</cflock>
<p>
<a href="welcome.cfm">Go back</a>
</cfoutput>
</body>
</html>
Listing 6: Application.cfm
<!--- Set this Variable in local scope:
can be accessed from the report-page directly --->
<cfset theTimeout = CreateTimespan(0,0,15,0)>
<!--- Set Application name and options
--->
<CFAPPLICATION NAME="My_Test_App"
CLIENTMANAGEMENT="YES"
SESSIONMANAGEMENT="YES"
SESSIONTIMEOUT=#theTimeout#>
Listing 7: OnRequestEnd.cfm
<!--- Session-Tracker Code --->
<cflock name="#APPLICATION.applicationName#" type="Exclusive" timeout="20" throwontimeout="Yes">
<!--- If Session-Tracker does not
exist, generate it... --->
<cfparam name="APPLICATION.SessionTracker"
default=#StructNew()#>
<!--- Instead of using the clients
IP-address we can also log the client's user-name
or similar session-scoped
login info here --->
<!--- It's important to specify
TRUE here to allow the overwriting of existing entries (= updating) --->
<CFSET dummy = StructInsert(APPLICATION.SessionTracker,
CGI.REMOTE_ADDR, Now(), true)>
<!--- ***** Message-Queue Code *****
--->
<cfif CompareNoCase(GetFileFromPath(CGI.SCRIPT_NAME),"sendMessage.
cfm") NEQ 0>
<!--- If Message-Queue does not
exist, generate it... --->
<cfparam name="APPLICATION.MessageQueue"
default=#StructNew()#>
<!--- Check Message-Queue for messages
for current user --->
<cfif StructKeyExists(APPLICATION.MessageQueue,
CGI.REMOTE_ADDR)>
<cfoutput>
<!--- Fetch current
user's queue --->
<cfset tmpQueue = StructFind(APPLICATION.MessageQueue,
CGI.REMOTE_ADDR)>
<!--- Loop through
messages in that queue and display each message --->
<cfloop index="i" from=1
to=#ArrayLen(tmpQueue)#>
<cfset tmpPackage
= tmpQueue[i]>
<SCRIPT LANGUAGE="JavaScript"
TYPE="text/javascript">
<!--
// Present
message
doReply = confirm("Message from #tmpPackage["from"]#:\n\n#tmpPackage["text"]#\n\nReply?");
if (doReply)
{
// Prompt
for reply
message
= prompt("Your reply to #tmpPackage["from"]#:","");
if ((message
!= "") && (message != null)) {
// Send reply message
parent.frames.frameBottom.location.href="sendMessage.cfm?message="+escape(message)+"&users=#URLEncodedFormat(tmpPackage["sender"])#";
}
}
//-->
</SCRIPT>
</cfloop>
<!--- Delete message
from the queue --->
<cfset dummy = ArrayClear(APPLICATION.MessageQueue[CGI.REMOTE_ADDR])>
</cfoutput>
</cfif>
</cfif>
</cflock>
Listing 8: sendMessage.cfm
<cfset tmpNickname = "">
<cfif IsDefined("SESSION.nickname")>
<cflock name="#SESSION.sessionID#"
type="ReadOnly" timeout="20" throwontimeout="Yes">
<!--- Remember user's nickname
--->
<cfset tmpNickname = SESSION.nickname>
</cflock>
</cfif>
<!--- Use either URL or FORM parameter to get the message to send --->
<cfparam name="URL.from" default=#tmpNickname#>
<cfparam name="URL.sender" default=#CGI.REMOTE_ADDR#>
<cfparam name="URL.message" default="">
<cfparam name="URL.users" default="">
<cfparam name="FORM.from" default=#URL.from#>
<cfparam name="FORM.sender" default=#URL.sender#>
<cfparam name="FORM.message" default=#URL.message#>
<cfparam name="FORM.users" default=#URL.users#>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Instant Messaging</title>
<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript">
<!--
// for going back to the user-listing
template
function gotoListUsers()
{
location.href="listUsers.cfm";
}
//-->
</SCRIPT>
</head>
<body onLoad="window.setTimeout('gotoListUsers()',
15000);">
<cfif IsDefined("FORM.users")>
<cflock name="#APPLICATION.applicationName#"
type="Exclusive" timeout="20" throwontimeout="Yes">
<cfoutput>
Sent the message "<b>#FORM.message#</b>"
to<p>
<!--- Loop through all receivers
of the message --->
<cfloop index="aUser" list=#FORM.users#>
<!--- Append
message at the receiver's queue --->
<cfscript>
// Generate Message-Queue
for receiver if it does not already exist
if (NOT StructKeyExists(APPLICATION.MessageQueue,
aUser)) {
StructInsert(APPLICATION.MessageQueue,
aUser, ArrayNew(1), true);
}
// Setting up the
message package to send
tmpInsert = StructNew();
tmpInsert["from"]
= FORM.from;
tmpInsert["sender"]
= FORM.sender;
tmpInsert["text"]
= FORM.message;
// Send the package
(= append it at receiver's Message-Queue)
ArrayAppend(APPLICATION.MessageQueue[aUser],
tmpInsert);
</cfscript>
<!--- Print current
receiver as sent --->
<cfif StructKeyExists(APPLICATION.NickNames,aUser)>
#StructFind(APPLICATION.NickNames,
aUser)#
<cfelse>
#aUser#
</cfif><br>
</cfloop>
</cfoutput>
</cflock>
<cfelse>
No users specified
</cfif>
<p>
<a href="listUsers.cfm">Go back</a>
</body>
</html>