Chris 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.
Sites built in PHP can find good linux hosting across all the major web hosting providers.
PHP suhosin, sessions and shared SSL certificates
Posted May 10th, 2012 in PHP
There's a patch for PHP called suhosin which is part of the Hardened PHP Project to make PHP more secure. I came across an issue with the way session data is encrypted when using a shared SSL certificate on an old osCommerce install I occasionally have to support.
Note, this is not an issue with suhosin itself, but an issue with the way data is encrypted when using a shared SSL certificate.
sushosin session data encryption
When session data is written/read, sushosin encrypts/decrypts it using a variety of options as the encryption key. Read the configuration page for more details, specifically the Transparent Encryption Options section which also looks at the cookie options.
In particular, suhosin.session.cryptua and suhosin.session.cryptdocroot are enabled by default. There are no issues with the cryptua setting when it comes to shared SSL certificates, just with the cryptdocroot setting, and even then it won't affect all hosting setups depending how shared hosting is configured.
Encrypting the session data is a good thing. Although I imagine it's fairly trivial to decrypt it, at least it offers some immediate protection from someone just browsing the database or session files.
The issue with shared SSL certificates
If you have an SSL certificate specifically set up for your website with the same domain name, then there shouldn't be any issues at all with the default settings, because all the variables to do with encryption won't be affected. The document root will be the same regardless of whether it's through SSL or not.
A shared SSL certificate, on the other hand, will most likely have a different document root with the non-SSL and SSL parts of the site. They may even be on different servers.
Let's say the site we are looking at is www.example.com and the SSL portion of the site is at www.secure-example.com/example
The paths to these might be /var/www/example.com and /var/www/secure-example/example
As you can see the document root is different for each, which means the encryption/decryption key will be different for the SSL and non-SSL version of the site using the default settings.
The solution
All you need to do to fix this, is to disable the cryptdocroot option. This can be done in the suhosin configuration file, Apache virtualhost or .htaccess.
I prefer to just do this on a site-by-site basis so recommend doing it just in the .htaccess file. Add the following line to it, and then everything should work fine for new sessions:
php_value suhosin.session.cryptdocroot off
osCommerce notes
I mentioned I came across this issue with an osCommerce install, which is the only site I support which uses a shared certificate. For the sake of completeness, here's the relevent osCommerce configuration to get cookies/sessions working across shared SSL, using the example domains above:
define('HTTP_SERVER', 'http://www.example.com');
define('HTTPS_SERVER', 'https://www.secure-example.com/example');
define('ENABLE_SSL', true);
define('HTTP_COOKIE_DOMAIN', 'example.com');
define('HTTPS_COOKIE_DOMAIN', 'www.secure-example.com');
define('HTTP_COOKIE_PATH', '/');
define('HTTPS_COOKIE_PATH', '/example');
Which version of CentOS or RHEL is running?
Posted May 1st, 2012 in Linux/Unix/BSD and Quick Tips
The uname -a command will tell you which kernel version of Linux is running but doesn't give you any information about the distribution or distro version number. This quick tip shows how to do this for CentOS / Red Hat Enterprise Linux.
CentOS / RHEL version
From the command line enter the following command:
cat /etc/redhat-release
This will show you something like this:
CentOS release 5.4 (Final)
Easy! Hopfully now I've posted this I won't forget it next time...
iOS Simulator and Xcode 4.3
Posted April 26th, 2012 in Applications and OSX
I installed/upgrade Xcode on my Mac Lion to 4.3 and couldn't work out where the iOS Simulator was. It turns out you have to manually configure Xcode to install the simulator but even then there's no obvious way to run the iOS Simulator. This post shows how I did it.
Installing iOS Simulator
Start up Xcode, then select the Xcode menu and the Preference menu option. Go to the Downloads option in the preferences dialog window and you'll see the list of simulators etc as shown in the screenshot below.

