White Sauce

Serves: 4


  • 2 cups milk
  • 40g butter
  • 3 tbsp flour
  • salt & pepper


  • 1 cup milk
  • 2 tablespoons butter
  • 2 tablespoons flour



  1. Mix flour, milk, salt & pepper with whisk very well.
  2. Heat the butter in a frying-pan. Add the mixture; Stir until the sauce is smooth and thickens. Not too thick. (Do not burn the mixture!)


Other sources: (!)

Creamy pumpkin soup

Original Source:

(Reproduced here for easy access because I use this recipe often.)



  • 2 tablespoons olive oil, plus extra to serve
  • 1 onion roughly chopped
  • 2 garlic cloves, roughly chopped
  • 600g peeled, chopped pumpkin
  • 1 potato, chopped
  • 2 carrots, chopped
  • 1 leek (white part only), chopped
  • 1/2 teaspoon ground nutmeg
  • 3 cups (750ml) chicken stock
  • 1/2 cup (125ml) pure (thin) cream
  • 1 tablespoon pumpkin seeds (pepitas), toasted
  • Dried cranberries and finely chopped flat-leaf parsley leaves, to serve



Step 1

  • Heat oil in a large saucepan over medium heat.
  • Add onion and cook for 2-3 minutes until soft.
  • Add garlic, vegetables and nutmeg, then toss to coat.
  • Add stock and 2 cups (500ml) water, then bring to the boil.
  • Reduce heat to low, cover and cook for 25 minutes or until the vegetables are tender.
  • Cool slightly.

Step 2

  • In batches, transfer to a blender and whiz until smooth.
  • Return soup to the saucepan and place over low heat.
  • Stir in cream, then season.
  • To serve, ladle into bowls and top with seeds, cranberries and parsley, then drizzle with extra oil.

Zucchini Slice


  • 550g zucchini
  • 1 medium (about 160g) onion, peeled and finely chopped
  • 130g bacon
  • 75g (1 cup, lightly packed) grated tasty cheddar cheese
  • 112g (3/4 cup) self-raising flour
  • Salt and pepper, to taste
  • 4 large eggs (we use eggs with a minimum weight of 59g)
  • 83ml (1/3 cup) oil (we use a mild-flavoured oil, such as sunflower)


Preheat oven to 180 degrees Celsius.

Line a 18cm by 28cm baking dish or slice pan with baking paper.

Oven rack to the middle of the oven.


Finely chop bacon. Heat a heavy-based nonstick frying pan over medium-high heat.

Fry for about six minutes, stirring occasionally, until onion has softened but not browned.

  • bacon: 130g bacon
  • onion: 1 medium (about 160g) onion, peeled and finely chopped

Set aside to cool.


Zucchini – finely grate. Squeeze handfuls of grated zucchini over sink to remove excess liquid.


Combine in a large bowl:

  • zucchini (2-3, 550g zucchini)
  • cooled onion
  • bacon mixture
  • cheese (1 cup, lightly packed)
  • flour (3/4 cup)
  • salt and pepper


Use a fork to mix together in a small bowl:

  • eggs (4 large)
  • oil (1/3 cup)

Add egg and oil mixture to the other ingredients and stir to combine.


Pour mixture into baking dish and spread evenly.

Bake for about 45 minutes, or until slice is golden brown and firm to the touch.

Set aside for five to ten minutes before slicing.

Application Security: Validate uploaded files before processing them

This is not a “how to” but a “what to”.

If you’re a software developer working on a system that allows file uploads, before you allow any code to process the file (i.e.  the file has uploaded, now you want to do something with it), you first need to check the file extension matches the “content” of the actual file.

A simple example: A user may upload a file with an “.ico” file extension, but it’s actually an image file with EXIF data, and your system has an EXIF data vulnerability. You can’t trust the underlying software libraries you use will first validate the file extension matches the actual data embedded in the file.

What this means is the software libraries you use may see the .ico extension, think that it’s OK (just an icon), not run any checks that would ordinarily be run to verify the file on file extensions containing EXIF data, but while processing the file it will still executes EXIF functions and processes the vulnerability.

You think that won’t happen? Think again. That’s an attack vector Black hat hackers use. And it works.

