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.

Updating bash for shellshock on Debian 5 LennyUpdating bash for shellshock on Debian 5 Lenny

Posted September 30th, 2014 in Linux/Unix/BSD

If you are running Debian 5 Lenny and upgrading the distro to Debian 6 or 7 is not an option, you will need to compile bash from source, applying patches in order to secure your server against the bash shellshock vulnerability.

Patching bash on Debian 5 Lenny

Follow the instructions on this page under the "Patching older and unsupported systems" section. The page is kept up to date as new vulnerabilities are found, and shows the tests you need to run.

You will need to continue to monitor the page and apply updates as and when they become available by manually patching and compiling from source each time.

Note that the compiler may stall on "checking for working mktime..." for some time, but it will continue and finish compiling eventually.

An alternative option is to remove bash from your install and use another shell instead, obviously first making sure any shell scripts you have running will continue to function.

Warning: Skipping the data of table mysql.eventWarning: Skipping the data of table mysql.event

Posted September 29th, 2014 in MySql (Updated September 30th, 2014)

The events table was introduced to MySQL in 5.1.6 and when upgrading you will start to see the warning "Warning: Skipping the data of table mysql.event" when using mysqldump. This is not an error as such, but more to make it clear to you that something has changed.

How to include the event table with mysqldump

Use the --events flag when using mysqldump to include the events table:

mysqldump -u[username] -p --events mysql > mysql.sql

This will then suppress the warning message from the output.

How to exclude the event table with mysqldump

Use the --ignore-table flag when using mysqldump to exclude the events table like so:

mysqldump -u[username] -p --ignore-table=mysql.event mysql > mysql.sql

This will then suppress the warning message from the output.

Output when using -T / --tab flag

This is an update the day after originally writing this post. Using the above flags suppresses output when doing a straight SQL dump to file. When using the -T / --tab flag to write the data out to tabbed data files, you will still get this output when dumping events:

--
-- Dumping events for database 'mysql'
--

and this when attempting to ignore the table (which is the original message addressed by this post):

-- Warning: Skipping the data of table mysql.event. Specify the --events option explicitly.

This happens for me on two different servers which run MySQL 5.1.73. If anyone has any suggestions about how to suppress this output, while allowing other errors/warnings to be displayed, it would be greatly appreciated to prevent output from being emailed from automated backup processes.

Signature verification error when running apt-get update on Debian 6Signature verification error when running apt-get update on Debian 6

Posted September 28th, 2014 in Linux/Unix/BSD

When updating a Debian 6 server for the bash shellshock bug, I got a signature verification error message when running apt-get update. This post shows how to fix it; it may also solve the issue for other versions of Debian, but this post was specifically written when updating Debian 6 Squeeze.

Error message

After running "sudo apt-get update" this was the error message:

W: A error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: http://ftp.nz.debian.org squeeze-updates Release: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 8B48AD6246925553

W: Failed to fetch http://ftp.nz.debian.org/debian/dists/squeeze-updates/Release  

W: Some index files failed to download, they have been ignored, or old ones used instead.

The fix

Run this to fix it:

sudo apt-get install debian-archive-keyring

Updating bash for shellshock on Debian 6 SqueezeUpdating bash for shellshock on Debian 6 Squeeze

Posted September 28th, 2014 in Linux/Unix/BSD (Updated September 30th, 2014)

An update has been made for the bash shellshock bug on Debian 6 Squeeze but it isn't available unless you update your apt sources to include the LTS repository.

Add the LTS repository

If you haven't already, add this to /etc/apt/sources.list:

deb http://http.debian.net/debian/ squeeze-lts main contrib non-free
deb-src http://http.debian.net/debian/ squeeze-lts main contrib non-free

Then run

sudo apt-get update
sudo apt-get upgrade

Check for vulnerabilities

The current checks I have found to ensure bash is not affected are as follows:

This test this will echo "vulnerable" if vulnerable:

