0% found this document useful (0 votes)
12 views

php_cookbook-43-72

PHP Book 5

Uploaded by

dhivakar.m23
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views

php_cookbook-43-72

PHP Book 5

Uploaded by

dhivakar.m23
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 30

PHP Programming Cookbook 34 / 63

4.3 PHP examples

4.3.1 From time stamp to human-readable

Below, we are seeing how to get the current time stamp, and to get a formatted date:
timestamp_to_human.php
<?php

$timestamp = time();
$date = date(’d-m-Y’, $timestamp);
$datetime = date(’d-m-Y h:i:s’, $timestamp);

echo "Unix timestamp: $timestamp <br>";


echo "Human-readable date: $date <br>";
echo "Human-readable datetime: $datetime";

The date() function supports a wide list of formats, some of them are:

• l for day name.


• N for day number of the week, being Monday the first.
• z for day number of year.
• W for month number of year.

Updating the script to use them:


timestamp_to_human.php
echo ’Day name: ’ . date(’l’, $timestamp) . ’<br>’;
echo ’Day number of week: ’ . date(’N’, $timestamp) . ’<br>’;
echo ’Day number of year: ’ . date(’z’, $timestamp) . ’<br>’;
echo ’Month number of year: ’ . date(’W’, $timestamp) . ’<br>’;

Note: The second parameter, were we have specified the time stamp, is optional. If we don’t specify any time stamp, current will
be used.

4.3.2 From human-readable to time stamp

Now, the reverse process: from human-readable format, to Unix time stamp:
human_to_timestamp.php
<?php

$ukDate = ’13-05-2016’; // For UK format, ’-’ must be the separator.


$usDate = ’05/13/2016’; // For US format, ’/’ must be the separator.

$ukTimestamp = strtotime($ukDate);
$usTimestamp = strtotime($usDate);

echo "Timestamp created from UK date format: $ukTimestamp <br>";


echo "Timestamp created from US date format: $usTimestamp";

strtotime() function does the job. Additionally, the function supports expressions like:

• Adverbs, like now, tomorrow; and next Friday, last Saturday, etc.
PHP Programming Cookbook 35 / 63

• Mathematical expressions, e.g., +2 weeks 5 days 12 hours.

Let’s see it:


human_to_timestamp.php
echo "Tomorrow’s time stamp is: " . strtotime(’tomorrow’) . ’<br>’;
echo ’And in 2 weeks, 5 days and 12 hours time: ’ . strtotime(’+2 weeks 5 days 12 hours’) . ←-
’<br>’;

4.3.3 DateTime class

Apart from those functions, it is also available a class named DateTime, with some useful methods.
We can, for example, calculate the difference between two dates:
difference_with_datetime.php
<?php

$currentDate = new DateTime();


$targetDate = new DateTime(’19-01-2038’); // Date when Unix timestamp will overflow in 32 ←-
bits systems!

$timeLeft = $currentDate->diff($targetDate);

$yearsLeft = $timeLeft->y;
$monthsLeft = $timeLeft->m;
$daysLeft = $timeLeft->d;
$hoursLeft = $timeLeft->h;
$minutesLeft = $timeLeft->i;
$secondsLeft = $timeLeft->s;

echo "Time left to Unix timestamp overflow in 32 bits systems:";


echo "| $yearsLeft years | $monthsLeft months | $daysLeft days | $hoursLeft hours | ←-
$minutesLeft minutes | $secondsLeft seconds |";

As we can see, we can specify a date when instantiating DateTime class, or we cannot specify it in order to use the current
datetime.

4.3.4 Increasing precision

In some scenarios, it could occur that the time stamp precision is not enough. For these occasions, we have available the
microtime() function, which gets the current Unix time, with microseconds. Let’s see an example with this:
datetime_with_microseconds.php
<?php

$microtime = microtime();

list($microseconds, $seconds) = explode(’ ’, $microtime);

$microseconds = str_replace(’0.’, ’’, $microseconds);

$datetime = date(’d-m-Y h:i:s’);


$datetime .= ’:’ . $microseconds;

echo "Current datetime with microseconds: $datetime";


PHP Programming Cookbook 36 / 63

For some reason, microtime() function returns a string with the following format: <microseconds> <seconds>,
separated by a blank space. So, we have to split it.
The microseconds are expressed as real number, so, we should remove the leading zero integer part. Then, we can manually add
to the formatted datetime the microseconds part.
The funny fact is that, actually, the date() function does support the microseconds formatter, u. But it’s not able to generate the
microseconds. If you try to get a date using date(’d-m-Y h:i:s:u’); it will generate only zeros in the microseconds part.
What were PHP developers thinking in?

4.3.5 Validating user introduced date

If we are having a web page where the user has to introduce same date, probably, we will use a JQuery plugin to allow the user
select the date graphically. In any case, after performing any operations, we should ensure that the date is correct.
If you try to calculate the time stamp of a nonsense date, for example, 40/15/2016, you will receive the following time stamp:
1555279200, with no error. And, if you try to calculate the date of that time stamp, you will receive a correct date, 14/04/
2019.
Depending on the scenario, this can be something to check, or not. If you are expecting a date introduced by an user, normally,
we want to ensure that it is actually a valid date expressed in human-readable format. Let’s see how we would validate it in the
following example:
validate_date.php
<?php

define(’DEFAULT_DATE_SEPARATOR’, ’-’);
define(’DEFAULT_DATE_FORMAT’, ’d’ . DEFAULT_DATE_SEPARATOR . ’m’ . DEFAULT_DATE_SEPARATOR . ←-
’Y’); // ’d-m-Y’.

/**
* Checks the validity of the date, using "checkdate()" function. Leap years are also taken ←-
into consideration.
*
* @param $date The input date.
* @return True if the date is valid, false if it is not.
*/
function validateDate($date) {
list($day, $month, $year) = explode(DEFAULT_DATE_SEPARATOR, $date);

$validDate = checkdate($month, $day, $year); // Not a typo; the month is the first ←-
parameter, and the day the second.

return $validDate;
}

// Flow starts here.

