30 November 2012

Why I'm done with Microsoft Operating Systems

**Warning rant alert**! I'm going to complain in this article, which is something I don't like doing, but I feel I must.

I'll preface this artcile by saying some of Microsoft's stuff does work. Windows Server is a good product, SQL Server is an phenomenal product that does you credit. The Xbox again works beautifully, I just don't understand why you can't apply the same standards to your desktop operating systems.

I've spent years supporting Microsoft's operating systems, literally years, in that time I've built hundreds of computers and I make my living in IT. I first started my love affair with Microsoft in the days of MS-DOS, since then I've used, abused and installed every major operating system they have released. So I flatter myself that I know the market and I've tried, I really have.

..but I'm sick of this crap from Microsoft. Windows 8 is diabolical.

You've had twenty years to get it right and you give me Windows 8. This is embarrassing, if I worked for Microsoft I'd quit out of shame! I'm glad they fired Steven Sinofsky, he deserved it. I haven't been this frustrated since my Scalextric got trodden on!

OK OK I get it, building an operating system is no easy task. There are infinite combinations of processor / motherboard / memory etc and you have to support drivers and every piece of software under the sun. I'll admit, probably not a lot of fun.
Yes, yes I know we're supposed to embrace change and be adaptable. That might apply to a the weather or a restaurant menu but this is an operating system. Do car manufacturers suddenly decide put the gear stick on the roof? My Mum and Dad have to use this thing, are you going to spend weeks on the phone explaining how they can find their files? No you're probably not. If I struggle to use an operating system, how do you expect "average Joe" to use it?

For goodness sake Google have built Android in four years, you've had thirty seven!
Windows XP was good. It worked, it had a few problems but it mostly did what I wanted. Windows Vista is an embarrassing, unstable, disgrace and I think you knew it. Windows 7, credit where it's due is pretty good. It's mostly stable, quite fast and the user interface isn't appalling. So build on that, don't give me something like Windows 8.

The main problem appears to be it's built for touch screens, why in planet earth you made this decision is beyond me. This is a desktop operating system. DESKTOP. As in mouse and keyboard. I don't have a touch screen monitor, neither do I want one. Does anyone really use a touch screen monitor for every day regular use?

OK So here are the main reasons I hate it:
  1. You've replaced the classic well known start button with a gimmicky looking sneeze of applications scattered across the screen. It looks more like a stack of building blocks a three year old put together. You created the start button and surprise, it works, stick with it.
  2. How do I close an app? Seriously?
  3. Internet Explorer is a festering turd of an application that's set back web development decades. This aside, I've now got two versions? One as an app and one on the desktop? How does that make sense?
  4. IE Tabs, I've been using this thing 3 days and I still can't figure out how to switch tabs? Why is this sort of thing hidden? Tabs were designed for quick switching between pages. You've just taken me back to the dark ages of multiple browsers running.
  5. What the hell is this right hand menu thing? I still haven't found a use for it other than just to hide the shut down button.
  6. My running apps are displayed how? By hovering over the left and then dragging down? Because just showing what I've got open needs to be hard?
  7. People - ok so I like that I can sign in with my "msn messenger / messenger / live messenger / skype" account, cool. Well done, this is a nice feature. The great big "people" app looks like it could be really good. A simple intuitive method of seeing all my friends and getting in touch. If it were implemented right....it's not. All I want to do is see a list of my friends who are online on msn. I want to send IMs to my BFFs about how much this product stinks. Unfortunately this task is almost impossible. I hover over this and drag that, it takes me hours to just get this simple view of who's online.
  8. Stability - This is the big one. After 37 years I expect your operating system to just work. No crashes, no hanging, no embarrassing blue screens of death. I had this brand new totally clean OS running for less than 4 hours and boom. My first total lock up.
    Several hard reboots later I thought I'd apply some windows updates. BOOM, failure two. After 20 minutes waiting windows update announced it had failed to update and it was going to roll everything back....time passes....more time passes. 40 minutes later we're back to square one. FFS.
