I have written some code to simple add/mod/del to a table called person. I would like comments on where this code could be comprising on security. I have used the PDO library in php.
GetPerson.php ( use this to retrieve details of a person using ajax )
<?php
include '../classes/person.php';
include '../classes/avaaz_mysql_db.php';
include '../config.php';
try
{
if(isset($_POST['id']))
{
$id = $_POST['id'];
//clean variable //clean further
settype($id, 'string');
$id = strip_tags($id);
//decode
$id = base64_decode($id);
//remove salt string
$id = str_replace($config['salt_string'], '', $id);
//clean again
settype($id, 'integer');
//get the person details and output as json
$db = new avaaz_mysql_db($config['db_connection_string'],$config['db_user_name'],$config['db_password']);
$row = $db->get_person($id);
$arr_peron_details = $row[0];
//clean data returned from db
foreach ($arr_peron_details as $key => $value)
{
$arr_peron_details[$key] = htmlentities($value);
}
echo json_encode(array($arr_peron_details));
}
}
catch (Exception $e)
{
echo "Getting person details: ".$e->getMessage();
}
?>
Person.php ( class that represents a person)
<?php
class person
{
private $id;
private $first_name;
private $last_name;
private $country;
private $city;
private $address;
private $email;
public function set_id($tmp_id)
{
//data type checking and validation happens here
settype($tmp_id, "integer");
if((!isset($tmp_id)) || $tmp_id==0)
{
throw new Exception('Incorrect person id');
}
$this->id = $tmp_id;
}
public function get_id()
{
return $this->id;
}
public function set_first_name($tmp_first_name)
{
//data type checking and validation happens here
settype($tmp_first_name, "string");
if((!isset($tmp_first_name)) || $tmp_first_name=='')
{
throw new Exception('First name cannot be empty');
}
$tmp_first_name = strip_tags($tmp_first_name);
if(!$this->is_only_letters_and_spaces($tmp_first_name))
{
throw new Exception('Only letters and spaces allowed in first name');
}
$this->first_name = $tmp_first_name;
}
public function set_last_name($tmp_last_name)
{
//data type checking and validation happens here
settype($tmp_last_name, "string");
if(!isset($tmp_last_name) || $tmp_last_name=='')
{
throw new Exception('Last name cannot be empty');
}
$tmp_last_name = strip_tags($tmp_last_name);
if(!$this->is_only_letters_and_spaces($tmp_last_name))
{
throw new Exception('Only letters and spaces allowed in last name');
}
$this->last_name = $tmp_last_name;
}
public function set_country($tmp_country)
{
//data type checking and validation happens here
settype($tmp_country, "string");
if(!isset($tmp_country) || $tmp_country=='')
{
throw new Exception('Country cannot be empty');
}
$tmp_country = strip_tags($tmp_country);
if(!$this->is_only_letters_and_spaces($tmp_country))
{
throw new Exception('Only letters and spaces allowed in country');
}
$this->country = $tmp_country;
}
public function set_city($tmp_city)
{
//data type checking and validation happens here
settype($tmp_city, "string");
if(!isset($tmp_city) || $tmp_city=='')
{
throw new Exception('City cannot be empty');
}
$tmp_city = strip_tags($tmp_city);
if(!$this->is_only_letters_and_spaces($tmp_city))
{
throw new Exception('Only letters and spaces allowed in city');
}
$this->city = $tmp_city;
}
public function set_address($tmp_address)
{
//data type checking and validation happens here
settype($tmp_address, "string");
if(!isset($tmp_address) || $tmp_address=='')
{
throw new Exception('Address cannot be empty');
}
$tmp_address = strip_tags($tmp_address);
$this->address = $tmp_address;
}
public function set_email($tmp_email)
{
//data type checking and validation happens here
settype($tmp_email, "string");
if(!isset($tmp_email) || $tmp_email=='')
{
throw new Exception('Email cannot be empty');
}
$tmp_email = strip_tags($tmp_email);
//check if first name contains only letters
if(!$this->is_valid_email($tmp_email))
{
throw new Exception('Invalid email address');
}
$this->email = $tmp_email;
}
public function get_first_name()
{
return $this->first_name;
}
public function get_last_name()
{
return $this->last_name;
}
public function get_country()
{
return $this->country;
}
public function get_city()
{
return $this->city;
}
public function get_address()
{
return $this->address;
}
public function get_email()
{
return $this->email;
}
//can later be moved to another helper classs
public function is_only_letters_and_spaces($string)
{
return preg_match('~^[a-zA-Z ]*$~', $string);
}
//can later be moved to another helper classs
public function is_valid_email($email)
{
if(!filter_var($email, FILTER_VALIDATE_EMAIL))
{
return false;
}
else
{
return true;
}
}
}
?>
avaaz_mysql_db.php ( database layer )
<?php
include_once('person.php');
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
class avaaz_mysql_db
{
//used to validate sory by variable
private $fields = array('first_name','last_name','country','city','address','email');
private $connection_string;
private $user_name;
private $password;
public function avaaz_mysql_db($tmp_connection_string,$tmp_user_name,$tmp_password)
{
$this->connection_string = $tmp_connection_string;
$this->user_name = $tmp_user_name;
$this->password = $tmp_password;
}
public function add_person($person)
{
$first_name = '';
$last_name = '';
$country = '';
$city = '';
$address = '';
$email = '';
try
{
//check if a person with the same name already exists
if($this->does_same_name_exist($person))
{
throw new Exception('Person with the same name already exists');
}
//check if a person with the same email already exists
if($this->does_email_exist($person))
{
throw new Exception('Person with the same email already exists');
}
//prepare db and pdo statement
$db = new PDO($this->connection_string,$this->user_name,$this->password);
$stmt = $db->prepare("INSERT INTO persons (first_name, last_name, country, city, address, email ) VALUES (:first_name, :last_name, :country, :city, :address, :email )");
$stmt->bindParam(':first_name', $first_name);
$stmt->bindParam(':last_name', $last_name);
$stmt->bindParam(':country', $country);
$stmt->bindParam(':city', $city);
$stmt->bindParam(':address', $address);
$stmt->bindParam(':email', $email);
// insert one row
$first_name = $person->get_first_name();
$last_name = $person->get_last_name();
$country = $person->get_country();
$city = $person->get_city();
$address = $person->get_address();
$email = $person->get_email();
$stmt->execute();
}
catch(Exception $e)
{
throw new Exception($e->getMessage());
}
}
public function edit_person($person)
{
$first_name = '';
$last_name = '';
$country = '';
$city = '';
$address = '';
$email = '';
//check if a person with the same name already exists
try
{
if($this->does_same_name_exist($person))
{
throw new Exception('Person with the same name already exists');
}
//check if a person with the same email already exists
if($this->does_email_exist($person))
{
throw new Exception('Person with the same email already exists');
}
//db and pdo statements
$db = new PDO($this->connection_string,$this->user_name,$this->password);
$stmt = $db->prepare("update persons set first_name=:first_name, last_name=:last_name, country=:country, city=:city, address=:address, email=:email where id = :person_id");
$stmt->bindParam(':first_name', $first_name);
$stmt->bindParam(':last_name', $last_name);
$stmt->bindParam(':country', $country);
$stmt->bindParam(':city', $city);
$stmt->bindParam(':address', $address);
$stmt->bindParam(':email', $email);
$stmt->bindParam(':person_id', $person_id);
// insert one row
$person_id = $person->get_id();
$first_name = $person->get_first_name();
$last_name = $person->get_last_name();
$country = $person->get_country();
$city = $person->get_city();
$address = $person->get_address();
$email = $person->get_email();
$stmt->execute();
}
catch(Exception $e)
{
throw new Exception($e->getMessage());
}
}
public function delete_person($person)
{
try
{
//check if a person with the same first name and last name already exists
$db = new PDO($this->connection_string,$this->user_name,$this->password);
$id = $person->get_id();
$statement = $db->prepare("delete from persons where id = :id");
$statement->bindParam('id', $id);
$statement->execute();
}
catch(Exception $e)
{
throw new Exception($e->getMessage());
}
}
public function get_persons($limit = 10, $offset = 0, $sort='first_name', $sort_type = 'asc')
{
//validate offet, limit, sort, sorttype , try catch should come here
try
{
if($limit>100)
{
throw new Exception('Cannot return more than 100 records at a time');
}
if(!in_array($sort, $this->fields))
{
throw new Exception('Sort field is not in the database');
}
if($sort_type!='asc' && $sort_type!='desc')
{
throw new Exception('Incorrect sort type');
}
//prepare db and prepare statment to get people from the db
$db = new PDO($this->connection_string,$this->user_name,$this->password);
$statement = $db->prepare("select * from persons order by $sort $sort_type limit $offset,$limit ");
$statement->execute();
$rows = $statement->fetchAll();
return $rows;
}
catch(Exception $e)
{
throw new Exception($e->getMessage());
}
}
public function does_same_name_exist($person)
{
try
{
//check if a person with the same first name and last name already exists
$db = new PDO($this->connection_string,$this->user_name,$this->password);
$first_name = $person->get_first_name();
$last_name = $person->get_last_name();
if($person->get_id()==0 || $person->get_id()=='') //check if any person exists with the same name
{
$statement = $db->prepare("select id from persons where first_name = :first_name and last_name = :last_name");
}
else //check if any person besides the one who's is specified exists with the same name
{
$statement = $db->prepare("select id from persons where first_name = :first_name and last_name = :last_name and id!=:id");
$id = $person->get_id();
$statement->bindParam('id', $id);
}
$statement->bindParam('first_name', $first_name);
$statement->bindParam('last_name', $last_name);
$statement->execute();
$rows = $statement->fetchAll();
if(sizeof($rows)>=1)
{
return true;
}
else
{
return false;
}
}
catch (Exception $e)
{
throw new Exception($e->getMessage());echo $e->getMessage();
}
}
public function does_email_exist($person )
{
//check if a person with the same first name and last name already exists
try
{
$db = new PDO($this->connection_string,$this->user_name,$this->password);
if($person->get_id()==0 || $person->get_id()=='') //check if any person exists with the same name
{
$statement = $db->prepare("select id from persons where email = :person_email");
}
else //check if any person besides the one who's is specified exists with the same name
{
$statement = $db->prepare("select id from persons where email = :person_email and id!=:id");
$id = $person->get_id();
$statement->bindParam('id', $id);
}
$email = $person->get_email();
$statement->bindParam('person_email',$email);
$statement->execute();
$rows = $statement->fetchAll();
if(sizeof($rows)>=1)
{
return true;
}
else
{
return false;
}
}
catch(Exception $e)
{
throw new Exception($e->getMessage());
}
}
public function get_person($id)
{
//variable validation happens here
settype($id,'integer');
try
{
$db = new PDO($this->connection_string,$this->user_name,$this->password);
$statement = $db->prepare("select * from persons where id= :id");
$statement->bindParam('id', $id);
$statement->execute();
$row = $statement->fetchAll();
if(sizeof($row)>=1)
{
return $row;
}
else
{
throw new Exception('Person with the id not found');
}
}
catch(Exception $e)
{
throw new Exception("get_person: ".$e->getMessage());
}
}
}
?>