<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Topper on ColdFusion</title><link>http://www.cftopper.com/</link><description>Topper on all things ColdFusion</description><image><title>Topper on ColdFusion</title><url>http://www.cftopper.com/images/rsslogo.jpg</url><link>http://www.cftopper.com/</link></image><language>en-us</language><ttl>400</ttl><item><title>MySQL - Create a user with access to just one database</title><pubDate>Wed, 08 Apr 2009 11:27:00 GMT</pubDate><description><![CDATA[Quick Tip: I wanted a user with access to just one database so I looked up the docs and ran:<br />
<blockquote>GRANT ALL ON mydatabase.* TO username@&quot;%&quot;<br />
IDENTIFIED BY 'mypassword';<br />
</blockquote><br />
But when I logged in as this user, he could see all the databases. The only way to give the user full access to just one database, so far as I can see is by spelling out what the user can do with<br />
<br />
<blockquote>GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,ALTER ON mydatabase.* TO username@&quot;%&quot;<br />
IDENTIFIED BY 'mypassword';</blockquote>]]></description><link>http://www.cftopper.com/index.cfm?blogpostid=225</link></item><item><title>eTag()</title><pubDate>Wed, 25 Mar 2009 02:14:00 GMT</pubDate><description><![CDATA[eTags are cool - read more about them here - <a href="javascript:void(0);/*1237991241031*/">eTags</a>.<br />
<br />
eTag() is a handy function that you can use to perform client-side programmable caching of your coldfusion pages.<br />
<br />
To get the benefit just call &lt;cfset eTag( &quot;My Page&quot; )&gt; and the next time a user visits this page, they will get a 403 not modified response and execution will stop here.<br />
<br />
Getting advanced... add in the date..<br />
<br />
&lt;cfset eTag( &quot;#pageName#_#lastUpdatedDate#&quot; )&gt;<br />
<br />
... this will regenerate the page IF the lastUpdatedDate has changed.<br />
<br />
We use this extensively in Teamwork Project Manager to reserve dynamic pages almost instantly. It also reduces server load because processing stops.<br />
<br />
Here is the code:<br />
<br />
&lt;!--- eTag will return a 304 not modified response if possible ---&gt;<br />
&lt;cffunction name=&quot;eTag&quot; output=&quot;no&quot;&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;cfargument name=&quot;eTag&quot; type=&quot;string&quot; required=&quot;yes&quot;&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;cfargument name=&quot;useHash&quot; type=&quot;boolean&quot; required=&quot;no&quot; default=&quot;yes&quot;&gt;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &lt;cfif useHash&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;cfset ARGUMENTS.eTag = Hash( ARGUMENTS.eTag )&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/cfif&gt;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &lt;cfheader name=&quot;ETag&quot; value=&quot;&quot;&quot;#ARGUMENTS.eTag#&quot;&quot;&quot;&gt;<br />
<br />
&nbsp;&nbsp;&nbsp; &lt;cfif ( StructKeyExists( CGI, 'HTTP_IF_NONE_MATCH' ) and CGI.HTTP_IF_NONE_MATCH contains ARGUMENTS.eTag )&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;cfcontent reset=&quot;yes&quot;&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;!--- nothing has changed, return nothing ---&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;cfheader statuscode=&quot;304&quot; statustext=&quot;Not Modified&quot;&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;cfabort&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/cfif&gt;<br />
&nbsp;&nbsp;&nbsp; <br />
&lt;/cffunction&gt;]]></description><link>http://www.cftopper.com/index.cfm?blogpostid=224</link></item><item><title>The BP Party</title><pubDate>Fri, 16 Jan 2009 09:13:00 GMT</pubDate><description><![CDATA[THE BP PARTY: In about 7 weeks I am leaving the 20's behind but instead of getting depressed I am taking the opposite tact - Guys, you are all invited to my joint 30th birthday (with my legendary first cousin Brian) on the 21st February at The Maritime Hotel in Bantry.<br />
<br />
<img height="296" width="600" src="http://www.cftopper.com/images/lib/Personal/TheBPParty600x.jpg" alt="The BP Party - your invited!" /><br />
<br />
In case you can't read the writing, download the big version here - <a href="http://www.cftopper.com/contentfiles/BP2.pdf">The BP Party (pdf)</a><br />
<br />
And please spread the word in case I miss anyone.<br />
Details again:<br />
<br />
<blockquote>Date: February 21st 2009<br />
Time: 9pm<br />
Activity: Copious Drinking<br />
Notes: It's fancy dress! You must come dressed up as something beginning with B or P. Prient, Princess, Baker, Pink, Boy George, Barney.. whatever you want..<br />
Accomodation: Lots of B&amp;Bs in town or just contact me directly - My house is crash friendly.<br />
</blockquote>]]></description><link>http://www.cftopper.com/index.cfm?blogpostid=223</link></item><item><title>Form Wizard launched</title><pubDate>Tue, 30 Dec 2008 08:24:00 GMT</pubDate><description><![CDATA[Yesterday I released version 1.1 of <a href="http://www.cftagstore.com/tags/formwizard.cfm">Form Wizard for ColdFusion</a>.<br />
<br />
It will save your hours and hours of tedious work designing forms for your website, and then doing the javascript validation, database store, email notifications etc.<br />
<br />
And the look and feel can be extended to integrate with any website design.<br />
<br />
<br />
<img height="446" width="600" src="http://www.cftopper.com/images/lib/MyWork/twFormWizard.jpg" alt="Form Wizard for ColdFusion" /><br />
<br />
<ul>
    <li>It's only $25 with the promotion code &quot;solo&quot;. Check it out here - <a href="http://www.cftagstore.com/tags/formwizard.cfm">Form Wizard for ColdFusion</a>.</li>
    <li>And try the <a href="http://demos.digital-crew.com/formwizard/">Form Wizard demo</a>.</li>