Well done MS, this stupid product is going back to the store and I'm switching to Ubuntu. After twenty odd years I've given up on you. I'm sorry, I really really really didn't want it to come to this but I've just run out of patience.

22 November 2012

ColdFusion - Find common elements in two lists

I recently stumbled across an interesting programming question, how to find the duplicates in two lists? In this case I had two lists of email addresses and wanted to know which email addresses were in both lists. Sounds simple.

I'm curious to know what is the optimum approach, both in terms of simplicity and in terms of speed.

The first solution (compareLists) is the one I came up with, the second (listCommon) is one I adapted a little from Phillip's Coldfusion Blog.

<cffunction name="compareLists" access="public" returnType="string" output="false">
    <cfargument name="strList1" type="string" required="true" />
    <cfargument name="strList2" type="string" required="true" />

    <cfscript>
        var stuCompare        = {};
        var intCount        = 0;
        var strTempElement    = "";
        
        //loop through second list
        for(intCount=1; intCount LTE listLen(arguments.strList2); intCount++){
            strTempElement    = listGetAt(arguments.strList2,intCount);
            if(listContainsNoCase(arguments.strList1,strTempElement)){
                //Add key to struct
                stuCompare[strTempElement]    = "";
            }
        }
    
        return structKeyList(stuCompare);
    </cfscript>
</cffunction>

<cffunction name="listCommon" access="public" output="false" returnType="string">
    <cfargument name="strList1" type="string" required="true" />
    <cfargument name="strList2" type="string" required="true" />
     
    <cfset var arrList1 = ListToArray(arguments.strList1) />
    <cfset var arrList2 = ListToArray(arguments.strList2) />
     
    <cfset arrList1.retainAll(arrList2) />
     
    <!--- Return in list format --->
    <cfreturn ArrayToList(arrList1) />
</cffunction>

I was a little surprised you could use a java function like retainAll quite so nativity, but other than that it's fairly self explanatory.
So to time the methods, I took a leaf out of Ben Nadel's book and used getTickCount() to count the processing of 10,000 iterations of the above functions with two small lists.

Function Name Time (in milliseconds)
compareLists 849
listCommon 611
compareLists 352
listCommon 182
compareLists 232
listCommon 234
compareLists 208
listCommon 151
compareLists 80
listCommon 104

So as you can see, the listCommon method is much quicker. However it seems after the first few runs, caching kicks in and from then on the compareLists method remains very fast. I don't really want to get into caching, I'd rather focus on the differences between the two methods. Does anyone have any suggestions or input? Anyone got any examples of how they'd do this kind of thing in Java or possibly even something lower level?

25 October 2012

Hamlet’s Monkey - Code for fun :)

Hamlet’s Monkey

We’ve all heard the jokes before that a monkey could do that job, or a monkey could type better than you. You may have even heard of the Infinite Monkey Theorem, well its something that made me laugh and an interesting programmatic problem:

http://en.wikipedia.org/wiki/Infinite_monkey_theorem

Given infinite time, could a monkey actually type out the works of William Shakespeare? Well I decided the complete works was a bit hard on our poor monkey. Lets start with just Hamlet!

A friend at work and I got to talking, how would we approach this programmatically? How would the monkey actually get on?
So it occurred to me there are two way of approaching this, the easy way and the hard way.

A few notes

  • My random character generator just generates A-Z
  • Case is just not fair, so I’ve made all strings lowercase
  • I’ve removed all punctuation

Green Light

I called it this because as soon as the monkey guesses a letter correctly, he gets a green light and moves onto the next letter. The correct letter is “banked” and he never has to start over. The hard bit here was really only how to progress, should we be removing the last letter added or just moving on?

Pastebin
<!--- Static Variables --->
<cfset variables.lstAlphabet         = "ABCDEFGHIJKLMNOPQRSTUVWXYZ">
<cfset variables.intNumLoops        = 100>
<cfset variables.Shakespeare        = "All your base are belong to me">

