URL Authentication – A New Approach

It is time for web developers and software engineers to make a new approach when checking the validity of URLs and emails that are provided by users. Icann has decided that it is going to allow new suffix’ and the ability to host a website on a domain that has no suffix ie: ‘http://codewithdesign/index.php’. With this change in URLs means that all regular expressions are going to have to not force a suffix or that last decimal as a root URL.

How Will The New Domains Affect Me?

The new domain scheme is going to change how your website validates proper emails and URLs which can be a rather large change on websites that do not have formatting called from one place. Because of this change you will have to overhaul your website/blog/app to support new URLs and emails.

How Should I Go About Making The Change

If you haven’t done so already it is a good idea to make sure that your formatting and checking is coming from one place and will be able to handle the errors accordingly. The first thing that is required is either a functions file or a class file that will support multiple formats of input. This way when something like this changes you only need to update the code once.

Ways To Check URLs And Emails

When working with a URL you can change your regular expression to just check for proper characters and the presence of ‘http://’ or ‘https://’, but there is a much more fun way to check for the new format as well. You should still be using a filter or a regular expression but make sure that your version of PHP is high enough if you are going to use a filter.

Check For An Existing Email

Because of the new URL scheme we are going to need to handle the case that the user is from a website such as ‘http://bearattacksarenotgood/’ This will require us to check for an existing email without the checking of a proper suffix in the email since a user can have the email ‘calebjonasson@bearattacksarenotgood’.

We can easily check for an existing email by using a function called ‘checkdnsrr’ but first we need to split the email name from the URL which will give us ‘calebjonasson’ and ‘bearattacksarenotgood’ which we can accomplish by using the list function will will break apart a string by finding a character.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
//load a variable with an email.
$emailAddress = 'calebjonasson@bearattacksarenotgood';
//split the email by the user name and domain name
list($userName, $domainName) = split('@', $emailAddress);
//use checkdnsrr to validate the domain names existence.
if(checkdnsrr($domainName, 'MX'))
{
    //return value on success.
    return true;
}else{
    //return value on failure.
    return false;
}
 
?>

Pinging A Server

It is possible to ping a server through PHP and it is also possible to just use a cURL to request the page information and check and the response headers. The first thing I will show you is how to send a request which will allow you to check for ping of the data server in question.

My prefered method of doing so is to install net ping onto the server. This is the best solution that I have found on the web to this day and is very simple to use. Here is a tutorial from Code Diesel.

Redundant Data Class in PHP {Theory}

As a server side programmer you are going to be spending a lot of time working with data that is pulled from the database and in order to make sure that you do not have any loose ends it is a good idea to handle this situation with a class. This article is not going to cover how to code a data class nor is it going to help you create a specific data class. This article is here to show you how to make your data redundant and error proof.

Pulling all of your information

When pulling the information off the get go you are going to want to do one thing and one thing only: query all of the data that you can use in the class. The query is going to take place inside of a function and will most likely be used every time that you are in need of the data in the database. Once the query to obtain this information has taken place then you are going to either have results or no results and the easy way to check is simply by checking the number of rows returned.

Say we were trying to access user information for a user page. It would be a good idea to query and make sure that all of the information is available. In this query we are most likely going to be joining up to multiple tables because having all of the user information stored in one table would create a fair amount of overhead and would increase the time it took to go through the table. For this reason we break things apart.

An Example Of Database Tables

A well structured database table is going to be pulling from an auto incrementing ID. This auto incrementing id is going to be found on every table but since we can not just assume that if we insert a record into tbl_user and tbl_user_profile at the same time we are going to get ID’s that match properly. Because this is a flawed way of looking at the table set up we are going to use the auto incremental ID from the tbl_user and plug this into a new column on the other user tables. This way we can simply join the tbl_user.user_id to tbl_user_profile.user_nid. Now that we have a relationship in the database that will work and is pretty redundant in theory we are still going to have to deal with the situation of a table not being created properly upon user registration and thus we are lead to…

Enforcing Existing Tables

Remember back up at the top when I was talking about the query all function either working or not working? Well this function upon returning zero rows will tell us one of two things. (Assuming the SQL was written properly.) The first thing that it will tell us is that this user does not exist, and the second thing is that the user is missing a table. This could mean that something was deleted, or maybe the table was recovered in backup at a later date and there was a record missing. Either way we know that by checking the user table for the users existence we are able to confirm that we are dealing with missing data and this is where the checking functions come into place.

In a well written data handling class there will be functions that exist to pull results from each of the individual tables. These functions are excellent for checking that a user does exist in the following table and are a great way to quickly and easily pull sections of content based on the user which are handy when loading content on an interval via AJAX. But now we are getting a little off topic. Creating a function that can pull information and return a number as a status and creating another function that will insert defaults into the table is an excellent way to make sure that you do not lose data and that all of the data is being pulled properly.

Recap

When using the class you are most likely just going to need to get the information which means that you will be using a function that behaves like the queryAll that I was talking about. If the user does not exist then you can simply return false.

The next step is to create functions that will check individual tables based on that original tbl_user.user_id (or whatever yours is) starting with the initial tbl_user which the rest of the tables are based on. This will tell you if it was created in the first place or not.

