Parallels 7 and Mountain Lion – You can’t use this version.

So you upgraded to Mountain Lion and attempted to start your legally purchased copy of Parallels 7 .. but you instead were greated with a lovely message;

You can’t use this version of the application ‘Parallels Desktop’ with this version of OS X. You have Parallels Desktop 7.0

The solution is simple. Download the latest copy of Parallels 7 (you may need to login), which includes an update that works on your beloved Mountain Lion. ALl your virtual machines will remain in tack.

Output Active Directory Lastlogontimestamp in readable format using PowerShell

If, like me, you’re stuck on Windows 2003 AD you are limited as to which cmdlets you can use.

I had a need to find out the last logon time for a bunch of users, so I put together this function (which I shamelessly borrowed from some where on the internet) and decided to post it up here so I could find it again if I needed it.

function Convert-IADSLargeInteger([object]$LargeInteger){ 

	$type = $LargeInteger.GetType() 
	$highPart = $type.InvokeMember("HighPart","GetProperty",$null,$LargeInteger,$null) 
	$lowPart = $type.InvokeMember("LowPart","GetProperty",$null,$LargeInteger,$null) 

	$bytes = [System.BitConverter]::GetBytes($highPart) 
	$tmp = New-Object System.Byte[] 8 
	$highPart = [System.BitConverter]::ToInt64($tmp,0) 
	$bytes = [System.BitConverter]::GetBytes($lowPart) 
	$lowPart = [System.BitConverter]::ToUInt32($bytes,0) 

	$lowPart + $highPart 

$strLDAP = [String] ("LDAP://<ldap path to user>")
$user = [ADSI] $strLDAP
$lastLogon = [DateTime]::FromFileTime([Int64]::Parse($(Convert-IADSLargeInteger $user.lastlogontimestamp.value))) 

write-host ($user.displayname + " last logged on at " + $strLastLogon)

Thanks to whoever wrote the function initially, I have forgotten where I found it.

Nginx custom headers for a Unicorn Rails app

Recently I had to implement an API for a Rails app running on Unicorn being proxied in from Nginx. The problem I had was that my custom header wasn’t being passed through from Nginx.

I had already gone ahead and added to my location directive

proxy_set_header        X_SESSION_KEY $http_x_session_key;

But alas I still had problems. Turns out there’s little thing called “underscores_in_headers” which needs to be turned on for my custom (with underscores) API header to work.

Simply add it to your main nginx.conf after the http {

underscores_in_headers on;

RVM – no such file to load — openssl

Installed ruby 1.9.2 via RVM and getting the following error?

no such file to load -- openssl

Try getting RVM to install the required openssl files. Unfortunately this means removing ruby and installing it again.

rvm pkg install openssl
rvm remove 1.9.2
rvm install 1.9.2 --with-openssl-dir=$HOME/.rvm/usr

But hey, it works.

Running Resque Workers from Upstart + RVM

I recently had the task of getting resque workings to start from Ubuntu’s upstart daemon.

First I created a bash script with the following;


# Load RVM into the shell
source "$HOME/.rvm/scripts/rvm"

# Switch to the right RVM version
rvm 1.9.2

# CD to the rails app
cd /home/myapp/

# Start the resque workers
QUEUE=* /home/myapp/.rvm/gems/ruby-1.9.2-p180/bin/rake resque:work

Put the above contents in a file called in your home directory.
Then give it executable status!

chmod +x

Next, create a file called resque.conf in /etc/init (you’ll need sudo access).

description "my App resque workers
start on (net-device-up and local-filesystems)
stop on runlevel [016]
exec su -c "/home/myapp/" myappuser >> /home/myappuser/resque.log 2>&1

If you run into errors, you can take a peek at /home/myappuser/resque.log to debug the problem.

Good luck! :)

Valum Fileupload +jQuery +csrf

I recently went to implement Valum’s Fileupload script with a Ruby on Rails jQuery project I was working on.

One thing I figured out is that all requests in Rails3 must send also send the X-CSRF-Token. Now normally the rails.js jQuery adapter takes care of this; but Valum’s fileupload script is written in raw javascript :)

The problem I had was a logged in user was automatically logged out whenever they attempted a fileupload (I was using the Devise auth gem).

Find line 1203 and add the following below it.

        var token = $('meta[name="csrf-token"]').attr('content');
        if (token) xhr.setRequestHeader('X-CSRF-Token', token);

