Home Uniquely NZ Travel Howto Pauline Small Firms Search
Web Site Design
PHP Scripts and an Ubuntu Linux Server

Introduction

I am starting to bring together the various sections I have written on  scripting in PHP for web sites and the testing on my Linux machines. This page has spun off from Fun with Ubuntu Linux but to ensure it is free standing there are a few overlaps.

The main use I have made for server side scripting on my web sites has been to handle the output from forms and to convert them into emails. The proceedures I am using are fairly secure but I have also been looking at storing data on the server,  encryption data on the server and sending encrypted emails.

PHP (PHP Html Preprocessor) is a server side scripting language designed to provide interactive pages  by extending HTML and is very simple in the way it works. The PHP code is normally included in a predominately HTML page within sections starting with <?php and ending with a ?> . Only pages with a .php ending are parsed for these PHP sections. The functions available in PHP extend HTML to: write and read files, access databases, perform math calculations anddefine: IF/THEN constructs; LOOPS, Error handlers and more. You can drop in and out of the PHP as often as you like on the page and HTML can appear in the middle of a PHP loop or condition statement. PHP offers features far more like a full programming language than a simple script language. Combined with Java Script within the same page, some powerful combinations of server and client-side programming are possible. 

The PHP 'grammar' is completely interpreted at the web server and the PHP sections are detected, parsed and resolved into data. The end result is a document only containing standard HTML tags when it arrives at the browser, which is fully HTML compliant. This eliminates the need for anything other than a normal browser to access the features (no plug-ins etc are needed) so all users will be able to access the full functionality of your Web pages. Other than the .php extension there is no way the user can tell that some or all of the page has been generated by PHP.

PHP was not readily available on servers when I first started writing scripts and I used ready made scripts such as FormMail which was based on PERL and latter my own more closely taylored scripts using iHTML. Now virtually every ISP offers PHP version 7.1 or higher.

Some introductory examples of PHP

Remember when you try these that PHP files must have extension .php to be recognised and parsed.  The files here are no surrounded by HTML so will not pass any of the HTML validators but the server and all common browsers will not care!

To find out if PHP is on your server and get lots of useful information create and upload a file called phpinfo.php containing the single line

<?php phpinfo() ?>

and then enter your.web.site/phpinfo.php in the browser - that will probably be the simplest script program you will ever write and you will use it often for useful information! 

PHP is very simple to get to grips with. 'Typing' is very weak and you can drop in and out of PHP as often as you like. There are lots of useful functions with meaningful names. Lines must end in a ; Variables do not have to be defined in advance and start with a $. Perhaps the only thing for existing programers to note is that Strings can be enclosed in "  " or '   ' quotes but variables which always start with a $ are handled differently - in the case of strings enclosed by " " the enclosed variables are recognised and substituted whilst with strings eclose by ' ' this does not occur - see the simple example program below. 

Try this simple program - put in a file called string_example.php and upload it to your site. Note: single line comments start with a // and multiple line comments are enclosed in a /*    */It will not work locally as PHP is server side scripting and runs on your web server to deliver an HTML page to the browser so it is a good job it is so simple! 

<?php
$example = "Hello World";
echo " $example "; // gives Hello World
echo ' $example'; // gives $example
?>

Form scripts using PHP 

The following is the 'guts' of the new code for my feedback form for PHP which can be dropped into the body of an HTML page. It is well commented and the PHP functions are mostly self explanatory from their names. You can look them up at uk.php.net - only a dozen or so functions and environment variables are used here which demonstrated the power of PHP. If you forget all error checking and security I think you could do a form to email in a single line!

The following code can be added to the page to reduce the chances of the script being cached. It works by generating raw HTTP headers and must be before any HTML at the top of the file even before the <!DOCTYPE declaration. The options cover HTTP 1.0 and 1.1 plus other ways of avoiding intermediate and local caching such as a date in the past. For some reason do not have any comments in it or you may lose output!

<?php
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Pragma: no-cache");
?>


This is now where the standard HTML page starts, ie. the head with titles etc and the opening of the body. The code following is placed in the body