</ul>
<br />
It's the shanizzle.]]></description><link>http://www.cftopper.com/index.cfm?blogpostid=222</link></item><item><title>Tip: Change the Railo port to port 80</title><pubDate>Thu, 13 Nov 2008 07:57:00 GMT</pubDate><description><![CDATA[We are really getting into Railo these days and enjoying it's blazing speed.<br />
Here's a quick Railo tip..<br />
<br />
To change the default railo server port from the current default of 8600 to port 80:<br />
<br />
<ol>
    <li>Open the C:\Program Files\Railo\conf\resin.conf file.<br />
    (You can use the free Notepad++ for this if you don't have another suitable editor, windows notepad won't do.)</li>
    <li>You'll find &lt;http address=&quot;*&quot; port=&quot;8600&quot;/&gt; around line 62</li>
    <li>Change that to port 80 and restart the server.</li>
</ol>]]></description><link>http://www.cftopper.com/index.cfm?blogpostid=221</link></item><item><title>MySQL Optimisation Tip #2: Store counters in seperate tables</title><pubDate>Sat, 08 Nov 2008 06:38:00 GMT</pubDate><description><![CDATA[<h3>Store counters in seperate tables</h3>
<br />
A common scenario, you have a &quot;pages&quot; table and you want to store a hit counter in that table so you will know which pages are the most popular, you would have something like:<br />
<br />
CREATE TABLE `pages` (<br />
&nbsp; `pageId` int(10) unsigned NOT NULL auto_increment,<br />
&nbsp; `pageName` varchar(255) NOT NULL,<br />
&nbsp; `pageHTML` text NOT NULL,<br />
&nbsp; `pageHitCounter` int(10) unsigned NOT NULL default '0',<br />
&nbsp; PRIMARY KEY&nbsp; (`pageId`)<br />
) ENGINE=InnoDB DEFAULT CHARSET=utf8;<br />
<br />
<br />
Now when you want to update the hit counter you will do something like:<br />
<br />
UPDATES pages set pageHitCounter = pageHitCounter+1 WHERE pageId = 12<br />
<br />
This is fine for normal database schemas... but if you are using the MySQL Query Cache feature (which you should), every time you execute the update you will invalidate the cache making the whole cache feature just about useless.<br />
<br />
Instead what you can do is store the hitCounter for each page in a seperate table.<br />
<br />
So add something like<br />
<br />
CREATE TABLE `pageHitCounter` (<br />
&nbsp; `pageId` int(10) unsigned NOT NULL auto_increment,<br />
&nbsp; `pageHitCounter` int(10) unsigned NOT NULL default '0',<br />
&nbsp; PRIMARY KEY&nbsp; (`pageId`)<br />
) ENGINE=InnoDB DEFAULT CHARSET=utf8;<br />
<br />
and update that instead. That was a fairly contrived example but you get the idea - be careful not to invalidate the cache.]]></description><link>http://www.cftopper.com/index.cfm?blogpostid=220</link></item><item><title>MySQL Optimisation Tip  #1 - Turn on the query cache</title><pubDate>Wed, 05 Nov 2008 12:59:00 GMT</pubDate><description><![CDATA[<h3>The Query Cache</h3>
<br />
If your using MySQL in production you should turn on the query cache - this is off by default ( even if you have installed using the wizard and choosen &quot;dedicated server&quot; ).<br />
<br />
The query cache basically remebers the results of your queries and saves them from being executed twice unnecessarily resulting in huge performance improvements.<br />
<br />
Bare in mind that any inserts or updates will reset the parts of the query cache that relate to the affect tables. Luckily most applications read from the table much more often that they write data into them.<br />
<br />
<h3>How to turn on the Query Cache</h3>
<br />
<ol>
    <li>Open your my.ini (or my.cfg) file in notepad and <strong>set query_cache_type</strong> to 1. There are 3 settings for this: 0 (disable / off), 1 (enable / on) and 2 (on demand).<br />
    Tip: If you can't find this in your config file, so just add it in.<br />
    </li>
    <li>Now you need to tell MySQL how much memory space to use. For this, find (or add) the <strong>query_cache_size</strong> option and set it to something that makes sense. This is a global setting so all sites and applications on the server will share this. You could try 30MB to start with<br />
    <strong>query-cache-size = 20M<br />
    </strong></li>
    <li>You will need to restart MySQL for the caching to begin.<br />
    </li>
