Multiple versions of PHP on Debian/Ubuntu

For some reason, when you search online for how to setup multiple versions of PHP on your Debian or Ubuntu server you will find many articles that state that you have to compile PHP manually. This is not true, as I will demonstrate. Compiling is not necessary, it’s complicated for less experienced users and requires you to install many additional packages on your server.

Having multiple versions is actually quite easy. You just need to install two prerequisites:

 

1
apt-get install apt-transport-https ca-certificates

Get the GPG key

1
wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg

Add custom repository:

1
echo 'deb https://packages.sury.org/php/ jessie main' >> /etc/apt/sources.list.d/php.list

Update apt cache:

1
apt-get update

And now you are able to install different versions of PHP alongside each other. For example you could install PHP 7.1 and php extension for this version like this:

1
apt-get install php7.1 php7.1-fpm php7.1 php7.1-mysql

PHP 7.1 will be installed to /usr/bin/php7.1 and symlink will be made in /etc/alternatives that will enable you to call this version of PHP from the command line with just ‘php’ command. Other versions you install from sury.org will be set up in similar manner. One thing is worth mentioning here – when setting cron jobs that execute PHP scripts via CLI you should set absolute path (e.g. /usr/bin/php7.0), or the version of PHP will change at some point if you install more version of PHP or upgrade your server and that could potentially cause problems with some PHP applications.

Configuring your web server to use this version of PHP is not that hard and there are multiple ways to do this. For example, this is how I configured Apache for an application that requires PHP 7.1:

1
2
3
<FilesMatch \.php$>
  SetHandler "proxy:fcgi://127.0.0.1:9071"
</FilesMatch>

PHP-FPM is configured to listen to loopback network interface on port 9071 in /etc/php/7.1/fpm/pool.d/www.conf by commenting out the default socket and adding a new entry, like this:

1
2
;listen = /run/php/php7.1-fpm.sock
listen = 127.0.0.1:9071

That’s all there is to it.

Read More

Using PHP logging

Every PHP developer learns early in his/her career to use var_dump(), print_r() and similar methods of debugging the code. These are easy to use and invaluable in writing anything but the simplest applications. However, sometimes dumping a variable is not a good option.

For example, at the moment I’m working on developing an API for a Symfony application. I’m using curl from the terminal to interact with this API. The problem is that when Symfony is in development mode it prints a lot of pretty HTML to the browser when there’s an error, which is a bit inconvenient when you are in the terminal. Piping the output to ‘more’ and paging through the HTML code in order to find the error message is slow and tedious process. Another example is working on an AJAX application which communicates in JSON or XML with the server. Dumping debug data into server responses would break JSON or XML.

In these cases, it is best to log errors or our debug data to a log file. In this example I’ll be using the default log file, set in php.ini. You could also output data directly to a file specified by you, for example:

1
file_put_contents(__DIR__.'/log-file',$debug_info);

This would create the specified file right next to the PHP file you are debugging, convenient when all you have to work with is an SSH terminal on a remote server.

So, we must first make sure that error logging is enabled and that PHP can log to the specified log file. Two (three) PHP directives are important here, log_errors must be set to On and error_log must point to a file. error_logging must also be set. Please note that you must select the right php.ini file, PHPINFO reveals which php.ini files are loaded, so check that first if in doubt. After you reload the server configuration, check if PHP can actually log errors to a file. Load up a PHP file that is intentionally faulty and see if this error was logged. One of the common issue that will cause errors not to be logged is the permissions. Your web server must be able to write to the PHP log file, as well as you if you are running CLI PHP scripts. For development servers you can set 666 permissions to the log file, but for production servers you should be more careful.

Now, this will catch all the errors that would otherwise be hard to see, but you can also log arbitrary data to this log file and this is where all the power of this thing comes in. First step is to dump the variable you are debugging to a variable that you are going to log:

1
$dump = var_export($a_variable,true);

This is necessary when dumping arrays or objects. The second step is to log this to the log file:

1
error_log($dump,0);

That’s all there is to it.

The log file is just a text file, any text editor can open it and many text editors will automatically reload it once it changes, so you can see it in (almost) real time. However, I use the terminal whenever I can, so I just use the tail command in streaming mode (tail -f).

Read More

Detecting AJAX calls in PHP