<cffunction name="generateRandomLetter" access="public" returntype="string" output="false">
    <cfset var strLowerCaseAlpha = "abcdefghijklmnopqrstuvwxyz">
    <cfreturn Mid(strLowerCaseAlpha,RandRange( 1, Len( strLowerCaseAlpha ) ),1)>
</cffunction>

<cfscript>
    variables.intCount                 = 0;
    variables.bProgress                = true;
    variables.strSubString            = "";
    variables.strShakespeare        = lcase(variables.Shakespeare.replaceAll("[^a-zA-Z]", "")); //Shakespeare without spaces etc
    variables.stuJson                = {};
    variables.strMonkeyString        = "";

    while (variables.intCount < variables.intNumLoops) {
        variables.intCount++;
        
        if(variables.bProgress EQ true){
            //we're adding a new letter
            variables.strMonkeyString    =    variables.strMonkeyString & generateRandomLetter();
        }else if(len(variables.strMonkeyString) EQ 1){
            //monkey string is just 1 char, just re-guess
            variables.strMonkeyString    =    generateRandomLetter();
        }else{
            //we're re-guessing the last letter, so we need to remove it, then add a new one.
            variables.strMonkeyString    =    left(variables.strMonkeyString,len(variables.strMonkeyString)-1) & generateRandomLetter();
        }
        
        //what we're expecting so far
        variables.strSubString    =    left(variables.strShakespeare,len(variables.strMonkeyString));

        //Did monkey do it?
        if(variables.strMonkeyString EQ variables.strSubString){
            if(variables.strMonkeyString EQ variables.strShakespeare){
                //100%
                customOutput("**WINNER**: " & variables.strMonkeyString);
                break;
            }else{
                //Good so far, progress to next letter
                variables.bProgress    =    true;
            }
        }else{
            variables.bProgress    =    false;
        }
    }
    
    writeoutput(variables.intCount);
    writeoutput("<br />");
    writeoutput(left(variables.strMonkeyString,len(variables.strMonkeyString)-1));
</cfscript>

Red Light

This is the hard way, the monkey has to get every letter of Hamlet correct and sequentially. If he makes a mistake, he starts from the beginning. I think this is the way the theorem is intended, but it probably won’t result in much success for the poor monkey! The code is actually pretty simple.

Pastebin
<!--- Static Variables --->
<cfset variables.lstAlphabet         = "ABCDEFGHIJKLMNOPQRSTUVWXYZ">
<cfset variables.intNumLoops        = 500>
<cfset variables.Shakespeare        = "All your base are belong to me">

<cffunction name="generateRandomLetter" access="public" returntype="string" output="false">
    <cfset var strLowerCaseAlpha = "abcdefghijklmnopqrstuvwxyz">
    <cfreturn Mid(strLowerCaseAlpha,RandRange( 1, Len( strLowerCaseAlpha ) ),1)>
</cffunction>

<cfscript>
    variables.intCount                 = 0;
    variables.strSubString            = "";
    variables.strShakespeare        = lcase(variables.Shakespeare.replaceAll("[^a-zA-Z]", "")); //Shakespeare without spaces etc
    variables.strMonkeyString        = "";
    variables.strBestSoFar            = "";
    
    while (variables.intCount LT variables.intNumLoops) {
        variables.intCount++;
        
        //generate the random guess, one keystroke at a time
        variables.strMonkeyString    = variables.strMonkeyString & generateRandomLetter();
        
        variables.strSubString        = left(variables.strShakespeare,len(variables.strMonkeyString));
        
        //check if we have a match
        if(variables.strMonkeyString EQ variables.strSubString){
            if(len(variables.strSubString) GT len(variables.strBestSoFar)){
                variables.strBestSoFar    =    variables.strSubString;
            }
        }else{
            variables.strMonkeyString    = "";
        }
    }
    
    writeoutput(variables.intCount);
    writeoutput("<br />");
    writeoutput(variables.strBestSoFar);