</ol>
<br />
<br />
<h3>How to know of the cache is being used</h3>
<br />
After restarting your server, execute the following SQL:<br />
<br />
<blockquote><strong>SHOW STATUS LIKE 'q%';<br />
</strong></blockquote><br />
You will get something like:<br />
<br />
<blockquote>Qcache_free_blocks&nbsp;&nbsp;&nbsp; 1613<br />
Qcache_free_memory&nbsp;&nbsp;&nbsp; 202554688<br />
Qcache_hits&nbsp;&nbsp;&nbsp; 679493<br />
Qcache_inserts&nbsp;&nbsp;&nbsp; 207317<br />
Qcache_lowmem_prunes&nbsp;&nbsp;&nbsp; 0<br />
Qcache_not_cached&nbsp;&nbsp;&nbsp; 4532<br />
Qcache_queries_in_cache&nbsp;&nbsp;&nbsp; 3488<br />
Qcache_total_blocks&nbsp;&nbsp;&nbsp; 8788<br />
</blockquote><br />
The important two are Qcache_queries_in_cache and Qcache_not_cached.<br />
<br />
Qcache_queries_in_cache is the total number og queries that are currently cached in memory.<br />
<br />
Qcache_not_cached is the total number of queries that were executed where MySQL could not use a cached version.<br />
<br />
<h3>References</h3>
<ul>
    <li><a href="javascript:void(0);/*1225891051380*/">http://dev.mysql.com/tech-resources/articles/mysql-query-cache.html</a></li>
    <li><a href="javascript:void(0);/*1225891068958*/">http://dev.mysql.com/doc/refman/5.0/en/query-cache-status-and-maintenance.html</a></li>
</ul>]]></description><link>http://www.cftopper.com/index.cfm?blogpostid=219</link></item><item><title>ColdFusion Optimisation Tip  #1 - Use StructKeyExists instead of isdefined</title><pubDate>Wed, 05 Nov 2008 12:57:00 GMT</pubDate><description><![CDATA[<h3>Use StructKeyExists instead of isdefined</h3>
<br />
Many of ye know this old nugget already so sorry if you know this already but StructKeyExists is much much much faster than isdefined.<br />
<br />
As Simon Whaylay says:<br />
&quot;IsDefined() checks not just if a variable exists, but if it is also syntactically correct. This clearly has runtime implications. That is why, when dealing with structures you should avoid isDefined() in favour of structKeyExists().&quot;<br />
<br />
<h4>The Proof</h4>
<br />
*** Code Here ***<br />
<br />
<h4>The Result</h4>
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IsDefined over 100000 loops: 337ms<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StructKeyExists over 100000 loops: 36ms<br />
<br />
<h4>References</h4>
<br />
<ul>
    <li>http://www.simonwhatley.co.uk/isdefined-vs-structkeyexists</li>
    <li>http://mkruger.cfwebtools.com/index.cfm?mode=alias&amp;alias=isdefined%20vs%20structkeyexists</li>
    <li>http://corfield.org/entry/isDefined_vs_structKeyExists<br />
    </li>