As a software developer, when you think about security you have to assume all the things that are “not likely” to happen are going to be the most likely attack vectors for hackers.


Our job as software developers is harder than ever. We have to think every “not likely to happen” scenario is going to be a step in an attack by someone malicious.

Predictable Links to Multiple GSuite/GMail Accounts

I run multiple personal and business domains with Google mail accounts.

I want to create links (both synced in Chrome bookmark bar and in a web page) to each mail account that I know will always take me to the account I want, even when accessing from different devices (I have a minimum of 2 primary laptop devices I login from regularly).

There is a URL schema Google uses to generated each logged-in account – e.g. (then increment the number for each inbox) – but if don’t login to each account in the exact same order on each device, then they get out of sync.


Today I found a solution.

To access the desired mailbox via a predictable URL, use the following template:

Change the to the actual email address.

This also works for emails in custom GSuite domains (e.g. my domain), because underneath all and GSuite domain emails redirect back to the same number based URL template I originally mentioned.

I also figured out the URL to link to a specific Google Calendar is:

Again, the URL will cause a redirect.


I’ve only tried these with accounts I’m already logged into. I’m not sure what happens on a new system where you haven’t logged in yet, but I expect they should still work just fine.



I originally performed a search for “link url to multiple gmail account” which lead to to answers at:


Update (same day): I somehow logged myself out of all Google accounts in Chrome while trying to re-establish a sync between computers. So mail account links I setup started going to the same Gmail account (the account I setup for the sync). But after logging back into each of my GMail/GSuite accounts all the links worked fine again, so I reckon that’s a validation the permalinks work.

Cannellini Beans (with crushed garlic and cumin)


  • 1 can Cannellini Beans (240g)
  • Cumin seeks – couple of pinches
  • 1-3 garlic cloves, crushed.
  • Olive oil – about a 1 tablespoon


  1. Heat oil in a small saucepan over medium-ish heat.
  2. Once oil is hot, add cumin seeds and cook for a minute or two (or until the start to jump a bit).
  3. Reduce the heat to low, add crushed garlic and cook for a minute or two until starting to golden. Stir so garlic doesn’t burn.
  4. Add drained Cannellini beans. Cook on low until warm through and skins are just starting to break and stick. Try not to over cook – they still want a firm-ish body. Stir occasionally.

Serve. Good for 2 people as a side or vegetable substitute for salmon or snags (sausages). Goes well with mushy mint peas.

Mushy Mint Peas


  • 1 tablespoon unsalted butter.
  • 300g frozen peas, thawed.
  • 1/3 cup lightly packed fresh mint leaves, coarsely chopped.
  • Coarse salt and ground pepper

Optional additions (recommended):

  • 1 bunch spring onion (6-8 onions), chopped
  • 1 clove of crushed garlic.


  1. In a large skillet, or a large pot, melt butter over medium-high.
  2. Add peas (and onion/garlic) and cook, stirring constantly, until warmed through.
  3. Transfer to a food processor.
  4. Add mint and season with salt and pepper. Add additional butter if you wish.
  5. Pulse until peas and mint are coarsely pureed.
  6. Serve warm.


See Also

PHP: Recursively zip a folder/directory structure

Status: Draft (31 May 2019)

This is a work in progress. I want to record my working as I go.

What I Want

I need to zip a folder structure – ultimately, theme and plug-in folder in WordPress – using PHP.

I’m currently developing and testing on a Windows 10 PC. Ultimately it will need to work in Linux (Ubuntu), but the first step is to it working in Windows.

I started with solutions from and but the zip file was being created, however, not files were added.

I realised the problem was the relative path for folders/files within the zip. My solution below is a modification of the referenced solutions, where I strip the source path from the fill file path of each folder and file to give the relative path to the source.

So far this works in Windows, next step is to test in Linux. I’m actively working the problem so stay tuned.


I created a file “D:\Temp\php\test_zip.php” with the code below.
I execute with the following command (I have XAMPP installed with includes PHP): “D:\Temp\php>D:\xampp\php\php.exe test_zip.php”.

The Code

(Aide: I used to convert raw PHP code to something I can past in between <pre> tags in the Classic WorPress content editor).

// Make sure the script can handle large folders/files
ini_set('max_execution_time', 600);