env 'x=() { :;}; echo vulnerable' 'BASH_FUNC_x()=() { :;}; echo vulnerable' bash -c "echo test"

This test will create a file at /tmp/echo and echo the date if vulnerable:

cd /tmp; rm -f /tmp/echo; env 'x=() { (a)=>\' bash -c "echo date"; cat /tmp/echo

This one will output "CVE-2014-7186 vulnerable, redir_stack" and possibly a segmentation fault if vulnerable:

bash -c 'true <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF <<EOF' || echo "CVE-2014-7186 vulnerable, redir_stack"

A gotcha with PHP's PDO::FETCH_CLASSA gotcha with PHP's PDO::FETCH_CLASS

Posted September 26th, 2014 in PHP

PHP's PDO has a nifty way of fetching database records into an object, but there's a slight gotcha when also using a constructor which initializes the class properties.

tl;dr

Data is populated before the constructor is called. To populate data after the constructor use PDO::FETCH_PROPS_LATE i.e.:

$stmt->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, 'className');

Longer answer

PDO's setFetchMode() allows you to specify the way data is retrieved, e.g. as an associative array, indexed array, etc or into an object.

In the following examples:
- $pdo is a connected PDO database object
- $sql is the query to run, with ? placeholders
- $data is an array of data for those placeholders
- $class is the name of the class to fetch the data into

Run a query using PDO and then fetch the result into an object like this:

$stmt = $pdo->prepare($sql);
$stmt->execute($data);
$stmt->setFetchMode(PDO::FETCH_CLASS, $class);
$object = $stmt->fetch();

This is really useful if you are implementing some sort of data object with a bunch of functions attached to it; the object returned is populated from the database and you can then call those functions.

The gotcha

In the above example, the data is populated into the object first, and then the constructor is called (if there is one). If the constructor does some sort of initialization, then values from the database may be overwritten with the same values every time.

Using the following trivial example, no matter what the value of "id" is in the database, the object will always set it to 1 after the record is loaded:

class foo {
    public $id;
    function __construct()
    {
        $this->id = 1;
    }
}

Again, this is a trivial example which you probably wouldn't do, but it illustrates the point. You might have a data object that sets default values in the constructor, which clobbers the values loaded from the database after they are set into the object.

The solution

This may not be an issue for you, and you may indeed want the constructor to run after the data is populated into the object. But if you don't, simply add PDO::FETCH_PROPS_LATE when calling setFetchMode() and the constructor will be called first:

$stmt->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, 'foo');

Done! I hope this was useful :)

Remove extension from a filename with PHPRemove extension from a filename with PHP

Posted September 24th, 2014 in PHP

If you've got a filename that you need to remove the extension from with PHP, there are a number of ways to do it. Here's three ways, with some benchmarking.

Using pathinfo

The pathinfo() function returns an array containing the directory name, basename, extension and filename. Alternatively, you can pass it one of the PATHINFO_ constants and just return that part of the full filename:

$filename = 'filename.html';
$without_extension = pathinfo($filename, PATHINFO_FILENAME);

If the filename contains a full path, then only the filename without the extension is returned.

Using basename

If the extension is known and is the same for the all the filenames, you can pass the second optional parameter to basename() to tell it to strip that extension from the filename:

$filename = 'filename.html';
$without_extension = basename($filename, '.html');

If the filename contains a full path, then only the filename without the extension is returned.

Using substr and strrpos

$filename = 'filename.html';
$without_extension = substr($filename, 0, strrpos($filename, "."));

If the filename contains a full path, then the full path and filename without the extension is returned. You could basename() it as well to get rid of the path if needed (e.g. basename(substr($filename, 0, strrpos($filename, ".")))) although it's slower than using pathinfo.

Benchmarking

Running each of these in a loop 10,000,000 times on my Mac with PHP 5.4:

