How To Backup your Data

Last Updated: June 2020

People often don’t backup their computer, usually because they “don’t know how”. So now and then I’ve taken to sharing some advice with my social networks (Anyone on my Facebook who’s not backed probably doesn’t sign in!).

If you want to keep your photos, documents, invoices, scans, videos and all the other stuff you accumulate safe (on either Windows, Mac or Linux), consider yourself informed:

Why Backup?

Sooner or later, your computer will stop working. Often it’s something like the screen or some other part and your data is recoverable, but the Hard Drive is also likely to die. When it does, chances of you getting your photos, documents etc back are slim. Hard Drives usually last anywhere between 1 and 10 years, and will often die without warning.

What is a backup?

A backup is a physically separate second copy of your files, if you only have one copy of a photo it is not backed up – likewise if you have two copies on the same device it’s also not backed up. I recommend you have three copies, because then when one storage device stops working you still have a backup until you can replace it (otherwise you’re left without a backup in the mean time).

Types of Backup

On Site Backups

There are two kinds of backup, On Site and Off Site. Sounds businessy but it’s just as relevant at home. On Site backups are great because they’re fast to backup to and restore from, but if you’ve lost your data to theft or a house fire chances are you’ve lost the on-site backup also.

  • USB Stick – Small and portable, great if you’re travelling.
  • External Hard Drive – You get more space for less money.
  • FreeFileSync is useful for automating these backups.

Off Site Backups

Offsite Backups are somewhere else, probably on the Internet/The Cloud (The Cloud is a marketing term for The Internet, don’t get confused between the two)! Chances are you’ll use one of the many services available for this very purpose, both of those listed below are fully automatic and fast.

Some of these are referral links. My opinion of any service is unaffected by the results of any referral options. – but where available I’ve included them because usually we both get a bonus for using one.

  • Free for up to 2GB (although you can earn more by inviting friends and other things)
  • Install it on more than one machine and you get an on-site backup too (since it syncs your files)
  • Gets quite pricey if you want more than 2GB
  • You have to store your files in your Dropbox folder, which means a slight change to the way you work

  • Very easy to use
  • Also backs up to an external drive
  • Seems to be very reliable
  • Lots of restore options
  • Keeps backups for 60 days
  • Has a business package, so you can use the same at home and work
  • Gets quite expensive after 125GB
  • The interface is quite sluggish

OneDrive (and Microsoft Office 365)

  • If you’re buying Office 365, you get 1TB of OneDrive storage included
  • Online editing
  • Integrates well with Windows and Office
  • If you edit the same file on multiple devices it’s not always 100% clear whether you’re editing the latest version of a file.
  • Microsoft may monitor your files for (potentially) illegal files and may take action (source). Other services might do this too – and just haven’t been caught.

Offsite backups always carry the risk of people snooping on your data, if you’re concerned do some research before uploading anything (but get your On Site backup sorted in the mean time!). prides themselves on being very secure, another popular method is to use Boxcryptor.

What I Do

Here’s what I do:

  • I have everything in a premium Dropbox
  • I adjust my Windows Libraries to include my Dropbox folders, and exclude the default ones.
  • I use Boxcryptor for encrypting sensative details.

Other General Tips

  • I wrote a more complete comparison of Cloud Storage a few years ago. It’s probably out of date now but the though process may be useful.
  • When you download photos from your camera, don’t remove them from the camera before they’ve reached one of your backups. I move them to a “downloaded” folder on the camera storage which I remove periodically.
  • If you have a memory card slot in your laptop, that can work as a fast on-site backup (if your laptop gets stolen so does the on-site backup though, so make sure you have an off-site one too)
  • Your initial off-site backup might take while, several days even. Leave your computer on and connected as much as possible since your files won’t be backed up until it’s complete.
  • You should test your backups to check they work as you think they will, restore your files onto a spare computer or borrow a friends. You can always delete them once you know you’ll be able to do it when you need to!

If you have any other advice or suggestions, feel free to leave them in the comments.


The BRITs 2014

Through John Lewis Saz won tickets to the BRITs! We decided to make a mid-week weekend of it so after a lovely long lie-in on Wednesday we had pancakes for breakfast before heading off to the hotel next to the ExCeL. The journey was uneventful, aside from hopping on the wrong DLR train, and upon arrival we met up with an incredibly friendly John who gave us our tickets and explained how everything was going to work.

After a cup of tea and glamming up we shared a cab to The O2 with some Partners from John Lewis Cambridge. Should have got the train… the Blackwell Tunnel at rush hour? Whoops. None the less, we made it to the venue with plenty of time to have something to eat and a drink or two (three, actually). Saz did an unintentional sneaky by ordering a pint of beer as she handed over her ticket – which said it was only for a bottle. Sami had read the ticket and asked for a bottle. Saz got a pint.