Click the install buttons for the ones you want and away you go. If you want it to check and install updates automatically then check that box. I left it as-is in my setup.
Where is iOS Simulator?
The files downloaded and installed, but where or where is the simulator? I couldn't find it anywhere in the menu options including the Xcode -> Open Developer Tool submenu. And it's not in /Applications either.
The only way I could work out how to run the iOS Simulator was to navigation to the Applications folder with Finder, right-click Xcode and Show Package Contents, then navigate like so:
Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Applications
In the Applications folder you'll find the iOS Simulator app.
Drag it to the Dock, run it, and away you go.
Disable the MySQL query cache without restarting MySQL
Posted April 23rd, 2012 in MySql
The MySQL query cache enables caching of queries which, in theory, should speed querying the database up. It's possible to disable the MySQL query cache without restarting the server, although you also need to edit the configuration file to make the changes stick on restart.
Query to disable the cache
From the MySQL command line, a application like phpMyAdmin, or from a script, run the following SQL command to disable the query cache:
SET GLOBAL query_cache_size = 0;
This will take effect immediately. You will also need to modify the MySQL configuration file to keep it disabled on reboot. Locate the query_cache_size setting in the file and set it to 0.
I needed to do this today myself because one of the websites I manage kept getting locks which were preventing other queries from running, and we decided to shut off the query cache to see if it makes a difference. It's too early so far to tell whether or not it has.
Check out the related posts below for more information about the query cache and how to enable it in the first place.
Extract inline image attachments from an email with PHP
Posted April 13th, 2012 in PHP
A month ago I posted a PHP email message class for extracting attachments and have been asked by a couple of people how to extract inline images and make it so they can appear in the HTML content of the email. This post shows how to do this, using my email class to get the email.
The email class
The email class can be downloaded here. The file is a plain text PHP file, compressed as a zip file. I can't really offer any support for this code other than with additional tutorials like this one. For the moment it is poorly documented but when I get more time I'll do more work on it.
Inline images
Images can be embeeded in the HTML content of an email and sent along with the email. When they are "inline images" like this, the src property of the image starts with cid: followed by a unique identifier for the image. It's then added as a "message part" which is more commonly known as an "attachment" and can be referenced by the unique identifier with my email class.
The exact format of the cid varies depending on the email client, and is not consistant. For example, I dragged and dropped two images (named 1.jpg and 2.jpg) into Apple's Mail client and then to Gmail, and this is the resulting HTML from each.
Apple Mail:
I've removed the html and boy tags in the example below so it's not quite such a mess of tag soup.
<img id="9583f2e3-aa95-49dd-9576-a29dc4e2a72b" height="450" width="600" apple-width="yes" apple-height="yes" src="cid:3FE80658-A359-4A43-82EA-BEAEA7CEBAEA@local"> <img id="e710c040-0288-44c5-afb5-14cf5294879d" height="450" width="600" apple-width="yes" apple-height="yes" src="cid:BE4DF124-417B-4AFC-9DC9-F01818A942B2@local">
Gmail:
<img src="cid:ii_136a895175f87da3" alt="Inline images 1"><br> <div><img src="cid:ii_136a895663ed0afd" alt="Inline images 2"><br></div>
So both have cid: followed by a unique identifier. Apple adds a @local at the end which is presumably the domain name, Gmail does not. Other email clients will format the identifier differently.
Using the email class to download the message
Connect using the imap mail functions first and then use the email class to fetch the first message. The class doesn't yet have functions for seeing how many messages are in the mailbox etc, use the regular imap functions for that.
$login = 'me@example.com';
$password = 'mypassword';
$server = '{imap.gmail.com:993/ssl/novalidate-cert}';
$connection = imap_open($server, $login, $password);
$emailMessage = new EmailMessage($connection, 1);
$emailMessage->fetch();
The structure of $emailMessage will be like this for the Gmail example:
EmailMessage Object
(
[connection:protected] => Resource id #4
[messageNumber:protected] => 1
[bodyHTML] => <img src="cid:ii_136a895175f87da3" alt="Inline images 1"><br>
<div><img src="cid:ii_136a895663ed0afd" alt="Inline images 2"><br></div>
[bodyPlain] => [image: Inline images 1]
[image: Inline images 2]
[attachments] => Array
(
[ii_136a895663ed0afd] => Array
(
[type] => 5
[subtype] => JPEG
[filename] => 2.jpg
[data] => ...
[inline] => 1
)
[ii_136a895175f87da3] => Array
(
[type] => 5
[subtype] => JPEG
[filename] => 1.jpg
[data] => ...
[inline] => 1
)
)
[getAttachments] =>
)
We can now do do a regular expression match to extract all the src="cid:..." from bodyHTML and then replace them with a full http (or https) URL to the image on our filesystem.
preg_match_all('/src="cid:(.*)"/Uims', $emailMessage->bodyHTML, $matches);
The $matches array will contain the following:
Array
(
[0] => Array
(
[0] => src="cid:ii_136a895175f87da3"
[1] => src="cid:ii_136a895663ed0afd"
)
[1] => Array
(
[0] => ii_136a895175f87da3
[1] => ii_136a895663ed0afd
)
)
So we want to loop on the items in $matches[1] as that contains the unique idenfier which is used as the array key for the attachments array. They can be saved to file with a unique name and the src attribute in the HTML changed to a full URL.
if(count($matches)) {
$search = array();
$replace = array();
foreach($matches[1] as $match) {
$uniqueFilename = "A UNIQUE_FILENAME.extension";
file_put_contents("/path/to/images/$uniqueFilename", $emailMessage->attachments[$match]['data']);
$search[] = "src=\"cid:$match\"";
$replace[] = "src=\"http://www.example.com/images/$uniqueFilename\"";
}
$emailMessage->bodyHTML = str_replace($search, $replace, $emailMessage->bodyHTML);
}
I'll leave it up to you to work out how you want to craft your unique filename. Note you'll need to change /path/to/images to the actual path where the file should be saved, and http://www.example.com/images/ to the actual URL that points to that location.
Download the code from this post
To save you having to copy and paste, here's download links for the full PHP example from this page (which contains additional inline comments), and also the EmailMessage class:
- PHP example
- EmailMessage class
Both are gzip compressed and contain a single PHP plain text file.
Remove ads at the top of Gmail
Posted April 10th, 2012 in Applications
Gmail by default shows ads above the list of emails. It's easy to switch these off but they're not intuitively named when looking at Gmail's settings. This post shows how to switch them off.
The defaults - ads above the message list
The first screenshot below shows the default setting, which is to show ads above the message list. I've highlighted the ad in the screenshot with a red box.