<?php
/*

This script carries out some error checking to make avoid
being used as a spam relay however the main checking of the
parameters should be done by JavaScript before the form is
submited as there is no provision to correct errors.

It first strips out invalid characters from the form input to
prevent hacking. It then checks that the script has not
been called directly and checks it is called from a permitted
domain. For security all of these are 'hard wired' into the script so
you will have to add the actual parameters you use.

First strip out invalid characterts from the email input to prevent hacking.
*/

$email=htmlspecialchars($_POST['email']);
$commentbox=$_POST['commentbox'];
$feedback_page=$_POST['feedback_page'];

echo "<center><h3>Form from $email on $feedback_page</h3></center>";

//
Set up for domain checks

$domain1 = 'yourdomain';
$domain2 = 'yourseconddomain';
$referrer=strtolower($_SERVER["HTTP_REFERER"]);
$pos1 = strpos($referrer, $domain1);
$pos2 = strpos($referrer, $domain2);

//
Check that the script has not been called directly

if (!isset($_POST['email'])) {
echo "<p>Error - possibly called directly
rather than from a web page</p>\n";
}
//
Now check it is called from a permitted domain
elseif (($pos1 === false) && ($pos2 === false) ) {
echo "Not called from a valid domain</p>\n";
}
//
Then check required parameters are set
elseif (empty($email) || empty($commentbox) || empty($feedback_page) ) {
echo "<p>Required parameters were not completed
- please use back button and try again</p>\n";
}
/*
and finally check email address is reasonable ie do we have
alphanumeric characters + an @ sign + a . + 2 to 4 alpha characters.
Thanks to tim at rocketry dot org for this code NOTE The function eregi is not supported in PHP 7.x and higher and will crash. It needs to be replaced or the test removed - I curently test before the information is posted as an alternative */
elseif(!eregi("^[[:alnum:]][a-z0-9_.-]*@[a-z0-9.-]+\.[a-z]{2,4}$", $email))
{
echo "<p>$email - This is not a reasonable email address
- please use back button and try again</p>\n";
}
else {
/*

Success - write what you are sending to the page then send out the emailThis code
first converts the string to HTML characters then changes
various forms of line end to the hTML break tag to avoid a spagetti
output from the form input. It processes \r\n's first so they
aren't converted twice. It then compacts multiple breaks.
Additional backslashes are removed
*/
$str = str_replace( array("\r\n","\n","\r"),'<br>',htmlspecialchars($commentbox));

for( $i = 5 ; $i >=0 ; $i -= 1 ) {
$str = str_replace( array(" <br>","<br> <br>","<br> <br>","<br><br>"),'<br>' , $str);
}
$str = stripslashes($str);

//
Write to the page

echo "An email with your input has been sent with: <p>";
echo "<b>SUBJECT:</b> Form from $email on $feedback_page<br>";
echo "<b>REPLY-TO:</b> $email<br>";
echo "<b>CONTENT:</b> $str<br>";
/*

Finally send the emails using mail() Note that a few servers
are not complient to the appropriate standard (Windows ones of course)
and may require a \n only rather than a \r\n (CRLF) as separators
*/
mail("you@yourdomain","Form from " . $email . "on" . $feedback_page , $commentbox ,
"From: website@yourdomain\r\nReply-To: " . $email . "\r\nX-Mailer: PHP/" . phpversion() );
}
/*
Please acknowledge that this is based on a PHP Script provided by Peter Curtis at www.pcurtis.com
*/
?>

Using PHP Email Scripts on TSOHost and Fasthosts Servers

There are few restrictions that I have found when the above is used on TSOHost Servers and everything worked almost immediately - I have not found limitations imposed on the server covering on the To and From addresses available hence all the care I have taken to reduce the chances of highjacking for spam.

In contrast a number of additional local checks are done by Fasthosts to prevent spamming. The To or From addresses must be on a Fasthosts domain and on the Windows servers an extra line to set the From address is required before mail() is called ie.

ini_set("sendmail_from", " email@yourfasthostdomain ");
mail("address@yourfasthostdomain","Form from " . $email , $message , "From: email@ yourfasthostdomain\nReply-To: " . $email . "\nX-Mailer: PHP/" . phpversion() );

Form to File Scripts