Having seen the Brits on TV and having been to The O2 for gigs before I had some idea of what I might expect, lots of good entertainment with the occasional reminder that this is a live show. As much as Saz appreciated having a toilet break every 15 minutes it’d have been nice to have a song or some entertainment while the rest of the world was watching adverts rather than three minutes of warning us to be back in our seats by the time James Corden was ready to speak again.

The show was great, with appearances from the Artic Monkeys, Bastille, Katy Perry, Prince and the legends of David Bowie (unfortunately just the legend, not the person). There was fire, balloons and glittery things from the sky.

Lovely stuff!

The After Party was a curious affair, mostly inhabited by people excited because they were at The After Party, while the famous people were at the VIP After Party. The music was loud and 70s and with two more free drink tokens we were having a jolly time.

The guy who had been giving out the flashy light accessories by the door had taken a break (or got bored), so Saz jumped in – helpful as ever – and ensured the rest were distributed.

Closing time was 1am, and along with hundreds of other people we wanted to get a cab home. We were a bit peckish so sought out the only burger van for miles, and in great vegan splendour I devoured 4 white baps filled with fried onions, ketchup and mustard. Actually, it could have been worse!

We had plans for the Thursday after, the Wallis Collection, climbing Monument, visiting some markets. In the end we had a late breakfast, then a nap, a coffee in East Westfield before a long relaxed lunch in West Hampstead (The Brocca, not highly recommended I’m afraid!) before meeting up with Emma, Shpend, Carla, Juli, Will and Bes for Yaniv in Ye Olde Swiss Cottage.

All in all, a lovely mid-week weekend away!


HTTPAuth Logout in Chrome, Firefox and IE with jQuery

I’ve recently setup a site which has multiple users and uses HTTP Auth. I wanted to implement a Logout button to allow switching users. Turns out, there’s no easy programmatic way to stop a browser from remembering your username and password.

Being a client feature it must be done in JavaScript, and since I’m using jQuery on the page I’ve utilised that. It should be easy enough to translate this into vanilla JavaScript, feel free to send me another version and I’ll post it alongside.

After much reading I came across this post: which works well in Firefox and Internet Explorer, below is my modified version which also works in Chrome. (I’ve only tested this on the latest versions of these browsers).