</cfscript>

Critisicm, comments and feedback welcome, but just a bit of fun.

19 July 2012

Connect Amazon EC2 Instance to RDS DB

This cost me some time and by the looks of some Google searches it cost a few other people time too.

You need to first click on DB Security Groups and add the Elastic IP of your EC2 instance as an CIDR. The important bit that I missed is you also need to add the EC2 Security Group that your EC2 instance is configured with.

This guy figured it out:
http://chris-allen-lane.com/2011/07/amazon-ec2-instance-cannot-connect-to-amazon-rds-database-server/

17 July 2012

Dropbox integration with EC2 Linux instance

So Dropbox has a great linux command line tool which comes in very useful for copying files to your Amazon linux EC2 instance, without having to open up FTP or copying each file by hand. It took me ages figuring out how to set this up, but it saves a lot of time.

First we download dropbox and unzip it:
$ wget -O dropbox.tar.gz "http://www.dropbox.com/download/?plat=lnx.x86"
$ tar -xvzf dropbox.tar.gz
Run it:
$ ~/.dropbox-dist/dropboxd &

..and you should see a message like this:
"This client is not linked to any account... Please visit https://www.dropbox.com/cli_link?host_id=XXXXX to link this machine."
Copy/paste that URL into a Web browser on your local machine; log into dropbox; and voila! The directory ~/Dropbox will be linked into your home directory! The repeating message on your console should then stop. If it doesn't press Ctrl+C.

You should now see a new folder called "Dropbox" sync'd with your dropbox account.

Now we need a package called dropbox.py, this is the dropbox command line tool. Very useful, if a little tricky to use sometimes.

$ wget -O ~/dropbox.py "http://www.dropbox.com/download?dl=packages/dropbox.py"

First there's a few folders we don't want sync'd so we add them to the exclude list.

$ python dropbox.py exclude add ~/Dropbox/Public   
Excluded: 
Dropbox/public
$ python dropbox.py exclude add ~/Dropbox/Photos 
Excluded: 
Dropbox/photos

Now we're going to add a symbolic link. This links our dropbox folder to our web root.

$ python dropbox.py dropbox stop                   
Dropbox daemon stopped.
$ sudo mv ~/Dropbox /opt/railo/tomcat/webapps
$ ln -s /opt/railo/tomcat/webapps/Dropbox ~/
$ python dropbox.py dropbox start
Starting Dropbox...Done!

13 July 2012

13 May 2012

ColdFusion Railo deployment with Jelastic

I thought I'd try one of the cloud java hosting platforms out there and I must say I'm delighted I did. I wanted to start up a Jelastic instance and throw Railo on it and see how it worked out.

First up sign in is super simple, just your email and thats all you need. The user interface is clean, powerful and incredibly simple. With simple drop downs to create your environment and configure the number of instances etc that you need. In just a few minutes you can be up and running.
So i chose Tomcat 6. I did initally try Tomcat 7 but apparently they have a few problems with 7 at the moment. Not to worry 6 is fine. Deploy your environment and then wait for it to be deployed. This takes just a minute or so while they build your instance.

Then down at the bottom you'll see the deployment manager tab, under that you should see upload. You'll need to upload your Railo.war you can upload one you've downloaded, or I believe, upload direct from www.getrailo.org:

Once you've uploaded the .war file, you need to deploy it. Simple, still in the deployment manager tab, click on the box dropdown and click deploy. It'll ask you to confirm "ROOT" as the context, but root is fine. Once this is done you should be able to click the "launch in browser" button and see the railo admin show.

That's it, you're basically done. I expect you want your own application to run, but that's just as easy. If you click on the spanner / config option next to Tomcat 6 a settings tab will open and you can tweak the tomcat settings. Expand webapps and root. This is your application home, you can delete everything in there except for the WEB-INF folder. Then upload your cfm files and you're done!