// Start the backup!
Zip('D:\\Temp\\php\\Source\\', './');
Zip('D:\\Temp\\hildas_prod_logs\\', 'D:\\Temp\\php\\');
testOne('D:\\Temp\\php\\Source\\debug.log', 'D:\\Temp\\php\\');

echo "Finished" . "\n";

// A quick, reduced test.
// This works in Windows.
function testOne($source, $zipTo)
	$zip = new ZipArchive;
	if (file_exists($source) === false)
		echo "Sourece does not exist" . "\n";
	if ($zip->open($zipTo, ZIPARCHIVE::CREATE) === true) 
		$zip->addFile($source, 'source\newname.txt');
		echo "OK" . "\n";
		echo "FAILED" . "\n";

// This works in Windows.
// Source and inspiration: - Marvin Menzerath. (
// Additional source and inspiration:
function Zip($source, $destination)
    if (!extension_loaded('zip')) 
		echo "Zip extension not loaded\n";
        return false;
	if (!file_exists($source)) 
		echo "Source not found:" . $source . "\n";
        return false;

    $zip = new ZipArchive();
    if (!$zip->open($destination, ZIPARCHIVE::CREATE)) 
		echo "Zip not created or opened\n";
        return false;
	$raw_source = $source;

    $source = str_replace('\\', '/', realpath($source));
	echo "Raw source: " . $raw_source . "\n";
	echo "Clean source: " . $source . "\n";

    if (is_dir($source) === true)
        $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);
		$sourceWithSeparator = $source . DIRECTORY_SEPARATOR;
        foreach ($files as $file)
            $file = str_replace('\\', '/', $file);

            // Ignore "." and ".." folders
            if( in_array(substr($file, strrpos($file, '/')+1), array('.', '..')) )

            $file = realpath($file);

            if (is_dir($file) === true)
				$dir_path = str_replace($sourceWithSeparator, '', $file . DIRECTORY_SEPARATOR);
				echo "Directory: " . $file . " (Path: " . $dir_path . ")\n";
                //$zip->addEmptyDir(str_replace($source . '/', '', $file . '/'));
            else if (is_file($file) === true)
				$zip_relative_path = str_replace($sourceWithSeparator, '', $file);
				$zip_relative_path = remove_from_start($zip_relative_path, $raw_source);
				echo "File: " . $file . " (Path: " . $zip_relative_path . ")\n";
                //$zip->addFromString(str_replace($source . '/', '', $file), file_get_contents($file));
				//$zip->addFile($file, str_replace($source . '/', '', $file));
				$zip->addFile($file, $zip_relative_path);
    else if (is_file($source) === true)
        $zip->addFromString(basename($source), file_get_contents($source));

    return $zip->close();

function remove_from_start($full_string, $prefix)
	if (substr($full_string, 0, strlen($prefix)) == $prefix) 
		$full_string = substr($full_string, strlen($prefix));
	return $full_string;



Ask questions!

My advice to everyone in general:

Ask questions!

The only way you can discover new things and learn is by asking questions.

I don’t believe there is such a thing as a dumb question.
Yes, there as “simple” or “basic” questions, but I’ve learnt through the years that these can also be the most important questions. Why? Because people often “assume” the answer should be known so the question is not asked and the topic is not covered. But not knowing answers to the simple questions means we don’t understand the foundations of what we are doing.

Some people are not going to react well to being asked questions, whether the the question is simple or complex.

People like that are ignorant.

Don’t let other people’s ignorance stop you. Keep asking questions until you have answers and understanding.

Asking questions is the simplest and easiest key to success.

Those who do well, love to teach

There’s an old saying:

Those who can, do;
Those who can’t, teach.

Maybe for some people that is true.

But there is a second truth:

Those who do well, love to teach.

Those are my words (I think), but I recently heard a similar sentiment from someone else (I can’t remember who, unfortunately) and a conversation I had today made me think of this again.

People who are good at what they do, and love what they do, love to teach others as well.

It makes sense. It’s biology. Ancient. The passing of information from generation to generation. The desire to give those who follow the knowledge of lessons learnt.

Teaching is not something to laugh at. It’s difficult. It’s important. And it’s worthy.

Without teaching, where would our knowledge come from?