http://mysecretbase.com/How_To_Build_A_Who_Is_On_Application_With_ColdFusion.cfm
001   <cfapplication 
002       name="whoison1543"
003      
sessionmanagement="no"
004       clientmanagement="Yes"
005       applicationtimeout="#CreateTimeSpan(0,2,0,0)#">
006   <!---
007   Initialize a couple of variables
008  
--->
009   <cfparam name="variables.itemReMade" default="N" type="string">
010   <cfparam name="variables.ArrayElements" default="0" type="numeric">
011   <cfparam name="variables.SessionLasts" default="20" type="numeric">
012


013   <!---
014   Determine whether the who's on array is defined, and define it if it is not
015   --->
016   <cflock scope="APPLICATION" type="EXCLUSIVE" timeout="10">
017       <cfif not isdefined ("application.WhoIsOnArray")>
018           <cfset application.WhoIsOnArray=ArrayNew(2)> 
019       </cfif>
020   </cflock>
021   <!---
022   Build the complete url of the current page
023   --->
024   <cfif Len(Trim(cgi.query_string)) gt 0>
025       <cfset variables.QueryDelim="&">
026   <cfelse>
027       <cfset variables.QueryDelim="">
028   </cfif>
029   <cfif not CompareNoCase(cgi.https,"ON")>
030       <cfset variables.HTTPData="https://">
031   <cfelse>
032      
<cfset variables.HTTPData="http://">
033  
</cfif>
034   <cfif not Compare(cgi.server_port,"80")>
035       <cfset variables.ServerPort="">
036  
<cfelse>
037      
<cfset variables.ServerPort=":"&cgi.server_port>
038   </cfif>
039  
<cfset variables.CurrPage=variables.HTTPData & cgi.server_name & variables.ServerPort & cgi.script_name & variables.QueryDelim & cgi.query_string>
040   <!---
041   Set the visitor's ID from the key pair
042   --->
043  
<cfset variables.ThisVisitor=client.CFID&":"&client.CFTOKEN>
044   <!---
045  
loop over the list of logged-in visitors. Use a conditional loop
046  
since the array element count can change during the loop itself
047  
--->
048   <!---
049   Lock everything with an exclusive to maintain integrity.
050   --->
051  
<cflock scope="APPLICATION" type="EXCLUSIVE" timeout="10">
052       <!---
053      
does the array have any elements?
054       --->
055      
<cfif not ArrayIsEmpty(application.WhoIsOnArray)>
056           <!---
057           Deal with the users whose sessions have expired
058           --->
059           <cfset variables.ArrayElements=ArrayLen(application.WhoIsOnArray)>
060           <!---
061           default the current loop iteration
062           --->
063           <cfset variables.CurrRow=0>
064           <cfloop
065               condition="#variables.ArrayElements# GT #variables.CurrRow#">
066               <!---
067               increment the row count
068               --->
069               <cfset variables.CurrRow=variables.CurrRow+1>

070               <!---
071               Has the visit expired?
072               --->
073              
<cfif not ArrayIsEmpty(application.WhoIsOnArray[variables.CurrRow])>
074                  
<cfset variables.ExpireChk=DateCompare(DateAdd('n',(variables.SessionLasts*-1),now()),application.WhoIsOnArray[variables.CurrRow][3])>
075               <cfelse>
076                  
<cfset variables.ExpireChk=1>
077               </cfif>
078              
<cfif Compare(variables.ExpireChk,"-1")>
079                   <!---
080                   It has expired.  Delete the visit element and bail out of the loop
081                  
--->
082                  
<cfset arrayDeleteAt(application.WhoIsOnArray,variables.CurrRow)>
083                  
<cfset variables.ArrayElements=variables.ArrayElements-1>
084 <cfelse>
085               <!---
086               
Does this element belong to the current visitor?
087               
--->
088                <cfif not Compare(application.WhoIsOnArray[variables.CurrRow][1],variables.ThisVisitor)>
089                    <!---
090                  
Yes.  Update the existing element and set the update flag
091                   
--->
092                    <cfset application.WhoIsOnArray[variables.CurrRow][2]=variables.CurrPage>
093                    <cfset application.WhoIsOnArray[variables.CurrRow][3]=now()>
094                   
<cfset application.WhoIsOnArray[variables.CurrRow][4]=cgi.http_user_agent>
095                   
<cfset variables.ItemReMade="Y">
096                </cfif>

097               </cfif>
098          
</cfloop>

099      </cfif>
100       <!---
101       The loops over the existing visit elements are done. 
102       Did we find an existing visit record and update it?
103      
--->
104      
<cfif not CompareNoCase(variables.ItemReMade,"N")>
105           <!---
106           No.  Must be a new visit.
107           --->
108           <cfset variables.Start=variables.ArrayElements+1>
109           <cfset application.WhoIsOnArray[variables.Start]=arrayNew(1)>
110           <cfset ArrayAppend(application.WhoIsOnArray[variables.Start],variables.ThisVisitor)>
111           <cfset ArrayAppend(application.WhoIsOnArray[variables.Start],variables.CurrPage)>
112          
<cfset ArrayAppend(application.WhoIsOnArray[variables.Start],Now())>
113          
<cfset ArrayAppend(application.WhoIsOnArray[variables.Start],cgi.http_user_agent)>
114      
</cfif>
115   </cflock>
116  
<cfdump var="#application#" label="Application variables">