If we have gotten far enough to know that the user does exist and the user simply doesn’t have a record in one of the tables then we can query each of the tables and find out where the record is missing. Now that we know the table we can simply insert blank data into the table and maybe send a notification to the user that they may need to update a certain part of their profile.

Knowing when we have an error in table creation

Through this data class it is just a matter of adding in an error log message to let the administrators tell if the application has a bug in it but this shouldn’t be a problem if you are handling proper inserts and updates through SQL and checking for an affected row upon creation.

cURL 403 Error Returning

The other day at work we ran into an issue where the server would return a 403 error page when retrieving page information from a cURL call. After searching around the web for a while thinking that we had a server permission issue on our hands it ended up just being a PHP problem.

In order to make a cURL request from your own server you must first make sure that the session has been destroyed prior to and cURL commands. This is because your server cannot have two pages that can access sessions up at the same time and the primary file that you are working from is going to lock the secondary file that you are trying to bring in.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
session_start();
 
//authentication code.
 
//destroy session first.
session_destroy();
 
//cURL code.
$ch_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
$response = curl_exec($ch)
curl_close($ch);
 
//now we can start the session again
session_start();
 
//do some other stuff...

My only guess as to why PHP does this is to protect itself from breaking sessions with multiple page access which is a pretty good security issue to have in place. Better error reporting would have been nice though.

Getting Secured Using Mysqli

Introduction

The Mysqli class is a great help to working towards proper security when sending and pulling information from the database. It can stop injection attacks in their tracks and will allow you to specify data types allowing you to not let anything bad slip into the system.

In this article I will be going through the step by step approach to creating a query using prepared statements through MySQL. We are going to follow best practices and use the object oriented style to achieve a connection and gather our results.

Connecting to the database

The first thing that we will be doing is connecting to the database. Traditionally this should be done using an outside class to prevent an access to the connection information. The connection string will attempt to connect to the database and open up a persistent connection.

1
$this->connection = new mysqli('localhost','username','password','database');

Creating the prepared statement

The next thing that is required is for us to store the prepared statement. This should be attempted inside of an if statement. This way we can handle any errors appropriately.

1
2
3
4
5
6
7
8
9
10
$sql = "SELECT id, name, year FROM tbl_books WHERE name = ? AND year = ? LIMIT ?";
 
//store the prepared statement into the $stmt variable.
//note that the $stmt is a common naming for prepared statements.
if($stmt = $this->connection->prepare($sql))
{
 
}else{
	die(trigger_error($this->connection->error));
}

Wild cards

You probably noticed that the sql code has something new inside of it. This is the wild card for the sql statement and a ‘?’ is used to display it. This will allow us to bind variables in place of these questions marks and specify their data type.

Bind parameters

Bind parameters is the next step that takes place when there are wild cards inside of the sql statement. These allow us to force a data type into the format of our choosing. There are 4 data types that we can use.

‘I’ Integer
‘s’ String
‘d’ Decimal
‘b’ Blob

1
2
3
4
5
6
7
8
9
10
11
$sql = "SELECT id, name, year FROM tbl_books WHERE name = ? AND year = ? LIMIT ?";
 
//store the prepared statement into the $stmt variable.
//note that the $stmt is a common naming for prepared statements.
if($stmt = $this->connection->prepare($sql))
{
	//Now bind the data to the types.
	$stmt->bind_param('sii', $bookName, $bookYear, $limit);
}else{
	die(trigger_error($this->connection->error));
}

The above function that we just used will take a minimum of two arguments, the first to define the variable types and everything after that is a variable. Notice that all of the type declarations are in the same string. A common error for this piece of code is that you have an invalid amount of arguments being passed. Another error commonly given is that you cannot have data placed directly in the string. You need to reference variables.

1
2
//This is not allowed:
$stmt->bind_param('sii',"the php book", 4, 20);

Execution

Once we have properly set up our bindings we can execute the prepared statement and try to get a result from the database. As you can see in the code below; this can fail and an error message will be stored in case it does. This is why we are going to have it placed inside of an if statement.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$sql = "SELECT id, name, year FROM tbl_books WHERE name = ? AND year = ? LIMIT ?";
 
//store the prepared statement into the $stmt variable.
//note that the $stmt is a common naming for prepared statements.
if($stmt = $this->connection->prepare($sql))
{
	//Now bind the data to the types.
	$stmt->bind_param('sii', $bookName, $bookYear, $limit);
	//We will now execute the statement. This will throw an error if unsuccessful.
	if($stmt->execute())
	{
 
	}else{
		die(trigger_error($stmt->error));
	}
}else{
	die(trigger_error($this->connection->error));
}

Number of Rows

The next step in our quest for world domination is to store the results inside of the statement variable. This is going to let us make a call for the number of rows so we can handle the case of no rows being returned.

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
$sql = "SELECT id, name, year FROM tbl_books WHERE name = ? AND year = ? LIMIT ?";
 