AJAX, or asynchronous page loading is a great way of improving the user experience on your site. No matter how fast the network is between your server and your users’ devices, there is always some lag in page loading times and every tenth of a second matters. With AJAX, you load only the relevant content and your site can approach the performance of desktop applications. This will also greatly reduce your traffic usage and server load.

However, not everyone can  benefit from AJAX and if you follow the Progressive enhancements strategy (as you should) you will want to be able to tell the difference between request made through AJAX and the ‘regular’ ones. The easiest way to achieve so is this:

1
2
3
4
5
6
if( isset($_SERVER['HTTP_X_REQUESTED_WITH']) AND strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'){
    //AJAX call
}
else{
    //non-AJAX (regular) call
}

It is that simple. Strictly speaking it is not necessary to use isset() first, but you will get PHP Notice error if $_SERVER[‘HTTP_X_REQUESTED_WITH’] is not set.

Note that whatever detection method you use, hackers will always be able to spoof the requests, so don’t assume that calls made through AJAX are any safer than the ‘regular’ ones.

Read More

IP logging plugin for WordPress

I’ve developed a small WordPress plugin for logging IP address, Referrer and User Agent strings to database. This plugin also displays total number of visits in WP Dashboard.

This kind of plugin is useful on hosting plans which don’t grant access to server logs. A while ago one of my blogs hosted on free hosting account got slammed with bot traffic. The free hosting plan had only 5 GB of monthly traffic and my blog was getting more than 2 GB per day. I couldn’t see the access parameters and had no way of doing anything.

This plugin saved my skin. It enabled me to track and block (with .htaccess)  about a dozen IP addresses and everything was fine afterwards.

The plugin is very simple and still a bit crude. You’d have to dig through database with phpmyadmin or in some other way to get to the data. I have plans for upgrades, but I have very little time.

You can get it from GitHub.

Read More

Using PHP’s built-in server from other computers

In PHP version 5.4 built in web server was introduced. This cool feature enables serving of PHP, HTML and other files without having a web server installed. It is simple and straightforward to use, just type

1
php -S localhost:8000

8000 here is a port number, you can choose any port that is available on your system. After running this command, you will be able to access this server only from your local machine, it won’t be accessible over network.

The intended usage of this feature is for demonstration and development. It’s not intended to be used in production. Most of the people use it only on their own machines, that is on machines which they use of development and this is probably why most books and tutorials only mention the above given command.

However, there might be a need to be able to access this server from other computers on the network and it is possible to do that as well. You just need to replace ‘localhost’ with the IP address of your network interface, or use ‘0.0.0.0’ to listen on all available networks. So, the command is:

1
php -S 0.0.0.0:8000

For more information see the manual.

Read More

Codeigniter – better way to load views

Codeigniter is great framework, but sometimes it feels like you have to do more work than it would be necessary. For example, loading views at first seems easy and straight forward.

1
$this->load->view('view_file', $data);

However, in a real world project you would rarely use only one view file, each controller would probably have to load views in multiple functions and there would be several controllers. It’s obvious we need something better.

The solution is easy, we need to define a method for loading views and put it in a base class that our controllers would extend. In Codeigniter this is done by creating My_Controller.php file and placing it in application/core/ directory. Our controllers can now extend MY_Controller instead of CI_Controller. All of these names are case sensitive. So, this is how this method looks like:

1
2
3
4
5
6
7
8
9
10
11
12
protected function loadViews($template, $data = null){
        if(!isset($data)){
            $data = $this->_viewData;
        }
        if(!isset($data['urls'])){
            $data = array_merge($this->_viewData, $data);
        }
        $this->load->view('common/header',$data);
        $this->load->view('common/navbar',$data);
        $this->load->view($template, $data);
        $this->load->view('common/footer', $data);
    }

loadViews() method doesn’t need to be public, so making it protected is the best choice. Note that I wasn’t following the Codeigniter naming convention here. All method names are written with underscores, I chose camel case deliberately to make my code distinct, you can make your own choices here.

Whenever we need to load views in our controllers we would simply type:

1
$this->loadViews('view_file', $data);