I think this is a brilliant hosting environment and so brethlessly simple I'm very impressed.

07 May 2012

Setting up a custom domain for your Google App Engine (GAE) app

Setting up a Google App Engine application with a custom domain is a pain in the ass. Its overly complicated and takes much too long. Still, i did it and made it work, so I figured I’d write it down.

  1. Sign into GAE and in the list of my applications, click on your application. You should see the GAE dashboard. Somewhere down the list on the left you should see Application Settings. Click on that. Scroll way down and somewhere under “Domain Setup” you’ll see a button “Add Domain”. Now open a new window or something because we’ll need to come back to this tab later. This is where you’ll need to signup for Google Apps.

  2. Google Apps. I’m not 100% sure exactly how to define Google Apps, but I think it’s best described as a host of business services all under one roof. It’s basically a central place for businesses to utilise online tools to work and collaborate. My words, not Googles! Anyway, you need an account to make this work, it is free so go ahead and sign up and answer the endless questions. Get everything sorted and when its all up and running you can move on to adding the domain you bought to your Google Apps account.

  3. Register your domain. Next you need to add your domain to Google Apps, this means telling Google about the domain that you’ve already registered and proving you own it. Google is nice here, they have a few methods of doing this. The one I used is for Google to ask you to copy a verification code of sorts and add it to a special txt key on your domain. If you’re using goDaddy like I am, this is pretty straight forward. You just need to sign into your goDaddy domain manager and paste in the code. From there Google will verify the domain and add the domain to your account. You can also upload a special Google HTML file to your server, but that’s a lot of work!

  4. Update your DNS. Now we need to change our DNS to point to google. I use goDaddy and this was deceptively simple, basically just login to GoDaddy’s DNS manager and click edit zone for your domain name. You want to change the www attribute for your CNAME record. Change it to ghs.google.com and your done.

  5. Finally you can go back to your original tab from step 1 where you’re still in GAE and add “www” (not inverted commas) as the domain. This should magically link everything up and hey presto your domain should point to your gae app.

This is a much shorter, and helpful description, well done “Mark” who figured it out and helped me a lot: http://stackoverflow.com/questions/817809/how-to-use-google-app-engine-with-my-own-domain-not-subdomain

08 March 2012

Setup an AWS EC2 Instance Running Railo

Setup an AWS EC2 Instance Running Railo

OK so you want to delve deep into cloud computing and start your own instance Amazon Web Services (AWS) Elastic Cloud Compute (EC2) instance? Sadly the “official” Railo AMI seems to have died, so here we’ll be starting our own new one. We’ll be running firmly within the free criteria here and choosing options appropriately, most significantly this means linux! We’ll also be using putty to connect to our instance. For part of this tutorial we’re going to be running alongside the official Amazon starting an instance guide. So I will skimp on the details already covered by Amazon themselves:

http://docs.amazonwebservices.com/AWSEC2/latest/GettingStartedGuide/GetStartedLinux.html

Start-up an Instance

  1. Click the giant “Launch an Instance” button. Select Basic Amazon Linux AMI I choose 32bit because it’s cheaper and (at the moment) free.
  2. Ensure you’ve selected a micro instance.
  3. Skip the instance details section, just accepting the defaults.
  4. Create and download a Key Pair. This is important as it allows us to log onto our instance securely.
  5. Next is the firewall or security groups section. This bit is important as it configures what applications and ports are allowed to access your instance. Create a new security group. You should select SSH and HTTP as a minimum, you can accept the default of 0.0.0.0 but that allows any IP access to these ports. This is fine for HTTP but if your ISP has given you a static IP then put this in for SSH.
  6. Done, your instance will begin powering up. Watch the instances dashboard to see it’s status, eventually the status will flick to green, display “running” and the status checks will show 2/2. Once that happens we’re ready to logon.