This will ensure that fileupload requests also send the csrf token.

SQL – Changing to British Datetime format

Error converting data type varchar to datetime
Are you getting the above error?

Run the following under your app user.

select @@Language, @@Langid

If it says us_english then you’re probably hitting errors when parsing dates as DD/MM/YYYY.
We can change the default language for a particular user. Login to your SQL server as an administrator account and run the following;


Then login with the user “yourapplogin” and run

select @@Language, @@Langid

Hopefully you now see “British” and 23.

Why iPhone and Android phones are unsuitable for the Enterprise world

Every month there seems to be another news article about a large enterprise investigating the possibility of replacing some or all of their Blackberry devices with iPhones or Android devices.

I can almost guarantee that the reason for this is due to senior managers who no longer want to carry around their funky iPhones as well as their boring old Blackberry. These senior managers see their kids using email on their iPhone and chew out their CIO because they can’t see their work email on their own. Unfortunately these senior managers don’t often understand the implications of their request, and this post is an attempt to help educate them.

1. iPhones have useless data encryption
The iPhone 3GS encryption is useless. It can be broken in under 2 minutes using software freely available on the internet.

In contrast, countries like the UAE and India are considering banning Blackberries within their country because even their government’s top science people can’t break the encryption.

For firms like UBS and JP Morgan this is a problem. More and more laws are being created relating to the encryption of customers financial data. For example, in Massachusetts:

The law requires any firm conducting business with state residents to deploy encryption and protect against data leakage. A combination of a person’s name along with their Social Security number, bank account number or credit card number must be encrypted when stored on portable devices, or transmitted wirelessly on public networks, according to the new law.

Encryption of personal information on portable devices carrying identity data like laptops, PDAs and flash drives must also be completed by Jan. 1, according to the Massachusetts Office of Consumer Affairs and Business Regulation, which announced the extension Thursday.

2. Control of device settings using policies
Blackberry’s have the ability to be controlled from a central administration console within the organisation. This means that systems administrators can control everything about a device from a server. This also ensures that all devices have a standard configuration making it far less likely they will stop working and easier (read: cheaper) for the service desk to support.

Enabling the encryption settings mentioned above on a fleet of 22,000 Blackberry’s involves changing one setting on a server. To change this setting on 22,000 iPhones it needs to be done manually on each device. Even then, there is no way to detect if it has actually been configured on each device. Something a financial auditor will pounce on immediately.

An enterprise solution also allows settings such as password unlock requirements to be enforced on the device. This allows administrators to ensure that if a device wiped clean if it is lost, and someone finds it and types the password wrong a few times. If this setting is configured manually on an iPhone or Android, it is often disabled by the user because they find it too cumbersome to type a password in each time they want to make a phone call or read an email.

3. Control of application installation
An enterprise solution, such as Blackberry, allows an administrator to control which applications an end user can install on their devices. This cannot currently be done on an iPhone or Android device. Allowing users to install any application that they choose on a corporate device poses several security problems.

A rogue application may have back doors or security flaws allowing it to steal corporate emails, calendar appointments and send them to the application author. A lot of malicious programmers embed this type of code within games or any other application that may seem initially harmless. This could allow sensitive customer data to fall into the wrong hands.

By only allowing users to install approved and tested applications system administrators can ensure this will not happen. It is amazing how many organisations ban installation of applications on locked down laptop and desktop computers but don’t seem to care what their users install on their mobile devices, which contain the same types of customer information.

At the end of the day, iPhones and Android phones are great and I couldn’t imagine life without one. However these are consumer products and therefore not designed for corporate use. Corporate devices are safe, secure and robust. This basically means that they are boring, which is why people want to stop using them. One day iPhones and Android might evolve to a point when they are suitable for corporate use, but I hope that never happens as it will take the fun, spontaneity and creativity out of them.

Vbscript: Output specific users mailbox sizes under Exchange 2000/2003 to csv

What does it do?
This script generates a CSV file containing a users name, exchange server, mailbox size and total number of items. It queries Active Directory to find out which mailbox server the user lives on, then goes and finds the total size of their mailbox.

How do I use it?
1. Edit the vbs file and change the strLDAPString to suit your environment
2. Provide a list of users (one AD user name per line) in the userlist.txt file
3. Run this script.
4. Open CSV file

'This VBS script queries a list of users and outputs a CSV file containing their mailbox sizes
'It is designed for Exchange 2000/2003. 2007 lets you do the same thing a lot easier with Powershell
'Written 07/10/2010 by Burnsie