</ul>]]></description><link>http://www.cftopper.com/index.cfm?blogpostid=218</link></item><item><title>Tip: Protect your MySQL from SQL Injection</title><pubDate>Mon, 20 Oct 2008 07:23:00 GMT</pubDate><description><![CDATA[Here's an important tip for everybody using MySQL, you need to set the following option in your my.ini or my.cnf configuration file to prevent SQL injection attacks.<br />
<br />
<blockquote><strong>sql-mode=NO_BACKSLASH_ESCAPES</strong><br />
</blockquote><br />
Before you do this, If you have a simple search on your site and a user inserts<br />
<br />
<blockquote>test\'' OR 1 = 1&nbsp;&nbsp; -- <br />
</blockquote><br />
instead of just<br />
<br />
<blockquote><em>test</em><br />
</blockquote><br />
The \'' will get escaped and your SQL statment will turn from something like:<br />
<br />
<blockquote>WHERE variable LIKE 'test' AND userId = 55;<br />
</blockquote><br />
to something like:<br />
<br />
<blockquote>WHERE variable LIKE 'test' OR 1 = 1 -- AND userId = 55;<br />
</blockquote><br />
Because -- is the start of a a comment in MySQL, the AND userId = 55 bit will be ignored.]]></description><link>http://www.cftopper.com/index.cfm?blogpostid=217</link></item><item><title>Great Review for TeamworkPM</title><pubDate>Tue, 02 Sep 2008 10:47:00 GMT</pubDate><description><![CDATA[I'm really delighted with a <a href="http://onlinebusiness.about.com/od/dailyoperations/fr/teamworkpm.htm">review</a> of our software, <a href="http://www.teamworkpm.net/">Teamwork Project Manager</a> from about.com!]]></description><link>http://www.cftopper.com/index.cfm?blogpostid=216</link></item><item><title>Supporting Multiple Languages</title><pubDate>Mon, 25 Aug 2008 12:39:00 GMT</pubDate><description><![CDATA[<div style="border: 1px solid rgb(221, 221, 221); padding: 6px; float: right; margin-left: 5px;"> <img height="271" width="370" src="http://www.cftopper.com/images/lib/MyWork/translating.jpg" alt="The Translation engine at work" />
<div style="color: rgb(153, 153, 153);"><small>Google API Translation at work</small></div>
</div>
Over the weekend, I wrote a resuable script that converts snippets of English text to 20 other languages using the new <a href="http://code.google.com/apis/ajaxlanguage/" target="_blank">Google translate Ajax API</a> for our <a href="http://www.teamworkpm.net/">Teamwork Project Manager</a> software.<br />
<br />
The script was hacked together quickly and isn't the best most structred code in the world but it works well - it cycles through any strings in the languages table that haven't been converted yet and one by one, converts them to a foreign language. Every time, the script has 20 results, it saves the changes to the database.<br />
<br />
Watching it at work is pretty cool with strings coming back in Arabic, Chinese, Russian etc.<br />
<br />
The strings are stored in the following table MySQL table:<br />
<br />
CREATE TABLE `languagestrings` (<br />
&nbsp; `languageStringId` int(10) unsigned NOT NULL auto_increment,<br />
&nbsp; `languageStringRef` varchar(255) collate utf8_bin NOT NULL,<br />
&nbsp; `languageCode` char(2) character set utf8 NOT NULL,<br />
&nbsp; `languageString` text character set utf8 NOT NULL,<br />
&nbsp; `languageStringUsageCount` int(10) NOT NULL default '0',<br />
&nbsp; PRIMARY KEY&nbsp; (`languageStringId`),<br />
&nbsp; UNIQUE KEY `langStringRef` (`languageStringRef`,`languageCode`)<br />
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;<br />
<br />
And translating the strings is done with the function<br />
translate( ref, english_default, bUpdateNow, language ) which works like so:<br />
<br />
#APPLICATION.teamworkpm.translate( &quot;Your Projects&quot;, &quot;Your Projects&quot;, false, &quot;ES&quot; )# gives &quot;Su Proyectos&quot;.<br />
<br />
Here is the translate function code:<br />
<br />
*** Code here - open article to view ***<br />
<br />
You can see that if the string has already been looked up, the result is returned immediately so that this function is nice and fast.<br />
<br />
If a string doesn't exist for a given language, the default english version is inserted for that language, so that it can be translated later.<br />
<br />
The languageStringUsageCount is updated whenever a string has to be looked up, usually after a server reboot. This will be useful when we want to strip the database of strings that are no longer used in a few months.<br />
<br />
The &quot;update now&quot; argument allows programmers to quickly change the value of english strings directly from the code base during development.<br />
<br />
Hopefully this will help you get your own multi-language systems up and running in ColdFusion.]]></description><link>http://www.cftopper.com/index.cfm?blogpostid=215</link></item><item><title>Backup Software Recommendations</title><pubDate>Thu, 14 Aug 2008 02:52:00 GMT</pubDate><description><![CDATA[I'm going to tell you a secret, but don't tell anyone. Shhhhsss.<br />
About 3 weeks ago on a quiet Tuesday evening I installed the latest version of subversion client <a href="http://tortoisesvn.tigris.org/">TortoiseSVN</a> on one of our website hosting servers in Dublin - I had to reboot the server after the install. This is when it all went wrong...<br />
<br />
I usually wait maybe 2 minutes and the server is backup serving a plethora of client websites and a few small web apps. I waited and waited, repeatedly pinging the server, searching for the first sign of life.<br />
<br />
The server was apparently lifeless. Nada. Nothing. Zip. &quot;No reply from server&quot;...<br />
<br />
We called our hosting company. No I lied ... we didn't. We actually had to use their brutal support chat program and bludgeon English into a pigeon-English speaking Polish guy to request that the server be manually restarted.<br />
<br />
I guessed that I had hit the &quot;shutdown&quot; option instead of the &quot;restart&quot; option and that the technicians would reboot the server in a jiffy and that all would be well.. so I tottered off home.<br />
<br />
Some time later I got a frantic phone call from <a href="http://www.cfdan.com/">Dan</a> informing me that the technicians said the server's hard drive was fried. I turned visibly white and raced back to the office for damage assessment.<br />
<br />
Hours later, the technicians in Dublin had managed to salvage some data by plugging the hard drive into another PC and running a Linux program to do a sector by sector copy where possible. We recovered a lot of data but we had still lost a fair amount. Luckily we had most, but not all, of the website databases backed up to a PC in my office thanks to <a href="http://navicat.com/">Navicat</a> and scheduled tasks.<br />
<br />
The technicians reinstalled a blank Windows 2003 server installation along with the data they managed to recover and Dan and I spent the entire night working feverishly to get all the websites and applications working before our clients got to work and started screaming.<br />
<br />
In the end, the only thing we lost was a very small website. We recovered the page content from Google page cache (isn't Google great) and then gave the client a new, much better website for free to make up for the down time which was 1 day while Dan knocked the new site out.<br />
<br />
And here's my point: disasters will happen, so plan for them.<br />
<br />
<h3> Our New Backup Plan</h3>
<br />
We have since installed <a href="http://www.carbonite.com/">Carbonite Backup</a> on all our servers. Everywhere. It's an absolutely bargain for only $30 a year per server for unlimited data. I thought there must be a catch at first, but no, it's a steal, easy-to-setup and works great.<br />
<br />
That's the files sorted. But what about the databases. Well, we use MySQL on all our servers (if you use anything else you are a stupid Microsoft whore or Oracle slut, sorry) and it's difficult to restore MySQL from just the raw data files. I wanted something that could backup an entire server of MySQL databases automatically including new databases without any additional configuration - the reason we lost that one website was because each website had to be manually configured with our old database backup system and we had missed a few.<br />
<br />
Eventually, after a serous amount of poking about ye olde internet, I found exactly what I was looking for in <a href="http://www.swordsky.com/">Auto Backup for MySQL from Swordsky SoftWare</a>. This is the only program I could find that would run as a service and backup multiple entire servers reliably without needing additional configuration as each new website is added.<br />
<br />
It also has a thoughtful array of options such as automatic removal of old backups after so-many days - something that I used to have to do manually in the past. The SwordSky team, whoever they are, have done a fantastic job here and I encourage you to give it a go. It's a bargain at only $100 or so too.<br />
<br />
So there you have it, two cheap, easy-to-setup products that may one day save your ass.]]></description><link>http://www.cftopper.com/index.cfm?blogpostid=214</link></item><item><title>CF_Desk action=&quot;upgrade&quot;</title><pubDate>Fri, 04 Jul 2008 03:00:00 GMT</pubDate><description><![CDATA[I took my old office desk, ripped the battered leather off the top, chucked a map down, put a pane of toughened glass on top and voila... I have a shiny new desk.<br />
<br />
<img height="297" width="500" src="http://www.cftopper.com/images/lib/MyWork/newDeskCropped.jpg" alt="My new desk" /><br />
<br />
<br />
<img height="375" width="500" src="http://www.cftopper.com/images/lib/MyWork/deskInUse500.jpg" alt="New desk in use" />]]></description><link>http://www.cftopper.com/index.cfm?blogpostid=213</link></item><item><title>Tip: Easily protect your include files</title><pubDate>Wed, 30 Apr 2008 12:38:00 GMT</pubDate><description><![CDATA[Hi All. Sorry I haven't posted in a while, I've been very very busy. Thanks to everyone who has been encouraging me to release our Content Management Software I demonstrated as CFUnited EUrope... soon I promise.<br />
<br />
I just thought I'd share this quick and useful tip:<br />
<br />
Put the following code in all your Application.cfm or Application.cfc fles to automatically protect your include files such like &quot;inc_test.cfm&quot; or &quot;act_deleteUser.cfm&quot; from being called directly.<br />
<br />
UPDATE: This code had a bug which was fixed 30th April 2008<br />
&lt;!--- Any script such as inc_file.cfm or dsp_file.cfm can not be called directly ---&gt;<br />
&lt;cfif mid( ListLast( cgi.script_name, &quot;/&quot; ), 4, 1 ) IS &quot;_&quot;&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;cflocation url=&quot;#APPLICATION.siteURL#&quot; addtoken=&quot;no&quot; /&gt;<br />
&lt;/cfif&gt;<br />
<br />
There is some code in fusebox that prevents calling files other than index.cfm but we have found this too limiting.]]></description><link>http://www.cftopper.com/index.cfm?blogpostid=212</link></item><item><title>CFUnited Europe 2008</title><pubDate>Sun, 16 Mar 2008 12:01:00 GMT</pubDate><description><![CDATA[Mission accomplished - I spoke at CFUnited and survived.<br />
<br />
<a href="http://www.carehart.org/" target="_blank"> Charlie Arehart</a> was nice enough to give me some tips and help me rearrange and improve my Powerpoint presentation for the 2 hours before my talk.<br />
<br />
With minutes to go, I saved my Powerpoint and suspended my laptop, then headed upstairs to the conference room. Now this was my first time speaking in front of more than 6 people and I was extremely nervous.<br />
<br />
I get to the conference room and there are a few people in there already. I head up to the stage, laptop in hand and start setting up... I hit the power button to restore my laptop and.... what the hell... my laptop is rebooting, not restoring.<br />
<br />
OK, not too bad, I'll just have to start ColdFusion, open the presentation and Firefox windows again. My laptop takes an age to start up.<br />
<br />
So I am 3 minutes into the presentation and still waiting for my laptop to warm up. Fortunately there are still a few stragglers filing into the small conference room.<br />
<br />
I double click to open the presentation and wait. And wait. It is taking ages to open. My laptop is being projected onto the 8 foot screen; everybody in the room feels my pain when Powerpoint reports that the file is corrupt and asks if I would like to restore it. Hell yes, restore that thing and fast.<br />
<br />
I start the presentation. My freyed nerves are shattered but the show must go on. I start into the slides and notice something strange on the &quot;About Me&quot; slide. It's not exactly right.<br />
<br />
Then I get to the &quot;Contents&quot; slide and notice that all the changes Charlie helped me make have been lost. Now this is a major curveball - there were entire topics that I had dropped, new sections I added and the whole thing had been rearranged.<br />
<br />
Next disaster. The first section in my presentation should have been the last - it's all about &quot;Source Control&quot;. I ask for a show of hands to make a point - &quot;How many people in this room use source control&quot;. I had expected about 4 hands. I am dismayed to see that of the room of maybe 35 people, only 1 does not have his hand up.<br />
<br />
Anyhow, I persevered and bluffed my way through the rest of the presentation. I'd like to thank everybody who was in the audience for their support. As promised here is the real presentation. Hopefully you all got something from the rest of the presentation. Topics covered:<br />
<ul>
    <li>Quick Tip: AJAX debugging</li>
    <li>Supporting Different Timezones</li>
    <li>Foreign Language Support</li>
    <li>Advanced File Uploading</li>
    <li>Quick Tip: CSS Hacking for IE6</li>
    <li>Working with Multiple Domains</li>
    <li>Database &ldquo;Sharding&rdquo;</li>
    <li>Source Control.</li>
