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 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.

Web Developer Form Filler plugin for Google ChromeWeb Developer Form Filler plugin for Google Chrome

Posted September 12th, 2014 in Applications

I need to test web forms a fair bit, and there's also a particular online registration website that I can't get all the information I need until I've submitted an initial form, and got tired of always filling these forms in. So enter the search for a decent automated form filler plugin for Google Chrome.

tl;dr

After trying out a couple, Web Developer Form Filler did exactly what I want with a nice interface, so I didn't look any further.

Longer answer with screenshots

I can't remember what the first form filling plugin I tried was, but it didn't really work as I wanted, which was to easily save the contents of an existing form and then populate a form with the saved data, from one of multiple URLs using the same form.

Plugins like this are useful for both developers like me, and also if you ever complete the same form on the same website many times over and want to save time next time.

The second one I tried was the web developer form filler, which can be installed here.

It puts a little pencil icon in the plugin area next to Chrome's omni bar and when you click it you can save the current form (and give it a useful name) or click "Restore" to load the form values into the current form:

web form filler plugin screenshot 1

The little cog icon button gives you some extra options. The list of saved forms will match the filter criteria, so you have to option to change the filter or show all the saved forms to choose from.

web form filler plugin screenshot 2

Nice little plugin and has worked really well for me so far.

There was an error message the first time I tried to use it, but I suspect it's because I was trying to do something with a form that was already loaded up before I installed the plugin. After reloading the form it all worked smoothly.

iPhone 6 and Responsive Web DesigniPhone 6 and Responsive Web Design

Posted September 11th, 2014 in Miscellaneous Postings (Updated September 13th, 2014)

So Apple have announced the iPhone 6 and 6 Plus, featuring bigger phones than before. As a web developer creating responsive websites, does the size matter?

Answer

While it might be an issue for app developers, it shouldn't be if you're a web developer, because there already a bazillion screen resolutions and you should be designing for breakpoints, not resolution.

I liked this Tweet, which I think sums it up perfectly:

Here's a couple of good articles on the subject:

Defining Breakpoints ("Breakpoints are the point a which your sites content will respond to provide the user with the best possible layout to consume the information.")

Logical Breakpoints For Your Responsive Design ("There are several tactics for deciding where to put breakpoints in a responsive design. There is the rusty idea that they should be based on common screen sizes, but this doesn’t scale well. There are no “common” screen sizes. Another popular tactic is to create a breakpoint wherever the layout breaks.")

Further reading

I added this on September 13th 2014: What iPhone 6 screen size means for developers was posted on Clean Crisp Code.

Location of MySQL's my.cnf fileLocation of MySQL's my.cnf file

Posted September 10th, 2014 in MySql

MySQL's main configuration file is my.cnf and it is located in different locations depending on the operating system, distribution and version. This post shows how to find out where MySQL will look for the config file.

Use mysql + grep to find out where MySQL will look

Running this command from the command line / terminal will show where MySQL will look for the my.cnf file on Linux/BSD/OS X systems:

mysql --help | grep "Default options" -A 1

This will output something like this:

Default options are read from the following files in the given order:
/etc/my.cnf /etc/mysql/my.cnf /usr/etc/my.cnf ~/.my.cnf

You can now check for files using the above output at /etc/my.cnf, then /etc/mysql/my.cnf and so on.

If there isn't one at one of those locations, you can create one and know MySQL will use it.

Often a distro will have defaults compiled into the MySQL Server and Client, and won't have even an empty my.cnf file, so if you want to have settings that stick when MySQL is restarted, then you'll need to create the file and put them in there.

Page history

This page was originally posted on November 8th 2010 and had at least one update between then and August 11th 2011. It originally showed locations of the my.cnf file on popular Linux distributions.

It was rewritten on September 10th 2014 to show how to work out where MySQL looks for the my.cnf file instead, because the file often doesn't exist on more recent distros unless you, the administrator, create it first.

Which version of Debian is running?Which version of Debian is running?

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

uname -a gives you a lot of useful information about the Linux kernel version running, but not the distro release version. This quick tip shows how to get the Debian release version from the command line.

Debian version

From the command line / terminal, enter the following command, which will output the version:

cat /etc/debian_version

Example output for Debian 7 Wheezy:

7.6

Example for Debian 6 Squeeze:

6.0.1

Example for Debian 5 Lenny:

5.0.7

Yes, there's some old servers there needing an upgrade :)

Get the MX records for domain mail hosted with GoDaddyGet the MX records for domain mail hosted with GoDaddy

Posted September 5th, 2014 in Miscellaneous Postings

I don't use GoDaddy for any services myself anymore, but one customer has some domains and email hosted with them, and I couldn't work out what the correct MX records should be. This post shows how to find them, with step by step screenshots.

tl;dr