'User Configurable settings
'This string contains your base domain LDAP string
strLDAPString =LDAP://dc=YOUR,dc=WINDOWS,dc=DOMAIN,dc=com

'Declare variables
Dim oSession
Dim oInfoStores
Dim oInfoStore
Dim StorageUsed
Dim NumMessages
Dim strProfileInfo
Dim sMsg

'Input and Output files
Set iFSO = CreateObject("Scripting.FilesyStemObject")
Set oFSO = CreateObject("Scripting.FilesyStemObject")

'Input file (Change this if you change the input file name)
Set ifile = iFSO.OpenTextFile("userlist.txt")

'Output file
Set ofile = iFSO.CreateTextFile("Mailbox Details.csv")
ofile.writeline "UserName,FullName,Exchange Server,Storage Used (Bytes),Total Items"

'Set up AD stuff
Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")

'Loop through each user one by one.
Do until ifile.AtEndOfLine
struser = ifile.ReadLine

'Connect to AD and find out where the users mailbox is located. Also grabs a lot of other details.
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection
objCommand.Properties("Page Size") = 1000
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE
'Change this if you change the domain
objCommand.CommandText = _
"SELECT Name, adspath FROM '" & strLDAPString & "' WHERE objectCategory='user' " & "AND sAMAccountName='" & struser & "'"
Set objRecordSet = objCommand.Execute
strpath = objRecordSet.Fields("ADsPath").Value
set objuser = GetObject(strPath)

'If there is no error, then get the details.
If Err.Number = 0 then
strExchangeServer = (Mid(objuser.msExchHomeServerName,(InStrRev(objuser.msExchHomeServerName,"=")+ 1)))
strFullName = objuser.fullname
wscript.echo "Error User Account May Not Exist or Corrupt AD Info For Account"
end if

On Error Resume Next

'Create MAPI Session object.
Set oSession = CreateObject("MAPI.Session")
if Err.Number <> 0 Then
sMsg = "Error creating MAPI.Session."
sMsg = sMsg & "Make sure CDO 1.21 is installed. (Run it on an Exchange server is probably easiest)"
sMsg = sMsg & Err.Number & " " & Err.Description
WScript.Echo sMsg
End If

'Build logon string
strProfileInfo = strExchangeServer & vbLf & strUser

'Log on to mailbox
oSession.Logon , , False, True, , True, strProfileInfo
if Err.Number <> 0 Then
Set oSession = Nothing
End If

'Grab the information stores.
Set oInfoStores = oSession.InfoStores
if Err.Number <> 0 Then

Set oInfoStores = Nothing
Set oSession = Nothing
End If

'Loop through information stores to find the user's mailbox.
For Each oInfoStore In oInfoStores
If InStr(1, oInfoStore.Name, "Mailbox - ", 1) <> 0 Then
StorageUsed = oInfoStore.Fields(&HE080003)
if Err.Number <> 0 Then
sMsg = "Error retrieving PR_MESSAGE_SIZE: "
sMsg = sMsg & Err.Number & " " & Err.Description
WScript.Echo sMsg
WScript.Echo "Server: " & obArgs.Item(0)
WScript.Echo "Mailbox: " & obArgs.Item(1)
Set oInfoStore = Nothing
Set oInfoStores = Nothing
Set oSession = Nothing
End If

'&H33020003 = PR_CONTENT_COUNT
NumMessages = oInfoStore.Fields(&H36020003)

if Err.Number <> 0 Then

sMsg = "Error Retrieving PR_CONTENT_COUNT: "
sMsg = sMsg & Err.Number & " " & Err.Description
Set oInfoStore = Nothing
Set oInfoStores = Nothing
Set oSession = Nothing
End If

strInfoStore = oInfoStore.Name
strStorageUsed = StorageUsed
strTotalItems = NumMessages
End If

' Log off.

' Clean up memory.
Set oInfoStore = Nothing
Set oInfoStores = Nothing
Set oSession = Nothing

'Echo to screen for people who are impatient and like to see what is going on
wscript.echo strUser &","& strFullName &","& strExchangeServer &"," & strStorageUsed &","& strTotalItems

'Write to CSV file
ofile.writeline strUser &","& strFullName &","& strExchangeServer &"," & strStorageUsed &","& strTotalItems


'Clean up memory and variables
set ifile = nothing
set ofile = nothing
set wsfile = nothing