I’ve basically added a fallback which should work everywhere, all be it in a not entirely beautiful fashion (it doesn’t work in the background, and forces an authentication popup where you might prefer to redirect to another page).This refreshes the page to request another login, but you could easily adapt it to send the user to a different page.

    $('#user_logout').on('click', function(e){
        // HTTPAuth Logout code based on:
        try {
            // This is for Firefox
                // This can be any path on your same domain which requires HTTPAuth
                url: "/any/path",
                username: 'reset',
                password: 'reset',
                // If the return is 401, refresh the page to request new details.
                statusCode: { 401: function() {
                    document.location = document.location;
        } catch (exception) {
            // Firefox throws an exception since we didn't handle anything but a 401 above
            // This line works only in IE
            if (!document.execCommand("ClearAuthenticationCache")) {
                // exeCommand returns false if it didn't work (which happens in Chrome) so as a last
                // resort refresh the page providing new, invalid details.
                document.location = "http://reset:[email protected]" + document.location.hostname + document.location.pathname;

Creating a Microsoft Office 365 Offline Installer

Update: This post is getting quite old now, and the process may well have changed. Please be sure to check the comments where some helpful people have posted updates, and please also share any tips you come across for future visitors too.

Recently I had to install Office 365 on a dozen machines at a location with 512mb Internet. After the nostalgia faded I wrestled through the directions to obtain an Offline installer. In the hope this will save somebody some head scratching, here are the directions.

This will install Office 365 Pro ready for you to activate it with your Office 365 Organisational Account. It’s been tested with an Office 365 Education A3 license.

1. Download the Office Deployment Tool

Download and run this tool, then give it a folder where you’d like it to extract the files we’re going to need. If you want both 32 and 64 bit versions of Office, you’re going to have to repeat this whole process again. I pointed this tool at a folder called office_installer_32 and then at office_installer_64

You should see a file called setup.exe and one called configuration.xml

Download Here:

2. Edit the XML configuration file

This file tells the tool which versions of the software you’d like to download and install.

In the same directory where you extracted the installer tool, edit the file called “configuration.xml” and fill it with the following, change the OfficeClientEdition value to 32 for a 32 bit  version.

  <Add OfficeClientEdition="64" >
    <Product ID="O365ProPlusRetail">
      <Language ID="en-us" />
  <Updates Enabled="TRUE" />
  <Display Level="None" AcceptEULA="TRUE" />
  <Property Name="AUTOACTIVATE" Value="1" />

This will install Office 365 Pro, automatically activate it (though it’ll still ask for your Office account), not show you the EULA (because it’s quicker to get it installed that way) and enable updates. If you have a file server which you wish to use, consider using the SourcePath parameter under both <add> and <updates>. See the Configuration Reference for more details.

See the XML Configuration Reference for more details:

3. Do the Download

Now open a command prompt in the folder which contains setup.exe and run:

setup.exe /download configuration.xml

This will download all the files required to install that which is specified in the configuration.xml. All in all, it’s about 1.1GB (0.9GB for 32 bit). All the files get put into a folder called ‘Office’ unless you specified ‘sourcePath’.

4. Install It

You install Office running:

setup.exe /configure configuration.xml

in the same was as you downloaded it. To speed this up if you’re running on multiple machines, create a file called setup.bat and fill it with the command above. Now, double clicking this file will install Office. The setup should require no interaction until it’s done and ready to activate.

Optional Extras

If you’re doing this for somebody else, you may want to also visit in their web browser and Always Enable the addon.

When you first use the Office products you will need to activate it by logging in with your username and password.

A note on licences

After you activate your suite with your login, if you delete that user the software will tell you to login to check things are OK. I have not found how you can re-activate with a different login.

Some of the official pages I used


Floating upon an emerald ribbon

The last few days have been a wonderful combination of all my favourite things. I’ve been cruising along the Oxford Canal with the good Saz. We started just south of Northampton and decided to head to Coventry, a short hour by train but a lovely countryside and pub filled three days floating.

Canals and pubs go hand in not least because while motorways and train tracks are built to get you to you destination as fast as possible, canals pass right by all the villages of days gone by. Once upon a time these village were important stop offs, a break from the hours of traveling day after day. In the age of cars and by-passing A-Roads it seems the only people here are locals not used to the fast paced cities and the leisurely boaters enjoying the journey.

Going on holiday is a great way to relax, but hanging out in community cafes and playing cards in enormous pub gardens is a whole new level of taking it easy.





Purim in Panama

This time last year I was living on a boat moored in a teeny village with a fantastic past. Unfortunately, it’s present has little more to offer tourists than great pizza and a place to anchor a boat. It did, however, have a painfully slow connection to Panama City. The village was Portobello, the former gold port of the world, and I was getting out of there for Purim.

One afternoon, while eating a great pizza with a glass of melon juice I noticed a guy wearing a Magen David around his neck. We are taught that there are Jews all over the world, but what does that really mean? And what does it mean to meet another Jew so far from home?

The curiosity of Jews

I’d already spent the last few weeks sailing with my new friend Tom, she and I had marvelled at our shared Jewish knowledge. It wasn’t that here, thousands of miles from home, we both know what a mezuzah is, and no, Rabbi, we didn’t have late night Torah study sessions (although we did do a Shabbat Service and Friday night dinner on board). For us, it was the songs, we knew the same words to the same tunes!

Here in Panama was another opportunity, rather than meeting Jews by chance through other activities, I now felt compelled to introduce myself to him. So I did. “Hey, are you Jewish?” sounds much stranger when you say it out loud but he smiled, said "yes, and we started chatting. He was visiting some family in Portobello, and heading back to Panama City, I was also heading to Panama City to buy some supplies for the boat and he offered me a lift. It’s an hour and a half’s drive during which we discussed Judaism in Panama and in London, and he explained that I’d be quite safe in the dangerous city of Colon because I was too scruffy to look worth robbing. Thanks…. I think!

I asked him about Purim, which was coming up in a few days, it’d be cool to see how they do things here. Without a moment’s hesitation he invited me along to his Synagogue! There are 3 or 4 communities in Panama City, and he was a member of the Progressive community, Kol Shearith Israel.

Purim Arrives!

A week went by, the captain said the weather was clear, we were going to set sail for San Blas on Thursday morning at dawn. I said I’m afraid I cannot come, I’ll be in Panama City for Pruim and can’t be back until the afternoon. I honestly felt like Mordechi, as if the whole of Judaism rested on my being a good Jew this week (which had nothing to do with the huge party Chabad were throwing that night, honest). The captains face wasn’t good, as his [[First Mate]] I helped to run the boat. It was only a small trip and he could manage without me (this captain was so epic he could manage without anyone), but I think he hoped I’d stay on after this last leg – despite knowing I had to get to Guatemala. He agreed to leave Friday morning (weather permitting) so I could make it back in time.

Wednesday afternoon I hopped on one of the amazing pimped out Panama buses, music blaring and neon lights streaking all the way to Colon where I changed for a comparatively dull coach to Panama City. A rude-beyond-belief taxi driver took me to the Synagogue which I entered tentatively. Greeted by smiles and offerings of fancy dress broke down all barriers, I entered the sanctuary and sought out my friend, not seeing him I sat next to a family and made a new one. Halfway through the service, I moved a few rows forward when I spotted him.

Right at Home

More than 5 thousand miles from home, on the coast of the Pacific, in a land of a Spanish, American and tribal mix, the closest to the Equator I’d managed, aside from reading the Megila in Spanish I could have been in Finchley. The rabbi was over dressed and over excited, the kids were running amok in their as super hero costumes, the teenagers chatted and the parents tried to make everyone enjoy it as much as they remembered enjoying it.

My Spanish was still awful, but I knew the story through and through and booed and cheered along with everyone else. At the end, some of the Bar Mitzva students came on and gave a little show. It seemed like one super talented young man wanted to perform and dragged his friends along. Ever seen that one before? He did some break dancing, and a magic show, and every was happy! He even had an en-core.

After the service there was a reception and I had food thrust upon me. Ahh Jews Smile There was Pizza, biscuits, wine and coke. Not too different from how we’d have done it at WLS. I mingled and spoke to bugs bunny and batman for about an hour before I had to head off to the Chabad Party. My friend had already left, but the Rabbi had found me earlier and asked whether I needed a lift anywhere, he introduced me to a family who offered me a lift without a moments hesitation.

Purim on a Boat

The week before all this happened I was staying in a hostel called Mamallenas, and there I saw a poster for a Purim party on a boat. Now that’s three of my favourite words in one title. It was the local Chabad house organising it, they had hired a massive boat and filled it with falafel and whisky. Charging a US$10 entrance to cover some costs, after that everything was free. Best of all, it started a about an hour after the service at Kol Shearith Israel finished, so after the friendly family dropped me off in the centre of town, they spoke to a Taxi driver so that he would know exactly where to take me – and a Panama price not Tourist price!

Finding the entrance was a bit tricky, it was down a dark road to the entrance of a small dock. I arrived to meet a large group of Israelis chatting in their typical super-fast Hebrew. Not the easiest conversations to join, but I made a few friends. The night was long, and excellent, the boat left the dock around 11pm and made a huge loop of Panama Harbour returning around 4 in the morning. After about an hour the falafel buffet and BBQ were unleashed, and soon after that was the Megila reading. In between and after everyone was chatting to everyone, it was a huge boat full of Jews from all over the world, with tales of their travels and stories of their own to tell.

Finding Jews Abroad

Panama was the first time I have sought out Jews while abroad, but I have done it ever since, in Nicaragua I visited the Chabad House for Friday night prayers, in Guatemala I the unique Adat Israel had my Guatemalan friend and myself round for Friday night dinner and in Mexico the Jewish area has many shops packed with Vegan goodies! The Internet has brought people closer together like never before, and special websites connect Jews all over the world to share in the joys of being Jewish. Particularly useful I found and for finding communities and making contact.

Backpacker Kit List

I meant to write this list before I went to Mexico, and compare it with what I arrived home with but I forgot on both occasions. The list is neither exhaustive nor specialised, just a collection of things I found useful around Central America and Israel in no particular order, as food for thought as you start preparing.

Rope/String A short piece a foot or two long. Handy for holding things together, and stopping toilet doors banging on long bus journeys.
Duct Tape Hardly needs explanation, good for fixing books, bottles, boats, beds, bags and all manner of things beginning with a b.
Playing Cards Great for breaking the ice with strangers, and having something to do when conversation is thin.
Pens One in your pocket, a few in your bag. Only ever carry pens with lids or where the nib is protected, else you’ll end up with ink stains everywhere.
Photocopies of your important documents Copies of anything you might possibly need: passport, vaccination record, visa. Keep one on you and one in your bag, or bags. In addition to the real things.
Notebook Jot down numbers, directions, hotel rooms so when you’re exhausted, drunk or lost in another language, you’re not stuck. Also great for jotting down words you’re currently learning.
Toilet Paper I was never to be found without a healthy wad of toilet paper in my back pocket. Great for when the toilets aren’t up to scratch, or when you spill your soup on the bus.
External Hard Drive When your camera memory card fills up, you need to unload it somewhere. Get a small one if possible, they take up less space and are powered by USB rather than a mains plug.
Backup External Drive Keep it in a separate bag/place to your storage drive. If the internet is frequent and reliable, you could backup to the Internet before deleting from your card (but after copying to your External Drive). Remember, if you don’t have two physically separate copies you don’t have a backup.
Alarm Clock So you don’t miss your bus, train station or evening meeting with the local you befriended the day before.
Tea Towel A personal favourite, I like to take packed lunches to save on eating out costs. Wrap it in the tea towel to keep it warm, then use the towel in case you make a mess.
Tupperware Container I like long thin flat-ish ones so you can shove them down the side of a bag. Obviously only useful if you want to carry packed lunches.
Sewing Kit Long bus journeys are a great time to finish patching up your trousers.
Small Torch or reading light For sneaking around dorm rooms, reading on dark buses and finding things you’ve dropped under tables. My phone has a built in torch.
Spare Phone Losing your phone abroad is bad enough, having to find out how to buy a new one can be expensive and time consuming.
Carrier Bags I’ve always got a few plastic bags in the side pocket of my rucksack. They’re handy for when you go shopping, as laundry bags, something to sit on, somewhere for your rubbish and for when things leak.
Contact Cards If your lucky, you’ll make loads of friends. The downside is having to write your email, facebook and number over and over again in ever scrawly writing. I met someone who had a couple of dozen business cards printed, saved lots of time!
Diary If your the kind to reminisce, keep a brief log with date and a few words about where you were. Once you get home, you may have great difficulty remembering the order of some events! I did mine in a document on the computer.
Skype Credit So when you run out of money, you’ve already topped up your Skype account with enough to phone home with.
First Aid Kit In addition to duct tape, a few plaster and magic creams. Ibuprofen for the long-journey cramps, Melatonin for the by-golly-I-wish-I-was-asleep moments and Imodium for the floods of diarrhoea.
Portable Charger Cool and useful. Don’t forget a cable!
Elastic Bands To seal unfinished bags of nibbles, tie your hair when you’re out of bands and to improvise games on the beach.
Money pouch Never have all your money in one place, keep most of it somewhere not pickpocket-able but have enough on you to get to a safe place if you lose everything else.
Compass If you’re a map-reader you’ll already have your map, hence I don’t need to list it here, however some places have really bad labelling of roads so being able to orient yourself without names is really handy. Also good for knowing which way to look for an excellent sunset (look west). If you want to get really cool, whip it out in a hostel to pick the best room for warmth (south facing windows) or a lie in (east facing windows).
Cooking Oil I don’t mention a whole cooking set because that’s up to you style of travel. I have, however, been known to whip out my olive oil to keep the hostel door quiet. Just make sure it’s leak proof.. there was this one time in Israel…
Spare Bank Card It could take weeks to get a replacement card sent to your home and then to your foreign location. My bank wouldn’t let me have two cards on one account, so I opened a joint account with my brother and took both cards, meaning I had three bank cards to lose before I was actually in trouble.
Stuff for getting home An envelope with some home money, an oyster card and house keys might be handy when you get back.
Hand bag I travel with three bags, a big one on my back, a smaller one on my front (which I hate and try to avoid), and an empty one inside the big one. This is so I can go to the pub with a few essentials without having to re-pack before and after.
Towel Ah, the famous towel from HHG2G. Not only does it dry you off, they make excellent blankets, holdalls, pillows, padding for souvenirs and insulation for cold beers.
Family Photo Bit of an odd one, but the places I’ve visited have been very family orientated and on several occasions I wish I’d had a small photo in my wallet to show off.
Small change from home You’re going to meet foreigners and travellers, they’re often interested in money from around the world, having something to show them can be good fun.

Some other thoughts:

  • Even though you have no idea if it’s a good deal, I always exchanged about £20 worth of cash with the traders at the border. You’ll never save that much by waiting, but having some cash for a bottle of water or a taxi can be really handy.
  • Some foods are better than others on a bus. Avoid crumbly bread and any peanut butter jars if you can’t scrape the bottom with your finger. I’ve stopped carrying anything I can’t eat the moment I get fed up carrying it (i.e food which needs cooking). Food is heavy.
  • Write your name and contact info on anything you’d like back if you lose (especially notebooks or cameras). You may not get them, but at least there’s a chance.
  • Backup your photos. Seriously, you will cry if you don’t.
  • Whenever you take a photo, think about what you’re going to say when you show it to someone. It’ll help you decide if you should be taking photos or watching the volcano erupt.
  • Think good and hard about carrying a laptop, and between eBooks and heavy paper ones. There’s a blog on that coming…. soon.

Feel free to leave more advice in the comments below!


Comparison of Cloud Storage Options

Over the past few months I’ve switched between several cloud-storage options. Here’s an overview of my thoughts on each. These are in the order which I tried them in with the newest (and so my current favourite) at the top.

Unless otherwise noted, all of these features are available in the free version also.



  • Cheap (may go up after Beta period).
  • DirectSync means you can use the Cubby software to sync files between computers on your LAN without those files counting towards your quota (unless you are also syncing them to the cloud) Only for paid accounts
  • Very simple interface.
  • Easily lets you merge a Cloud folder with a Local folder.


  • You get told how many files and how many bytes still need to be synced, but you don’t get any indication as to the speed it’s transferring at.
  • You can share a Cubby with other users, but you can’t share only a subfolder.
  • Support are not very helpful. Syncing got stuck with files left for me on two machines, on one occasion a support guy phoned me to try and diagnose, but basically told me to look through the log file myself and find the problem. Email support then refused to help because I had mentioned I’d used a network drive on one machine, they left me with “we don’t support network drives” regardless of my other machine having the same problem without the network drive.



  • The security concious will enjoy their pre-transfer encryption.
  • Sync files and folders in place, no need to move or symlink them.
  • Backup Option lets you have a single-directional syncing folder.
  • Small, cheap options for sizing.
  • Easy to contact support by email or through the forum.


  • Very limited view of the status of your files.
  • Requires Java for both


Self-Hosted option, based on Git.


  • Self Hosting gives you flexibility and the option of cheap space.


  • Self-Hosting means you’re responsible for your own redundancy.
  • On large amounts of files (dozens of thousands) SparkleShare appeared to try and handle them in batches of a few hundred, but still froze and never finshed.

Google Drive


  • Get to your files quickly if you use Gmail.


  • Hogged resources when tracking many files (I added dozens of thousands, and often had to quit Drive to keep everything else running).
  • You have to keep your files in the Google Drive folder.
  • Doesn’t follow symlinks.
  • You can only sync into an empty folder, you cannot merge your Drive contents with some local files (an issuee after a reinstall) to save downloading files again.



  • Most of the people I’ve wanted to share files with, already have Dropbox.
  • Easily see the status of your files and you have the information you need to judge how long until everythnig is in sync.
  • Share individual folders with other users.
  • Follows Symlinks (Junctions/Hardlinks).


  • The smallest package is £10 for 100GB, if you only need 20GB it can feel nasty to pay for all the space you don’t need.
  • Based on Amazon s3 you’re supporting Amazon and their less than friendly business and environmental practices.
  • All your files must be in your Dropbox folder, however following Symlinks eases this trouble.

Using xDebug’s Clickable Stack trace with Programmer’s Notepad (and MINGW32) in Windows

I’ve spent far more time trying to make this work than I care to admit. The mistake I’ve made in the past is to try and do this in a batch file, I’ve now done it in bash (which I have anyway since I installed Git and asked for unix-tools to be globally available).

xDebug lets you turn file names into click able links, which can in turn be used to launch your text editor in the right place.


  • bash & sed – These come when you install Git and ask for the Unix tools to be globally available
  • Programmers Notepad – naturally. Though this is easy enough to tweak to any editor.
  • Firefox and xDebug

Step 1 – Create the SH file

Put this text into a file called “” and save it somewhere sensible. You may need to tweak the last line, especially if you want to use this for an editor other than PNotepad.

protocol=$(echo $uo | sed 's/\([a-z]*\):\/\/\(.*\):\([0-9]*\)\//\1/');
file=$(echo $uo | sed 's/\([a-z]*\):\/\/\(.*\):\([0-9]*\)\//\2/');
line=$(echo $uo | sed 's/\([A-z]*\):\/\/\(.*\):\([0-9]*\)\//\3/');
"C:\Program Files (x86)\Programmer's Notepad\pn.exe" --line $line "$file" &

Step 2 – Register the protocol

Open regedit and create the following keys – we’ll set the values after. Do this by right clicking on the parent (HKEY_CLASSES_ROOT, then pontepad etc) and clicking on New > Key.


Click on pnotepad and the double click on (default) to change it. Set it to “URL: PNotepad Protocol”.

Under that same (default) key right click in the blank space and click on New > Key and name it “URL Protocol”. It needs no value.

Now click on Command and set its (default) to your own version of the following, be careful not to mess up the quotes or spaces.

"C:\Program Files (x86)\Git\bin\sh.exe" "D:\Path\To\Your\" "%1"

Step 3 – Tell xDebug how to format URLs

Open up your php.ini and add or edit this line, then restart PHP/Apache as required.


Step 4 – Test

That should be it, make some code code throw an error and try clicking the link.

Any touble, or updates let me know!


Magical Image Resizing URL’s with Zend_Framework (and cached for Apache)

As a lazy programmer I don’t like resizing images all the time. So I made this bit of code to let me write a URL including the file size and have the work done for me.

  • Written for Zend Framework 1.11.12
  • It will resize the image and save it into the correct location so that Apache will find it next time and not call the PHP.
  • You can specify the required width, height, both or neither.
  • If a width or height is given as 0 then the original dimension will be used.

Add some settings to application.ini

cache.publicDir = '/cache'
cache.dataDir = APPLICATION_PATH "/../public/cache"
data.dataDir = APPLICATION_PATH "/../public/data

Add a route in the Bootstrap

The regex router must match a URL containing the required file sizes, the file name and as many sub directories as thrown at it. It matches the following and sends them to the ThumbAction on FilesController:

  • /cache/100/200/file.jpg
  • /cache/100/200/subdir/file.jpg
  • /cache/100/200/another-subdir/file.jpg
$router->addRoute('file_resized_thumbnail', new Zend_Controller_Router_Route_Regex(
			'controller'	=> 'files',
			'action'		=> 'thumb',
			1	=> 'width',
			2	=> 'height',
			3	=> 'subdir',
			4	=> 'file'


*	Loads the file, gets a resized version and saves it in a location identical to 
*	the current URL so Apache can find it next time.
public function thumbAction()
	$options = $this->_helper->container->get('options');
	$fileName = $this->getRequest()->getParam('file');
	$subdir = $this->getRequest()->getParam('subdir');
	$width = $this->getRequest()->getParam('width');
	$height = $this->getRequest()->getParam('height');
	$cacheUrlPrefix = $options['cache']['publicDir'];
	$cachePathPrefix = $options['cache']['dataDir'];
	$dataPathPrefix = $options['data']['dataDir'];
	$fileName = urldecode($fileName);
	$subdir = ($subdir == "") ? "" : urldecode($subdir);
	$fullPath = $dataPathPrefix.'/'.$subdir.$fileName;
	if(realpath($fullPath) == false){
		throw new Zend_Controller_Action_Exception('File not Found: '.$fullPath, 404);
	$file = new Pata_File(array(
		'path'			=>	$fullPath
	if ($file == false) {
		throw new Zend_Controller_Dispatcher_Exception('That file was not found in that subdir');
	$cacheDir = $cachePathPrefix.'/'.$width.'/'.$height.$subdir;
	$cacheFile = $cacheDir.'/'.$fileName;
	if (file_exists($cacheDir) == false) {
		mkdir($cacheDir, 0777, true);
	imagepng($file->getThumbnailPng($width, $height), $cacheFile);
	header('content-type: image/png');


*	This is a model I use to make working with files a bit easier. Several of the functions are used by thumbAction but the code could be moved to the controller if you so desired.
class Pata_File
	protected $path;
	protected $relativePath;
	protected $url;
	protected $image;
	protected $thumbUrl;
	protected $thumbnailDimensions = array();

	protected $thumbnailPng = array();
	protected $description;
	public function __construct($options)
		if (isset($options['path'])) {
			$this->path = $options['path'];
		if (isset($options['relativePath'])) {
			$this->relativePath = $options['relativePath'];
		if (isset($options['url'])) {
			$this->url = $options['url'];
		if (isset($options['thumbUrl'])) {
			$this->thumbUrl = $options['thumbUrl'];

	public function getName()
		return basename($this->getPath());
	public function getPath()
		if ($this->path == null) {
			throw new Exception('No path has been set');
		return $this->path;
	public function getRelativePath()
		return $this->relativePath;
	public function getDir()
		return substr($this->getPath(), 0, - strlen($this->getName()));
	public function setDescription($description)
		$this->description = $description;
	public function getDescription()
		return $this->description;
	 * The URL to the actual file itself - not a page displaying it, see getPageUrl()
	 * @return type 
	public function getUrl($width = 800, $height = null)
		if ($this->url == null) {
			throw new Exception('No url has been set');
		$height = $height ?: round($width * 0.75, 0);
		return str_replace(array(':width:', ':height:'), array($width, $height), $this->url);
	public function getThumbUrl($width = 120, $height = null)
		if ($this->thumbUrl == null) {
			throw new Exception('No thumbUrl has been set');
		$height = $height ?: round($width * 0.75, 0);
		return str_replace(array(':width:', ':height:'), array($width, $height), $this->thumbUrl);

	public function setPath($new)
		$this->path = $new;
	public function setUrl($new)
		$this->url = $new;
	public function setThumbUrl($new)
		$this->thumbUrl = $new;
	public function setPageUrl($new)
		$this->pageUrl = $new;
	 *	Page Url is the URL to the page on which this image can be viewed
	public function getPageUrl()
		if ($this->pageUrl == null) {
			throw new Exception('No pageUrl has been set');
		return $this->pageUrl;
	public function getExtention()
		if (preg_match('/\.[A-z0-9]+$/', $this->getPath(), $ext)) {
			$ext = $ext[0];
			$ext = substr($ext, 1);
		} else {
			$finfo = new finfo(FILEINFO_MIME);
			$mime = $finfo->file($this->getPath());
			$mime = explode(";", $mime);
			$mime = $mime[0];
			$mimeToExt = array(
				"text/plain" => "txt",
			if (isset($mimeToExt[$mime])) {
				$ext = $mimeToExt[$mime];
			} else {
				$ext = "";
		return $ext;
	public function freeMemory()
		$this->img = null;
	public function getImage()
		if ($this->image == null) {
				case "jpg":
				case "jpeg":
					$this->img = imagecreatefromjpeg($this->getPath());
				case "png":
					$this->img = imagecreatefrompng($this->getPath());
				case "gif";
					$this->img = imagecreatefromgif($this->getPath());
				case "bmp";
					$this->img = imagecreatefrombmp($this->getPath());
				case ".txt";
				case "doc";
					$this->img = imagecreatefrompng(realpath(dirname(__FILE__).'/File/Images/thumb_doc.png'));
				case "xls";
					$this->img = imagecreatefrompng(realpath(dirname(__FILE__).'/File/Images/thumb_excel.png'));
					$this->img = imagecreatefrompng(realpath(dirname(__FILE__).'/File/Images/thumb_unknown.png'));
		return $this->img;
	public function getThumbnailDimensions($width, $height, $return = 'both')
		$cacheName = $width.'x'.$height.$return;
		if (isset($this->thumbnailDimensions[$cacheName])) {
			return $this->thumbnailDimensions[$cacheName];
		if ($this->getType() == 'images') {
			$imgSize = getimagesize($this->getPath());
			$imgWidth = $imgSize[0];
			$imgHeight = $imgSize[1];
		} else {
			$img = $this->getImage();
			$imgWidth = imagesx($img);
			$imgHeight = imagesy($img);
		if ($width > 0) {
			$thumbWidth = $width;
		} else {
			$thumbWidth = ($imgWidth / $imgHeight) * $height;
		if ($height > 0) {
			$thumbHeight = $height;
		} else {
			$thumbHeight = ($imgHeight / $imgWidth) * $width;
		$thumbWidth = floor($thumbWidth);
		$thumbHeight = floor($thumbHeight);
		$returnValue = null;
		if ($return == 'both') {
			$returnValue = array('width' => $thumbWidth, 'height' => $thumbHeight);
		} elseif ($return == 'width') {
			$returnValue = $thumbWidth;
		} elseif ($return == 'height') { 
			$returnValue = $thumbHeight;
		} else {
			throw new Exception($return . ' is not a valid parameter for return type for getThumbnailDimensions in Pata_File');
		$this->thumbnailDimensions[$cacheName] = $returnValue;
		return $returnValue;
	public function getThumbnailPng($width = 0, $height = 0)
		if (!isset($this->thumbnailPng[$width.'x'.$height])) {
			$img = $this->getImage();
			$imgWidth = imagesx($img);
			$imgHeight = imagesy($img);
			$thumbTop = 0;
			$thumbLeft = 0;
			// If we have specified widths and heights, use them. Otherwise calculate them
			if ($width == 0 && $height == 0) {
				$thumbWidth = $imgWidth;
				$thumbHeight = $imgHeight;
			} else {
				$dimensions = $this->getThumbnailDimensions($width, $height);
				$thumbWidth = $dimensions['width'];
				$thumbHeight = $dimensions['height'];
			// These default to not being changed
			$scaleWidth = $thumbWidth;
			$scaleHeight = $thumbHeight;

			if ($imgWidth > $imgHeight) {
				$scaleHeight = ($imgHeight / $imgWidth) * $thumbWidth;
				$thumbTop = ($thumbHeight - $scaleHeight) / 2;
			} elseif($imgWidth < $imgHeight) {
				$scaleWidth = ($imgWidth / $imgHeight) * $thumbHeight;
				$thumbLeft = ($thumbWidth - $scaleWidth) / 2;
			$thumb = ImageCreateTrueColor($thumbWidth, $thumbHeight);
			// Fill the image with transparency
			imagesavealpha($thumb, true);
			$trans_colour = imagecolorallocatealpha($thumb, 0, 0, 0, 127);
			imagefill($thumb, 0, 0, $trans_colour);
			imagecopyresampled($thumb, $img, $thumbLeft, $thumbTop, 0, 0, $scaleWidth, $scaleHeight, $imgWidth, $imgHeight);
			imageinterlace($thumb, true);
			$this->thumbnailPng[$width.'x'.$height] = $thumb;
		return $this->thumbnailPng[$width.'x'.$height];
	function getType()
		$types = $this->getFileTypeExtentions();
		foreach ($types as $type => $exts) {
			if (in_array(strtolower($this->getExtention()), $exts)) {
				return $type;
		return 'unknown';
	function getFileTypeExtentions($type = null)
		$types = array(
			'images'		=> array('jpg','jpeg','gif','png','tiff','bmp'),
			'documents'		=> array('doc', 'docx', 'txt', 'rtf', 'odt', 'pdf'),
			'spreadsheets'	=> array('xls'),
		if ($type != null) {
			if (!isset($types[$type])) {
				throw new Exception('Pata_Gallery->getFileTypeExtentions() does not have a list of extentions for the "'.$type.'" type');
			return $types[$type];
		return $types;