//store the prepared statement into the $stmt variable.
//note that the $stmt is a common naming for prepared statements.
if($stmt = $this->connection->prepare($sql))
{
	//Now bind the data to the types.
	$stmt->bind_param('sii', $bookName, $bookYear, $limit);
	//We will now execute the statement. This will throw an error if unsuccessful.
	if($stmt->execute())
	{
		//check the number of rows.
		$stmt->store_result();
		if($stmt->num_rows >= 1)
		{
 
		}else{
			echo 'Nothing was returned from the database.';
		}
	}else{
		die(trigger_error($stmt->error));
	}
}else{
	die(trigger_error($this->connection->error));
}
<pre>
<h2>Binding Results to Variables</h2>
The last thing that is required is binding the results and looping through the results. As you can see we are actually creating variables with this function and storing the information into them. The variables created are gathered from the select part of the statement. This means that we need to define the variables in the same order as the sql statement.
<pre lang="PHP" line="1">
$sql = "SELECT id, name, year FROM tbl_books WHERE name = ? AND year = ? LIMIT ?";
 
//store the prepared statement into the $stmt variable.
//note that the $stmt is a common naming for prepared statements.
if($stmt = $this->connection->prepare($sql))
{
	//Now bind the data to the types.
	$stmt->bind_param('sii', $bookName, $bookYear, $limit);
	//We will now execute the statement. This will throw an error if unsuccessful.
	if($stmt->execute())
	{
		//check the number of rows.
		$stmt->store_result();
		if($stmt->num_rows >= 1)
		{
			//bind the results
			$stmt->bind_result($id, $name, $year);
			//loop through the results.
			while($stmt->fetch())
			{
				echo "$name: $year<br>";
			}
		}else{
			echo 'Nothing was returned from the database.';
		}
	}else{
		die(trigger_error($stmt->error));
	}
}else{
	die(trigger_error($this->connection->error));
}

It is now time to run your code and gather the results using the fetch function. If you only have to return one row from the database then you can just use the fetch function outside of the while loop and it will allow you to pull the results and use the variables in the same way you would in the while loop.

Searching With %?% In a Prepared Statement

A while back when working on a project I learned that when using the wild card: ‘%’ in SQL with a prepared statement you are going to get an error message. This is because the prepared statement class has an issue with a wild card surrounding wild cards. ‘%?%’.

Because of this a simple sql query such as this is going to have issues pulling data from the database.

1
$sql = "SELECT * FROM tbl_comments WHERE comment LIKE %?% LIMIT 20";

Rather than attempt to get the above code to work you are going to need to take a separate approach and store the wild cards in with the search variable. This only takes one extra line of code and your search will be back up and running in no time at all.

1
2
$comment = '%'.$comment.'%';
$sql = "SELECT * FROM tbl_comments WHERE comment LIKE ? LIMIT 20";

Stop Direct Page Access With PHP

There are a few ways to stop direct access of a page. I will go over a few simple techniques that will help out those of you that are just getting into PHP.

Method number 1

Assuming that all of your pages require a function that was made by yourself and is brought in from another page. ie: “require_once(‘functions.php’);” then we can just do a simple check for the function.

1
2
3
4
5
6
<?php
if(!function_exists('yourfunction'){
    header('/index.php');
    die('Page cannot be accessed directly.');
}
?>

Method 2

This way of checking for the page is usually a good idea for pages that handle process information. Whether that information is handled through get or post you will still be able to use this form factor.

1
2
3
4
5
6
<?php
if(!isset($_GET['id']){
    header('location: index.php');
    die('You cannot access this page directly.');
}
?>

Just a little note for using GET and POST information. PHP is a lot more strict then people will give it credit for and this is because most of the time the errors are small and turned off. If you were to take a look at your error log you will get an entry whenever a page loads a variable with GET or POST and said GET or POST does not exist. For this reason you should check if it is set prior to loading the content into any variable.

Summary of Methods

In this short tutorial we have gone over how to prevent page access. Although these are good clean ways to prevent users from seeing pages that you don’t want them to see it is often easier to modify your HTACCESS page to prevent a page from being access directly a quick way would be do add this your .htaccess file.

1
2
3
4
<files process.class.php>
 order allow,deny
 deny from all
</files>

Check Email Function PHP

Just recently created this piece of code for dream in codes new framework.

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
function check_email($email, $rec = 'MX'){
//	1. clean up email
	$email = trim($email);
 
	$v1 = strstr($email, ' ');
	if($v1 != null){
		echo 'There is a space.';
		return false;
	}
//	2. check if it has the proper characters
	list($start, $domain) = split("@", $email);
	if(isset($start) && isset($domain) && eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$", $email) > 0){
		echo  "good<br>";
 
		// 3. split email into two and check dns
		if(!empty($domain)) {
			if( $rec == '' ) $rec = "MX";
			exec("nslookup -type=$recType $hostName", $result);
			// check each line to find the one that starts with the host
			// name. If it exists then the function succeeded.
			foreach ($result as $line) {
				if(eregi("^$hostName",$line)) {
					echo "hostname is good";
					return true;
 
				}
		}
		// otherwise there was no mail handler for the domain
		return false;
	}return false;
    }return false;
}

The code isn’t exactly rocket science and thus I won’t be leaving you with any more information on this function.