Pop-Out

<!---
    Purpose: To provide different means of handling error in a generic way for CFMX 6.1
    Attributes:
        type="custom | database | any | application | lock | template | security | object | expression | normal | missinginclude" -default "normal"
        sendEmail="yes | no" -default no
        message="[some error message to be displayed]" -default "No error message specified." -notes Should only be specified when having a "normal" type error
        additionalDetail="[some error detail to be displayed]" -default "No additionalDetail specified."
        debug="yes|no" -default "no"
        to="[email address to send email to]" -default "errors@my-site-here.com"
        from="[from email address]" -default "#application.applicationname#.errors@my-site-here.com"
        errorfile="#errorfile#" -defualt errorfile.cfm
    Usage Notes:
         if installed under custom tags directory:
         <cf_errorHandler [type="custom|database|any|application|lock|template|security|object|expression|normal|missinginclude"] [sendEmail="yes|no"] [message="#somemessage#"] [details="#somedetails#"] [url="#url"] [debug="yes|no"]>
         if installed in relative directory to your application:
         <cfmodule template="#path#/errorHandler.cfm" [type="custom|database|any|application|lock|template|security|object|expression|normal|missinginclude"] [sendEmail="yes|no"] [message="#somemessage#"] [details="#somedetails#"] [url="#url"] [debug="yes|no"]>
         if this custom tag has thesame name as another tag in custom tags directory:
         <cfmodule name="#dir#.#dir2#.errorHandler"[type="custom|database|any|application|lock|template|security|object|expression|normal|missinginclude"] [sendEmail="yes|no"] [message="#somemessage#"] [details="#somedetails#"] [url="#url"][debug="yes|no"]>
--->
<!--- Set default values on attributes --->
<cfparam name="attributes.sendEmail" default="no">
<cfparam name="attributes.message" default="No error message specified.">
<cfparam name="attributes.additionalDetail" default="No additionalDetail specified.">
<cfparam name="attributes.type" default="normal">
<cfparam name="attributes.debug" default="no">
<cfparam name="attributes.errorfile" default="">
<cfparam name="attributes.sourcefile" default="unknown">
<cfparam name="attributes.to" default="errors@my-site-here.com">
<cfparam name="attributes.errorTemplate" default="No error template specified.">
<!--- offending app --->
<cftry>
<cfset appName = Application.ApplicationName>
    <cfcatch>
     <cfset appName = "">
    </cfcatch>
</cftry>
<!--- create a unique id for each error; based on appName timestamp random num --->
<cfset errorID = appName & "_">
<cfset errorID = errorID & DateFormat(now(), "yyyy-mm-dd") & "_">
<cfset errorID = errorID & TimeFormat(Now(), "hh-mm-ss-l") & "_">
<cfset errorID = errorID & RandRange(1,9999)>
<!--- if it's a custom error type (like cfthrow), then create variables differently --->
<cfif attributes.type IS "custom">
<!--- get template and message from caller --->
<cfset errorTemplate = attributes.errorTemplate>
<cfset errorLine = "???">
<cfset errorMsg = attributes.message>
<cfelse>
    <!--- get offending template and line --->
    <cftry>
     <!--- look at the rootcause level first --->
     <cfset errorTemplate = Caller.CFCatch.rootcause.tagContext[1].template>
     <cfset errorLine = Caller.CFCatch.rootcause.tagContext[1].line>
     <cfcatch>
     <cftry>
     <!--- then check above that, for when the error type is "Template" --->
         <cfset errorTemplate = Caller.CFCatch.tagContext[1].template>
         <cfset errorLine = Caller.CFCatch.tagContext[1].line>
         <cfcatch>
                 <cfset errorTemplate = "tagContext[1].template couldn't be captured">
             <cfset errorLine = "tagContext[1].line couldn't be captured">
         </cfcatch>
     </cftry>
        </cfcatch>
    </cftry>
    <!--- get error message --->
    <cftry>
     <!--- look at the rootcause level first --->
     <cfset errorMsg = Caller.CFCatch.rootcause.message>
     <cfcatch>
         <cftry>
     <!--- then check above that, for when the error type is "Template" --->
     <cfset errorMsg = Caller.CFCatch.message>
     <cfcatch>
     <cfset errorMsg = "error message couldn't be captured">
     </cfcatch>
     </cftry>
        </cfcatch>
    </cftry>
<!--- /check for custom type --->
</cfif>
<!--- check if application name exist --->
<cfif Len(appName)>
    <cfset tmpStr = "#appName#.">
<cfelse>
    <cfset tmpStr = "">
</cfif>
<cfparam name="attributes.from" default="#tmpStr#errors@my-site-here.com">
<!--- needed to support fusebox --->
<cfif isDefined("CALLER.dsn")>
<cfset dsn = CALLER.dsn>
<cfelseif isDefined("ATTRIBUTES.dsn")>
<cfset dsn = ATTRIBUTES.dsn>
<cfelse>
<cfset dsn = "UNDEFINED!!">
</cfif>
<!--- Make sure no garbage was given as a value for the type attribute. --->
<cfswitch expression="#lcase(attributes.type)#">
    <cfcase value="normal,any,application,database,expression,missinginclude,template,object,security,lock,custom" delimiters=",">
    </cfcase>
    <cfdefaultcase>
<cfset variables.subtype = attributes.type>
        <cfset attributes.type = "unknown">
    </cfdefaultcase>
</cfswitch>
<cfsavecontent variable="errorText">
<cfoutput>
<strong>Template:</strong><br>
&nbsp;&nbsp;&nbsp; #errorTemplate# (line: #errorLine#)<br>
<strong>Message:</strong><br>
&nbsp;&nbsp;&nbsp;#errorMsg#<br>
<strong>Additional Details:</strong><br>
&nbsp;&nbsp;&nbsp;#attributes.additionalDetail#<br>
<strong>Type:</strong><br>
     &nbsp;&nbsp;&nbsp; #attributes.type#<br>