The alternative to sending the output of a form as an email is to put it into a file on a protected area of ones web site to download later, having perhaps notified oneself by sending an email. With PHP, Secure (SSL) web space and password protected private folders becoming more readily available this is an option when forms contain confidential information. TSOHost's Plesk servers offer private password protected folders as standard on all the package I use and I have been experimenting with PHP scripts to write files. It is not to a point of providing scripts here but I have found that it is easy in PHP to read .htm files and one can write and append to files almost as easily - including those in the password protected areas - provided that they already exist and that the permissions have been set to read and write for the owner group and other in advance. This can be done using the TSOHost Plesk control panel's file manager or ones FTP package if it has the facility. (In gFTP LE right click on a remote file to get to Permissions (unix only)).

As far as I can tell one can not create new files or change permissions from a PHP script on the TSOHost servers - a reasonable and sensible restriction on the grounds of security but one which does limit one to 'log' type files. I have not experimented on the Fasthosts servers as I do not have the password protected folders on them to make it worthwhile.

The functions to look up on PHP.net to start you off are fopen(), fread(), fwrite() feof(), fclose() and the test functions file_exists() and is_writable(). NOTE file_get_contents() is only available on PHP 4.3 or higher and file_put_contents() is only on PHP 5.0 and higher.TSOHost uses PHP 7.1 and Fasthosts PHP 7.0 or 7.2 depending on the type of server PHP.net not only has a very full description of every function but there are also feedback areas under each one and one will find lots of code and discussion.

Apache Server and PHP

PHP is a server side scripting language which means that everything has to be tested on a web server with PHP support which results in every change having to be uploaded and tested on ones web site. After a near escape from writing all over the wrong areas of the server I realised that testing a powerful language with the abilty to write files and call raw Linux commands might not be a very bright thing to do and loaded the Apache web server and the associated libraries for PHP support onto my desktop. I expected it to be complicated but it was very quick and easy and the server is now accessed from a browser as http://localhost on the local machine or by IP address such as http://192.168.1.n  from other machines on the local network. The home directory is, by default,  in the /var/www directory.

Loading Apache can be done by Applications -> Add/Remove -> Advanced -> Search for apache2 then mark apache2 and mark libapache2-mod-php5 You will be informed that some other packages are being included and you just  -> Apply and apache is installed and set up to run every time the machine starts.

The only thing you will need to do before you can use it is to change the permissions on the /var/www folder so you can copy your web site files into it. I find the easy way to do this is to run nautilus (the GUI file browser) with root privileges by starting it from the command line with sudo

sudo nemo
this means I can just right click to properties on any file or folder and use the permissions tab.  The command line alternative is

chmod 777 /var/www
You may also wish to create an addition folder with the same permissions so scripts can read and write files and/or set the permissions on your private folders (those requiring a login).  PHP is run as user www-data on my local set-up and apache on the TSOHost server. The versions recommended for ubuntu are Apache2 and PHP 7.x

PHP Test Script fragments including File handling

The following is a copy of the script file I used on the Ubuntu Linux Apache server for tests and checking various aspects to do with writing and reading files and setting up for encryption. I have left every completed fragment but commented out those not in use.

?php
// This is my phptest.php file for /var/www or uploading.

// Following line provides very full information about the PHP set up - essential reading!
// phpinfo(); 

/* Lists the current directory (should be the web home directory) displaying permissions - a good and useful test to locate one
 the backticked code is run as if from a command line the HTML avoids spaghetti output */
// echo "<pre>".`ls  -al`."</pre>" ;

/* A check gpg was accessible on the machine or remote server
The 2>&1 is added to route error output to the page for de-bugging. */
// echo "<pre>".`gpg --help 2>&1`."</pre>" ; 

/* Make the directory in home directory for gpg with owner www-data RUN ONCE
This could be encoded into a IF THEN ELSE as below */
// echo "<pre>".`mkdir ~/.gnupg 2>&1`."</pre>" ;
// echo "<pre>".`chmod 777 .gnupg 2>&1`."</pre>" ;

/* Check keys are present after copying them from the usual default using Nautilus and setting permissions
 The --homedir option over-rides the default location on the machine - very important on a remote server */
// echo "<pre>".`gpg --list-keys --homedir ~/.gnupg 2>&1`."</pre>" ; //

