1. <!---
  2.     Purpose: To provide different means of handling error in a generic way for CFMX 6.1
  3.     Attributes:
  4.         type="custom | database | any | application | lock | template | security | object | expression | normal | missinginclude" -default "normal"
  5.         sendEmail="yes | no" -default no
  6.         message="[some error message to be displayed]" -default "No error message specified." -notes Should only be specified when having a "normal" type error
  7.         additionalDetail="[some error detail to be displayed]" -default "No additionalDetail specified."
  8.         debug="yes|no" -default "no"
  9.         to="[email address to send email to]" -default "errors@my-site-here.com"
  10.         from="[from email address]" -default "#application.applicationname#.errors@my-site-here.com"
  11.         errorfile="#errorfile#" -defualt errorfile.cfm
  12.     Usage Notes:
  13.          if installed under custom tags directory:
  14.          <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"]>
  15.          if installed in relative directory to your application:
  16.          <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"]>
  17.          if this custom tag has thesame name as another tag in custom tags directory:
  18.          <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"]>
  19. --->
  20. <!--- Set default values on attributes --->
  21. <cfparam name="attributes.sendEmail" default="no">
  22. <cfparam name="attributes.message" default="No error message specified.">
  23. <cfparam name="attributes.additionalDetail" default="No additionalDetail specified.">
  24. <cfparam name="attributes.type" default="normal">
  25. <cfparam name="attributes.debug" default="no">
  26. <cfparam name="attributes.errorfile" default="">
  27. <cfparam name="attributes.sourcefile" default="unknown">
  28. <cfparam name="attributes.to" default="errors@my-site-here.com">
  29. <cfparam name="attributes.errorTemplate" default="No error template specified.">
  30. <!--- offending app --->
  31. <cftry>
  32. <cfset appName = Application.ApplicationName>
  33.     <cfcatch>
  34.      <cfset appName = "">
  35.     </cfcatch>
  36. </cftry>
  37. <!--- create a unique id for each error; based on appName timestamp random num --->
  38. <cfset errorID = appName & "_">
  39. <cfset errorID = errorID & DateFormat(now(), "yyyy-mm-dd") & "_">
  40. <cfset errorID = errorID & TimeFormat(Now(), "hh-mm-ss-l") & "_">
  41. <cfset errorID = errorID & RandRange(1,9999)>
  42. <!--- if it's a custom error type (like cfthrow), then create variables differently --->
  43. <cfif attributes.type IS "custom">
  44. <!--- get template and message from caller --->
  45. <cfset errorTemplate = attributes.errorTemplate>
  46. <cfset errorLine = "???">
  47. <cfset errorMsg = attributes.message>
  48. <cfelse>
  49.     <!--- get offending template and line --->
  50.     <cftry>
  51.      <!--- look at the rootcause level first --->
  52.      <cfset errorTemplate = Caller.CFCatch.rootcause.tagContext[1].template>
  53.      <cfset errorLine = Caller.CFCatch.rootcause.tagContext[1].line>
  54.      <cfcatch>
  55.      <cftry>
  56.      <!--- then check above that, for when the error type is "Template" --->
  57.          <cfset errorTemplate = Caller.CFCatch.tagContext[1].template>
  58.          <cfset errorLine = Caller.CFCatch.tagContext[1].line>
  59.          <cfcatch>
  60.                  <cfset errorTemplate = "tagContext[1].template couldn't be captured">
  61.              <cfset errorLine = "tagContext[1].line couldn't be captured">
  62.          </cfcatch>
  63.      </cftry>
  64.         </cfcatch>
  65.     </cftry>
  66.     <!--- get error message --->
  67.     <cftry>
  68.      <!--- look at the rootcause level first --->
  69.      <cfset errorMsg = Caller.CFCatch.rootcause.message>
  70.      <cfcatch>
  71.          <cftry>
  72.      <!--- then check above that, for when the error type is "Template" --->
  73.      <cfset errorMsg = Caller.CFCatch.message>
  74.      <cfcatch>
  75.      <cfset errorMsg = "error message couldn't be captured">
  76.      </cfcatch>
  77.      </cftry>
  78.         </cfcatch>
  79.     </cftry>
  80. <!--- /check for custom type --->
  81. </cfif>
  82. <!--- check if application name exist --->
  83. <cfif Len(appName)>
  84.     <cfset tmpStr = "#appName#.">
  85. <cfelse>
  86.     <cfset tmpStr = "">
  87. </cfif>
  88. <cfparam name="attributes.from" default="#tmpStr#errors@my-site-here.com">
  89. <!--- needed to support fusebox --->
  90. <cfif isDefined("CALLER.dsn")>
  91. <cfset dsn = CALLER.dsn>
  92. <cfelseif isDefined("ATTRIBUTES.dsn")>
  93. <cfset dsn = ATTRIBUTES.dsn>
  94. <cfelse>
  95. <cfset dsn = "UNDEFINED!!">
  96. </cfif>
  97. <!--- Make sure no garbage was given as a value for the type attribute. --->
  98. <cfswitch expression="#lcase(attributes.type)#">
  99.     <cfcase value="normal,any,application,database,expression,missinginclude,template,object,security,lock,custom" delimiters=",">
  100.     </cfcase>
  101.     <cfdefaultcase>
  102. <cfset variables.subtype = attributes.type>
  103.         <cfset attributes.type = "unknown">
  104.     </cfdefaultcase>
  105. </cfswitch>
  106. <cfsavecontent variable="errorText">
  107. <cfoutput>
  108. <strong>Template:</strong><br>
  109. &nbsp;&nbsp;&nbsp; #errorTemplate# (line: #errorLine#)<br>
  110. <strong>Message:</strong><br>
  111. &nbsp;&nbsp;&nbsp;#errorMsg#<br>
  112. <strong>Additional Details:</strong><br>
  113. &nbsp;&nbsp;&nbsp;#attributes.additionalDetail#<br>
  114. <strong>Type:</strong><br>
  115.      &nbsp;&nbsp;&nbsp; #attributes.type#<br>
  116. <strong>DSN:</strong><br>
  117.      &nbsp;&nbsp;&nbsp; #dsn#<br>
  118.     <strong>Date of error:</strong><br>
  119.      &nbsp;&nbsp;&nbsp; #DateFormat(now(), "mm/dd/yyyy")#<br>
  120.     <strong>Time of error:</strong><br>
  121.      &nbsp;&nbsp;&nbsp; #TimeFormat(now(), "hh:mm:ss")#<br>
  122. <strong>errorID:</strong> #errorID#<br>
  123. <br>
  124. </cfoutput>
  125. <!--- loop through the application structure (if it exits) and print out the variables --->
  126. <u>Application variables:</u><br>
  127. <cfif IsDefined("APPLICATION") AND IsStruct(APPLICATION) AND StructCount(APPLICATION)>
  128. <cfloop collection="#application#" item="itm">
  129. <cfif IsObject(application[itm]) OR IsStruct(application[itm])>
  130. <!--- <cfdump var="#application[itm]#"> --->
  131. <cfoutput>
  132. &nbsp;&nbsp;&nbsp;<strong>#itm#</strong>: StructCount (#StructCount(application[itm])#)<br>
  133. </cfoutput>
  134. <cfelse>
  135. <cfoutput>
  136. &nbsp;&nbsp;&nbsp;<strong>#itm#</strong>: #application[itm]#<br>
  137. </cfoutput>
  138. </cfif>
  139. </cfloop>
  140. <cfelse>
  141. &nbsp;&nbsp;&nbsp;None Defined
  142. </cfif>
  143. <!---
  144. <cftry>
  145. <cfdump var="#Exception#" label="Exception" expand="true">
  146. <cfcatch>couldn't dump Exception<br></cfcatch>
  147. </cftry><br>
  148. <br> --->
  149. <!--- only try this dump if Caller.CFCatch is available --->
  150. <cfif IsDefined("Caller.CFCatch")>
  151. <cftry>
  152.      <br>
  153.      <cfloop collection="#Caller.cfcatch#" item="i">
  154.                 <cfset data = StructFind(Caller.cfcatch, i)>
  155.                 <cfif IsSimpleValue(data) AND (Not i CONTAINS "stacktrace")>
  156.                  <cfoutput><strong>#Ucase(i)#</strong> = #data#<br></cfoutput>
  157.                 </cfif>
  158.             </cfloop>
  159.      <cfset tagContextInfo = "">
  160.             <!--- loop thru array of templates and stick it into a comma-delimited list --->
  161.             <cfloop index="i" from="1" to="#ArrayLen(Caller.CFCATCH.TAGCONTEXT)#">
  162.                 <cfset stCurrent = Caller.CFCATCH.TAGCONTEXT[i]>
  163.                 <cfset tagContextInfo = tagContextInfo & "ID: " & stCurrent["ID"]>
  164.      <cfset tagContextInfo = tagContextInfo & "<br> LINE: " & stCurrent["LINE"]>
  165.      <cfset tagContextInfo = tagContextInfo & "<br> TEMPLATE: " & stCurrent["TEMPLATE"] & "<br><br>">
  166.             </cfloop>
  167.      <cfoutput>
  168.      <br>
  169.      <strong><u>Tag Context:</u></strong><br>
  170.      #tagContextInfo#
  171.      </cfoutput>
  172. <cfcatch>couldn't dump Caller.CFCatch</cfcatch>
  173.      </cftry><br>
  174.      <br>
  175. <!--- TODO: implement this CF hot fix, so the code below can run:
  176. http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=1a9c83c
  177.      <cftry>
  178.      <cfdump var="#Caller.CFCatch#" label="Caller.CFCatch" expand="true">
  179.      <cfcatch>couldn't dump Caller.CFCatch</cfcatch>
  180.      </cftry><br>
  181.      <br> --->
  182. </cfif>
  183.     <cftry>
  184. <cfdump var="#Client#" label="Client" expand="true">
  185. <cfcatch>couldn't dump Client scope<br></cfcatch>
  186. </cftry><br>
  187. <br>
  188. <!--- since we use FB, and use the attributes scope liberally, dump it --->
  189. <cftry>
  190. <cfdump var="#Caller.attributes#" label="Caller.attributes" expand="true">
  191. <cfcatch>couldn't dump Caller.attributes scope<br></cfcatch>
  192. </cftry><br>
  193. <br>
  194.     <cftry>
  195. <cfdump var="#Form#" label="Form" expand="true">
  196. <cfcatch>couldn't dump Form scope<br></cfcatch>
  197. </cftry><br>
  198. <br>
  199.     <cftry>
  200. <cfdump var="#URL#" label="URL" expand="true">
  201. <cfcatch>couldn't dump URL scope<br></cfcatch>
  202. </cftry><br>
  203. <br>
  204.     <cftry>
  205. <cfdump var="#CGI#" label="CGI" expand="true">
  206. <cfcatch>couldn't dump CGI scope<br></cfcatch>
  207. </cftry><br>
  208. <br>
  209.     <cftry>
  210. <cfdump var="#Cookie#" label="Cookie" expand="true">
  211. <cfcatch>couldn't dump Cookie scope<br></cfcatch>
  212. </cftry><br>
  213. <br>
  214.     <cftry>
  215. <cfdump var="#Session#" label="Session" expand="true">
  216. <cfcatch>couldn't dump Session scope<br></cfcatch>
  217. </cftry><br>
  218. <br>
  219. </cfsavecontent>
  220. <!--- Sends the email with all of the approriate info to the administrator --->
  221. <cfif Trim(attributes.sendEmail) is "yes">
  222. <cfmail to="#attributes.to#"
  223.      from="#attributes.from#"
  224.      subject="An error has occurred; ID: #errorID#"
  225.      timeout="900"
  226.      type="HTML">
  227.     #errorText#
  228.     </cfmail>
  229. </cfif>
  230. <!---
  231.     if debug is set to yes just throw all pertinent info to the screen; otherwise forward to
  232.     customized error file
  233. --->
  234. <cfif attributes.debug eq "yes">
  235. <cfoutput>#errorText#</cfoutput>
  236. </body>
  237. </html>
  238. <cfelse>
  239. <cfif attributes.errorfile NEQ "">
  240.     <cf_location url="#attributes.errorfile#" addtoken="false">
  241. </cfif>
  242. </cfif>