<strong>DSN:</strong><br>
     &nbsp;&nbsp;&nbsp; #dsn#<br>
    <strong>Date of error:</strong><br>
     &nbsp;&nbsp;&nbsp; #DateFormat(now(), "mm/dd/yyyy")#<br>
    <strong>Time of error:</strong><br>
     &nbsp;&nbsp;&nbsp; #TimeFormat(now(), "hh:mm:ss")#<br>
<strong>errorID:</strong> #errorID#<br>
<br>
</cfoutput>
<!--- loop through the application structure (if it exits) and print out the variables --->
<u>Application variables:</u><br>
<cfif IsDefined("APPLICATION") AND IsStruct(APPLICATION) AND StructCount(APPLICATION)>
<cfloop collection="#application#" item="itm">
<cfif IsObject(application[itm]) OR IsStruct(application[itm])>
<!--- <cfdump var="#application[itm]#"> --->
<cfoutput>
&nbsp;&nbsp;&nbsp;<strong>#itm#</strong>: StructCount (#StructCount(application[itm])#)<br>
</cfoutput>
<cfelse>
<cfoutput>
&nbsp;&nbsp;&nbsp;<strong>#itm#</strong>: #application[itm]#<br>
</cfoutput>
</cfif>
</cfloop>
<cfelse>
&nbsp;&nbsp;&nbsp;None Defined
</cfif>
<!---
<cftry>
<cfdump var="#Exception#" label="Exception" expand="true">
<cfcatch>couldn't dump Exception<br></cfcatch>
</cftry><br>
<br> --->
<!--- only try this dump if Caller.CFCatch is available --->
<cfif IsDefined("Caller.CFCatch")>
<cftry>
     <br>
     <cfloop collection="#Caller.cfcatch#" item="i">
                <cfset data = StructFind(Caller.cfcatch, i)>
                <cfif IsSimpleValue(data) AND (Not i CONTAINS "stacktrace")>
                 <cfoutput><strong>#Ucase(i)#</strong> = #data#<br></cfoutput>
                </cfif>
            </cfloop>
     <cfset tagContextInfo = "">
            <!--- loop thru array of templates and stick it into a comma-delimited list --->
            <cfloop index="i" from="1" to="#ArrayLen(Caller.CFCATCH.TAGCONTEXT)#">
                <cfset stCurrent = Caller.CFCATCH.TAGCONTEXT[i]>
                <cfset tagContextInfo = tagContextInfo & "ID: " & stCurrent["ID"]>
     <cfset tagContextInfo = tagContextInfo & "<br> LINE: " & stCurrent["LINE"]>
     <cfset tagContextInfo = tagContextInfo & "<br> TEMPLATE: " & stCurrent["TEMPLATE"] & "<br><br>">
            </cfloop>
     <cfoutput>
     <br>
     <strong><u>Tag Context:</u></strong><br>
     #tagContextInfo#
     </cfoutput>
<cfcatch>couldn't dump Caller.CFCatch</cfcatch>
     </cftry><br>
     <br>
<!--- TODO: implement this CF hot fix, so the code below can run:
http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=1a9c83c
     <cftry>
     <cfdump var="#Caller.CFCatch#" label="Caller.CFCatch" expand="true">
     <cfcatch>couldn't dump Caller.CFCatch</cfcatch>
     </cftry><br>
     <br> --->
</cfif>
    <cftry>
<cfdump var="#Client#" label="Client" expand="true">
<cfcatch>couldn't dump Client scope<br></cfcatch>
</cftry><br>
<br>
<!--- since we use FB, and use the attributes scope liberally, dump it --->
<cftry>
<cfdump var="#Caller.attributes#" label="Caller.attributes" expand="true">
<cfcatch>couldn't dump Caller.attributes scope<br></cfcatch>
</cftry><br>
<br>
    <cftry>
<cfdump var="#Form#" label="Form" expand="true">
<cfcatch>couldn't dump Form scope<br></cfcatch>
</cftry><br>
<br>
    <cftry>
<cfdump var="#URL#" label="URL" expand="true">
<cfcatch>couldn't dump URL scope<br></cfcatch>
</cftry><br>
<br>
    <cftry>
<cfdump var="#CGI#" label="CGI" expand="true">
<cfcatch>couldn't dump CGI scope<br></cfcatch>
</cftry><br>
<br>
    <cftry>
<cfdump var="#Cookie#" label="Cookie" expand="true">
<cfcatch>couldn't dump Cookie scope<br></cfcatch>
</cftry><br>
<br>
    <cftry>
<cfdump var="#Session#" label="Session" expand="true">
<cfcatch>couldn't dump Session scope<br></cfcatch>
</cftry><br>
<br>
</cfsavecontent>
<!--- Sends the email with all of the approriate info to the administrator --->
<cfif Trim(attributes.sendEmail) is "yes">
<cfmail to="#attributes.to#"
     from="#attributes.from#"
     subject="An error has occurred; ID: #errorID#"
     timeout="900"
     type="HTML">
    #errorText#
    </cfmail>
</cfif>
<!---
    if debug is set to yes just throw all pertinent info to the screen; otherwise forward to
    customized error file
--->
<cfif attributes.debug eq "yes">
<cfoutput>#errorText#</cfoutput>
</body>
</html>
<cfelse>
<cfif attributes.errorfile NEQ "">
    <cf_location url="#attributes.errorfile#" addtoken="false">
</cfif>
</cfif>

Cut-N-Paste