pathinfo: 10.13 seconds
basename: 7.87 seconds
substr/strrpos: 6.05 seconds
basename(substr/strrpos): 11.98 seconds

If the filename doesn't contain the full path or it doesn't matter if it does, then the substr/strrpos option appears to be the fastest.

If the filename does contain a path and you don't want the path but do know what the extension you want to remove is, then basename appears to be the fastest.

If the filename contains a path, you don't want the path and you don't know what the extension is, then use the pathinfo() option.

Conclusion

There will be plenty of other ways to do this, and some may be faster. In a lot of cases, the speed probably doesn't really matter that much (the 10 seconds to run pathinfo was 10 million times, after all); the purpose of this post was to show a few ways to remove the extension from the filename with PHP.

PhpStorm 8 and the backspace/delete keyPhpStorm 8 and the backspace/delete key

Posted September 22nd, 2014 in Applications and PHP

PhpStorm is an IDE for PHP and version 8 was released a few days ago. The update included a "backspace smart indent" option, which I personally find quite annoying.

What's the problem?

Take some example code like this:

for( ... ) {
    if( ... ) {
    }
}

If the insertion point is just after the closing curly bracket that's part of the if condition, hitting return creates a new line and puts the insertion point in the correct indented place, as it did in the previous versions.

Hitting delete (on a Mac) / backspace (on Windows) then deletes that entire blank line and moves the insertion point back to just after that closing curly bracket. This is the bit I find annoying.

This logically makes sense and I'm sure I can get used to it in time, but it was driving me nuts because I'm so used to the delete key taking me back one indentation point.

The solution

Go to PhpStorm's preferences, and in the IDE Settings section go to Editor -> Smart Keys.

Uncheck "Backspace smart indent" and then click the "OK" button.

Done.

Alrernatively, learn to use it the new way :) 

PHP 5.4+ session_is_registered, session_register, session_unregisterPHP 5.4+ session_is_registered, session_register, session_unregister

Posted September 18th, 2014 in PHP

Often it can be difficult to upgrade legacy websites to newer versions of PHP without substantial refactoring of the code. Sometimes it's fairly easy with wrapper functions, which is possible for the deprecated session_is_registered(), session_register(), and session_unregister() which were removed in PHP 5.4.

Wrapper functions for session_is_registered() etc

Include the following code for PHP 5.4+ projects that require the use of session_is_registered(), session_register(), and session_unregister():

function session_is_registered($name)
{
	if (isset($_SESSION[$name])) {
		return true;
	}
	else {
		return false;
	}
}

function session_register()
{
	$args = func_get_args();
	foreach ($args as $key) {
		$_SESSION[$key] = $GLOBALS[$key];
	}
}

function session_unregister($name)
{
	unset($_SESSION[$name]);
}

Obviously it's a good idea to replace the function calls in the legacy code, but the above code can be a quick fix so you can move on and sort out any other legacy issues... 

How to create passwords for NginxHow to create passwords for Nginx

Posted September 17th, 2014 in Nginx Web Server

Apache has the htpasswd command line tool to generate passwords for basic HTTP authentication but Nginx doesn't, as far as I am aware. So how do you create passwords for Nginx?

tl;dr

printf "USERNAME:$(openssl passwd -crypt)\n" >> /path/to/password/file

Substitute USERNAME with the actual username and /path/to/password/file with the file to append it to. You will then be prompted for the password and then again to verify it. See below for another option where you can have the password included in the one line command.

Longer answer

I can't remember where I got the above snippet from, but it seems to work just fine on the websites I've enabled it on using Debian 7 Wheezy. I've seen other posts which suggest installing apache2-utils, but that seems a bit like overkill to just create some encrypted passwords.

Let's say we want to create a password for "chris" in the file at /var/www/mywebsite/.htpasswd The file doesn't need to be named .htpasswd, but we may as well follow the Apache convention.

Add the following to your Nginx config into the appropriate section (e.g. the server as a whole, or a specific location block):