// Test of file writing and reading from PHP - this appends a test string every time it is run
// echo "<pre>".`mkdir tmp 2>&1`."</pre>" ; // Run once to make directory and comment out
// echo "<pre>".`chmod 777 tmp 2>&1`."</pre>" ; // Run once to set permissions and comment out
$handle = fopen("tmp/test.htm" , "ab" );
fwrite($handle, "Hello File ");
$mesg = file_get_contents("tmp/test.htm");
echo "<br>$mesg" ;
fclose($handle) ;
?>


See below for continuation covering encryption

PHP Test Script fragments for Encryption

The above code fragments show how to encrypt a file under PHP with no explanation of encryption or the function used, which is a Linux built in function There are Windows versions but you should not expect the code above to work on a Windows machine without tuning. 

Anyway some background on why I am interested in encryption. We require encryption to protect any sensitive information whilst we are travelling. The best known standard is probably PGP (Pretty Good Privacy). Linux has the newer Open Source standard - OpenPGP which offers a superset of the usual PGP standard but defaults to be compatible with the encryption levels available in PGP 8 which we are using. It is accessed by the gpg program which normally operates in terminal mode but can be accessed from PHP. Simple early examples  of operation which encrypt and decrypt a file on the desktop using ones default keys are:

gpg --encrypt ~/Desktop/homewine.htm > ~/Desktop/homewine.htm.pgp

gpg --decrypt ~/Desktop/homewine.htm.pgp > ~/Desktop/homewine.htm

There is also a GUI interface called Seahorse which can be installed by Add/Remove which handles the creation and management of keys much easier tha using gpg directly. It is also supposed to add facilities into the text editor and file browser.  The right click encryption of a file and encryption/decryption in the text editor work fine as does the GUI programme to create and manage keys. In theory double clicking on a .pgp file ought to bring up the screens to open it but there seems to be a problem in Ubuntuwhich prevent that. After a bit of searching and playing about I realised that I was using the PGP default extension for compatibility and it worked if the gpg  default extension of .gpg was used so it was a simple job to add the same program as an option for opening .pgp files namely seahorse --decrypt using the right click menu on a .pgp file -> Open with other application -> Use a Custom Command and filling in the box with seahorse --decrypt .

When I came to revisit gpg for use through PHP I realised that, like everything under Linux, gpg is a very flexible program with a huge number of options and my use above was simplistic and also involved considerable interaction. 

The test code below specifies where the keyrings are held (--homedir)  as you have put in a suitable place accessible to PHP/Apache ie a folder on the website. You look up the recipients public key based on his email address ( --recipient ) which must have been added to the keyring in advance. The output is ascii encoded or armoured using the --armor option so it can be put into an email body.  The --no_permission_warning removes one error message which would cause the punters confusion or concern. I have used the long versions of all the options for clarity. The test scripts are:


<?php
/*
 Tests of encryption of file into a temporary ascii armoured file to send to a recipient  with an email address matching a key files already set up on a keyring in .gnupg
It tests if the file exists and if so deletes it to avoid errors - modify some of above code to check the same way
*/
$recipient="you@youraddress.com";
$clear_text_file="efreezone.htm";
$temporary_encrypted_file = '/var/www/tmp/temporary_encrypted_file.asc';

if(file_exists($clear_text_file)) {
    if(file_exists($temporary_encrypted_file)){ unlink($temporary_encrypted_file);
 }
    echo "<pre>".`gpg --no-permission-warning --homedir /var/www/.gnupg --encrypt --recipient "$recipient" --armor --output "$temporary_encrypted_file" "$clear_text_file" 2>&1`."</pre>";
    echo "<b>$temporary_encrypted_file </b>created <br>";
}
else {
    echo "Input file <b>$clear_text_file </b>does not exist";
}
?>


/* 
This is a string to string version with the input string piped into gpg and the output saved into another string then echoed to see what is going on.
*/

$clear_input = "This is a test message";
$recipient="peter@pcurtis.com";
$gpg_output = `echo "$clear_input" | gpg --no-permission-warning --homedir /var/www/.gnupg --encrypt --recipient "$recipient" --armor `;
echo "<pre>Encrypted Output is <p>". $gpg_output ."</pre>";

?>

This has given me the tools I will need if I chose to enhance my form handling by saving encrypted files and send encrypting emails from a Linux server

Link to W3C HTML5 Validator Copyright © Peter & Pauline Curtis
Fonts revised: 28th April, 2021