Testing IE6 and IE7 using VirtualBox on Windows

Testing various IE version as always been a chore. Back in the days, I managed to install both IE7 and use a standalone IE6 version.

Then, I discovered IETester that became a lifesaver (my IE6 standalone tends to crash a little too often). It would allow me to test various IE versions side by side.

Unfortunatly, the emulation wasn't perfect, some ajax calls were returning errors and the Flash support wasn't so good.

Additionnaly, there was not way to use the IEDebugBar nor the WebPageTest plugin.

Switching to VM

I finally decided to switch to a Virtual Machine. This would allow me to have an exact snapshot of a given OS/IE version.

VirtualBox is free, so this was my choice. Microsft used to provide free downloads of various flavors of Windows/IE, but it seems to be only working with their proprietary VirtualPC (which only works under Windows 7).

So I took the long road, and manually installed a Windows XP Pro through VirtualBox, using my Windows XP cd.

I used the same serial than my main windows XP. I'm not exactly sure if legally, I'm allowed to do that. How does a VM fits inside the legal statements ? Am I allowed to use one windows activation key inside itself ? Well, I don't really know and don't care that much.

Starting with some housekeeping

I ended up with a nice and clean WinXP install. I had to add an antivirus quick if I wanted to keep it clean. VirtualBox provides a Shared Folder feature to exchange files between the host and the guest.

Start by adding shared folders to your guest (Devices > Shared Folders).

Then install the "Guest Additions", just mount the VBoxGuestAdditions.iso found in your VirtualBox installation directory, using DaemonTools and run the installer.

Don't be as silly as I was. Do not install the Guest Additions on your host, but on your guest. Yeah, seems more logical that way. Just select the options in the Devices menu of your guest window. Reboot after the installation.

You should now be able to access your shared folders by opening the windows Explorer (Windows + E), and going to Network places > All network > VirtualBox Shared Folders

Accessing your websites

I then updated the C:\WINDOWS\system32\drivers\etc\hosts file to bind all requests made to my still-in-development websites to my host.

10.0.2.2        www.pixelastic
10.0.2.2        s1.pixelastic
10.0.2.2        s2.pixelastic
10.0.2.2        s3.pixelastic

You can find your host ip by doing a ipconfig /all in a command prompt.

You then just have to go to http://www.pixelastic/ in IE6 to display the correct website. You can even switch to the Seamless mode to display your IE6 inside your main host.

Running a cakePHP shell script as cronjob on Dreamhost

Dreamhost as a wonderful wiki on how to set cron jobs and cakePHP has a cookbook page on how to do it too, but getting it just right was a little frustrating.

I finally managed to run my shell task as a cronjob, and here is how I did it.

The magic command

First, here is the command I wrote in my Dreamhost panel :

/home/username/domain.com/cake/console/cake -app /home/username/domain.com/app/ shell_name

You have to set the full path to the cake console because it obviously is not in the pre-saved paths on a default Dreamhost install.

You also have to specify the app directory otherwise cake will search your shell in the wrong directories. This is even more important if your shell is located in a plugin directory.

But, this won't work as-is, you'll have to do several other stuff, mostly explained by Miles Johnson, but I'll recap them

Setting the file as executable

You have to set the cake/console/cake file as executable. It is kind of obvious, but you have to do it anyway.

Set the TERM variable

Update you cake/console/cake to replace the first lines with :

LIB=${0/%cake/}
APP='pwd'
TERM=linux
export TERM

If you don't, you'll have notice errors in the resulting log. No big deal, but it is cleaner that way.

Forcing using php5

While in command line, the php command refer to the php4 version. If you need to use php5 (and I guess you should), you would have to manually reference the binary file. Hence, you have to update your cake/console/cake file one more time and change the execline to :

exec /usr/local/php5/bin/php -q ${LIB}cake.php -working "${APP}" "$@"

And it's ok

Your cronjob should not work effortlessly. It took me some long hours to track all this down (along with other issues on my local dev machine that make debugging even more cloudy).

Knowing dev from prod in a cakePHP shell

I wrote a cakePHP shell to synchronize an IMAP mailbox with a mysql table. I wanted to test my shell on local first, then upload it and make a CRON job of it.

Whenever I tried to run the shell from my development environment I was greeted with various "Database table is missing" messages.

After some digging, it occurs that the shell was connecting to my prod database, not the dev one.

The culprit

I wrote a little snippet to automatically switch to the correct database based on the current server name. If it was localhost, I used the $dev credentials, while keeping the $default credentials for other cases (ie. production).

This worked great and I added this little code to my database.php file.

But when running a shell, the env('SERVER_ADDR') was empty, thus my test was always selecting the prod database.

I couldn't find anyway to guess if I was running a shell from prod or dev. I sure had access to a lot of config informations through env and $_SERVER but none seemed to be enough to guess the correct environment.

Solution

I finally decided that the only way was to manually pass a flag to my shell call to tell if it was to use the dev or prod credentials.

I decided that adding a dev arg to the shell call will switch to dev mode, while not adding it will use production mode.

My final shell call looked like :

cake -app "path/to/app" mail_import dev

And I added the following logic in my database switching logic :

// Defining the Environment (prod or dev)
if (defined('CAKEPHP_SHELL')) {
  // Based on the prod/dev flag
  $args = env('argv');
  $environment = 'prod';
  foreach($args as $flag) {
    if ($flag=='dev') {
      $environment = 'dev';
      break;
    }
  }
} else {
  // Based on the server url
  $environment = (env('SERVER_ADDR')=='127.0.0.1') ? 'dev' : 'prod';
}

Note that I checked if the script was accessed through normal server/php delegation or through the CLI using defined('CAKEPHP_SHELL')

Adding extensions to a Windows PHP

My development environment is set up thanks to EasyPHP. I've used this app since the first days that I started to write PHP and it followed me since.

I guess I have a better understanding of what it does under the scenes now and could probably work with a clean and custom Apache/MySQL/PHP install. But I like simplicity.

Anyway, I just wanted to run my imap script from the CLI but ran into "Fatal error : imapopen not defined_".

The same script was perfectly working when accessing it from my browser but failed when launched from the CLI.

That when I remember that I needed to enabled the php_imap.dll extensions in both EasyPHP PHP options (for web access) and C:\windows\php.ini (for cli access)

Migrating mails from GMail to other IMAP server

I have previously blogged on how I migrate mails from one IMAP server to another. Today I had to migrate some mails again.

My client's staff wasn't happy about the GMail webmail we gave them. The lack of a true "Draft" feature (one tha could be used and reused) had them drop a lot of productivity, so we decided to get back to Squirel Mail.

I started by manually recreating all the email adresses on the back-end on the Dreamhost server. Once at least one address is created, Dreamhost automatically creates the matching A and MX records.

I had to update my zone file on my registrar to update the previously MX and A records that were set to point to Google and updated to point to Dreamhost. I have to use an intermediate zone file on my registrar because I'm dealing with a limitation of the .fr TLD here.

Once the zone were updated and changes repercuted accross the network, I connected to the new Squirel mail. My inbox was empty.

So I ran imapsync to copy all mails from the google hosted service to my new server.

The syntax to be used is a little different than the one I mentioned on my previous post, so here it is :

imapsync --host1 imap.gmail.com --ssl1 --authmech1 LOGIN --user1 foo@domain.fr --passfile1 /path/to/pass1 --host2 208.97.*.* --user2 foo@domain.fr --passfile2 /path/to/pass2 --useheader="X-GMail-Received" --useheader 'Message-Id' --noauthmd5

After that, I reloaded my Squirel Mail inbox, and it was populated. I just had to do that for every account.