Connect to your instance
I’m going to leave this bit a little to Amazon to explain. You’ll need to download and install putty and convert your key pair file (from step 4 above) into a putty private key file. Then grab your amazon public dns value (something like ec2-11-11-111-111.compute-1.amazonaws.com) and connect to it using putty. Don’t forget to enter the username ec2-user.

Get Linux straight & Install Railo

  1. First lets get Linux to update itself:
sudo yum update
  1. Download Railo to the instance:
wget http://www.getrailo.org/down.cfm?item=/railo/remote/download/3.3.1.000/tomcat/linux/railo-3.3.1.000-pl1-linux-installer.run
  1. Assign permissions
sudo chmod 777 railo-3.3.1.000-pl1-linux-installer.run
  1. Run Railo
sudo ./railo-3.3.1.000-pl1-linux-installer.run

Here you’ll want to accept all the defaults except three. First change the default password to something good. Second you should set the port to 80 (not 8888). This will allow normal connections to your server and links into why we had to allow HTTP (port 80) in the EC2 security group. Lastly you should say no to the apache connectors. This sets up railo with tomcat and installs tomcat for you. Of course if you’re more familiar with apache then go with that.

Hit your url
http://ec2-11-11-111-111.compute-1.amazonaws.com
The above link (customized for your public DNS) should show you the default Railo welcome page.

Use putty and VI to change your cfm files
  1. Navigate to the webroot:
cd /opt/railo/tomcat/webapps/ROOT/
  1. Remove all these files
sudo rm -rf *
  1. Create a new index.cfm file
sudo vi index.cfm
VI - Linux editor
  1. In vi to delete the contents of the whole file type
  2. :1,$d
  3. To swap between command and insert modes just press escape

  4. To exit without saving, switch to command mode and press
  5. :q!
  6. To exit and save switch to command mode and press
  7. :x

09 February 2012

ColdFusion and Amazon AWS SES - Simple Email Service

Amazon Web Services (AWS) have a service called Simple Email Service (SES), SES is an excellent e-mail sending service for businesses and developers. It enables developers to quickly and easily send emails without having to go through the pains of setting up an SMTP server or any of that nonsense. It is intended for bulk sending marketing material, but you can also use it in very low volumes and it becomes a great tool.

To demonstrate the service, we’re going to use SES to send an email to ourselves using coldFusion. First and foremost you’ll need to sign up to SES (https://aws.amazon.com/ses/) and verify an email address. SES starts up in “development mode” where you have to verify every email address you want to send mail too. This is a fantastic feature that prevents accidental sending of email and lets you test out the functionality. For the purpose of this example development mode is perfect, so sign up and verify your own email address.

There are quite a few ways to get SES to send an email for you, we’re going to use what I think is the easiest to get started with, a POST request. It’s basically just liked submitting a form, but we’re going to use cfhttp to mimic a form post. First though, there’s a few things we need to setup before we actually do any coding.

1) Security details
Obviously it would be a pretty crummy service if anyone could use your email service to send emails to anyone, spam would run rampant! So there a few security details we need to get from amazon to authenticate each SES request. I won’t go into too much detail but you’ll need an “Access Key ID” and a “Secret Access Key”. You get these from amazon by logging into your aws account and clicking security credentials from the top right drop down. Look at this page for a bit more info:
http://docs.amazonwebservices.com/ses/latest/DeveloperGuide/QueryInterface.Authentication.html#QueryInterface.Authentication.Signatures

2) HMAC - Hash-based Message Authentication Code
http://en.wikipedia.org/wiki/HMAC
To authenticate our message Amazon requires use of a security algorithm called HMAC. The theory being if we (us and Amazon) have a shared private key, we can encrypt a known variable and authenticate ourselves. This is a very very brief introduction if you’ve never come across HMAC. HMAC is a cryptography method of creating a hash using a secret key. Normally a hash takes any value and creates a fixed length string. For example, using the MD5 hash in CF:


 hash(‘all your base are belong to us’)  