</ul>
<ul>
    <li><a target="_blank" href="http://www.cftopper.com/contentfiles/presentations/CFEurope2008.pptx">Download my presentation - CFEurope 2008.pptx</a></li>
</ul>
I also gave a demo of our content management system, TeamworkCMS, and it's powerful plug-in architecture. As promised this will be released in May 2008. Stayed tuned.<br />
<br />
I learned a lot from this experience and i'm sure that next time, i'll be more prepared and much more confident. It was a great experience all-in-all.
<pre>This is the latest CF9 prototype (codename MoHawk):<br /><img width="500" height="441" src="http://www.cftopper.com/images/lib/MyTrips/CFUnitedEurope2008/CF9_CFUnited_Europe_2008.jpg" alt="CF9 (foot) at CFUnited 2008" /></pre>]]></description><link>http://www.cftopper.com/index.cfm?blogpostid=210</link></item><item><title>I&apos;m speaking at CF-United Europe!</title><pubDate>Tue, 11 Dec 2007 03:01:00 GMT</pubDate><description><![CDATA[I'm going to be speaking at CF-United Europe! It's my first real public-speaking effort so please lend your support.
<p>The topic is:<br />
<strong>How we made it: Teamwork Project Manager - tips for development of highly-scalable web2.0 apps in ColdFusion</strong>.</p>
<span class="q">We developed <a href="http://www.teamworkpm.net/" target="_blank">Teamwork Project Manager</a> </span>over the last 7 months. There aren't many web2.0 CF apps taking on the Ruby crowd these days and I think my speech will be interesting.<br />
<br />
Some items would include:<br />
<br />
<ul>
    <li>Industry Analysis</li>
    <li>Ajax &amp; ColdFusion
    <ul>
        <li>Debugging techniques</li>
    </ul>
    <ul>
        <li>Processing the response</li>
        <li>Using JSON with CF</li>
    </ul>
    </li>
    <li>Handling Multiple Domains with one application</li>
    <li>Advanced file uploading - hundreds of files in one go</li>
    <li>Database design</li>
    <li>Scalability<span class="q"></span></li>
    <li><span class="q">Support</span></li>
    <li><span class="q">Sales &amp; marketing</span></li>
