Chris Hope's LAMP Blog - The Electric ToolboxChris Hope's LAMP Blog - The Electric Toolbox

Linux Apache MySQL and PHP articles by Chris Hope

This is Chris Hope's blog for Linux, Apache, MySQL and PHP (known as LAMP) and Javascript/jQuery. I started this website several years ago with articles about web programming, Linux and Windows tips and tricks, howtos etc.

The ten most recent articles can be found below in their entirety. Navigating the sections in the right navigation (under Categories) will bring up all the other posts, and you can also use the search box at the top of the page to find what you might be looking for.

How to do a tick/check and a cross in ExcelHow to do a tick/check and a cross in Excel

Posted May 11th, 2015 in Applications

There are several fonts which let you easily type a tick/check or cross into a cell in Excel, or use in any other application; or you can use unicode.

Using fonts

Use the Marlett or Webdings fonts, and use "r" for a cross and "a" for a check or tick.

Using unicode

There are a few checkmarks and crosses that can be used with unicode too.

U+2714 is "heavy check mark"

U+2718 is "heavy ballot x"

This page at Wikipedia shows how to put unicode into a document:

Xamarin Android Player to simulate Android devicesXamarin Android Player to simulate Android devices

Posted May 7th, 2015 in Applications

Five years ago, I bought a Mac Mini so I could use the iOS Simulator (and then quickly "upgraded" to a more powerful MacBook Pro when I realised I far preferred OS X to Windows) but struggled to find a decent equivalent for Android devices. After a quick Google today I found the Xamarin Android Player, which does the trick nicely.

Xamarin Android Player

Download it from here:

There are versions for both Windows & OS X. I've only tried the OS X version. You download and install it, and then there's a list of downloadable devices. At the present time, these are:

  • Nexus 4 KitKat, Lollipop & Jelly Bean - 768x1280
  • Nexus 5 KitKat & Lollipop - 1080x1920
  • Nexus 7 KitKat, & Jelly Bean - 800x1280
  • Nexus 10 KitKat - 1600x2560 (i.e. 800x1280)
  • Nexus S KitKat - 480x800

I'm not sure how or if you can add other images.

The only annoyance I have found so far is that the virtual device will only use DNS for domain lookups, and won't look at your local hosts file (whereas the iOS Simulator will use the hosts file first, and DNS lookups next).

Set PHP configuration options with NginxSet PHP configuration options with Nginx

Posted April 26th, 2015 in Nginx Web Server and PHP

There may be times you need to set specific PHP options for a virtualhost on Nginx, for example adding an automatically prepended file to all pages. This post shows how to do this.

PHP auto_prepend_file example with Nginx

Let's say you have a setting like this to make all .php files be parsed as PHP:

server {
  ... configuration options ...
  location ~ \.php$ {
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_param	QUERY_STRING		$query_string;
    fastcgi_param	REQUEST_METHOD		$request_method;
    fastcgi_param	CONTENT_TYPE		$content_type;
    fastcgi_param	CONTENT_LENGTH		$content_length;
    ... etc etc ...

Simply add this in with the other fastcgi_param values:

fastcgi_param PHP_VALUE auto_prepend_file=/path/to/prepend.php;

The above example will automatically prepend the file at /path/to/prepend.php to all files that have a .php extension and parse them as PHP.

You should be able to set any other PHP value that can be configured outside the php.ini file in the same way, changing auto_prepend_file to the confguration name, and /path/to/prepend.php to the configuration value.

Fix "access denied" error when parsing HTML as PHP with NginxFix "access denied" error when parsing HTML as PHP with Nginx

Posted April 25th, 2015 in Nginx Web Server and PHP

If you are attempting to get files with a .html extension parsed as PHP with Nginx + php-fpm, you might get an "access denied" error in your browser, and the error message "Access to the script '...' has been denied (see security.limit_extensions)" in your Nginx error log. This post shows how to allow html files to be parsed successfully as PHP with Nginx + php-fpm.

Nginx configuration block

Your Nginx configuration block will look something like this to parse HTM files as PHP:

server {
  ... configuration options ...
  location ~ \.html$ {
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_param	QUERY_STRING		$query_string;
    fastcgi_param	REQUEST_METHOD		$request_method;
    fastcgi_param	CONTENT_TYPE		$content_type;
    fastcgi_param	CONTENT_LENGTH		$content_length;
    ... etc etc ...

Error message

And yet when you access e.g. somefile.html you get "Access denied" in the browser.

You check the Nginx error log and see this:

2015/04/25 07:38:28 [error] 5942#0: *108814 FastCGI sent in stderr: "Access to the script '/path/to/somefile.html' has been denied (see security.limit_extensions)" while reading response header from upstream, client:, server:, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/var/run/php5-fpm.sock:", host: ""

The fix needed is suggested in the error message: "see security.limit_extensions"

Set security.limit_extensions

On Debian 7 Wheezy, the configuration file to edit this setting is at /etc/php5/fpm/pool.d/www.conf; on other distributions it may be in a different place.

Then search for security.limit_extensions. It should look something like this in the file by default:

; Limits the extensions of the main script FPM will allow to parse. This can
; prevent configuration mistakes on the web server side. You should only limit
; FPM to .php extensions to prevent malicious users to use other extensions to
; exectute php code.
; Note: set an empty value to allow all extensions.
; Default Value: .php
;security.limit_extensions = .php .php3 .php4 .php5

If the security.limit_extensions has been set already, then add .html to it; if it hasn't then add it in with all the extensions you need to allow, e.g.:

security.limit_extensions = .php .html

Is it safe to do this?

When enabling this myself, my first thought was "Is this safe" and "Can a regular HTML file suddenly be parsed as PHP" and then obviously "Will this cause security issues with any WordPress blogs installed on my server?"

As far as I can tell, it shouldn't cause any issues, because you still have to allow .html files to be parsed through php-fpm in the Nginx config. If you haven't done that, then they won't.

If I am wrong, please add a comment below.

How to shrink a VMWare Fusion Linux virtual diskHow to shrink a VMWare Fusion Linux virtual disk

Posted April 21st, 2015 in OSX and VMWare

VMWare Fusion on Mac OSX allows you to shrink virtual disks easily for Windows virtual machines right from the graphical interface (Virtual Machine -> Settings -> General -> Clean Up Virtual Machine) but there isn't the same option to do this with Linux, so you need to do it from the command line.

1. Clean up space

First of all you should clean up whatever space you can on the Linux virtual machine by deleting uncessary files, etc. After doing that, run this command as the root user on the Linux VM to zero out any free space - if you don't do it, then the shrinking process won't reclaim any space:

cat /dev/zero > zero; sync; sleep 1; rm -f zero

You'll see this message when it has finished:

cat: write error: No space left on device

That's OK, because the idea was to fill the disk up and then delete the file afterwards.

2. Shut down the virtual machine

You can't reclaim space with the virtual machine running, so shut it down first.

3. Run the shrinking process

Open up Terminal on your Mac, change to the directory the virtual machine files are in (for example I have mine at ~/Virtual Machines/<vm name>) and then run the following commands, replacing "Virtual Disk.vmdk" with the actual name of your virtual disk image.

Note that if the filename contains spaces then the filename parameter to the command needs quotes around it, as in my examples.

The following examples assume VMWare Fusion is installed in Applications at the OSX disk root.

The first command defragments the disk:

/Applications/VMware\ -d "Virtual Disk.vmdk"

I got the message "VixDiskLib: Invalid configuration file parameter. Failed to read configuration file." when running this command. I don't know what this error means, but the command worked successfully and this was the other output:

Defragment: 100% done.
Defragmentation completed successfully.

The second command then shrinks the disk:

/Applications/VMware\ -k "Virtual Disk.vmdk"

Once again, I got the message "VixDiskLib: Invalid configuration file parameter. Failed to read configuration file." but again it all worked fine, and this was the output

Shrink: 100% done.
Shrink completed successfully.

I managed to reclaim 9GB of wasted space from doing this.

What is the virtual disk filename?

When you do a directory listing, you'll see a bunch of files and directories like this:

Debian 7 64-bit-03868d7d.vmem
Debian 7 64-bit.nvram
Debian 7 64-bit.plist
Debian 7 64-bit.vmsd
Debian 7 64-bit.vmx*
Debian 7 64-bit.vmx.lck/
Debian 7 64-bit.vmxf
Virtual Disk-s001.vmdk
Virtual Disk-s002.vmdk
Virtual Disk-s003.vmdk
Virtual Disk-s004.vmdk
Virtual Disk-s005.vmdk
Virtual Disk-s006.vmdk
Virtual Disk-s007.vmdk
Virtual Disk-s008.vmdk
Virtual Disk-s009.vmdk
Virtual Disk-s010.vmdk
Virtual Disk-s011.vmdk
Virtual Disk.vmdk
Virtual Disk.vmdk.lck/

The disk images have the .vmdk file extension and in the above example have been split into 11 different files with numbered filenames. You don't need to defrag and shrink the numbered filenames, just the one without the numbers.

So in the above example, ignore Virtual Disk-s001.vmdk to Virtual Disk-s011.vmdk and run the command on Virtual Disk.vmdk.

If you do attempt to run the command on one of the numbered files, you'll get an error message like this one:

The file '/.../Virtual Disk-s001.vmdk' appears to be a sub-component of a virtual disk.
Did you mean '/.../Virtual Disk.vmdk'?
Failed to defragment: The specified file is not a virtual disk (0x3ebf).

Version used

I ran the above commands on VMWare Fusion 7.1.1 on OSX Yosemite 10.10.3.

Where are Vudu To Go downloaded movies stored on my Mac?Where are Vudu To Go downloaded movies stored on my Mac?

Posted April 19th, 2015 in Applications

The Vudu To Go app allows you to download movies you have purchased from Vudu* and stores them on your computer to watch using the app. But where are the files stored?

Location of Vudu To Go files on a Mac

The files are stored at /Users/<username>/Library/Preferences/com.vudu.air.Downloader\Local Store

When browsing for that location in Finder, click the "Go" file menu option and hold down the option key to show the "Library" option.

Then locate "Preferences"

Then "com.vudu.air.Downloader"

The "Local Store"

Under the local store you will find folders named with numbers. The media files are there.

Copying the files to another computer

It is possible to copy them to another computer in the same location. I attempted to copy the entire com.vudu.air.Downloader folder but it kept crashing on the other computer.

So I deleted it and ran the app again, started downloading the movie, shut down the app, copied the movie directory over and it worked fine. You probably don't need to go through the "start download and stop the app" step and can probably just copy the movie directory over, just probably don't mess with the files in the root level of that folder.

Can you control where they are saved?

No, but it might be possible to symlink the directory location to somewhere else, e.g. an external hard drive, but I haven't tried this myself.

Can you download rented movies too?

* I noted at the start that Vudu 2 Go lets you download movies you purchased with Vudu, but possibly it can let you download the ones you've rented to. I'm not sure about this, either way.

Tools for setting up and testing secure certificatesTools for setting up and testing secure certificates

Posted April 18th, 2015 in Linux/Unix/BSD

This is a quick reference page for some tools for configuring web server settings and testing secure certificates.

Mozilla SSL Configuration Generator

This tool provides you with SSL configurations for Apache, Nginx, HAProxy & AWS Elb, depending on the server version and openssl version.

To find out your openssl version, do this:

openssl version

To find out your Apache version, do this (depending on distro it'll be apache2 or httpd, and you may need to prefix it with /usr/sbin):

apache2 -v
httpd -v

To find out your Nginx version, do this (again you might need to prefix with /usr/sbin):

nginx -v

Qualys SSL Labs SSL Server Test

This tool tests your secure certificate and gives it a grade. On a couple of older servers, I was able to improve the grade from an "F" to a "B" simply by using the Mozilla SSL configuration generator above. We should be able to get them to an "A" by fixing the intermediate certificate when we renew.

[Update] I bought a new certificate for a site using RapidSSL, the Mozilla configuration generator and with up to date Nginx & openssl on Debian 7 Wheezy and got an A+ with the testing tool.

Screen: cannot open your terminal '/dev/pts/0'Screen: cannot open your terminal '/dev/pts/0'

Posted April 17th, 2015 in Linux/Unix/BSD

If you are logged in as a user using "su" or "sudo su" and attempt to use screen, you'll get the error message "Cannot open your terminal '/dev/pts/0' - please check". This post shows how to fix this.

Solution 1

Log out of the terminal/SSH session and log back in as the user you want to run screen as instead of using su.

Solution 2

script /dev/null


This worked for me on Debian 7.8 Wheezy.

MySQL: order a string column as an integerMySQL: order a string column as an integer

Posted April 16th, 2015 in MySql

If you order a string column that contains only numeric values with MySQL, it will order them as string values, e.g.: 1, 10, 100, 2, 3, 31, 32, 4, etc. If you want to order them as if they were an integer, cast them in the order by clause.


SELECT * FROM <table> ORDER BY CAST(<column> AS unsigned)


Normally you'd store numeric values in a numeric column in the database, but sometimes this isn't possible. For example, the postmeta table in WordPress has a meta_value column which is a string and in which you might store only numeric values for a particular meta_key field.

When the values are strings, they are sorted as strings, so 1, 2, 3, 4, 10, 31, 32, 100 would be sorted as 1, 10, 100, 2, 3, 31, 32, 4 as shown in the example in the first paragraph.

Casting the value as "unsigned" or "signed" in the sort part of the query will instead sort the value as an integer and give the desired result, assuming all the values are indeed numeric.

Speed impact?

I haven't measure this myself, but there will be an obvious impact in speed, especially if the resultset is large. However, it may be fairly minimal and depending on what you are using this query for, it may not matter.

A couple of WordPress examples

Using WordPress as an example, here's a query on the wp_postmeta table finding records with a meta_key of _ct_text_552c8612842c1, which was created using CustomPress, and then ordering them numerically:

SELECT * FROM wp_postmeta
WHERE pm.meta_key = '_ct_text_552c8612842c1'
ORDER BY CAST(pm.meta_value as unsigned)

In my case, I needed to join this to all posts of type 'forum', and here's another example:

SELECT p.ID, pm.meta_value
FROM wp_posts p
INNER JOIN wp_postmeta pm ON pm.post_id = p.ID
WHERE p.post_type = 'forum'
AND p.post_status = 'publish'
AND pm.meta_key = '_ct_text_552c8612842c1'
AND pm.meta_value != ''
ORDER BY CAST(pm.meta_value as unsigned)

That's all for now, I hope you found this useful!

Cast a Javascript variable as an integerCast a Javascript variable as an integer

Posted March 11th, 2015 in Javascript

If you attempt to add a numeric value to a string in Javascript, you'll end up with a string. If you get what appears to be a numeric value from a select option with Javascript, it's a string. To use a number that is cast as a string in Javascript as a number, first cast it to an integer with parseInt().

Use parseInt() to cast a string as an integer with Javascript

To ensure the value is an integer that you can do addition, subtraction, etc to, do this:

var x = parseInt(y);

If the number may have leading zeroes, pass the radix parameter to ensure the value is cast as base 10, otherwise it may be cast as an octal (or other) value:

var x = parseInt(y, 10);

As an example, if you're reading a value from a select with id "myselect" and need it to be a number, do this:

var ele = document.getElementById('myselect');
var x = parseInt(ele.options[ele.selectedIndex].value);