would return
847DBEB849668D30722D8A67BCED1C59

With HMAC we introduce a secret key to add an extended element of cryptography and security to the proceedings. Here’s an example:
 

 toString(toBase64(HMAC_SHA1('password','all your base are belong to us')))  
z0A498Rx0aNzXNOwfbjSKkhBdbA=

HMAC can use MD5 or SHA1 and Amazon does support both, but we’re going to use SHA1. Now coldFusion doesn’t offer the HMAC function by default, but that’s not to say we can’t write or borrow our own..



 <cffunction name="HMAC_SHA1" returntype="binary" access="public" output="false" hint="I create an HMAC hashed string from a given message and secret key.">  
      <cfargument name="signKey" type="string" required="true" hint="Secret key with which to encrypt message" />  
      <cfargument name="signMessage" type="string" required="true" hint="Message you want to hash"/>  
      <cfset var jMsg = JavaCast("string",arguments.signMessage).getBytes("iso-8859-1") />  
      <cfset var jKey = JavaCast("string",arguments.signKey).getBytes("iso-8859-1") />  
      <cfset var key = createObject("java","javax.crypto.spec.SecretKeySpec") />  
      <cfset var mac = createObject("java","javax.crypto.Mac") />  
      <cfset key = key.init(jKey,"HmacSHA1") />  
      <cfset mac = mac.getInstance(key.getAlgorithm()) />  
      <cfset mac.init(key) />  
      <cfset mac.update(jMsg) />  
      <cfreturn mac.doFinal() />  
 </cffunction>  

3) Create your Amazon authenticated header

Next we want to create our HMAC hash to pass to Amazon, they require us to encrypt the date and time, so to do so looks a little like this:
 <cfset variables.dteOldDate = now() />  
 <cfset variables.strDateString = "#DateFormat(variables.dteOldDate, 'ddd, dd mmm yyyy')# #timeFormat(variables.dteOldDate,'HH:mm:ss')# GMT" />  
 <!--- encrypt date --->  
 <cfset variables.xxxHMac = toString(toBase64(HMAC_SHA1(“yoursecretaccesskeygoeshere”,variables.strDateString))) />  

Next we need to integrate our hashed date with a header called a X-Amzn-Authorization

 <cfset variables.strAmazonHeader = "AWS3-HTTPS AWSAccessKeyId=#youraccesskeyidgoeshere#, Algorithm=HmacSHA1, Signature=#xxxHMac#" />  

So obviously replace youraccesskeyidgoeshere with the Access Key you got from Amazon.


4) Make the httpd call

That’s the complicated bit done, now all we have to do is make the cfhttpd call.

 <cfhttp url="https://email.us-east-1.amazonaws.com/" method="post" result="result">  
      <cfhttpparam type="header"       name="X-Amzn-Authorization" value="#variables.strAmazonHeader#" />  
      <cfhttpparam type="header"       name="Date" value="#variables.strDateString#" />  
      <cfhttpparam type="formfield"      name="Action" value="SendEmail" />  
      <cfhttpparam type="formfield"      name="Destination.ToAddresses.member.1" value="#yourToEmailAddressGoesHere#" />  
      <cfhttpparam type="formfield"      name="Message.Body.Text.Data" value="#yourEmailContentGoesHere#" />  
      <cfhttpparam type="formfield"      name="Message.Subject.Data" value="#yourEmailSubjectGoesHere#" />  
      <cfhttpparam type="formfield"      name="Source" value="yourFromEmailGoesHere" />  
 </cfhttp>   

That's it, run your code and you should receive an email!

25 January 2012

Assigning your GoDaddy domain name to your Amazon S3 bucket

In the previous post we setup a static website using Amazon Web Services (AWS) S3 bucket storage. Now we’re going to assign the fancy new godaddy domain we just bought to that bucket.
You will need:
    - A GoDaddy Domain
    - An working S3 bucket hosting your website