Now you might be wondering about $_viewData property. Here’s the whole MY_Controller file that I use in my projects:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class MY_Controller extends CI_Controller {

    protected $_viewData = array();    //holds data that is being passed to view files, read from config file

    public function __construct(){
        parent::__construct();
        $this->config->load('my_config', TRUE);    //my_config is my custom configuration file
        $this->setViewData();
    }

    private function setViewData(){
        $this->_viewData = $this->config->item('my_config');
    }  

        /**
        *    Loads views
        *
        *    @param string $template Name of the template file
        *    @param array $data Data array that is being passed to the views
        */

    protected function loadViews($template, $data = null){
        if(!isset($data)){
                        //if no data is passed, use only $_viewData
            $data = $this->_viewData;
        }
        if(!isset($data['urls'])){
                        //some data is passed, but this is not whole $_viewData array from the config file
                        //$data['urls'] is something I always have in my configuration files
            $data = array_merge($this->_viewData, $data);
        }
        $this->load->view('common/header',$data);
        $this->load->view('common/navbar',$data);
        $this->load->view($template, $data);
        $this->load->view('common/footer', $data);
    }

I use a configuration file to hold basic data such as navigation links, links to files, etc. I load this into MY_Controller and pass that array to views, so whenever I load views I have the same basic set of data, plus the data necessary for the current view. I also have a choice of calling loadViews() in my controllers without passing any data, passing only the data I need for the one specific view, or passing all of the (view) data. Controllers can, of course, override loadViews() method if that is necessary.

Codeigniter is very flexible and people are using it in many different ways. I’d just like to know how many other developers have come up with the same approach as I did.

Read More

More about passwords

In my previous post I said that proper password hashing is not harder to code than MD5 and here I’m going to demonstrate that. Here’s how it works:

 

1
2
3
4
5
6
7
8
9
10
11
//calculate hash from cleartext $password
$hash = password_hash($password, PASSWORD_BCRYPT, array('cost' => 12));
//now store it in database

//when registered user wants to log in
if(password_verify($password, $hash){
    //OK, password is valid
}
else{
    //wrong password
}

This is it in its simplest form. The second argument here specifies the algorithm used. PASSWORD_DEFAULT uses bcrypt and it will change over time, so the hash string length might change. PASSWORD_BCRYPT uses CRYPT_BLOWFISH and it will always produce 60 character long hash, however it will only process first 72 characters of the input and discard the rest. Optional third argument specifies salt and cost. If salt is omitted, random salt will be generated and stored in the hash string. This is intended mode of usage. The beauty of password_hash() is that it stores algorithm and cost in the hash, so you don’t have to worry about these things when you are using password_verify()

Cost is more interesting option, it specifies the cost in terms of CPU cycles needed to calculate the hash. Values must be in range of 04-31 and this is logarithmic (base 2) scale, meaning that each step is 2 times slower (as you go up) or slower (as you go down). Default value for cost is 10, which is good baseline value, but you should experiment with your server to see what suits you. Here’s a simple benchmark test:

1
2
3
4
5
$start = microtime(true);
$hash = password_hash('test', PASSWORD_BCRYPT, array('cost' => 11));
$end = microtime(true);
$time = $end - $start;
echo "Elapsed time: $time\n";

I also spoke of password entropy. Entropy is a measure of password strength expressed as base 2 logarithm of the number of guesses it would take to break the password. For example 30 bit password has 230 possible combinations. So, how do you calculate this, most calculators don’t base 2 log and how do you calculate password strength in the first place?

Password strength is calculated as the number of characters in the character set used raised to the power of password length. So, if we use password with 8 characters and it has lowercase letters and numbers, password strength is (26+10)8. This is theoretical value assuming that the password is random, which is never the case, but that’s another story. Base 2 log of number N is easily calculated by using base 10 log or natural logarithm (ln) like this: log10(N)/log10(2), or ln(N)/ln(2).

And finally, here’s snippet of jQuery code I use on my Numbers Relay Page to calculate password strength on registration. This gives only an approximate value.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var password = $('#regPassword').val(); //grab password from the form
var chBase = 0; //initialize counter to 0
if(password.match(/[a-z]/g)){
    chBase += 26; //if password contains lowercase letters increase counter by 26
}
if(password.match(/[A-Z]/g)){
    chBase += 26;  //the same for uppercase letters
}
if(password.match(/[0-9]/g)){
    chBase += 10; //digits
}
if(password.match(/[^a-zA-Z0-9]/g)){
    chBase += 32;  //standard US keyboard has 32 non-alphanumeric characters
}

var entropy = Math.round(Math.log(Math.pow(chBase, password.length)) / Math.log(2));

If you want to find out more about this topic I suggest you start with an excellent Wikipedia article.

Read More