</ul>
<span class="q"><br />
</span>]]></description><link>http://www.cftopper.com/index.cfm?blogpostid=208</link></item><item><title>Another reason to hate IE</title><pubDate>Sun, 25 Nov 2007 02:11:00 GMT</pubDate><description><![CDATA[<div style="border: 1px solid rgb(207, 207, 207); margin: 10px; padding: 10px; background-color: rgb(255, 255, 255); -moz-border-radius-topleft: 5px; -moz-border-radius-topright: 5px; -moz-border-radius-bottomright: 5px; -moz-border-radius-bottomleft: 5px;"> Like we need <a target="_blank" href="http://www.sitepoint.com/blogs/2007/11/22/in-all-fairness-%e2%80%a6-internet-explorer-still-stinks">another reason to hate IE</a>. But here it is.<br />
<br />
I recently implemented rounded edges throughout <a target="_blank" href="http://www.teamworkpm.net/">Teamwork Project Manager</a> and it's a painful process involving nested divs and workarounds for IE6 glitches.<br />
<br />
Today I was procrastinating on <a href="http://www.digg.com/">Digg.com</a> and I stopped to admire the rounded edges on their notification bar. <br />
<br />
<img width="500" height="50" src="http://www.cftopper.com/images/lib/MyWork/rant/diggEdges.jpg" alt="Digg.com - nice rounded edges" /><br />
<br />
I decided to look at the page source to to see their nested divs - are they using 4 nested divs for maximum flexibility bar with rounded edges - 1 div for each corner, or, where they using just 2 divs - one for each side with a height limitation?<br />
<br />
The answer perplexed me - They just had something like &lt;div id=&quot;announce&quot;&gt;&lt;p&gt;Check out...&lt;/p&gt;&lt;/div&gt;.<br />
<br />
I thought &quot;they must be using the &lt;P&gt; tag as a container with a background image&quot; so I download their CSS source code and was confounded to see this:<br />
<br />
<pre>     -moz-border-radius: 1em;<br />     border-radius: 1em; <br /></pre>
<br />
What in the blazes is that? CSS supports rounded edges? My pain was for nought? Could I have just shoved these 2 lines of code in and saved myself hours of work?<br />
<br />
In a perfect world, a world without Internet Explorer, then yes, I could. If you are using FireFox, <strong>this entire post will have rounded edges</strong>. If you are using IE, you'll just see a plain box.<br />
<br />
Here you see the same announcement banner in IE - notice anything different?<br />
<br />
<img width="500" height="50" src="http://www.cftopper.com/images/lib/MyWork/rant/diggEdgesIE.jpg" alt="Digg.com - no rounded edges in IE" /><br />
<br />
Here is another example.<br />
<br />
<img width="423" height="302" src="http://www.cftopper.com/images/lib/MyWork/rant/roundedEdgesComparison.jpg" alt="Rounded edges browser comparison" /> <br />
<div style="border: 1px solid rgb(207, 207, 207); margin: 10px; padding: 10px; background-color: rgb(255, 255, 255); -moz-border-radius-topleft: 5px; -moz-border-radius-topright: 5px; -moz-border-radius-bottomright: 5px; -moz-border-radius-bottomleft: 5px;">I hereby confirm, <strong>IE sucks</strong>.</div>
</div>]]></description><link>http://www.cftopper.com/index.cfm?blogpostid=206</link></item><item><title>Announcing CF Debug Live Link (free tool for CF Developers)</title><pubDate>Wed, 07 Nov 2007 12:45:00 GMT</pubDate><description><![CDATA[Want to save time developing ColdFusion applications? - Just install <strong>CF Debug Live Link</strong>.<br />
<br />
It changes the links in the standard ColdFusion MX 7 debugging output so that when the file names are clicked, they open for editing instantly.<br />
<br />
<img width="540" height="408" src="http://www.cftopper.com/images/lib/MyWork/cfDebugLiveLinks.jpg" alt="CF Debug Live Link - turns file names into clickable links to quickly edit files" /><br />
<br />
It does this by registering a protocol handler with Windows, which in turn calls a small .net application which tells your editor of choice to edit the file.<br />
It's Windows / CFMX7 Only. Tested on both Vista &amp; XP.<br />
<br />
I made a simple installer so you can install this in seconds.<br />
<br />
<ul>
    <li><a href="http://www.cftopper.com/contentfiles/software/CF_Debug_Live_Link_MX7_Setup.zip">Download CF Debug Live Link now (free)  </a></li>