1. Bucket Name
First and foremost in the last post we named our bucket whatever we want. In this post it’s crucially important we are very careful with what we name our bucket. Amazon gets the bucket name to use from the URL, so you’ll need to match your domain with your bucket name. For example if my domain was www.mygreatwebsite.com you would need to make sure your bucket was called www.mygreatwebsite.com So if you haven’t already done that, go ahead and create a new bucket. You can easily copy and paste your files across from your old bucket. Of course make sure it’s setup as a website all works with the S3 URL.

2. GoDaddy Domain Manager
First we need to open what GoDaddy call the zone manager, there may be better ways to find it but here’s how i get there. Open godaddy.com, hover the mouse over Domains and click “Domain Manager” and login. Hover over Tools and click “DNS Manager”. In the list of your domains click “Edit Zone” next to your domain. You’ll see a bunch of information here, but in short you’re looking under the CNAME heading for www. By default it’s value is @. You need to remove this at symbol and change it to: mygreatwebsite.com.s3-website-eu-west-1.amazonaws.com
Obviously replacing the url with the one for your S3 bucket. Especially the “eu-west” bit and the mygreatwebsite.com with yourgreatwebsite.com and save. This is where the name of your bucket we mentioned in step one becomes so important.

You may want to check you don’t have forwarding turned on. The first time I set this up I just used domain forwarding, which is a neat and easy to use feature, but it just creates an iframe for your site, which won’t help your SEO one little bit. That said, it is a very quick and simple to use feature of GoDaddys. You can turn domain forwarding on and off in the DSN manager using the forward button at the top.

If you own http://mysite.com and http://www.mysite.com then (I believe) you have to either setup two buckets one called mysite.com and one called www.mysite.com or of course you could forward one domain to the other.

That’s it, sit back and be patient, domain changes can take a few hours to process so go buy some donuts and cross your fingers. Hopefully that all worked like a dream.

I owe a lot to this guy, Aaron Blohowiak and his excellent blog entry: http://aaronblohowiak.com/using-amazon-s3-and-cloudfront-to-host-a-stat

and also this this one by Steve Liles:
http://steveliles.github.com/pointing_a_domain_name_to_an_amazon_s3_bucket.html

18 January 2012

Creating an Amazon AWS S3 Static Website

OK this is going to be a fairly short and simple post, but I want to take you through the steps as it will lead nicely into my follow up post. Basically what we’re going to do is use Amazon Web Services (AWS) S3 to host our static website. This is a great feature of AWS whereby their cloud storage services can be used to host a website.

  1. Create a bucket - Sign Up for AWS and goto the console. Then click the S3 tab at the top and click “Create Bucket” underneath the tab. Buckets are amazon’s storage containers, they hold all your files. You’ll want to choose a region closest to where your users will be. Your bucket name has to be unique, and obviously useful to you, in my next post I’ll talk more about how you need to link it to your domain name if you decide to use a custom domain for your bucket.
  1. Upload your files - Click on your bucket and upload your files. CSS, HTML, Images etc. I like to have a separate bucket for my images and or you can use AWS CDN services, but that’s another story.
  1. Setup the bucket as a website - Click on your bucket and click properties. Goto the website tab and click Enabled and set the index document to your index.htm file or whatever. Click save.
  1. Set bucket permissions - Click the permissions tab and click “Add bucket Policy” copy the following text, replacing the name of your bucket with the words mybucketname, then click save.


{
 "Version":"2008-10-17",
 "Statement":[{
    "Sid":"
PublicReadForGetBucketObjects",
       "Effect":"Allow",
      "Principal": {
           "AWS": "*"
        },
     "Action":["s3:GetObject"],
     "Resource":["arn:aws:s3:::mybucketname:/*"
     ]
   }
 ]
}




That’s it, your URL should be something like:
http://mybucketname.s3-website-region.amazonaws.com