Remove the ads
To remove the ads, click the settings cog icon above-right from the message list. This will show a drop down menu where you can select the "Settings" option. This is shown in the screenshot below, with a red box around the icon and menu.

Don't show "Web Clips"
The ads are called "Web Clips". Along the top of the settings are a series of tabs/options and you'll see one labelled "Web Clips". Click that and then un-check the "Show my web clips above the Inbox" option. You don't need to click a button to save; it immediately takes effect.
Again, the relevent things to click are highlighted with a red box in the screenshot below.

Now there are no ads above the message list
Now go back to your inbox and there are no longer any ads above the message list.

Disable the screenshot shadow on Mac OS X
Posted April 9th, 2012 in OSX
When you take screenshots on Mac OS X there's a shadow around the screenshot by default. This post shows how to disable the shadow from the screenshot and how to subsequently restore the shadow.
Screenshot example with shadow
The first example below is a screenshot with the default shadow around the window. It's a nice effect but makes the image a lot bigger than it needs to be, which can be less than useful when doing documentation etc.

Screenshot example with shadow disabled
The second example below shows a screenshot of the same terminal window above, but this time with the shadow disabled.

The downside with this particular example is there's no borders showing on the window in the screenshot, so there appears to be a lot of whitespace between the top of the screenshot and this text here, even though all that white space is part of the image.
So depending on the app you are taking a screenshot of, the result of removing the shadow may be good, or it may be not so good.
Disable the shadow from the screenshot
Open up Terminal and enter the following two commands:
defaults write com.apple.screencapture disable-shadow -bool true killall SystemUIServer
The next screenshot you take will not have the shadow.
Enable the shadow in the screenshot
To reverse the above, enter the following two commands in Terminal. As you can see the only difference is changing "true" to "false".
defaults write com.apple.screencapture disable-shadow -bool false killall SystemUIServer
Now shadows will appear in the screenshots again.
Recursively upload files via FTP using NCFTPPUT
Posted April 3rd, 2012 in Linux/Unix/BSD
If you have a lot of files to upload to a website and the only access is via FTP then you can use a nice GUI tool to just drag and drop the directory, or you can use the command line ncftpput tool.
Why use a command line tool?
I needed to upload a directory containing thousands of files and directories with many subdirectories. I could have used a GUI tool to do it but it would have taken a really long time. There was no SSH, SFTP, rsync or SCP access to the website in question so I did this:
1) tar up and gzip the directory on my local machine
2) copy it via sftp to my US based VPS (just one file copied up)
3) decompress it on the VPS
4) use ncftpput to copy it to the website (all files copied from VPS to website)
The whole process took a couple of minutes or so, instead of potentially 30 minutes or longer using a GUI tool like Transmit on my crappy ADSL connection.
How to use ncftpput to recursively copy a directory
Let's say the directory containing the files to upload is to go into the website's root directory and is called "myapplication".
The current working directory looks like this:
$ ls -l total 8380 drwx------ 5 chris chris 4096 Aug 23 2010 myapplication -rw-r--r-- 1 chris chris 8418990 Apr 3 11:36 myapplication.tar.gz
To recursively upload the myapplication directory, do this:
ncftpput -u [username] -p [password] -R [hostname] / myapplication
Substitute [username], [password] and [hostname] with the appropriate values; -R tells ncftpput to recursively upload; / is the directory you want to upload to, and myapplication at the end is the directory to upload.
How to set the Gmail notification ringtone on Android
Posted April 2nd, 2012 in Applications
On an Android phone there is a notification ringtone which will be used by default for all notifications. The Gmail app allows you to specify a different notification ringtone which can be quite useful for having the default for SMS messages and something else for new emails, but the option is buried quite deep and I can never remember where it is, so this post will help to remind me in the future.
Default notification ringtone
The default notification ringtone for all apps etc is at:
Android Setttings -> Sound -> Notification Ringtone
This will be used for everything unless specified differently in each app, when it can be specified in the app. As I mentioned above, this can be useful in the case of Gmail for having a different notification ringtone for email than the default, which will be used for text messages.
Gmail notification ringtone
You can specify a different notification ringtone for each account and it's buried quite deep in the app settings. When I wanted to change it myself yesterday, it took a while to work out where it was.
Gmail App -> Menu -> More -> Settings -> [Account Name] -> Labels to notify -> Inbox
Phew, and now you can set it by touching the "Ringtone" setting.
PHP email message class for extracting attachments
Posted March 15th, 2012 in PHP
I've done a bit of work in the past extracting attachments from email with PHP and posted a few articles here showing how to do it. None of them have really been all that satisfactory and so a little earlier this year I started again from scratch. I've posted here what is a work-in-progress due to requests from several people. It's not complete but it does work.
Notes about the email class
When working on it, I discovered just how difficult it is to actually get information out of emails because email clients format emails differently, and also differently depending on whether there are attachments, inline attachments, html and/or plain text body parts.
This class recursively loops through the email and finds all the attachements including email messages themselves that may have been attached and recurses through those too. While doing all this it puts the html and plain text body of the top level message into the bodyHTML and bodyPlain properties.
Unfortunately I didn't write any comments through the code because I was intending to get it finished at the time and write a blog about it which would have served that function, but time ran away from me.
Basically the format of a message is in "parts" and they can be like e.g. 1, 1.1, 1.2, 1.2.1, 1.2.2, etc and you need those numbers to be able to get the "attachments". I worked out through trial and error with many emails that the order and numbering varies considerably.
At some point in the future I will do some more work on this code, making it more usable for email in general, adding commenting etc and probably post it to GitHub.
Download the email class
The file is a plain text PHP file, compressed as a zip file. I can't really offer any support for this code so it's really up to you to try it out and see what you can do with it.