$inputDate = $_GET[’input-date’];
$validDate = validateDate($inputDate);

if ($validDate) {
$response = "The date $inputDate is valid.";
} else {
$response = "Error: the date $inputDate is not correct.";
}

echo $response;

Fortunately, PHP has a built-in function for this cases, named checkdate(), that checks the validity of a Gregorian date,
considering also leap years. So, 29-02-2016 would be considered valid, while 29-02-2015 wouldn’t.
PHP Programming Cookbook 37 / 63

The problem here is that we have to parse manually the date, to extract the day, month and year, and also to the specified format.
If we use any other function to change the format, or to retrieve the date numbers, it would automatically fix the date, doing the
same as we saw before the example, so we could not validate the date.

4.4 Summary

We have seen that saving dates in any human-readable format is not a good idea, because the same date can have many different
representations, which will depend on the region. We have seen that Unix time format solves this, using a portable format, that
does not rely on region or languages, and how to deal with this format in PHP.

4.5 Download the source code

This was an example of date formatting with PHP.


Download You can download the full source code of this example here: PHPDateFormatExample
PHP Programming Cookbook 38 / 63

Chapter 5

SoapClient Example

In this example we will see an example of a SOAP client communicating with a server. SOAP is one of many web service
protocol definition. A web service is a technology that uses a protocol (SOAP in this example) for exchanging data between
applications over the network.
If we are developing a client for consuming a web service, we have to look at the protocol that the service is using. This example
is for looking at the resources provided by PHP for developing a client for a web service implementing the SOAP protocol.
For this example, we will use:

• Ubuntu (14.04) as Operating System.

• Apache HTTP server (2.4.7).


• PHP (5.5.9).

5.1 Preparing the environment

5.1.1 Installation

Below, commands to install Apache and PHP are shown:


sudo apt-get update
sudo apt-get install apache2 php5 libapache2-mod-php5
sudo service apache2 restart

5.1.2 PHP configuration

Even if it’s not necessary, is recommendable to disable the SOAP WSDL cache for development environments. In /etc/php5/
apache2/php.ini file, set the soap.wsdl_cache_enabled directive to 0:
php.ini
soap.wsdl_cache_enabled=0

Don’t forget to restart Apache after doing any change.


Note: if you want to use Windows, installing XAMPP is the fastest and easiest way to install a complete web server that meets
the prerequisites.
PHP Programming Cookbook 39 / 63

5.2 What is SOAP?

SOAP (Simple Object Access Protocol) is a standard protocol that defines how two different objects in different processes can
communicate each other, through data exchange in XML format. Is one of the widest protocols used in web services.
In other words, this protocol allows to call method of objects that are defined in remote machines.

5.3 PHP example of SOAP clients

The server offering their SOAP services can define them in two different ways:

• With WSDL (Web Services Definition Language)


• Without WSDL

From the client point of view, there are very few differences, but let’s see how to proceed for each one.
We will consider the following scenario, which is quite typical: a web service that inserts and reads from a database (simulated
with a plain text file), for which we will develop a client.
Is responsibility of the server offering the service to let know the protocol used, as same as the available method definitions, in
order to let the clients know how to deal with the service.
Even if this tutorial is about the client itself, we will see also the server side, in order to test that the client is actually working.

5.3.1 Working directory structure

For this example, we will use the following structure:


php_soapclient_example/
simple_soap_client_class.php
simple_soap_server_class.php
handle_soap_request.php
no_wsdl
server_endpoint.php
wsdl
server_endpoint.php
simple_service_definition.wsdl

Where the root directory, php_soapclient_example, will be in the web server’s root directory, which is /var/www/
html/ by default.
Briefly explained each file:

• simple_soap_client_class.php is the class defined for the SOAP client methods.


• simple_soap_server_class.php is the class defined for the SOAP server methods.
• handle_soap_request.php is for instantiate and use the SimpleSoapClient class defined in simple_soap_cl
ient_class.php.
• In the directories wsdl and no_wsdl, the service defined in simple_soap_server_class.php is offered, in the way
it accords to each of the modes. We won’t go into details for these, since it is not the purpose of this example. The only thing
we have to know is that in one of the directories there is a service offered in WSDL mode, and that in the other, in no WSDL
mode; they are two independent web services that use the code defined in simple_soap_server_class.php.

Note: the WSDL mode needs a .wsdl file, where the web service is defined. We are not going to see it in this example, since
the aim is not to see how to build a WSDL definition file, but it’s also available to download in the last section of the example.
PHP Programming Cookbook 40 / 63

5.3.2 The server

As said, our server will read and write data into a text file. Let’s see it:
simple_soap_server_class.php
<?php

/**
* Methods of our simple SOAP service.
*/
class SimpleSoapServer {

const FILENAME = ’data.txt’;

/**
* Inserts data. Invoked remotely from SOAP client.
*
* @param $data Data to insert.
* @return Resume of operation.
*/
public function insertData($data) {
$writtenBytes = file_put_contents(self::FILENAME, $data . ’<br>’, FILE_APPEND);

if ($writtenBytes) {
$response = "$writtenBytes bytes have been inserted.";
} else {
$response = ’Error inserted data.’;
}

return $response;
}

/**
* Reads data. Invoked remotely from SOAP client.
*
* @return Data of file.
*/
public function readData() {
$contents = file_get_contents(self::FILENAME);

return $contents;
}
}

So simple, about reading and writing into a text file.


Note the functions this server implements, in lines 16 and 33. This functions will be those invoked by the client.

5.3.3 The client

As we said above, depending of the mode (WSDL or not WSDL), the client has to handle the connection in a different way
but, once stablished, the procedure is the same. So, let’s code a class that works for both modes, handling the SoapClient class
instantiation accordingly to the mode:
simple_soap_client_class.php
<?php

/**
* Methods for dealing with SOAP service.
*/
PHP Programming Cookbook 41 / 63