</ul>
<br />
NOTE: By default, CF Debug Live Link is configured for Homesite+ but you can change this to any editor by editing C:\Program Files\CF Debug Live Link\cfdebugfilelink.exe.config]]></description><link>http://www.cftopper.com/index.cfm?blogpostid=204</link></item><item><title>Teamwork Project Manager - The Sstory</title><pubDate>Tue, 30 Oct 2007 09:59:00 GMT</pubDate><description><![CDATA[<strong>We hear a lot about people building web2.0 apps like Twitter using Ruby on rails. Rarely do we hear a mention of ColdFusion being use to build a scalable high-availability ajax enabled application. But at Digital Crew we <a href="http://www.teamworkpm.net/index.cfm/page/blog?rbId=11" target="_blank">recently launched</a><a href="http://www.teamworkpm.net/" target="_blank"> Teamwork Project Manager</a> - an application that as the name suggests, allows organisations to manage their internal and external projects and get productive.<br />
<br />
The whole thing is built on our own 'SiteEngine' framework using ColdFusion and MySQL.<br />
<br />
Here is the story so far.</strong> <br />
<br />
<h2>The Teamwork Project Manager Story</h2>
<div class="copy">
<h4>January 2007</h4>
<br />
Peter Coppinger &amp; Dan Mackey founded their company Digital Crew almost 8 years earlier and have made a living building websites, intranets and custom web-based solutions for clients in Cork, Ireland. At this point their company has a good reputation internationally and they <a target="_blank" href="http://www.cftagstore.com/">sell website components online</a>.<br />
<br />
However they found themselves up to their eyeballs in client projects.<br />
Peter Coppinger says, &quot;<em>Every Monday we held a meeting and discussed the current projects - reassigned tasks and set milestones. We maintained a large whiteboard separated into 5 segments - Active Projects. Upcoming Projects, Sales, Meetings and Billing.<br />
<br />
The whiteboard was neatly organised and gave us a sense that we were organised.... but we weren't.<br />
<br />
The meetings were taking longer and longer. We knew we needed a better system.</em>&quot;.<br />
<br />
<h4>March 2007</h4>
<br />
Peter and Dan spent some time reviewing and using project management software. Many are very expensive and all are overly complex. They wanted something intuitive that doesn't take time to learn and maintain. Something everybody in the company can use - not just the project manager.<br />
<br />
Peter dreams of a software system that would basically manage a company. Call it a project management system, if you will - something extremely easy-to-use and generic enough that it could be used by all sorts of companies. He starts scribbling ideas on paper. In the morning he returns to work and the confused whiteboard overlord.<br />
<br />
<h4>May 2007</h4>
<br />
Peter and Dan discuss the software they want to make almost daily now. And they have a name - Teamwork Project Manager (styled after TeamworkCMS - Digital Crew's bespoke website content management system).<br />
<br />
A credos is set - &quot;Project Management Made Easy!&quot;<br />
<br />
Peter and Dan are too busy with 'real work' to dedicate time to developing the product idea. But fate intercedes and a manager from a multinational client calls Peter to ask if he would have time to do a &quot;simple&quot; project management system. They want something extremely easy-to-use that would list upcoming and late milestones. This is the opportunity Peter has been waiting for. He eagerly tells the client about the software he has been thinking about making for a while and <strong>the client agrees that it is exactly what they need</strong>.<br />
<br />
Peter first reviews other popular project management systems to find out what they are doing right and what they are doing wrong. Although other Project Management solutions exist, they are all too slow, clunky and badly designed. None are what the client wants and Peter has in his head. He makes a list what he likes and dislikes and puts pen to paper designing the software.<br />
<br />
While on holiday to visit his sister in Boston for 3 weeks, Peter shamelessly neglects holidaying to stay up night-and-day working on the 'Project Management System'. Dan, busy with other client work back in Cork, checks in every morning. Screenshots fly back and fourth but Peter is reluctant to show the software running &quot;until it's ready&quot;. Dan, also passionate about the development of their first &quot;real&quot; product, provides a steady steam of encouragement and suggestions.<br />
<br />
<br />
<h4>June 2007</h4>
<br />
The software is installed for the client. Peter nervously waits for their feedback. Will they love it or loath it? Peter checks back an hour later and the client manager has already set-up several projects, added staff, assigned tasks and milestones. Just then, the phone rings. The client manager tells Peter that <strong>this is exactly what he was looking for</strong>. He was able to use it right off-the-bat with no instruction manual. Software, the way it should be.<br />
<br />
<br />
<h4>August 2007</h4>
<br />
Dan works post-haste on TeamworkPM adding his fair share of sleepless-nights to the tally. The software is lovingly sculpted bit-by-bit with sometimes heated 'discussions' over items such as the color of a link. <strong>Their mission is simple - to make the worlds most easy-to-use, fastest and best Project Management System.</strong><br />
<br />
<br />
<h4>September 2007</h4>
<br />
Weeks of preparation. Servers are set-up. Database is optimized. Software continually improved. The promotional website is made. And finally the launched date is set.<br />
<br />
<br />
<h4>October 2007</h4>
<br />
Everything is ready and has been tested a hundred times.<br />
Teamwork Project Manager is launched on October 4th 2007.<br />
<br />
Almost immediately, through their respective software development blogs, curious users start browsing the website and Teamwork Project Manager receives it first sign up within a hour of launch!<br />
<br />
It's only been 3 weeks so far and the feedback has been great. We didn't expect the sales to start until at least the 30-day mark but we things are going better than expected. We believe we have a great product and we are now working hard on the marketing side of things.<br />
Stay tuned to the blog. I look forward to updating this story.<br />
<br />
Thanks for reading the story. So far we have had a great response and we are continually improving the software. We believe that our software lives up to our credos - &quot;Project Management Made Easy&quot;. We want the software to be so easy-to-use, our own computer-shy mothers could use it (and indeed they do).<br />
<br />
We are working extremely hard to deliver more features and continually improve TeamworkPM. Please <a target="_blank" href="http://www.teamworkpm.net/index.cfm/page/pricing">try Teamwork Project Manager for free</a>. 	</div>]]></description><link>http://www.cftopper.com/index.cfm?blogpostid=203</link></item><item><title>Teamwork Project Manager - Password stored securely</title><pubDate>Sun, 07 Oct 2007 05:39:00 GMT</pubDate><description><![CDATA[RE: <a href="http://www.teamworkpm.net" target="_blank">Teamwork Project Manager - Project Management made Easy!</a><br />
<br />
That <a href="http://www.teamworkpm.net/index.cfm/page/blog?rbId=13">feedback feature I added</a> has worked out great so far. We've got some great suggestions and enquiries in.<br />
<br />
One customer used to feedback option to contact us. He had used the option to retrieve a lost password and wondered why the password we emailed him was different to the password he originally provided.<br />
<br />
The answer, I replied, is security.<br />
We do not store your passwords!<br />
<br />
Instead we store a HASH of the passwords.<br />
A HASH is a one-way transform. For example in the database, the password &quot;tulsar256&quot; might have been transformed to a string like &quot;DDC3954CB4BC3AFE4A278BE8D7A1662&quot; using hashing. And there is no way to determine what the original password is from this string.<br />
<br />
<div id="mb_4">So when you login, we convert the password your have entered into another hash and then compare it to the hash we have stored in the database.<br />
<br />
This is all great and gives our customers that extra little piece of mind - knowing that even if we wanted to, we couldn't see what passwords you are using. However we can't just email you with your password now when you forget it - we simply don't know it.&nbsp; Instead we email you a hash of a your password hash. <br />
<br />
So we have absolutely no idea what our customer passwords are (and we shouldn't know!).&nbsp; Many people use the same password on several sites and all IMHO all sites that care about their customers security should use hashing for storing all passwords.<br />
<br />
<a href="http://www.teamworkpm.net" target="_blank">Teamwork Project Manager - Project Management made Easy!</a><br />
<br />
</div>]]></description><link>http://www.cftopper.com/index.cfm?blogpostid=202</link></item></channel></rss>