My Account -> Launch button in email section (don't expand it) -> Server Settings

Note: don't expand email and click the launch button next to the appropriate domain (as per the GoDaddy instructions), which is how I got lost myself.

Longer answer with screenshots

I couldn't work out where to find out what the MX records should be for GoDaddy hosted email (our DNS records are hosted using DNS Made Easy, not GoDaddy). After a quick Google search, I found this post, which is wrong. It heads you in the right direction but then leaves you scratching your head about where to find the server settings option.

As at September 4th 2014, this is how to do it. It may change in the future.

Step 1 - Launch email manager

Go to "My Account" and click the "Launch" button next to "Email", as highlighted in the screenshot below with the red box.

Do not expand it using the + button and then launch next to one of the domain names, which is what GoDaddy's instructions say to do.

getting godaddy mx records step 1

Step 2 - Click server settings

Now click "Server settings" as highlighted below with the red box.

getting godaddy mx records step 2

Step 3 - MX Records popup

This will open a popup window where you can select the domain name from a drop down box (the one in the screenshot were I've blacked out the domain name).

If the MX records are set correctly fgor GoDaddy, then it was say so as shown below. If they are not, it will first show the existing MX records on the left, and then what they should be on the right to use GoDaddy for mail.

getting godaddy mx records step 3

By the time I went back to get this screenshot, my new MX settings had updated and were showing as correct, otherwise I'd have shown a screenshot when the settings are incorrect too.

Photoshop CC 2014 pslog.txt filePhotoshop CC 2014 pslog.txt file

Posted September 4th, 2014 in Applications (Updated September 15th, 2014)

For some reason Photoshop CC 2014 on OS X always creates a file called pslog.txt in your user root directory whenever it starts. If you delete it, it's recreated the next time you start Photoshop.

What's in the file?

The file contains the following line, where the first section is a date and time stamp:

00000.2014.09.03_16:51:41.056(+00.000) Headlights logging is not enabled

What can you do about it?

Not much. Adobe are aware of this issue and will apparantly be addressesing it in the next update, according to this message thread.

If it really bothers you, you can hide it by running this command in Terminal:

chflags hidden ~/pslog.txt

And if you need to show it again:

chflags nohidden ~/pslog.txt

Please note, this post originally used the "setfile" command to change the file's flags but this is not part of the default install of OS X, whereas chflags is. Thanks to Jesse Jackson for pointing this out.

PHP PDO class to set the MySQL auto_increment_incrementPHP PDO class to set the MySQL auto_increment_increment

Posted September 3rd, 2014 in MySql and PHP

A few days ago, I posted how to temporarily change the auto increment increment in MySQL. This post has an extension class to PHP's PDO to get the current auto increment value, change it to a new value and then reset it back to the original.

tl;dr

Download the PHP file here, compressed as a ZIP file.

More information

This PHP script has a class called PDOMySQLExtension, which extends PDO. You then create the database object in the same way as you would when using PDO, but there's three additional methods and a protected property which stores the original auto increment value for restoring it to how it was before you started messing around with it.

If you don't use PDO, then it should be easy enough to use the code in the functions as separate functions or as a subclass from another database class.

Subclass methods

getAutoIncrement(): this returns the current auto increment increment value from the current MySQL connection. By default this is 1, but on replicated master-master servers it's often set to a different number, typcially the number of servers in the replication chain. When this is called, the original value is stored in the protected originalAutoIncrement property if it hasn't already been.

setAutoIncrement(): this changes the setting to the new value, storing the original value in the protected originalAutoIncrement property if it hasn't already been. Note that it only retains this setting for as long as the connection to the MySQL server is going. A second script connecting to the database will insert records using the default increment.

restoreAutoIncrement(): resets the auto increment increment value back to what it was before being changed with setAutoIncrement.

But why?

I personally needed to do this for a particular project so have shared the code here for others to use. In my case, the two servers had an increment value of 2 and increment offsets of 1 & 2 (so one will do 1, 3, 5 and the other 2, 4, 6 etc) but the table in question needed to increment in 1s each time a new record was added, as per the client's request.

So the code looked something like this:

$pdo->setAutoIncrement(1);
$pdo->query('sql query to insert record into table');
$pdo->restoreAutoIncrement();

Gotcha #1

One thing to be aware of is that the increment value in the database will be stored as part of the table after a record is inserted.

If you have an auto increment increment value of 3 and an offset of 1, then after the first record is inserted (1) the next one will be 4, even if you change the increment value to 1 after the first insert. I found this out from testing/experimenting with the script linked to from this post.

Gotcha #2

Another gotcha is that the next record inserted won't necessarily be the last record plus the increment value. Again using 3 as the example with 1 as an offset, records would normally be inserted as 1, 4, 7, 10, 13 and so on.

If you change the increment to 1 the next two records inserted will be 16 then 17.

If you then change it back to 3, the next record will be 19, because that's the regular sequence for a table incrementing in 3s with an offset of 1.

Conclusion

I hope this script is useful to some people. It's a bit of an edge case but useful to share for the odd person who might need it.

Feedly icon appearing over web pagesFeedly icon appearing over web pages

Posted September 1st, 2014 in Applications

When Google announced the death of Google Reader, the RSS reading world threw their hands up in collective horror. And then we discovered there were better alternatives, such as Feedly. Feedly has a Chrome plugin, which from yesterday/today has "Feedly Mini" which appears on the bottom right of all pages. I find this somewhat annoying, but it's very easy to disable.

tl;dr

  • Go to Chrome's options.
  • Select "Extensions" from the left nav
  • Uncheck the "enabled" checkbox next to the feedly plugin to completely disable the plugin OR
  • Click "Options" under the feedly plugin THEN
  • Uncheck the "Show feedly mini icon on the bottom right of each page" option
  • You will need to reload pages for the icon to go away

More information

There's really not much more to it than the above, other than to send you in the direction of the blog post annoucing that "Feedly Mini is Back" which also covers some of the things it does.

I had forgotten that I'd installed a Feedly plugin, so was somewhat surprised when Chrome suddenly started showing a Feedly icon bottom right on all pages and though it was some sort of browser bug. Restarting didn't solve the problem, and Google quickly found me the above blog post which steered me in the right direction.

Note as per the Feedly blog post, should you wish to use it, Feedly Mini is currently only available for Chrome but Firefox and Safari are in the pipeline, as is support for https pages.