<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Orange is my favorite color &#187; ColdFusion</title>
	<atom:link href="http://www.ghidinelli.com/c/webinternet/coldfusion/feed" rel="self" type="application/rss+xml" />
	<link>http://www.ghidinelli.com</link>
	<description></description>
	<lastBuildDate>Wed, 04 Jan 2012 08:06:13 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.3</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>CFHTTP Error Handling for Status Codes</title>
		<link>http://www.ghidinelli.com/2012/01/03/cfhttp-error-handling-http-status-codes</link>
		<comments>http://www.ghidinelli.com/2012/01/03/cfhttp-error-handling-http-status-codes#comments</comments>
		<pubDate>Wed, 04 Jan 2012 03:23:10 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[CFHTTP]]></category>
		<category><![CDATA[cfpayment]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1433</guid>
		<description><![CDATA[A test of the exception types thrown by ColdFusion for all HTTP status codes]]></description>
			<content:encoded><![CDATA[<p>We&#8217;re <a href="https://groups.google.com/forum/#!topic/cfpayment/e_gjlAbAWqY">discussing some refactoring</a> before releasing a <a href="http://cfpayment.riaforge.org">cfpayment 1.0</a> and one of the things I&#8217;m working on is figuring out when to use ColdFusion&#8217;s in-built error handling and when to use HTTP status codes.  Currently we use the throwonerror option for CFHTTP which results in issues like 404 throwing an exception.  This works but as more and more services expose RESTful APIs which use status codes other than 200 to communicate results, this is not perfect.</p>
<p>That got me to thinking&#8230; what status codes does ColdFusion throw an error for when throwonerror is set to yes?  Here&#8217;s the list for <a href="http://en.wikipedia.org/wiki/List_of_HTTP_status_codes">every HTTP status code</a>:</p>
<h2>CFHTTP with throwonerror=&#8221;yes&#8221;</h2>
<table>
<tr>
<td>200</td>
<td>Returned normally with status 200 OK</td>
</tr>
<tr>
<td>201</td>
<td>Returned normally with status 201 Created</td>
</tr>
<tr>
<td>202</td>
<td>Returned normally with status 202 Accepted</td>
</tr>
<tr>
<td>203</td>
<td>Returned normally with status 203 Non-Authoritative Information</td>
</tr>
<tr>
<td>204</td>
<td>Returned normally with status 204 No Content</td>
</tr>
<tr>
<td>205</td>
<td>Returned normally with status 205 Reset Content</td>
</tr>
<tr>
<td>206</td>
<td>Returned normally with status 206 Partial Content</td>
</tr>
<tr>
<td>207</td>
<td>Returned normally with status 207 Multi-Status</td>
</tr>
<tr>
<td>208</td>
<td>Returned normally with status 208 Already Reported</td>
</tr>
<tr>
<td>226</td>
<td>Returned normally with status 226 IM Used</td>
</tr>
<tr>
<td>300</td>
<td>COM.Allaire.ColdFusion.HTTPMultipleChoices</td>
</tr>
<tr>
<td>301</td>
<td>COM.Allaire.ColdFusion.HTTPMovedPermanently</td>
</tr>
<tr>
<td>302</td>
<td>COM.Allaire.ColdFusion.HTTPMovedPermanently</td>
</tr>
<tr>
<td>303</td>
<td>COM.Allaire.ColdFusion.HTTPSeeOther</td>
</tr>
<tr>
<td>304</td>
<td>COM.Allaire.ColdFusion.HTTPNotModified</td>
</tr>
<tr>
<td>305</td>
<td>COM.Allaire.ColdFusion.HTTPUseProxy</td>
</tr>
<tr>
<td>306</td>
<td>Returned normally with status 306 Switch Proxy</td>
</tr>
<tr>
<td>307</td>
<td>Returned normally with status 307 Temporary Redirect</td>
</tr>
<tr>
<td>308</td>
<td>Returned normally with status 308 Resume Incomplete</td>
</tr>
<tr>
<td>400</td>
<td>COM.Allaire.ColdFusion.HTTPBadRequest</td>
</tr>
<tr>
<td>401</td>
<td>Returned normally with status 401 Unauthorized</td>
</tr>
<tr>
<td>402</td>
<td>COM.Allaire.ColdFusion.HTTPPaymentRequired</td>
</tr>
<tr>
<td>403</td>
<td>COM.Allaire.ColdFusion.HTTPForbidden</td>
</tr>
<tr>
<td>404</td>
<td>COM.Allaire.ColdFusion.HTTPNotFound</td>
</tr>
<tr>
<td>405</td>
<td>Returned normally with status 405 Method Not Allowed</td>
</tr>
<tr>
<td>406</td>
<td>COM.Allaire.ColdFusion.HTTPNotAcceptable</td>
</tr>
<tr>
<td>407</td>
<td>COM.Allaire.ColdFusion.HTTPProxyAuthenticationRequired</td>
</tr>
<tr>
<td>408</td>
<td>Returned normally with status 408 Request Timeout</td>
</tr>
<tr>
<td>409</td>
<td>COM.Allaire.ColdFusion.HTTPConflict</td>
</tr>
<tr>
<td>410</td>
<td>COM.Allaire.ColdFusion.HTTPGone</td>
</tr>
<tr>
<td>411</td>
<td>COM.Allaire.ColdFusion.HTTPFailure</td>
</tr>
<tr>
<td>412</td>
<td>COM.Allaire.ColdFusion.HTTPPreconditionFailed</td>
</tr>
<tr>
<td>413</td>
<td>COM.Allaire.ColdFusion.HTTPCFHTTPRequestEntityTooLarge</td>
</tr>
<tr>
<td>414</td>
<td>COM.Allaire.ColdFusion.HTTPRequestURITooLarge</td>
</tr>
<tr>
<td>415</td>
<td>COM.Allaire.ColdFusion.HTTPUnsupportedMediaType</td>
</tr>
<tr>
<td>416</td>
<td>Returned normally with status 416 Requested Range Not Satisfiable</td>
</tr>
<tr>
<td>417</td>
<td>Returned normally with status 417 Expectation Failed</td>
</tr>
<tr>
<td>418</td>
<td>Returned normally with status 418 I&#8217;m a teapot</td>
</tr>
<tr>
<td>422</td>
<td>Returned normally with status 422 Unprocessable Entity</td>
</tr>
<tr>
<td>423</td>
<td>Returned normally with status 423 Locked</td>
</tr>
<tr>
<td>424</td>
<td>Returned normally with status 424 Failed Dependency</td>
</tr>
<tr>
<td>425</td>
<td>Returned normally with status 425 Unordered Collection</td>
</tr>
<tr>
<td>426</td>
<td>Returned normally with status 426 Upgrade Required</td>
</tr>
<tr>
<td>428</td>
<td>Returned normally with status 428 Precondition Required</td>
</tr>
<tr>
<td>429</td>
<td>Returned normally with status 429 Too Many Requests</td>
</tr>
<tr>
<td>431</td>
<td>Returned normally with status 431 Request Header Fields Too Large</td>
</tr>
<tr>
<td>444</td>
<td>Returned normally with status 444 No Response</td>
</tr>
<tr>
<td>449</td>
<td>Returned normally with status 449 Retry With</td>
</tr>
<tr>
<td>450</td>
<td>Returned normally with status 450 Blocked by Windows Parental Controls</td>
</tr>
<tr>
<td>499</td>
<td>Returned normally with status 499 Client Closed Request</td>
</tr>
<tr>
<td>500</td>
<td>COM.Allaire.ColdFusion.HTTPServerError</td>
</tr>
<tr>
<td>501</td>
<td>COM.Allaire.ColdFusion.HTTPNotImplemented</td>
</tr>
<tr>
<td>502</td>
<td>COM.Allaire.ColdFusion.HTTPBadGateway</td>
</tr>
<tr>
<td>503</td>
<td>COM.Allaire.ColdFusion.HTTPServiceUnavailable</td>
</tr>
<tr>
<td>504</td>
<td>Returned normally with status 504 Gateway Timeout</td>
</tr>
<tr>
<td>505</td>
<td>COM.Allaire.ColdFusion.HTTPVersionNotSupported</td>
</tr>
<tr>
<td>506</td>
<td>Returned normally with status 506 Variant Also Negotiates</td>
</tr>
<tr>
<td>507</td>
<td>Returned normally with status 507 Insufficient Storage</td>
</tr>
<tr>
<td>508</td>
<td>Returned normally with status 508 Loop Detected</td>
</tr>
<tr>
<td>509</td>
<td>Returned normally with status 509 Bandwidth Limit Exceeded</td>
</tr>
<tr>
<td>510</td>
<td>Returned normally with status 510 Not Extended</td>
</tr>
<tr>
<td>511</td>
<td>Returned normally with status 511 Network Authentication Required</td>
</tr>
<tr>
<td>598</td>
<td>Returned normally with status 598 Network read timeout error</td>
</tr>
<tr>
<td>599</td>
<td>Returned normally with status 599 Network connect timeout error</td>
</tr>
<tr>
<td>999</td>
<td>Returned normally with status 999 Invalid HTTP status code</td>
</tr>
</table>
<p>I also ran it with throwonerror=&#8221;no&#8221;, which has <em>almost</em> the results you would expect with the exception of code 411:</p>
<h2>CFHTTP with throwonerror=&#8221;no&#8221;</h2>
<table>
<tr>
<td>200</td>
<td>Returned normally with status 200 OK</td>
</tr>
<tr>
<td>201</td>
<td>Returned normally with status 201 Created</td>
</tr>
<tr>
<td>202</td>
<td>Returned normally with status 202 Accepted</td>
</tr>
<tr>
<td>203</td>
<td>Returned normally with status 203 Non-Authoritative Information</td>
</tr>
<tr>
<td>204</td>
<td>Returned normally with status 204 No Content</td>
</tr>
<tr>
<td>205</td>
<td>Returned normally with status 205 Reset Content</td>
</tr>
<tr>
<td>206</td>
<td>Returned normally with status 206 Partial Content</td>
</tr>
<tr>
<td>207</td>
<td>Returned normally with status 207 Multi-Status</td>
</tr>
<tr>
<td>208</td>
<td>Returned normally with status 208 Already Reported</td>
</tr>
<tr>
<td>226</td>
<td>Returned normally with status 226 IM Used</td>
</tr>
<tr>
<td>300</td>
<td>Returned normally with status 300 Multiple Choices</td>
</tr>
<tr>
<td>301</td>
<td>Returned normally with status 301 Moved Permanently</td>
</tr>
<tr>
<td>302</td>
<td>Returned normally with status 302 Found</td>
</tr>
<tr>
<td>303</td>
<td>Returned normally with status 303 See Other</td>
</tr>
<tr>
<td>304</td>
<td>Returned normally with status 304 Not Modified</td>
</tr>
<tr>
<td>305</td>
<td>Returned normally with status 305 Use Proxy</td>
</tr>
<tr>
<td>306</td>
<td>Returned normally with status 306 Switch Proxy</td>
</tr>
<tr>
<td>307</td>
<td>Returned normally with status 307 Temporary Redirect</td>
</tr>
<tr>
<td>308</td>
<td>Returned normally with status 308 Resume Incomplete</td>
</tr>
<tr>
<td>400</td>
<td>Returned normally with status 400 Bad Request</td>
</tr>
<tr>
<td>401</td>
<td>Returned normally with status 401 Unauthorized</td>
</tr>
<tr>
<td>402</td>
<td>Returned normally with status 402 Payment Required</td>
</tr>
<tr>
<td>403</td>
<td>Returned normally with status 403 Forbidden</td>
</tr>
<tr>
<td>404</td>
<td>Returned normally with status 404 Not Found</td>
</tr>
<tr>
<td>405</td>
<td>Returned normally with status 405 Method Not Allowed</td>
</tr>
<tr>
<td>406</td>
<td>Returned normally with status 406 Not Acceptable</td>
</tr>
<tr>
<td>407</td>
<td>Returned normally with status 407 Proxy Authentication Required</td>
</tr>
<tr>
<td>408</td>
<td>Returned normally with status 408 Request Timeout</td>
</tr>
<tr>
<td>409</td>
<td>Returned normally with status 409 Conflict</td>
</tr>
<tr>
<td>410</td>
<td>Returned normally with status 410 Gone</td>
</tr>
<tr>
<td>411</td>
<td>Returned normally with status Connection Failure.  Status code unavailable.</td>
</tr>
<tr>
<td>412</td>
<td>Returned normally with status 412 Precondition Failed</td>
</tr>
<tr>
<td>413</td>
<td>Returned normally with status 413 Request Entity Too Large</td>
</tr>
<tr>
<td>414</td>
<td>Returned normally with status 414 Request-URI Too Long</td>
</tr>
<tr>
<td>415</td>
<td>Returned normally with status 415 Unsupported Media Type</td>
</tr>
<tr>
<td>416</td>
<td>Returned normally with status 416 Requested Range Not Satisfiable</td>
</tr>
<tr>
<td>417</td>
<td>Returned normally with status 417 Expectation Failed</td>
</tr>
<tr>
<td>418</td>
<td>Returned normally with status 418 I&#8217;m a teapot</td>
</tr>
<tr>
<td>422</td>
<td>Returned normally with status 422 Unprocessable Entity</td>
</tr>
<tr>
<td>423</td>
<td>Returned normally with status 423 Locked</td>
</tr>
<tr>
<td>424</td>
<td>Returned normally with status 424 Failed Dependency</td>
</tr>
<tr>
<td>425</td>
<td>Returned normally with status 425 Unordered Collection</td>
</tr>
<tr>
<td>426</td>
<td>Returned normally with status 426 Upgrade Required</td>
</tr>
<tr>
<td>428</td>
<td>Returned normally with status 428 Precondition Required</td>
</tr>
<tr>
<td>429</td>
<td>Returned normally with status 429 Too Many Requests</td>
</tr>
<tr>
<td>431</td>
<td>Returned normally with status 431 Request Header Fields Too Large</td>
</tr>
<tr>
<td>444</td>
<td>Returned normally with status 444 No Response</td>
</tr>
<tr>
<td>449</td>
<td>Returned normally with status 449 Retry With</td>
</tr>
<tr>
<td>450</td>
<td>Returned normally with status 450 Blocked by Windows Parental Controls</td>
</tr>
<tr>
<td>499</td>
<td>Returned normally with status 499 Client Closed Request</td>
</tr>
<tr>
<td>500</td>
<td>Returned normally with status 500 Internal Server Error</td>
</tr>
<tr>
<td>501</td>
<td>Returned normally with status 501 Not Implemented</td>
</tr>
<tr>
<td>502</td>
<td>Returned normally with status 502 Bad Gateway</td>
</tr>
<tr>
<td>503</td>
<td>Returned normally with status 503 Service Unavailable</td>
</tr>
<tr>
<td>504</td>
<td>Returned normally with status 504 Gateway Timeout</td>
</tr>
<tr>
<td>505</td>
<td>Returned normally with status 505 HTTP Version Not Supported</td>
</tr>
<tr>
<td>506</td>
<td>Returned normally with status 506 Variant Also Negotiates</td>
</tr>
<tr>
<td>507</td>
<td>Returned normally with status 507 Insufficient Storage</td>
</tr>
<tr>
<td>508</td>
<td>Returned normally with status 508 Loop Detected</td>
</tr>
<tr>
<td>509</td>
<td>Returned normally with status 509 Bandwidth Limit Exceeded</td>
</tr>
<tr>
<td>510</td>
<td>Returned normally with status 510 Not Extended</td>
</tr>
<tr>
<td>511</td>
<td>Returned normally with status 511 Network Authentication Required</td>
</tr>
<tr>
<td>598</td>
<td>Returned normally with status 598 Network read timeout error</td>
</tr>
<tr>
<td>599</td>
<td>Returned normally with status 599 Network connect timeout error</td>
</tr>
<tr>
<td>999</td>
<td>Returned normally with status 999 Invalid HTTP status code</td>
</tr>
</table>
<p>Notice Status Code 411 doesn&#8217;t return a numerical status code but rather a string &#8220;Connection Failure. Status code unavailable.&#8221;  The FileContent is set to &#8220;Connection Failure&#8221; while all other status codes are left blank (assuming that the request doesn&#8217;t return any data, as my test script does).  Good to know.</p>
<p><img src="http://www.ghidinelli.com/wp-content/uploads/2012/01/statuscode411.png" alt="How ColdFusion handles Status Code 411" title="How ColdFusion handles Status Code 411" width="426" height="220" class="aligncenter size-full wp-image-1441" /></p>
<h2>Problematic SSL Certificates</h2>
<p>For processing credit cards and payment processing transactions in general, the most insidious error I have run into is the &#8220;I/O Exception: peer not authenticated&#8221; error.  This basically means ColdFusion is <a href="http://www.ghidinelli.com/2008/01/19/using-invalid-expired-or-mismatched-ssl-certs-from-coldfusion">unable to read and authenticate the SSL certificate</a> and initiate a secure connection.  Generally this is either a self-signed certificate or, these days, a <a href="http://www.elliottsprehn.com/cfbugs/bugs/82997#comments">wildcard SSL certificate</a>.  Interestingly,  ColdFusion handles these scenarios a little bit differently depending on how throwonerror is set:</p>
<table border="1">
<tr>
<th>Test</th>
<th>ThrowOnError</th>
<th>Status/Message</th>
<th>ErrorDetail/Exception</th>
</tr>
<tr>
<td>Self-signed SSL Cert</td>
<td>Yes</td>
<td>Connection Failure: Status code unavailable</td>
<td>COM.Allaire.ColdFusion.HTTPFailure</td>
</tr>
<tr>
<td>Self-signed SSL Cert</td>
<td>No</td>
<td>Connection Failure. Status code unavailable.</td>
<td>I/O Exception: peer not authenticated</td>
</tr>
<tr>
<td>Wildcard SSL Cert</td>
<td>Yes</td>
<td>Connection Failure: Status code unavailable</td>
<td>COM.Allaire.ColdFusion.HTTPFailure</td>
</tr>
<tr>
<td>Wildcard SSL Cert</td>
<td>No</td>
<td>Connection Failure. Status code unavailable.</td>
<td>I/O Exception: peer not authenticated</td>
</tr>
</table>
<p>In summary, using throwonerror=no looks reasonably safe but you still must account for the catch-all COM.Allaire.ColdFusion.HTTPFailure.  My <a href="http://cfpayment.riaforge.org">battle-tested code</a> (which has processed more than $15MM) suggests you also need to check for coldfusion.runtime.RequestTimedOutException which is a different kind of exception when CFHTTP times out or the page times out.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2012/01/03/cfhttp-error-handling-http-status-codes/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Autopilot in the ColdFusion Updater Minefield</title>
		<link>http://www.ghidinelli.com/2011/12/20/autopilot-in-coldfusion-updater-minefield</link>
		<comments>http://www.ghidinelli.com/2011/12/20/autopilot-in-coldfusion-updater-minefield#comments</comments>
		<pubDate>Wed, 21 Dec 2011 06:18:05 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[server]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1426</guid>
		<description><![CDATA[Applying ColdFusion server security updates automatically with Unofficial Updater 2]]></description>
			<content:encoded><![CDATA[<p>If you manage a ColdFusion 8 or 9 server, you are likely aware of the complete and total train wreck that is applying security updates from Adobe.  Not only are directions vague, but on occasion Adobe likes to go back and modify the security update without changing filenames or rev-ing the version number.  It can drive a SysOp to insanity.</p>
<p>So seems to be the mental state of <a href="http://www..com">David Epler</a> as he has been driven to build the &#8220;<a href="http://www.dcepler.net/post.cfm/unofficial-updater-2-for-coldfusion-8">Unofficial Updater 2</a>&#8220;.  It is an Ant script on steroids bundled in a JAR that knows how to go out and fetch all of the updates from Adobe.com and apply them to your CF8 or CF9 server installation.</p>
<p>I&#8217;m not going to belabor the awesomness; here&#8217;s how to get your server up to date in about 5 minutes:</p>
<ol>
<li>Start by verifying your current security issues, use Pete Freitag&#8217;s <a href="http://www.hackmycf.com">HackMyCF.com</a> for a baseline</li>
<li>Backup your /opt/jrun directory (just be safe): tar -cf /opt/jrun4</li>
<li>Download the Unofficial Updater from http://uu2.riaforge.org/</li>
<li>Run it: java -jar Unofficial-Updater2.jar text</li>
<li>Tell it where stuff lives in your installation (it knows how to handle Standalone, Jrun Multi-server and EAR/WAR installs)</li>
<li>Wait about 4 minutes for it to finish grabbing everything and install&#8230;</li>
<li>Re-run HackMyCF.com and BOOM!  Rest easy, friend.</li>
<li>Proceed to <a href="http://twitter.com/#!/ghidinelli/status/149361873878396928">have David Epler&#8217;s baby</a></li>
</ol>
<p>Please Adobe, please send David a big check so you can take his IP and use it for your next update, mmmm kay?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2011/12/20/autopilot-in-coldfusion-updater-minefield/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>3 Useful Regular Expressions</title>
		<link>http://www.ghidinelli.com/2011/02/08/three-useful-regular-expressions</link>
		<comments>http://www.ghidinelli.com/2011/02/08/three-useful-regular-expressions#comments</comments>
		<pubDate>Tue, 08 Feb 2011 21:42:35 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[Eclipse]]></category>
		<category><![CDATA[regexp]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1238</guid>
		<description><![CDATA[Three useful regular expressions for cleaning up code]]></description>
			<content:encoded><![CDATA[<p>When I posted <a href="http://www.ghidinelli.com/2011/01/17/regex-cffunction-output-false">the regexp for adding output=&#8221;false&#8221;</a> recently, it reminded me that I had saved a number of other regular expressions for previous search-and-replace operations.  Here&#8217;s three others I&#8217;ve found helpful in cleaning up code in the past.</p>
<h2>Strip whitespace from end of lines</h2>
<p>Extra white space at the end of a line probably won&#8217;t cause any problems but it&#8217;s unnecessary and just taking up space.  You can strip it with this.</p>
<pre><code>Find: ([\S])[ |\t]+$
Replace: $1</code></pre>
<p>A variant of this one is to find &#8220;^[ |\t]+$&#8221; which will find all lines that only contain spaces and tabs.  </p>
<h2>Find unescaped ampersands</h2>
<p>Most ampersand characters need to be escaped in web apps &#8211; this will track all ampersands not followed by the most commonly escaped variants like &amp;nbsp; &#8211; add your own as needed.</p>
<pre><code>Find: [^ ]&amp;amp;[^ |(amp;)|(nbsp;)|(gt;)|(lt;)]

 </code></pre>
<h2>Convert isDefined to structKeyExists</h2>
<p><a href="http://livedocs.adobe.com/coldfusion/8/functions_s_27.html">StructKeyExists</a> is the preferred method of checking if a variable is defined but updating all of those isDefined()s by hand is a drag.  Convert your entire code base with this search and replace:</p>
<pre><code>Find: [iI]sDefined\("(FORM|URL).([A-Za-z0-9]+)"\)
Replace: structKeyExists($1, "$2")</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2011/02/08/three-useful-regular-expressions/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Regular Expression to add output=false to cffunction</title>
		<link>http://www.ghidinelli.com/2011/01/17/regex-cffunction-output-false</link>
		<comments>http://www.ghidinelli.com/2011/01/17/regex-cffunction-output-false#comments</comments>
		<pubDate>Tue, 18 Jan 2011 00:22:51 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[memory leak]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1226</guid>
		<description><![CDATA[Fix memory leaks in ColdFusion applications by ensuring every cffunction tag has output="false" with this RegExp]]></description>
			<content:encoded><![CDATA[<p>Not the sexiest post you&#8217;ll run across, but based on many people&#8217;s findings<sup>1,2</sup>, you need to have an explicit output=&#8221;false&#8221; on every cffunction in order to prevent memory leaks on Adobe ColdFusion 7 and CF8.  This is not a new issue but what caught me by surprise today is that popular frameworks have this problem, and indeed, our own code base had them as a result.  Luckily, we can use  regular expressions to get the job done quickly.  Using CFEclipse/Eclipse, hit CTRL+H to bring up your workspace-wide search, tick the &#8220;Regular Expression&#8221; box and use the following search pattern (base regexp courtesy of <a href="http://blog.maestropublishing.com/fixing-a-mysterious-memory-leak-on-coldfusion#pcomment_commentunit_2270899">Josh Knutson</a>):</p>
<pre><code>^((?!output)[^&gt;\n\r])*&lt;cffunction(((?!output)[^&gt;])*)&gt;</code></pre>
<p>This regular expression should handle cases where cffunction start tag is on one line and end tag is on another, where start and end tags are on one line and <a href="http://www.bennadel.com/">Ben Nadel</a>-style &#8220;attribute-per-line&#8221; tags broken up by newlines.  Click the &#8220;replace&#8221; button and when prompted for the replace pattern, use:</p>
<pre><code>$1&lt;cffunction$2 output="false"&gt;</code></pre>
<p><strong>BEFORE you run this search and replace, save and commit your code so anything that goes sideways can be easily reverted.</strong></p>
<p><img src="http://www.ghidinelli.com/wp-content/uploads/2011/01/eclipse_sr.png" alt="Eclipse search and replace regular expression to add output=false to all cffunction tags" title="Eclipse search and replace regular expression to add output=false to all cffunction tags" width="426" height="364" class="aligncenter size-full wp-image-1230" /></p>
<p>You can test this in a single file using the CTRL+F search and replace dialog box first as demonstrated in the above screenshot (note, the screenshot does not have the right regex).</p>
<p>There are a huge number of functions in popular frameworks like <a href="http://www.coldspringframework.org">Coldspring 1.2</a>, <a href="http://www.modelglue.org">Model-Glue 2</a> and <a href="http://www.transfer-orm.com">Transfer ORM</a> that are missing an output tag (and a smaller number of instances where output=&#8221;true&#8221;, which should also be corrected).  If you instantiate these frameworks in persistent scopes (who doesn&#8217;t?), this is a fix you&#8217;ll want to apply.</p>
<p>This issue may also be fixed in <a href="http://kb2.adobe.com/cps/529/cpsid_52915.html">CF 8.0.1 cumulative hot fix 4</a> but it was also supposed to be fixed in CHF3.  In all cases, the update is easy and is one less thing to worry about.</p>
<p>I have no knowledge of whether or not this exists in CF9.</p>
<p>[1] &#8211; <a href="http://wiki.mxunit.org/display/default/How+cfcomponent+output%3Dtrue++can+affect+memory+consumption">How cfcomponent output=true can affect memory consumption</a> (MxUnit.org)<br />
[2] &#8211; <a href="http://blog.maestropublishing.com/fixing-a-mysterious-memory-leak-on-coldfusion">Fixing a mysterious memory leak on ColdFusion</a> (Peter Farrell)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2011/01/17/regex-cffunction-output-false/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>ColdFusion hangs or slow on startup due to MessageBrokerServlet</title>
		<link>http://www.ghidinelli.com/2011/01/11/cold-fusion-slow-start-messagebrokerservlet</link>
		<comments>http://www.ghidinelli.com/2011/01/11/cold-fusion-slow-start-messagebrokerservlet#comments</comments>
		<pubDate>Tue, 11 Jan 2011 22:20:13 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jvm]]></category>
		<category><![CDATA[SSL]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1208</guid>
		<description><![CDATA[I&#8217;m setting up a new server as recent posts and tweets have suggested.  Just about everything was working with one exception: horribly slow startup times of 2-4 minutes on a dual quad-core Xeon machine with 16GB of RAM.  Tailing the cfusion-event.log during startup, ColdFusion would hang either when starting the SQL manager pool [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m setting up a new server as recent posts and <a href="http://twitter.com/ghidinelli">tweets</a> have suggested.  Just about everything was working with one exception: horribly slow startup times of 2-4 minutes on a dual quad-core Xeon machine with 16GB of RAM.  Tailing the cfusion-event.log during startup, ColdFusion would hang either when starting the SQL manager pool or MessageBrokerServlet.  It looked something like this (note the timestamps):</p>
<pre><code>01/10 13:03:28 user MessageBrokerServlet: init
**** 90 seconds of "working" ****
01/10 13:05:13 user CFFormGateway: init</code></pre>
<pre><code>01/10 12:32:58 Information [scheduler-12] - Starting debugging...
01/10 12:32:58 Information [scheduler-12] - Starting sql...
****  almost 2 minutes here ****
01/10 12:34:46 Information [scheduler-12] - Pool Manager Started
01/10 12:34:46 Information [scheduler-12] - Starting mail... </code></pre>
<p>This simply would not do.  Not only was it slow, it was unpredictable, sometimes taking 90-115 seconds and other times as long as 224 seconds.  We generally restart our CF servers when we do deployments and the sluggish startup meant more queued requests and timeouts as we come back from an update.  No bueno.</p>
<p>I turned to my friends on the CFGURU list hoping someone had the answer.  The always helpful <a href="http://www.pengoworks.com">Dan Switzer</a> pointed me to a <a href="http://www.mail-archive.com/cfaussie@googlegroups.com/msg14524.html">cfaussie thread</a> which was Ubuntu specific but had my same behavior:</p>
<blockquote><p>With the startup you can see that cranking up the Message Broker Servlet (ie Livecycle/Blaze) is taking almost a minute, which I find is usually due to some network ports used by LCDS still being open from the last time ColdFusion was run.</p></blockquote>
<p>The good news was that they were experiencing the exact same problem I was.  The bad news is that I have nothing to do with Blaze or LiveCycle so I wasn&#8217;t sure this was related.   We are also running RHEL/CentOS but the Ubuntu connection proved helpful later in my research.</p>
<p>Anytime I see hanging processes in ColdFusion, I generate a <a href="http://www.ghidinelli.com/2009/07/16/finding-memory-leaks-coldfusion-jvm">complete JVM stack trace</a>.  Unfortunately, I&#8217;m quite bad at reading them.  I identified a BLOCKED process but <a href="http://www.darylb.net/">Daryl Banttari</a> took a look and set me straight:</p>
<pre><code>This is the thread that's your root problem:

"scheduler-10" prio=10 tid=0x00002aaaac28c800 nid=0x5edd runnable [0x00000000441de000]
   java.lang.Thread.State: RUNNABLE
at java.io.FileInputStream.readBytes(Native Method)
at java.io.FileInputStream.read(FileInputStream.java:199)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:256)
at java.io.BufferedInputStream.read(BufferedInputStream.java:317)
- locked &lt;0x00002b4fc75a5018&gt; (a java.io.BufferedInputStream)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:258)
at java.io.BufferedInputStream.read(BufferedInputStream.java:317)
- locked &lt;0x00002b4fc75a4ce0&gt; (a java.io.BufferedInputStream)
at sun.security.provider.SeedGenerator$URLSeedGenerator.getSeedByte(SeedGenerator.java:453)
at sun.security.provider.SeedGenerator.getSeedBytes(SeedGenerator.java:123)
at sun.security.provider.SeedGenerator.generateSeed(SeedGenerator.java:118)
at sun.security.provider.SecureRandom.engineGenerateSeed(SecureRandom.java:114)
at java.security.SecureRandom.generateSeed(SecureRandom.java:495)
at com.rsa.jsafe.provider.c7.engineGenerateSeed(Unknown Source)
at java.security.SecureRandom.generateSeed(SecureRandom.java:495)
at java.security.SecureRandom.getSeed(SecureRandom.java:482)
at com.rsa.jsafe.crypto.au.g(Unknown Source)
at com.rsa.jsafe.crypto.au.a(Unknown Source)
at com.rsa.jsafe.provider.JSA_FIPS186PRNGXChangeNoticeGeneral.engineNextBytes(Unknown Source)
at java.security.SecureRandom.nextBytes(SecureRandom.java:433)
- locked &lt;0x00002b4fdca32370&gt; (a java.security.SecureRandom)
at java.security.SecureRandom.next(SecureRandom.java:455)
at java.util.Random.nextInt(Random.java:253)
at flex.messaging.util.UUIDUtils.createUUID(UUIDUtils.java:110)
at flex.messaging.util.UUIDUtils.createUUID(UUIDUtils.java:97)
at flex.messaging.log.AbstractTarget.&lt;init&gt;(AbstractTarget.java:52)
at flex.messaging.log.LineFormattedTarget.&lt;init&gt;(LineFormattedTarget.java:79)
at flex.messaging.log.ConsoleTarget.&lt;init&gt;(ConsoleTarget.java:34)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at java.lang.Class.newInstance0(Class.java:355)
at java.lang.Class.newInstance(Class.java:308)
at flex.messaging.config.MessagingConfiguration.createLogger(MessagingConfiguration.java:298)
at flex.messaging.MessageBrokerServlet.init(MessageBrokerServlet.java:114)
at coldfusion.flex.ColdFusionMessageBrokerServlet.init(ColdFusionMessageBrokerServlet.java:24)
at coldfusion.bootstrap.ClassloaderHelper.initServletClass(ClassloaderHelper.java:94)
at coldfusion.bootstrap.BootstrapServlet.init(BootstrapServlet.java:59)
at jrun.servlet.WebApplicationService.loadServlet(WebApplicationService.java:1213)
- locked &lt;0x00002b4fdbc4e5c8&gt; (a java.lang.Object)
at jrun.servlet.WebApplicationService.preloadServlets(WebApplicationService.java:793)
at jrun.servlet.WebApplicationService.postStart(WebApplicationService.java:295)
at jrun.ea.EnterpriseApplication.start(EnterpriseApplication.java:203)
at jrun.deployment.DeployerService.initModules(DeployerService.java:708)
at jrun.deployment.DeployerService.createWatchedDeployment(DeployerService.java:243)
at jrun.deployment.DeployerService.deploy(DeployerService.java:428)
- locked &lt;0x00002b4ed0c3f140&gt; (a java.util.HashMap)
at jrun.deployment.DeployerService.checkWatchedDirectories(DeployerService.java:179)
at jrun.deployment.DeployerService.run(DeployerService.java:889)
- locked &lt;0x00002b4ed0c3f140&gt; (a java.util.HashMap)
at jrunx.scheduler.SchedulerService.invokeRunnable(SchedulerService.java:230)
at jrunx.scheduler.ThreadPool$DownstreamMetrics.invokeRunnable(ThreadPool.java:320)
at jrunx.scheduler.ThreadPool$ThreadThrottle.invokeRunnable(ThreadPool.java:428)
at jrunx.scheduler.ThreadPool$UpstreamMetrics.invokeRunnable(ThreadPool.java:266)
at jrunx.scheduler.WorkerThread.run(WorkerThread.java:66)

Looks like it's stuck trying to read from /dev/random while trying to create a UUID?</code></pre>
<p>The key was that Java was waiting on input to the secure number generator code.  Thanks to Daryl&#8217;s stack trace reading kung fu, I had something to Google.  On Linux, /dev/random is a &#8220;blocking&#8221; number generator meaning if it doesn&#8217;t have enough random data to provide, it will simply wait until it does.   Here&#8217;s some <a href="http://en.wikipedia.org/wiki//dev/random">background on /dev/random</a>.  Keyboard and mouse input as well as disk activity can generate the randomness, or entropy, needed but perhaps not fast enough for particular applications.   A lack of random data would force the JVM and ColdFusion to wait, for eternity if necessary, until chaos caught up with /etc/init.d/coldfusion8multi. </p>
<p>It turns out a lot of applications experience this problem: any that use random number generators.  I found frustrated users of Apache, SSL, Livecycle/Blaze DS and a myriad of other applications as my search terms refined.</p>
<h2>Verify the culprit</h2>
<p>Before you try the changes below, verify that this is indeed your problem.  It&#8217;s easy!  First, start by checking how much entropy you have:</p>
<pre><code>cat /proc/sys/kernel/random/entropy_avail</code></pre>
<p>This kernel facility in /proc has been available since 2.3.16 so it should work on any reasonably recent Linux.  A full pool should be 4096 (check your poolsize config in /proc/sys/kernel/random/poolsize).  On my normal servers, I had values around 3500 but this particular server was 150.  Stop ColdFusion (or Apache or LCDS or whatever app is giving you fits) and run the following command before starting CF again:</p>
<pre><code>watch –interval 0.1 cat /proc/sys/kernel/random/entropy_avail</code></pre>
<p>Now start ColdFusion and what you may see is as it gets to MessageBrokerServlet, the available entropy drops to near-zero, climbs back up to around 50-70, then drops to zero and repeats like a stairmaster until it completes and CF can resume at a normal pace.</p>
<h2>Make random data non-randomly appear</h2>
<p>Now we know roughly what the problem is: there ain&#8217;t enough random data.  How do we make it so ColdFusion and JRun can start up faster?  We need to ensure that there is a constantly available source of entropy so the JVM can seed its secure number generator quickly.</p>
<p>Armed with new search terms for Java&#8217;s SecureRandom, I came across a StackOverflow thread which offered a JVM argument to <a href="http://stackoverflow.com/questions/137212/how-to-solve-performance-problem-with-java-securerandom">switch from the blocking /dev/random</a> to the less-secure-but-non-blocking /dev/urandom:</p>
<pre><code>-Djava.security.egd=file:/dev/./urandom</code></pre>
<p>I appended that onto the end of java.args in /opt/jrun4/bin/jvm.config and the server started up in 12 seconds!  I felt a little bit of hair on my head grow back at that moment.</p>
<h2>Solving for Production</h2>
<p>At this stage I&#8217;ve identified the culprit but I had uneasy feelings about using /dev/urandom in production where evil doers are constantly trying to do evil things to our server, application and users.   We don&#8217;t want an insecure random number generator.</p>
<p>Following the Ubuntu connection from Stack Overflow, this post on <a href="http://whatan00b.com/slow-apache-starts-on-ubuntu">slow Apache starts</a> described the same symptoms and the use of rngd (a random number generator daemon) to populate the entropy pool.   <a href="http://linux.die.net/man/8/rngd">Rngd</a> is included in rng-tools or rng-utils depending on your distro.  On RHEL 5.5, it was already installed under /sbin.</p>
<p>The trick is to feed rngd data from the kinda-insecure /dev/urandom and let it figure out what is secure enough to pass to /dev/random with a FIPS-140 test.  You can run rngd two ways.  If you want to populate /dev/random once, right now, run it in the foreground:</p>
<pre><code>/sbin/rngd -r /dev/urandom -o /dev/random -f -t 5</code></pre>
<p>Ctrl-C out of it after 15 seconds and check entropy_avail &#8211; you should find it&#8217;s up around 4000.  Very nice!  Now, how about running it as a daemon so you don&#8217;t have to ever worry if ColdFusion has enough to start quickly?   I added this to my /etc/rc3.d/S99local file so it will automatically start every time the server is started:</p>
<pre><code>
/sbin/rngd -r /dev/urandom -o /dev/random -t 5
 </code></pre>
<p>Fire that up, restart ColdFusion, crack a beer and ride off into the sunset.  Another ridiculous unexpected behavior solved by yours truly.</p>
<p>Interesting side note: Once upon a time, Intel included hardware RNGs in their chip sets that would be exposed as /dev/hw_random.  If you had one of those, you could use it as the parameter for -r.  Unfortunately that practice died out in the 800 series chips and are no longer available.  You can still buy external, cryptographically secure hardware RNGs that can be used for rngd but the above seems to be &#8220;good enough&#8221; according to the tubes.  </p>
<p>If you want to go nuts, you can use a <a href="https://bmearns.net/wwk/view//dev/random">radio tuned to static as an audio input</a> to provide the source data.  Unless your a crypto-nerd, <a href="http://www.groupsrv.com/linux/about157480.html">this thread about RNG sources</a> will make your eyes bleed.</p>
<h2>Resources</h2>
<p><a href="http://egd.sourceforge.net/">EGD</a> &#8211; entropy gathering daemon is a userspace substitute for /dev/random, written in perl.  It could be used with the java.security.egd parameter above in lieu of /dev/random.</p>
<p><a href="http://whatan00b.com/slow-apache-starts-on-ubuntu">http://whatan00b.com/slow-apache-starts-on-ubuntu</a> Llinked to from the StackOverflow thread on the Java SecureRandom slowness, explained entropy and how to monitor it.</p>
<p><a href="http://blog.sbf5.com/?p=50">http://blog.sbf5.com/?p=50</a>  Pointed me in the right direction for using rngd to generate entropy for /dev/random</p>
<p><a href="http://www.vglug.info/how-increase-entropy-pool-2-6-kernel-rhel-fedora-system-without-keyboard-mouse">Increasing entropy pool on RHEL/Fedora without keyboard or mouse</a>  Another source to monitoring entropy and using rngd that turned up in Google as I got more specific with my searches.</p>
<p><a href="http://en.wikipedia.org/wiki/Hardware_random_number_generator">Wikipedia on Hardware RNGs</a> An overview of ways to source random data</p>
<p>Did you know?  /proc/sys/kernel/random/uuid contains a <a href="http://lwn.net/Articles/259121/">fresh Version 4 UUID</a>. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2011/01/11/cold-fusion-slow-start-messagebrokerservlet/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>ColdFusion sessions persisting across server restarts</title>
		<link>http://www.ghidinelli.com/2011/01/05/coldfusion-sessions-restored-on-startup</link>
		<comments>http://www.ghidinelli.com/2011/01/05/coldfusion-sessions-restored-on-startup#comments</comments>
		<pubDate>Wed, 05 Jan 2011 18:59:37 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[jrun]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1199</guid>
		<description><![CDATA[ColdFusion server persisting sessions across restarts?  Here's how to (really) disable it.]]></description>
			<content:encoded><![CDATA[<p>Working on a new server and I am debugging why startup is so slow.  We are using multi-instance on JRun with two instances on a dual quad-core machine.  The startup is taking forever (~300s) and I noticed this in the log file which I had never seen before:</p>
<pre><code>info Recovering 719 session(s)</code></pre>
<p>Turns out there was a corresponding line during shutdown:</p>
<pre><code>info 719 session(s) persisted</code></pre>
<p>Poking around the Internet, how to disable session persistence is <a href="http://www.houseoffusion.com/groups/cf-talk/thread.cfm/threadid:61955">an unanswered question</a>.  With some searching (mostly JRun-focused), you can find how to <a href="http://livedocs.adobe.com/jrun/4/JRun_Administrators_Guide/clustering2.htm">enable it</a> but there is nothing on how to disable what is seemingly default behavior.  This had stumped myself and at least two other experienced admins so I went hunting.</p>
<p>The first bit of useful information I picked up from the JRun docs is that session persistence across restarts is possible and the default behavior is to put it into files stored in the WEB-INF/sessions directory.  Sure enough, I had about 700 files in there (in my case, in /opt/jrun4/servers/INSTANCE1/cfusion.ear/cfusion.war/WEB-INF).  Deleted the contents of that directory so my next restart wouldn&#8217;t take so long.  Progress!</p>
<p>Next was to investigate the WEB-INF/jrun-web.xml file which controls the session persistence config.  The contents (minus comments) are quite short:</p>
<pre><code>&lt;jrun-web-app&gt;
    &lt;enable-jrun-web-services&gt;false&lt;/enable-jrun-web-services&gt;
    &lt;session-config&gt;
      &lt;persistence-config&gt;
        &lt;active&gt;false&lt;/active&gt;
      &lt;/persistence-config&gt;
    &lt;/session-config&gt;
&lt;/jrun-web-app&gt;</code></pre>
<p>Well, that certainly <em>looks</em> right, but why are the sessions still being persisted?  No session replication options were checked in the enterprise manager and there was no JRun or ColdFusion clustering enabled.  What gives?</p>
<p>The answer is the added instances were <em>missing the jrun-web.xml and the default behavior is to persist sessions</em>!  Copying in jrun-web.xml from the default &#8220;cfusion&#8221; instance in /opt/jrun4/servers/cfusion/cfusion-ear/cfusion-war/WEB-INF (and j2ee-web.xml, also missing, for good measure) resolved the problem and eliminated the session persistence and recovery with a restart.</p>
<p>Next quest to solve: Why JRun doesn&#8217;t pass java.ext.dirs from jvm.config to the underly JRE.</p>
<p><strong>Update, literally 3 minutes after posting:</strong>  So I&#8217;m moving on to my next quest, the above-stated java.ext.dirs conundrum and I type into Google: &#8220;jrun 4 java.ext.dirs&#8221; and up pops THIS post in spot #7!  <a href="http://www.ghidinelli.com/wp-content/uploads/2011/01/google-instant-is-instant.png">Google instant MEANS instant!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2011/01/05/coldfusion-sessions-restored-on-startup/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Checking for SSL behind a load balancer</title>
		<link>http://www.ghidinelli.com/2010/12/29/checking-for-ssl-behind-a-load-balancer</link>
		<comments>http://www.ghidinelli.com/2010/12/29/checking-for-ssl-behind-a-load-balancer#comments</comments>
		<pubDate>Wed, 29 Dec 2010 20:48:11 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Web/Internet]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1191</guid>
		<description><![CDATA[Secure or not?  Check if ColdFusion is receiving an encrypted SSL/HTTPS request with or without a load balancer.]]></description>
			<content:encoded><![CDATA[<p>We&#8217;re migrating some servers from our own colo to a managed infrastructure and one change we&#8217;re dealing with is the switch from passing through SSL to the web server vs. terminating it at an F5 Load Balancer.  Many load balancers offer this capability and while the parameter below is F5-specific, this approach will work for most makes and models.  In this setup, all connections, including those originally secured by SSL, reach the web server as plain HTTP.  The advantage is reduced overhead on the web/application server for more throughput.  </p>
<p>The question becomes, how do you tell if the connection was secure?  For payments or other sensitive data requirements we might want to or need to require SSL.  Typically in a ColdFusion application you would check the CGI variable &#8220;HTTPS&#8221; or &#8220;SERVER_PORT_SECURE&#8221;:</p>
<pre><code>&lt;cfif NOT cgi.server_port_secure&gt;
  // redirect to secure version of the URL
&lt;/cfif&gt;</code></pre>
<p>In the case of the F5 BIG IP, it sets a CGI parameter called &#8220;BIGIPSSL&#8221; that we can check in ColdFusion, so all is not lost:</p>
<pre><code>&lt;cfif NOT cgi.bigipssl&gt;
  // redirect to secure version of the URL
&lt;/cfif&gt;</code></pre>
<p>But there&#8217;s a rub (of course!)  We also have DNS that points to each individual server for debugging purposes and we might want to access them securely.  That means that we&#8217;ll be hitting the sites via SSL directly as well as proxied through the load balancer.  What happens when we want to check a CGI parameter that doesn&#8217;t exist?</p>
<pre><code>&lt;cfif NOT cgi.server_port_secure
       AND cgi.bigipssl NEQ true&gt;
  // redirect to secure version of the URL
&lt;/cfif&gt;</code></pre>
<p>Turn out, nothing!  CF just returns a blank string when you check a CGI parameter that doesn&#8217;t exist so the above code will safely work for all possible scenarios: secure and insecure connections in front of and behind an F5 load balancer. </p>
<h2>Bonus hack</h2>
<p>If you wanted to only rely on one variable, you could add the following line (assuming mod_env is enabled in your Apache setup) to your HTTPS VirtualHost config:</p>
<pre><code>SetEnv bigipssl true</code></pre>
<p>This will cause any SSL connections that bypass the load balancer to also set the bigipssl value which can be checked in the CGI scope.  This technique can be used for any number of helpful host-specific setup values.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2010/12/29/checking-for-ssl-behind-a-load-balancer/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>CFDocument page scaling &amp; blank pages</title>
		<link>http://www.ghidinelli.com/2010/10/06/cfdocument-page-scaling-blank-pages</link>
		<comments>http://www.ghidinelli.com/2010/10/06/cfdocument-page-scaling-blank-pages#comments</comments>
		<pubDate>Wed, 06 Oct 2010 19:52:54 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Web/Internet]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1139</guid>
		<description><![CDATA[CFDocument throws another curveball with inconsistently interpreted right margins and page scaling]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.ghidinelli.com/wp-content/uploads/2010/10/techform.png"><img src="http://www.ghidinelli.com/wp-content/uploads/2010/10/techform-300x180.png" alt="SCCA Tech Form" title="SCCA Tech Form" width="300" height="180" class="alignright" /></a>Four years ago I detailed how to <a href="http://www.ghidinelli.com/2006/08/02/forcing-image-size-in-cfdocument">force image sizes in CFDocument</a> using CSS with dimensions in inches.  That&#8217;s worked well for a very long time but recently we introduced a new PDF report that uses a background image of a form with data overlaid on top.</p>
<p>In my development environment, this report printed as expected but we received reports that in production, there was a blank page inserted between each printed page.  I couldn&#8217;t replicate it locally but I did see it on our live servers.  Same code and same versions of ColdFusion (8.0.1 with chf3) but different results.  It wasn&#8217;t until I put the two Acrobat windows on top of each other and flipped between them that I could see the entire page was being scaled.  In the case of the production server, it was being scaled <em>larger</em> so that it overran the margins and triggered a second, blank page.  Here&#8217;s the code:</p>
<pre><code>&lt;cfdocument pagetype="letter"
                  backgroundvisible="yes"
                  format="#attributes.format#"
                  margintop="0.20"
                  marginright="0"
                  marginbottom="0"
                  marginleft="0.25"
                  orientation="portrait"&gt;</code></pre>
<p>See in this image how the margin has disappeared when CFDocument scaled the page:</p>
<p><a href="http://www.ghidinelli.com/wp-content/uploads/2010/10/rightmargin.png"><img src="http://www.ghidinelli.com/wp-content/uploads/2010/10/rightmargin-300x130.png" alt="Disappearing right margin" title="Disappearing right margin" width="300" height="130" class="aligncenter" /></a></p>
<p>With some trial and error I was able to determine that it was specifically the two fields at the top right of the report, Car Class and Car Number, that were determining whether or not the page was scaled.  By increasing the width of the absolutely-positioned &lt;div&gt; tags used to display that data, I forced CFDocument to believe the content was wide enough and prevent scaling.  In short, I changed the code like so:</p>
<pre><code>Original:
&lt;div class="data" style="top: 0.31in;
                  left: 6.9in;
                  width: 0.85in;"&gt;#vchVehicleNumber#&lt;/div&gt;
Fix:
&lt;div class="data" style="top: 0.32in;
                  left: 7.07in;
                  width: 1in;"&gt;#vchVehicleNumber#&lt;/div&gt;</code></pre>
<p>You can compare how this impacted the rendering in this side-by-side image with the div size made visible with a background color:</p>
<p><a href="http://www.ghidinelli.com/wp-content/uploads/2010/10/comparemargins.png"><img src="http://www.ghidinelli.com/wp-content/uploads/2010/10/comparemargins-300x65.png" alt="Compare Right Margins" title="Compare Right Margins" width="300" height="65" class="aligncenter size-medium wp-image-1140" /></a></p>
<p>Left to right the right margins are captured from: Production server with 1in width and no blank pages, production server with 0.85in width and blank pages, development server with 0.85in width and no blank pages.</p>
<p>No rhyme or reason to this that I&#8217;m aware of but another nail in the coffin for CFDocument.  The underlying icebrowser library may have been the best thing available when CFMX was released but I agree with Jason Delmore that <a href="http://www.cfinsider.com/index.cfm/2009/12/11/10-Things-ColdFusion-10-Really-NEEDS">CFDocument needs an overhaul</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2010/10/06/cfdocument-page-scaling-blank-pages/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Create contacts with the Batchbook API + ColdFusion</title>
		<link>http://www.ghidinelli.com/2010/08/30/create-contacts-batchbook-rest-api-coldfusion</link>
		<comments>http://www.ghidinelli.com/2010/08/30/create-contacts-batchbook-rest-api-coldfusion#comments</comments>
		<pubDate>Tue, 31 Aug 2010 00:47:50 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[My Software]]></category>
		<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[CFHTTP]]></category>
		<category><![CDATA[cloud]]></category>
		<category><![CDATA[REST]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1112</guid>
		<description><![CDATA[Using the Batchbook REST API to create contact records from ColdFusion]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.batchblue.com/images/batchBookLogo.gif" width="286" height="49" class="alignright" />This is going to be mostly code because I don&#8217;t have time to really annotate much.  However, if you&#8217;re an Adobe ColdFusion developer and you also use (or are considering) the very good <a href="http://www.batchblue.com">Batchbook Social CRM</a> then you may also want to use their <a href="http://developer.batchblue.com/">REST API</a> in order to programmatically create or read your contact data.</p>
<p>While Batchbook does have the pretty cool <a href="http://batchblue.com/webforms.html">web forms</a> which can capture contact data from any ole web form, it doesn&#8217;t give you total flexibility with filling in customized data fields.  In our case, we wanted to create companies rather than individuals as part of a sales pipeline so we needed to have more control than the web forms currently allow.</p>
<h2>Start with a contact form</h2>
<p>Here&#8217;s the HTML form that we&#8217;re using &#8211; it still uses the original web form field names so all I&#8217;ve done here is changed the form ACTION to point at my CFM instead of Batchbook:</p>
<pre><code>&lt;form method="post" action="https://ourserver.com/form.cfm"&gt;
&lt;input type="hidden" name="location[address][country]" value="US" /&gt;
&lt;h2&gt;Sign-up Now!&lt;/h2&gt;
&lt;table class="form"&gt;
&lt;tr&gt;&lt;td&gt;&lt;label&gt;Company *&lt;/label&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;input type="text" name="company[name]" size="30" /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;label&gt;Account Type *&lt;/label&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;select name="supertags[sales first contact][plan]"&gt;&lt;option value=""&gt;Select a plan - you can change later&lt;/option&gt;&lt;option value="Plan 1"&gt;Plan Uno&lt;/option&gt;&lt;option value="Plan 2"&gt;Plan Dos&lt;/option&gt;&lt;option value="Plan 3"&gt;Plan Tres&lt;/option&gt;&lt;/select&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;label&gt;First Name *&lt;/label&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;input type="text" name="contact_details[first_name]" size="30" /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;label&gt;Last Name *&lt;/label&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;input type="text" name="contact_details[last_name]" size="30" /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;label&gt;Email *&lt;/label&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;input type="text" name="location[email]" size="30" /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;label&gt;Phone *&lt;/label&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;input type="text" name="location[phone]" size="30" /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;label&gt;Organization Address&lt;/label&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;input type="text" name="location[address][address_1]" size="30" /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;label&gt;Address 2&lt;/label&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;input type="text" name="location[address][address_2]" size="30" /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;label&gt;City, State Zip&lt;/label&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;input type="text" name="location[address][city]" size="15" /&gt;, &lt;input type="text" name="location[address][state]" size="4" /&gt; &lt;input type="text" name="location[address][zip_code]" size="10" /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;label&gt;Company URL&lt;/label&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;input type="text" name="location[website]" size="40" /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;label&gt;Do you have an existing service?  If so, which:&lt;/label&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;input type="text" name="supertags[sales first contact][existing_service]" size="40" /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;label&gt;Date of next event:&lt;/label&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;input type="text" name="supertags[sales first contact][date_of_first_event]" size="15" /&gt;&lt;br /&gt;&lt;small&gt;Format date like mm/dd/yyyy&lt;/small&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;label&gt;Questions/Comments&lt;/label&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;textarea name="supertags[sales first contact][customer_comments]" rows="10" cols="50"&gt;&lt;/textarea&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr class="submit"&gt;&lt;td&gt;&lt;input class="button" type="submit" value="Request Account" /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/form&gt;</code></pre>
<p>It&#8217;s the same contact form you&#8217;ve whipped up 100 times before.  If you&#8217;re using the built in web forms, the field names must match what is above.  If I was writing my form handler from scratch I would have selected more normalized names.  </p>
<p>Note that we a hidden field at the beginning &#8211; not all of the data must be user editable.  Of course, I could also just set it in my form handler.  The country value is a holdover from the original web form.</p>
<h2>Process those fields</h2>
<p>Our next step is to process that form submission with ColdFusion and use the Batchbook API to create my contacts and populate my custom data fields:</p>
<pre><code>&lt; !--- credentials ---&gt;
&lt;cfset variables.api_key = 'YOUR-SECURITY-KEY' /&gt;&lt; !--- get this from "Your Account", right column ---&gt;
&lt;cfset variables.root_uri = 'https://[YOUR HOST].batchbook.com/service' /&gt;

&lt;cfhttp url="#variables.root_uri#/companies.xml" method="post" username="#variables.api_key#" password="x" charset="UTF-8" timeout="30" throwonerror="no"&gt;
	&lt;cfhttpparam name="company[name]" value="#form['company[name]']#" type="formfield" /&gt;
	&lt;cfhttpparam name="company[notes]" value="" type="formfield" /&gt;
&lt;/cfhttp&gt;
&lt; !--- cfdump var="#cfhttp#" ---&gt;

&lt;cfif structKeyExists(cfhttp, "responseheader") AND isStruct(cfhttp.responseheader) AND structKeyExists(cfhttp.responseheader, "location")&gt;

	&lt;cfhttp url="#cfhttp.responseheader.location#" method="get" username="#variables.api_key#" password="x" charset="UTF-8" timeout="30" throwonerror="no"&gt;
	&lt;/cfhttp&gt;
	&lt; !--- cfdump var="#cfhttp#" ---&gt;

	&lt;cfset xmlCompany = xmlParse(cfhttp.fileContent) /&gt;
	&lt;cfset id = xmlCompany.company.id.xmlText /&gt;

	&lt; !--- now add location to company ---&gt;
	&lt;cfhttp url="#variables.root_uri#/companies/#id#/locations.xml" method="post" username="#variables.api_key#" password="x" charset="UTF-8" timeout="30" throwonerror="no"&gt;
		&lt;cfhttpparam name="location[label]" value="work" type="formfield" /&gt;
		&lt;cfhttpparam name="location[email]" value="#form['location[email]']#" type="formfield" /&gt;
		&lt;cfhttpparam name="location[website]" value="#form['location[website]']#" type="formfield" /&gt;
		&lt;cfhttpparam name="location[phone]" value="#form['location[phone]']#" type="formfield" /&gt;
		&lt;cfhttpparam name="location[street_1]" value="#form['location[address][address_1]']#" type="formfield" /&gt;
		&lt;cfhttpparam name="location[street_2]" value="#form['location[address][address_2]']#" type="formfield" /&gt;
		&lt;cfhttpparam name="location[city]" value="#form['location[address][city]']#" type="formfield" /&gt;
		&lt;cfhttpparam name="location[state]" value="#form['location[address][state]']#" type="formfield" /&gt;
		&lt;cfhttpparam name="location[postal_code]" value="#form['location[address][zip_code]']#" type="formfield" /&gt;
		&lt;cfhttpparam name="location[country]" value="#form['location[address][country]']#" type="formfield" /&gt;
	&lt;/cfhttp&gt;
	&lt; !--- cfdump var="#cfhttp#" ---&gt;

	&lt; !--- set default values for sales super tag and capture user-provided information ---&gt;
	&lt;cfset arrSuperTag = arrayNew(1) /&gt;
	&lt;cfset arrayAppend(arrSuperTag, "super_tag[existing_service]=#URLEncodedFormat(form['supertags[sales first contact][existing_service]'])#") /&gt;
	&lt;cfset arrayAppend(arrSuperTag, "super_tag[date_of_first_event]=#URLEncodedFormat(form['supertags[sales first contact][date_of_first_event]'])#") /&gt;
	&lt;cfset arrayAppend(arrSuperTag, "super_tag[customer_comments]=#URLEncodedFormat(form['supertags[sales first contact][customer_comments]'])#") /&gt;
	&lt;cfset arrayAppend(arrSuperTag, "super_tag[plan]=#URLEncodedFormat(form['supertags[sales first contact][plan]'])#") /&gt;
	&lt;cfset arrayAppend(arrSuperTag, "super_tag[requested_demo]=#URLEncodedFormat(form['supertags[sales first contact][requested_demo]'])#") /&gt;
	&lt;cfset arrayAppend(arrSuperTag, "super_tag[active]=true") /&gt;
	&lt;cfset arrayAppend(arrSuperTag, "super_tag[paperwork_sent]=false") /&gt;
	&lt;cfset arrayAppend(arrSuperTag, "super_tag[agreement_back]=false") /&gt;
	&lt;cfset arrayAppend(arrSuperTag, "super_tag[announced_on_facebook]=false") /&gt;
	&lt;cfset arrayAppend(arrSuperTag, "super_tag[buddy_check_complete]=false") /&gt;	

	&lt;cfhttp url="#variables.root_uri#/companies/#id#/super_tags/sales.xml" method="put" username="#variables.api_key#" password="x" charset="UTF-8" timeout="30" throwonerror="no"&gt;
		&lt;cfhttpparam type="header" name="Content-Type" value="application/x-www-form-urlencoded" /&gt;
		&lt;cfhttpparam type="body" value="#arrayToList(arrSuperTag, "&amp;")#" /&gt;
	&lt;/cfhttp&gt;
	&lt; !--- cfdump var="#cfhttp#" ---&gt;

	&lt; !--- create person---&gt;
	&lt;cfhttp url="#variables.root_uri#/people.xml" method="post" username="#variables.api_key#" password="x" charset="UTF-8" timeout="30" throwonerror="no"&gt;
		&lt;cfhttpparam name="person[first_name]" value="#form['contact_details[first_name]']#" type="formfield" /&gt;
		&lt;cfhttpparam name="person[last_name]" value="#form['contact_details[last_name]']#" type="formfield" /&gt;
		&lt;cfhttpparam name="person[company]" value="#form['company[name]']#" type="formfield" /&gt;
	&lt;/cfhttp&gt;
	&lt; !--- cfdump var="#cfhttp#" ---&gt;
&lt;/cfif&gt;</code></pre>
<p>Some notes about the above:</p>
<ul>
<li><strong>What&#8217;s my password?</strong>  Your password is X.  Or Y.  Or Z.  It doesn&#8217;t matter &#8211; Batchbook only authenticates you on your unique key which is sent as the username.  The password can be anything.</li>
<li>If you&#8217;re new to REST APIs, I suggest enabling the CFDUMPs as they will show you how data comes and goes.  Plus, you&#8217;ll see what the response headers look like (hint, they aren&#8217;t all <em>200 OK</em>s).</li>
<li><strong>Associating people with companies</strong> &#8211; there is no official way to do this.  Just make sure the &#8220;company&#8221; value for the person is a string match for the company record and Batchbook will make the magic happen on their end.</li>
<li>There is basically no error checking or exception handling here &#8211; I&#8217;ve got my code wrapped up in some try/catch and I fall back to sending an email to us if all else fails.  <strong>Plan for failure.</strong> At some point the API will be down or the Internet will break and you need to have a contingency plan when dealing with remote third parties.</li>
</ul>
<p>The above code took me a day or two of toying around to get working properly.  While the docs are pretty good, my experience is that API implementations never quite match their documentation.  Getting super tags to work (key to our sales process) took a lot of fooling around plus some assistance from the very helpful Eric Krause at Batchbook.</p>
<p>Next post will be how we&#8217;re integrating the results of this sales pipeline with <a href="http://www.emailcenterpro.com">Email Center Pro</a> to dynamically generate and send out contracts in preparation for our sales cycle this winter.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2010/08/30/create-contacts-batchbook-rest-api-coldfusion/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bounce Detector r18 Released</title>
		<link>http://www.ghidinelli.com/2010/08/05/bounce-detector-r18-released</link>
		<comments>http://www.ghidinelli.com/2010/08/05/bounce-detector-r18-released#comments</comments>
		<pubDate>Fri, 06 Aug 2010 04:56:43 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[My Software]]></category>
		<category><![CDATA[Web/Internet]]></category>
		<category><![CDATA[bouncedetector]]></category>
		<category><![CDATA[opensource]]></category>

		<guid isPermaLink="false">http://www.ghidinelli.com/?p=1079</guid>
		<description><![CDATA[New release of Bounce Detector - returned email detection software for ColdFusion]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.ghidinelli.com/wp-content/uploads/2010/08/2657896516_df3d23939c_m.jpg" alt="Got Email Bounces?  Kill it with Bounce Detector.  Image courtesy of SomewhatFrank: http://www.flickr.com/photos/somewhatfrank/" title="Got Email Bounces?  Kill it with Bounce Detector.  Image courtesy of SomewhatFrank: http://www.flickr.com/photos/somewhatfrank/" width="135" height="195" class="alignright" />Catching up on our unmatched nightly bounces, I released an updated version of my <a href="http://bouncedetector.riaforge.org">Bounce Detector</a> CFC on riaforge tonight.  Bounce Detector looks at returned email bodies and uses a lengthy signature list to identify the cause of the bounce.  Switching to an SVN commit release numbering system, tonight&#8217;s r18 includes a few important updates:</p>
<ol>
<li>New limited support for autoresponders and OOO messages which return a code &#8220;5&#8243;</li>
<li>Added new temporary, permanent and spam bounce signatures</li>
<li>Added new demo that doesn&#8217;t require Coldspring to simplify integration for new users</li>
</ol>
<p>Download it from <a href="http://bouncedetector.riaforge.org">bouncedetector.riaforge.org</a> today and upgrade!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ghidinelli.com/2010/08/05/bounce-detector-r18-released/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