class SimpleSoapClient {

const MODE_WSDL = ’wsdl’;


const MODE_NO_WSDL = ’no_wsdl’;

private $client;

/**
* SimpleSoapClient class constructor.
*
* @param $soapMode The SOAP mode, WSDL or non-WSDL.
* @param $serverLocation The location of server.
*/
public function __construct($soapMode, $serverLocation) {
$this->initializeClient($soapMode, $serverLocation);
}

/**
* Instantiates the SoapClient, depending on the specified mode.
*
* For WSDL, it just has to be instantiated with the location of the service, which ←-
actually has to be the
* .wsdl location.
*
* For non-WSDL, the first parameter of the constructor has to be null; and the second, ←-
an array specifying
* both location and URI (which can be the same, the important parameter is the ←-
location).
*/
protected function initializeClient($soapMode, $serverLocation) {
switch ($soapMode) {
case self::MODE_WSDL:
$this->client = new SoapClient($serverLocation);

break;

case self::MODE_NO_WSDL:
$options = array(
’location’ => $serverLocation,
’uri’ => $serverLocation
);

$this->client = new SoapClient(NULL, $options);

break;

default:
throw new Exception(’Error: invalid SOAP mode provided.’);
break;
}
}

/**
* Inserts data remotely into the SOAP service.
*
* @param $data Data to insert remotely.
* @return Response from remote service.
*/
public function insertData($data) {
$response = $this->client->insertData($data);

return $response;
PHP Programming Cookbook 42 / 63

/**
* Reads data from SOAP service.
*
* @return Data received from remote service.
*/
public function readData() {
return $this->client->readData();
}
}

The lines 35 and 45 instantiate the SoapClient class, depending on the $mode received. This is how it works for each mode:

• For WSDL mode, we have just to pass the server location to the constructor. For this mode, the location must be the WSDL
definition file (.wsdl), not a PHP file.
• For non WSDL mode, the first parameter has to be null (because we are not accessing a WSDL definition). So, the location
must be defined in a different way, providing an array with ’location’ and ’uri’ elements, with the server location as
values. In this case, the location must be the PHP file handling the web service.

After the instantiation, the communication with the service is pretty simple. We have just to call the methods that we saw defined
in SimpleSoapServer class, in simple_soap_client_class.php, through the SoapClient class instance. As we
said before, we are calling methods that are defined in other place. What PHP SoapClient does, is to provide us those methods
defined by the web service, and, when we call them, it will execute them in the server through the SOAP protocol that it has
already implemented, with no needing to care about how it works. Seems magic, doesn’t it?
If you don’t believe it, let’s see a script to use this client.

5.3.4 Using the client

The following script allows us to use the client to communicate with the service, through GET parameters. These are the
parameters available:

• ’mode’, to specify the mode (WSDL or non WSDL).


• ’action’, to specify the action to perform. Available values are ’insert’ and ’read’.
• ’value’, to specify the value to insert, only necessary when the action is ’insert’.

handle_soap_request.php
<?php

require_once(’simple_soap_client_class.php’);

// GET parameter definition.


define(’ACTION_INSERT’, ’insert’);
define(’ACTION_READ’, ’read’);
define(’INSERT_VALUE’, ’value’);
define(’MODE_WSDL’, ’wsdl’);
define(’MODE_NO_WSDL’, ’no_wsdl’);

// Server location definition.


define(’LOCATION_WSDL’, ’https://127.0.0.1/php_soapclient_example/wsdl/ ←-
simple_service_definition.wsdl’);
define(’LOCATION_NO_WSDL’, ’https://127.0.0.1/php_soapclient_example/wsdl/server_endpoint. ←-
php’);

// Function definitions.
PHP Programming Cookbook 43 / 63

/**
* Checks if the given parameters are set. If one of the specified parameters is not set,
* die() is called.
*
* @param $parameters The parameters to check.
*/
function checkGETParametersOrDie($parameters) {
foreach ($parameters as $parameter) {
isset($_GET[$parameter]) || die("Please, provide ’$parameter’ parameter.");
}
}

/**
* Instantiates the SOAP client, setting the server location, depending on the mode.
* If any error occurs, the page will die.
*
* @param $mode The SOAP mode, ’wsdl’ or ’no_wsdl’.
* @return SoapClient class instance.
*/
function instantiateSoapClient($mode) {
if ($mode == MODE_WSDL) {
$serverLocation = LOCATION_WSDL;
} else {
$serverLocation = LOCATION_NO_WSDL;
}

try {
$soapClient = new SimpleSoapClient($mode, $serverLocation);
} catch (Exception $exception) {
die(’Error initializing SOAP client: ’ . $exception->getMessage());
}

return $soapClient;
}

// Flow starts here.

checkGETParametersOrDie([’mode’, ’action’]);

$mode = $_GET[’mode’];
$action = $_GET[’action’];

$soapClient = instantiateSoapClient($mode);

switch($action) {
case ACTION_INSERT:
checkGETParametersOrDie([INSERT_VALUE]);
$value = $_GET[INSERT_VALUE];

try {
$response = $soapClient->insertData($value);
echo "Response from SOAP service: $response<br>";
} catch (Exception $exception) {
die(’Error inserting into SOAP service: ’ . $exception->getMessage());
}

break;

case ACTION_READ:
try {
$data = $soapClient->readData();
PHP Programming Cookbook 44 / 63

echo "Received data from SOAP service:<br>";


echo $data;
} catch (Exception $exception) {
die(’Error reading from SOAP service: ’ . $exception->getMessage());
}

break;

default:
die(’Invalid "action" specified.’);
break;
}

Let’s try it.


If we enter in the browser https://127.0.0.1/php_soapclient_example/handle_soap_request.php?mode=
no_wsdl&action=insert&value=testing_no_wsdl, the service will create a no_wsdl/data.txt file (if not ex-
ists already), writing the provided value ’testing_no_wsdl’, and the following will be printed: Response from SOAP
service:19 bytes have been inserted. (The 4 bytes extra correspond to additional <br> characters inserted into
the file).
The service offers a method to reading all the data, so, if we enter in the browser https://127.0.0.1/php_soapclient
_example/handle_soap_request.php?mode=no_wsdl&action=read, the following will be printed: Received
data from SOAP service:testing_no_wsdl We can check it also for WSDL mode, setting mode=wsdl in the
parameters.

5.4 Considerations

As said in section 3, when we are developing a web service client (no matter if SOAP, REST, etc.), the service provider has to
provide also documentation about the available methods; we need to know the definition of these: which parameters is expecting,
af if it returns something. Because of that, the most usual way to develop a SOAP web service is using WSDL files, to provide
documentation of the available methods. In any case, the SoapClient has a method to get the available methods, for debugging
purposes, named __getFunctions(). So, we could see the offered methods by the service with the following:
var_dump($soapClient->__getFunctions())

Assuming that $soapClient has been instanced properly.


Also note that, if the service does not offer an encrypted connection, the communication between the client and the server will
be made in plain text. So, if we have to develop a client that has to deal with sensible information, we should ensure that the
communication with the server can be considered safe.

5.5 Summary

We have seen how to develop a client for a SOAP web service using PHP’s SoapClient class. The server may offer the service
using WSDL, or not, something to take into account when we are instantiating the SoapClient class. Then, to use the methods
provided by the service, we just have to call those methods in SoapClient instance, as they were ours.

5.6 Download the source code

This was an example of SoapClient with PHP.


Download You can download the full source code of this example here: PHPSoapClientExample
PHP Programming Cookbook 45 / 63

Chapter 6

Login Form Example

In this example we will see how to make a login mechanism in PHP. The login systems is one of the most liked targets of
attackers, so we have to be extremely careful with every aspect of the login.
For this tutorial, we will use:

• Ubuntu (14.04) as Operating System.


• Apache HTTP server (2.4.7).
• PHP (5.5.9).
• SQLite3, a lightweight and process-less DBMS. Credentials are almost always saved in databases, so we have chosen the
lightest option for developing purposes. This not should be an option in production environments.

6.1 Preparing the environment

6.1.1 Installation

Below, commands to install Apache, PHP and SQLite are shown:


sudo apt-get update
sudo apt-get install apache2 php5 libapache2-mod-php5 php5-sqlite
sudo service apache2 restart

6.1.2 PHP configuration

We have to configure PHP to add the SQLite driver. Open /etc/php5/apache2/php.ini, and add the following directive,
if it not exists:
extension=sqlite.so

Don’t forget to restart Apache after doing any change.


Note: check the write permissions of your working directory, since the database will be placed in that directory.

6.2 How should passwords be stored?

After developing any login system, we first need to decide how the passwords are going to be stored. Let’s see which are the
possible ways to store password, from worse option, to best:
PHP Programming Cookbook 46 / 63

6.2.1 Worse: plain text

Even if can be an obviousness, is something that must be said (mostly, because it’s still being done): please, don’t store
passwords in plain text. At the same time a password is stored as plain text, it’s compromised. Anyone having access to the
password storage (commonly, a database), will know the password, when is something that is thought to be known only by its
owner. And if the system is compromised by the attacker, it would have all the passwords readable.

6.2.2 Not bad: password hashing

To avoid this, password hashing was designed. This consists on calculating the hash of the password, to store that hash. Hash
functions are one-way functions, that is, if hf(password) =hash, where hf is the hash function, is computationally un-
feasible to deduce password from hash. So, for a login, the stored hash has to be compared with the hash of the password
provided but the user.
Password hashing is a much better password storing system that plain text, but keeps being vulnerable. Precomputed tables of
hash values could be used (many of them are available already on Internet) to force the login, or to get the original password
from its hash, also called digest. One of the features of hash functions is that they are extremely fast, and this, for login, is a
disadvantage, since an attacker has more chances to attempt logins in less time.

6.2.3 Better: password hashing + salting

This solves, partially, the problem described in paragraph above. Salting consists on adding a random string of bytes (called
salt) to the password before its hashing. So, same passwords, would have different hashes. To perform the login, the hash of the
password provided by the user plus the stored salt for that user has to be calculated, and then compare with the stored one.
If an attacker uses a precomputed table of hash values, it still could attempt a brute-force attack, but it won’t be that easy to revert
the hash to get the plain password, because the random salt has been part of the hash calculation.
In this case, to calculate the hash, we would do the following: hf(password + salt) =hash.
Note: when calculating salts, strong random functions based on entropy should be used, not that weak and predictable functions
like rand().

6.2.4 Even better: Key Derivation Functions

As we said above, password hashing plus salting helps to keep the passwords secret against precomputed table-like attacks. But
an attacker could gain access to a system with a brute-force attack, without needing to know the password.
To avoid this, Key Derivation Functions (KDF) where designed. This functions are design to be computationally intense, so,
needs much time to derive the key. Here, computationally intense, means a second, maybe something more. Actually, the concept
is the same that in hashing + salting, but here another variable is used: the computational cost, which defines the intensity we
mentioned above.
So, the operation would be: kdf(password, salt, cost) =dk, where dk is the derived key generated.
Let’s see a time comparison between a common hash function (SHA1, which is deprecated, but it’s still widely used), and a KDF
(bcrypt):
sha1_vs_bcrypt.php
<?php

$password = ’An insecure password’;

$starttime = microtime(true);
sha1($password);
$sha1Time = microtime(true) - $starttime;

$bcryptOptions = array(’cost’ => 14);


$starttime = microtime(true);
PHP Programming Cookbook 47 / 63

password_hash($password, PASSWORD_BCRYPT, $bcryptOptions);


$bcryptTime = microtime(true) - $starttime;

echo "sha1 took: $sha1Time s <br>";


echo "bcrypt took: $bcryptTime s <br>";

The output will be something like this (depending on the hardware):


sha1 took: 1.5020370483398E-5 s
bcrypt took: 1.2421669960022 s

As you can see, we reduce significantly the attempts an attacker could perform, passing from 1.5*10-5 seconds, to 1,2 seconds.
And, for a user, waiting a second for a login is almost imperceptible.
Is it possible to adjust the intensity the algorithm takes, as in line 9, to find the value that fits better with our hardware.
The derived password (the return value of password_hash() function) will be similar to the following string:
$2y$14$WH1yQiP1naJD8b8lWOK1bOxGQUjgCpFwuzSKohGL/ZV1NaYYr5Cge

Which follows the following format:


$<algorithm_id>$<cost>$<salt (22 chars)><hash (31 chars)>

So, in that example, would be:

• Algorithm id: 2y (bcrypt).


• Cost: 14
• Salt: WH1yQiP1naJD8b8lWOK1bO
• Hash, or derived key: xGQUjgCpFwuzSKohGL/ZV1NaYYr5Cge

Taking this into account, for authenticating the user, we would have to extract the cost and the salt to reproduce the operation, to
then compare the hashes. We will see this in the login implementation.
Note: in the password_hash() function, in the $options array, we can also specify a salt. If any salt is specified, the
function will generate one. For creating salts, the recommended way is using mcrypt_create_iv() function.

6.3 Creating users

Let’s do a simple script that allows to create user, to later test that our login system works correctly.
create_user.php
<?php

require_once(’db.php’);

function checkGETParametersOrDie($parameters) {
foreach ($parameters as $parameter) {
isset($_GET[$parameter]) || die("’$parameter’ parameter must be set by GET method." ←-
);
}
}

checkGETParametersOrDie([’username’, ’password’]);

$username = $_GET[’username’];
$password = $_GET[’password’];
PHP Programming Cookbook 48 / 63

$db = new DB();


$db->createUser($username, $password);

echo "User ’$username’ has been created successfully.";

To create the user in the database, we developed a class named DB. We will see it below. Now, enter the URL to the script
location:
127.0.0.1/php_loginform_example/create_user.php?username=myuser&password=mypassword

With the username and password you prefer.

6.4 Login

6.4.1 Form

A simple login form that asks for an username and password.


login_form.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Login form</title>
</head>
<body>
<form action="login.php" method="POST">

<label for="username">Username:</label>
<input type="text" name="username" id="username" required>

<label for="password">Password:</label>
<input type="password" name="password" id="password" required>

<input type="submit" value="Login">

</form>
</body>
</html>

6.4.2 Form handling

To handle the form, we will create the following script:


login.php
<?php

require_once(’db.php’);

/**
* Checks if the given parameters are set. If one of the specified parameters is not set,
* die() is called.
*
PHP Programming Cookbook 49 / 63

* @param $parameters The parameters to check.


*/
function checkPOSTParametersOrDie($parameters) {
foreach ($parameters as $parameter) {
isset($_POST[$parameter]) || die("’$parameter’ parameter must be set by POST method ←-
.");
}
}

// Flow starts here.

checkPOSTParametersOrDie([’username’, ’password’]);

$username = $_POST[’username’];
$password = $_POST[’password’];

$db = new DB();

$authenticated = $db->authenticateUser($username, $password);

if ($authenticated) {
$response = "Hello $username, you have been successfully authenticated.";
} else {
$response = ’Incorrect credentials or user does not exist.’;
}

echo $response;

Actually, only retrieves the parameters sent by the form, and calls DB class function authenticateUser() method. Let’s see now
that class.

6.4.3 Login against database

The interesting part. This class is the one that interacts with the database, to perform the login, and also to create the users:
db.php
<?php

/**
* Methods for database handling.
*/
class DB extends SQLite3 {

const DATABASE_NAME = ’users.db’;


const BCRYPT_COST = 14;

/**
* DB class constructor. Initialize method is called, which will create users table if ←-
it does
* not exist already.
*/
function __construct() {
$this->open(self::DATABASE_NAME);
$this->initialize();
}

/**
* Creates the table if it does not exist already.
*/
protected function initialize() {
PHP Programming Cookbook 50 / 63

$sql = ’CREATE TABLE IF NOT EXISTS user (


username STRING UNIQUE NOT NULL,
password STRING NOT NULL
)’;

$this->exec($sql);
}

/**
* Authenticates the given user with the given password. If the user does not exist, ←-
any action
* is performed. If it exists, its stored password is retrieved, and then ←-
password_verify
* built-in function will check that the supplied password matches the derived one.
*
* @param $username The username to authenticate.
* @param $password The password to authenticate the user.
* @return True if the password matches for the username, false if not.
*/
public function authenticateUser($username, $password) {
if ($this->userExists($username)) {
$storedPassword = $this->getUsersPassword($username);

if (password_verify($password, $storedPassword)) {
$authenticated = true;
} else {
$authenticated = false;
}
} else {
$authenticated = false;
}

return $authenticated;
}

/**
* Checks if the given users exists in the database.
*
* @param $username The username to check if exists.
* @return True if the users exists, false if not.
*/
protected function userExists($username) {
$sql = ’SELECT COUNT(*) AS count
FROM user
WHERE username = :username’;

$statement = $this->prepare($sql);
$statement->bindValue(’:username’, $username);

$result = $statement->execute();
$row = $result->fetchArray();

$exists = ($row[’count’] === 1) ? true : false;

$statement->close();

return $exists;
}

/**
* Gets given users password.
*
PHP Programming Cookbook 51 / 63

* @param $username The username to get the password of.


* @return The password of the given user.
*/
protected function getUsersPassword($username) {
$sql = ’SELECT password
FROM user
WHERE username = :username’;

$statement = $this->prepare($sql);
$statement->bindValue(’:username’, $username);

$result = $statement->execute();
$row = $result->fetchArray();
$password = $row[’password’];

$statement->close();

return $password;
}

/**
* Creates a new user.
*
* @param $username The username to create.
* @param $password The password of the user.
*/
public function createUser($username, $password) {
$sql = ’INSERT INTO user
VALUES (:username, :password)’;

$options = array(’cost’ => self::BCRYPT_COST);


$derivedPassword = password_hash($password, PASSWORD_BCRYPT, $options);

$statement = $this->prepare($sql);
$statement->bindValue(’:username’, $username);
$statement->bindValue(’:password’, $derivedPassword);

$statement->execute();

$statement->close();
}
}

Remember when we said in 2.4 section that, for comparing the provided password with the string generated by the KDF algo-
rithm, we would have to extract the cost and the salt from that string? Well, the password_verify() function, in line 45,
does this for us: repeats the operation for the provided $password, extracting the algorithm, the salt and the cost from the
existing derived key $storedPassword, and then compares it to the original password that is the "reference".
Note that, when querying the database, we use something called $statement. These are called Prepared Statements. We can
execute directly a string SQL with a SQLite method called exec(), but this would be vulnerable against SQL Injection, and an
attacker could gain access to the system injecting SQL commands. The Prepared Statement does not allow this, because it binds
the parameters using a different protocol, and don’t need to be escaped looking for characters like ’.
If we try to fill the form with the credentials we created in section 3, we will receive the following message: Hello <user>,
you have been successfully authenticated. Whereas, if we introduce incorrect credentials, we will see: Inco
rrect credentials or user does not exist.
PHP Programming Cookbook 52 / 63

6.5 Summary

We have seen that there are different mechanisms to design a login system, analysing the weakness of each one, concluding
that the KDFs are the most secure alternative currently, and how to implement it in PHP. We have also seen the need of the use
of the Prepared Statements, not to allow hypothetical attackers to introduce malicious commands to gain access or to extract
information.

6.6 Download the source code

This was an example of a login form in PHP.


Download You can download the full source code of this example here: PHPLoginFormExample
PHP Programming Cookbook 53 / 63

Chapter 7

Curl Get/Post Example

If you have worked with Linux, you will have probably used cURL for downloading resources from the Internet. This powerful
library can also be used in PHP scripts, and that is what we are going to see in this example.
For this example, we will use:

• Ubuntu (14.04) as Operating System.

• Apache HTTP server (2.4.7).


• PHP (5.5.9).

7.1 Preparing the environment

7.1.1 Installation

Below, commands to install Apache, PHP and PHP cURL library are shown:
sudo apt-get update
sudo apt-get install apache2 php5 libapache2-mod-php5 php5-curl
sudo service apache2 restart

7.1.2 PHP configuration

In /etc/php/apache2/php.ini file, we need to include the cURL extension, in order to use it:
extension=php_curl.so

Don’t forget to restart Apache after doing any change.

7.2 GET requests

Let’s see how we can use cURL to create GET requests:


curl_get.php
PHP Programming Cookbook 54 / 63

<?php

/**
* Checks if the given parameters are set. If one of the specified parameters
* is not set, die() is called.
*
* @param $parameters The parameters to check.
*/
function checkGETParametersOrDie($parameters) {
foreach ($parameters as $parameter) {
isset($_GET[$parameter]) || die("Please, provide ’$parameter’ parameter.");
}
}

/**
* Gets the GET parameters.
*
* @return GET parameter string.
*/
function stringifyParameters() {
$parameters = ’?’;

foreach ($_GET as $key => $value) {


$key = urlencode($key);
$value = urlencode($value);
$parameters .= "$key=$value&";
}

rtrim($parameters, ’&’);

return $parameters;
}

/**
* Creates the cURL request for the given URL.
*
* @param $url The URL to create the request to.
* @return The cURL request to the url; false if an error occurs.
*/
function createCurlRequest($url) {
$curl = curl_init();

if (!$curl) {
return false;
}

$configured = curl_setopt_array($curl, [
CURLOPT_URL => $url . stringifyParameters(),
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_RETURNTRANSFER => true
]);

if (!$configured) {
return false;
}

return $curl;
}

// Flow starts here.


PHP Programming Cookbook 55 / 63

checkGETParametersOrDie([’url’]);

$url = $_GET[’url’];

$curl = createCurlRequest($url);

if (!$curl) {
die(’An error occured: ’ . curl_error($curl));
}

$result = curl_exec($curl);

if (!$result) {
die(’An error occured: ’ . curl_error($curl));
}

echo ’The result of the cURL request:’;


echo ’<hr>’;
echo $result;

curl_close($curl); // Don’t forget to close!

This is what we have done:

• First, we created a cURL session, with curl_init() function, as in line 41. If some error occurs, false will be returned,
so we have to check it before continuing (line 43).
• Once we have created successfully the cURL session, we have to configure it, as we do with curl_setopt_array()
function. In this case, we have configured it with the following options:

– The URL itself. For GET requests, we just have to specify the URL with the parameter string, in key=value format, as
you already know. Note how is the parameter string constructed in stringifyParameters() function: the values
should be encoded to URL encoding, with urlencode() function (lines 24 and 25).
– The CURLOPT_FOLLOWLOCATION option to true. This is for following the 3XX HTTP redirections. If we set to false,
and the specified URL makes a redirection, we won’t reach the final URL.
– The CURLOPT_RETURNTRANSFER option to true. This allows to save the HTTP response into a variable. If set to
false, the response will be printed directly.

• We should always check that the cURL functions don’t return any errors, checking the return values of the functions. When
false is returned, we can get the information of the last error for the given cURL session with curl_error() function, as
in lines 69 and 75.
• If any error has occurred initializing and configuring the cURL session, we can proceed to execute it, just calling curl_exe
c() function, specifying for which session we are executing the request. In this case, as we configured the CURLOPT_RETU
RNTRANSFER option, we can save the response value into a variable.
• Finally, when we have ended the cURL session handling, we must close it, curl_close() function.

We can test this script, entering, for example, localhost/path/to/curl_get.php?url=webcodegeeks.com&s=


php in the browser. We will see that the output generated by the script, is the same of that which we would have received making
a search in the above search box, in this page, entering php.

7.3 POST requests

For POST requests, we have to configure the cURL options in a slightly different way:
curl_post.php
PHP Programming Cookbook 56 / 63

// ...

function createCurlRequest($url) {
$curl = curl_init();

if (!$curl) {
return false;
}

$configured = curl_setopt_array($curl, [
CURLOPT_URL => $url,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => stringifyParameters(),
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_RETURNTRANSFER => true
]);

if (!$configured) {
return false;
}

return $curl;
}

// ...

Note that, when setting the URL, we just set the URL itself without the parameters, that’s for GET requests. Those parameters
are specified in CURLOPT_POSTFIELDS option. And, apart from that, we are specifying that the request will be made for
POST method, with CURLOPT_POST option.
The only difference between cURL POST and GET requests is the configuration of the session. The rest of the script, can be the
same for both.

7.4 Encapsulating operations in a cURL class

When we are going to use cURL in a project, is recommendable to have encapsulated all the code instead of using every time
the functions we have used above, because we would be repeating much code, and the possibilities of introducing errors would
increase. So, we are going to create a class that encapsulates this logic.
curl_class.php
<?php

/**
* Methods for cURL request handling.
*/
class CURL {

/**
* The cURL request object.
*/
private $request;

/**
* CURL class constructor.
*
* @throws Exception if an error occurs initializating.
*/
public function __construct() {
PHP Programming Cookbook 57 / 63

$this->request = curl_init();

$this->throwExceptionIfError($this->request);
}

/**
* Configure the cURL request.
*
* @param $url The target url.
* @param $urlParameters The array of parameters, with ’key’ => ’value’ format.
* @param $method ’GET’ or ’POST’; ’GET’ by default.
* @param $moreOptions Any other options to add to the cURL request. By default,
* ’CURLOPT_FOLLOWLOCATION’ (follow 3XX redirects) and ’CURLOPT_RETURNTRANSFER’
* (return HTTP response as a value, instead of outputting directly) are set.
* @throws Exception if an error occurs configurating.
*/
public function configure($url, $urlParameters = [], $method = ’GET’,
$moreOptions = [CURLOPT_FOLLOWLOCATION => true, CURLOPT_RETURNTRANSFER => true]) {

curl_reset($this->request);

switch ($method) {
case ’GET’:
$options = [CURLOPT_URL => $url . $this->stringifyParameters($urlParameters ←-
)];
break;

case ’POST’:
$options = [
CURLOPT_URL => $url,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $this->stringifyParameters($urlParameters)
];

break;

default:
throw new Exception(’Method must be "GET" or "POST".’);
break;
}

$options = $options + $moreOptions;

foreach ($options as $option => $value) {


$configured = curl_setopt($this->request, $option, $value);

$this->throwExceptionIfError($configured);
}
}

/**
* Executes the cURL request for the options configured.
*
* @return The return value of curl_exec(). If CURLOPT_RETURNTRANSFER was configured,
* the return value will be the HTTP response. In other case, a true value (or ←-
false
* if some error has occured).
* @throws Exception if an error occurs executing.
*/
public function execute() {
$result = curl_exec($this->request);
PHP Programming Cookbook 58 / 63

$this->throwExceptionIfError($result);

return $result;
}

/**
* Closes cURL session.
*/
public function close() {
curl_close($this->request);
}

/**
* Checks if a curl_* function returns success or failuer, throwing an exception
* with the cURL error message if it has failed.
*
* @param $success IF the curl function has succeeded or not.
* @throws Exception if the curl function has failed.
*/
protected function throwExceptionIfError($success) {
if (!$success) {
throw new Exception(curl_error($this->request));
}
}

/**
* Creates a string of GET parameters.
*
* @param $parameters Parameter array.
* @return Parameters in string format: ’?key1=value1&key2=value2’
*/
protected function stringifyParameters($parameters) {
$parameterString = ’?’;

foreach ($parameters as $key => $value) {


$key = urlencode($key);
$value = urlencode($value);

$parameterString .= "$key=$value&";
}

rtrim($parameterString, ’&’);

return $parameterString;
}
}

This class doesn’t do anything we haven’t seen before, except the way the options are configured (in line 60), with curl_seto
pt() function, to set the options with no needing to know which options are.
In order to use this class, we would only have to do something similar to this:
<?php

require_once(’curl_class.php’);

try {
$curl = new CURL();

$curl->configure(’webcodegeeks.com’);
$response = $curl->execute();
PHP Programming Cookbook 59 / 63

$curl->close();
} catch (Exception $exception) {
die(’An exception has been thrown: ’ . $exception->getMessage());
}

Which is much more clean, readable and easy to maintain. And also more flexible, since it allows to configure any cURL option
(and there is a large list of available options).
Note: cURL requests can be reused, increasing the performance. For example:
<?php

require_once(’curl_class.php’);

try {
$curl = new CURL();

$curl->configure(’webcodegeeks.com’);
$response1 = $curl->execute();

$curl->configure(’webcodegeeks.com’, [’s’ => ’php’], ’GET’);


$response2 = $curl->execute();

$curl->close();
} catch (Exception $exception) {
die(’An exception has been thrown: ’ . $exception->getMessage());
}

The above script will work with any problem, and being more optimal than closing and opening a new cURL session for each
request. In this case, the difference would probably be negligible, but for several request can suppose a significant change.
To reuse the cURL sessions, we should clean and remove the options of this before adding new ones, as done in curl_class.
php in line 38, with curl_reset curl_reset() function.

7.5 Summary

This example has shown how we can use the cURL library in PHP scripts, for making both GET and POST requests, which have
to be handled in a slightly different way. Apart from that, we have developed a class for handling cURL in a much more ordered,
clean and flexible way, allowing to reuse already opened sessions, in order to improve performance.

7.6 Download the source code

This was a cURL example for PHP.


Download You can download the full source code of this example here: PHPCurlGetPostExample
PHP Programming Cookbook 60 / 63

Chapter 8

HTML Table Example

In this example we shall show you how to create html tables with dynamic php. PHP is a server-side scripting language used
by most web developers for creating dynamic and responsive web pages(A dynamic webpage is one whose content change
automatically each time the page is viewed).
Html is simply a language used to describe webpages. Html tables allow web developers arrange data into rows and columns
also html tables also allow web developers display structured data in a web page.
For this example we would use

• A computer with PHP 5.5 installed

• notepad++

8.1 Getting Started

To explain dynamic PHP and html tables we are going to develop a trivial web app which allows a teacher record the scores of
students on a remote server. The server counts the number of records it has received, after the third count it outputs the received
record in an html table and resets its counter. Before we continue let’s start by explaining some concepts.

8.1.1 Forms

Html forms are used to collect user input. We are going to use forms to collect each student details(firstname, lastname, subject
and score) and submit it
index.html
<form action=action.php method=post onsubmit="return validateForm()">
<input type=text placeholder=FirstName id=firstname name=first required><br>
<input type=text placeholder=LastName id=lastname name=last required><br>
<input type=text placeholder=Subject id=subject name=subject required><br>
<input type=text placeholder="Student Score" id=score name=score required><br>

<input type=submit value=submit id=sub>

</form>

This code displays a form to the user, the required attribute in each textbox tells the browser that this field is required and
must be filled while the placeholder is just a short hint that describes the expected input. The validateForm() function
that is called when the form is submitted checks if the user has entered all the required fields. If the user entered all the required
PHP Programming Cookbook 61 / 63

fields it returns true and the form is submitted else the function returns false and halts the submission process alerting the user to
the error encountered.
index.html
function validateForm(){
var firstname=document.getElementById("firstname").value.trim();
var lastname=document.getElementById("lastname").value.trim();
var subject=document.getElementById("subject").value.trim();
var score =document.getElementById("score").value.trim();
if(firstname==""||lastname==""||subject==""||score==""){
alert("All Fields Must be Filled")
return false;
}

return true;
}

8.1.2 Session in php

We need store each student record processed by our php script, to do this we will make use of php session(in an advanced and
scalable web app we would store all records in a database but for the sake of simplicity we would use php session) Simply put
a session is a way to store information, which can be accessed across mutiple webpages.When the form is submitted our script
access each data submitted and saves it in session variables
action.php
<?php
session_start();
if($_SESSION[’num’]==null)//check if the num variable is empty
$_SESSION[’num’]=1;// if it is empty set it to 1
?>

To use session in php we call the session_start() function before anything else is output to the browser. All session
variable values are stored in the global $_SESSION associative array. Assigning a session variable is as simple as writing
$_SESSION[’num’]=1 and we can read from it the same way we would read from a normal variable. We use the $_SESSI
ON[’num’] variable as a counter to store the number of times the script has received a record.
action.php
if($_SESSION[’num’]==1){
$_SESSION[’num’]++;
$_SESSION[’first’]=$_POST[’first’];
$_SESSION[’last’]= $_POST[’last’];
$_SESSION[’subject’]=$_POST[’subject’];
$_SESSION[’score’]=$_POST[’score’];
include("index.html");
}
else if($_SESSION[’num’]==2){
$_SESSION[’num’]++;
$_SESSION[’first1’]=$_POST[’first’];
$_SESSION[’last1’]= $_POST[’last’];
$_SESSION[’subject1’]=$_POST[’subject’];
$_SESSION[’score1’]=$_POST[’score’];
include("index.html");
}
else if($_SESSION[’num’]>=3){
$_SESSION[’num’]=1;
$_SESSION[’first2’]=$_POST[’first’];
$_SESSION[’last2’]= $_POST[’last’];
$_SESSION[’subject2’]=$_POST[’subject’];
PHP Programming Cookbook 62 / 63

$_SESSION[’score2’]=$_POST[’score’];
?>
<!DOCTYPE html>
<html lang=eng>
<head>
<title>
Dynamic php and html table testing
</title>
<style>
html, body{
width:100%;
height:100%;
margin:0%;
font-family:"helvetica","verdana","calibri", "san serif";
overflow:hidden;
padding:0%;
border:0%;
}
table{
width:50%;
border:2px solid #343434;
margin-left:auto;
margin-right:auto;
}
td{
text-align:center;
width:25%;
border:2px solid #343434;
}
#he{
height:10%;
background-color:#343434;
margin-bottom:2%;
}
</style>
</head>
<body bgcolor="#e5a010">

<table>
<thead>
Student Result Score
</thead>
<tbody>
<th>Firstname</th><th>Lastname</th><th>Subject</th><th>Score</th>

<?php
echo "|" . $_SESSION[’first’]. "";
echo "|" . $_SESSION[’last’]. "";
echo "|" . $_SESSION[’subject’]. "";
echo "|" . $_SESSION[’score’]. "";
echo "";

echo "";
echo "|" . $_SESSION[’first1’]. "";
echo "|" . $_SESSION[’last1’]. "";
echo "|" . $_SESSION[’subject1’]. "";
echo "|" . $_SESSION[’score1’]. "";
echo "";

echo "";
echo "|" . $_SESSION[’first2’]. "";
echo "|" . $_SESSION[’last2’]. "";
PHP Programming Cookbook 63 / 63

echo "|" . $_SESSION[’subject2’]. "";


echo "|" . $_SESSION[’score2’]. "";
echo "";
//this removes all the session variable
session_unset();
//this functions destroys the session
session_destroy();
}
?>
<tbody>

</body>
</html>

We check how many times our script has received a record, if it’s not up to three we increment our counter variable, store each
record received in our session array and display the form to the teacher(we do this by calling the include("index.html")
function). After three records has been submitted we reset the counter variable and output an html table containing each student
record to the browser. It is considered good practice to clean up after using session. we call php session_unset() to delete
all session data and session_destroy() to the destroy the session.

8.1.3 Html Tables

Let’s start by explaining each tag used in our example

• The <table> tag: it is used to define/create a table in html

• The <thead> tag: it is used to define an header for a table.


• The <tbody> tag: it is used in conjunction with the <thead> and <tfoot> tag to describe a table. It always comes after
the <thead> tag and before the <tfoot> tag
• The <tr> tag: it is used to define a row in an html table

• The <th> tag: This tag defines a table header.


• The <td> tag: This tag defines a cell in an html table

8.1.4 Other table tags worthy of mention

• <caption> tag : This is an optional tag, it gives the title of the table. It is always the first descendant of the <table> tag.
• <tfoot> : This tag defines a set of rows summarizing the columns of the table.

8.2 Summary

In this example we have learnt about dynamic php and html tables(what they mean and how to use them). we also discussed
about html forms and php sessions(how to create and destroy them).

8.3 Download the source code

Download You can download the full source code of this example here: Phphtmltableexample

You might also like