Ruby On Rails AJAX File Upload With Valum

Some sample code I wrote with Andrew Valums’s AJAX uploader script and Ruby On Rails.

Note; I use the prototype javascript library to manipulate the DOM during the onComplete event.

If you need any help getting this to work, simply use the comments below.

  function createUploader(){            
      var uploader = new qq.FileUploader({
          allowedExtensions: ['jpg', 'jpeg', 'png', 'gif'], 
          element: document.getElementById('file-uploader-demo1'),
          action: '/vendor/products/12/upload',
          params: {
                 postid: '9999'
          onComplete: function(id, fileName, responseJSON){
            if (responseJSON.success) {
              $$('.qq-upload-failed-text').first().update('Successfully Uploaded!');
              $$('.qq-upload-failed-text').first().update('Hmm .. upload failed');
  // in your app create uploader as soon as the DOM is ready
  // don't wait for the window to load  
  window.onload = createUploader;

and the ruby on rails code

  def upload
    @filename = params['qqfile']
    newf ='assets/' + @filename, "wb")
    str = 
    render :text => '{success:true}'

Review: Zenithink ZT-180 ePad

The release of the iPad has inspired many copy-cat devices, mostly originating from China. The Zenithink ZT-180 ePad is one of these devices, recently released with Android 2.1 as it’s OS. Being a Google fanboy, the idea of a 1Ghz tablet running Android had me very intruiged and I ordered one for $AU280.

I was excited to receive it and have a tinker. I quickly discovered that it is an absolute piece of garbage and here is why:

1. It does not in fact have a 1Ghz processor as advertisied, it is an ARM11 CPU with a coreclock of 800MHz. The OS is sluggish and it often freezes for 5-10 seconds as it catches up with what I am trying to do.
2. It has a resistive touch screen, not a capacitive one like the iPad. This makes it frustrating to use. It is also not multi touch. (Explained here:
3. There is no access to the Android Market out of the box. You can get access to the market by following a series of unnecessarily complicated steps, which I did and they indeed work a treet. I have a lot of respect for the people who hacked this together. (
4. The wifi antenna is on a PCB, and about the size of a match stick. This causes the wifi to drop out if you walk more than 5m away from your access point.
5. It is called an ePad, with the ‘e’ of their logo directly ripped off from the Microsoft Internet Explorer logo.

But like a puppy with only three legs, it is impossible not to simultaneously love this device. It shows so much potential and I can’t wait for an Android tablet from a decent hardware manufacturer. Even with the above major flaws it is much better than an iPad in the following ways:

1. It has USB ports, allowing you to plug in a wide variety of peripherals such as web cams, USB sticks and 3G modems.
2. It has a MicroSD slot which means you can upgrade the memory whenever you damn please. You can also have more than one storage device for it allowing you to copy movies or music to it without having to bollocks around with itunes or DRM. At the time of writing 16GB and 32GB microSD cards cost $60 and $110 respectively.
3. It plays a wide variety of formats like Divx, and it allegedly does this in 1080p.
4. You can install apps from the internet without having to go through the market place. Just click on a link on the developers website, or even have a friend email the application to you.
5. It multi-tasks quite well.
6. If you use the Google cloud, then this is a perfect companion for checking your emails, calendar or documents when you’re on the couch and can’t be bothered waiting for your laptop to boot.
7. Using apps from the Android store, you can access file shares from other computers in your house using Wifi.

You have to hand it to Apple though, they’ve once again found a piece of technology that has existed for many years and re-invented it as something that excites people. I thank them for re-launching the tablet PC world with the enthusiasm it deserves.

At the end of the day, considering ZT-180 is 1/3rd the price of an iPad, you really can’t expect much. It shows excellent potential and will continue to keep an eye on the Android tablet PC market. There are some exciting projects in the pipeline from people like Samsung and Asus which will be worth a look.

I love living in the future.

Since upgrading the device firmware to the latest version the device is infinitely more stable and the touch screen is somehow a lot more responsive.

WordPress on Mobile (iPhone and Android)

WPTouch is a fantastic plugin for WordPress that allows your users to browse your WordPress Blog on iPhone and Android mobile phones.

If you want to customise the mobile theme, you can modify the PHP theme included in your wp-content/plugins/wptouch/themes folder in the same way as any other theme.

See a customised theme in action by visiting on your Android or iPhone.

« Previous Entries