auth_basic "Restricted Access";
auth_basic_user_file /var/www/mywebsite/.htpasswd

And now create/add chris to the .htpasswd file:

printf "chris:$(openssl passwd -crypt)\n" >> /var/www/mywebsite/.htpasswd

You'll now be prompted for the password, and then again to confirm. The name:password pair will be written to the file, so all you need to do now is reload Nginx for the configuration change to take affect and you're good to go. You can add/remove users from the file without having to reload Nginx.

If you want, you can also enter the password as part of the command like so:

printf "chris:$(openssl passwd -crypt p@ssw0rd)\n" >> /var/www/mywebsite/.htpasswd

This will of course then be recorded in your bash history so is best not to do. (Refer to my "Clear the bash history" post for details about how to clear it for the session or empty it completely.)

Gotchas

The nice thing about Apache's htpasswd command is it will replace an entry for an existing username; using this method will not. If you add a new username/password combination for a user that is already in the file, the first username/password in the file that matches the username is the one that is used.

So if you need to update a password, you need to remove the user from the file first, or run the command without concatenating it to the file and copy and paste the new encrypted password into the file manually.

Versions tested on

I've tested this on Nginx 1.6 on Debian 7 Wheezy, using Nginx from the Dotdeb repository.

Over to you

Any ideas of a better / more correct way to do this?

CSS :not and :empty selectors to apply styles when an element is empty and not emptyCSS :not and :empty selectors to apply styles when an element is empty and not empty

Posted September 16th, 2014 in HTML and CSS

There may be times you need to apply a style if an element is empty, or if it is not empty. Use the :not & :empty selectors to do this, as shown in this post. They are supported by all modern browsers, and Internet Explorer from 9 and up.

tl;dr

Check out the example here or download the compressed version here.

Applying styles to an empty element

You can use :empty to apply styles to element that contains no content. For example:

<p class="test2"><!-- this contains no content other than an HTML comment --></p>

You can apply a style to this element if it contains no content like so:

.test2:empty {
    border: 1px solid blue;
}

This will put a blue border around the element. Note that because it contains no content, if the element has no padding then it will be more like a line than a bordered element, but it's just an example.

Note that being empty means there is no content at all, including white space.

Applying styles to an element that is not empty

You can also :not in conjunction with :empty to do the opposite: apply a style when the element is not empty. Consider the following two paragraphs:

<p class="test1">This element contains content</p>
<p class="test1"><!-- this contains no content other than an HTML comment --></p>

When the following style is applied, the first paragraph will have a red border and some padding, and the second paragraph with have no additional styling applied, unless it's been defined elsewhere:

.test1:not(:empty) {
    border: 1px solid red;
    padding: 10px;
}

Browser support

This has been tested with a <!doctype html> and has the following browser support, according to W3Schools (:not & :empty):

  • Chrome 4.0+
  • Firefox 3.5+
  • Internet Explorer 9.0+
  • Safari 3.2+
  • Opera 9.6+

I've personally tested it myself on the following, which it works on:

  • Chrome 36 on Windows 7
  • FF29 on Windows 7
  • FF30 & FF32 on WindowsXP
  • IE9 on Windows 7
  • IE10 on Windows 8
  • IOS7
  • Default browser on Android 4.1.2 on a Sony Xperia Acro S
  • Chrome 36 on Android 4.1.2 on a Sony Xperia Acro S

And of course I double checked that it doesn't work in IE8, and it doesn't.

Examples

As linked to at the start of this post, have a look at the example here or download the compressed version here.

Try it yourself

I given a couple of pretty basic examples but the world is your oyster; try it out where needed and see what you can do. I personally came across :not and :empty when needing to suppress the styling of some empty messages divs in a CMS system - I'd keep seeing blank yellow or blue boxes all over the place. Using :empty I was able to remove the existing styling when the element didn't have a message, without having to hack the core stylesheet.