I am still working on my own database class with pdo:
class Database {
private $databaseConnection;
public function __construct($path = "", $dbUsername = "", $dbPassword = ""){
$parts = explode('.',$path);
$documentType = array_pop($parts);
if(($path == "") || ((strcmp($documentType, "sq3") !== 0) && (strcmp($documentType, "sqlite") !== 0))) {
throw new OwnException("The Database must bee .sq3 or .sqlite and Path must be stated");
}
$this->databaseConnection = new PDO('sqlite:' . $path, $dbUsername, $dbPassword);
$this->databaseConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->databaseConnection->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$this->databaseConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
self::query('CREATE TABLE IF NOT EXISTS User(
id INTEGER PRIMARY KEY AUTOINCREMENT,
username VARCHAR(40) NOT NULL UNIQUE,
numberoflogins INTEGER DEFAULT 0,
bannedstatus BOOLEAN DEFAULT FALSE,
dateofjoining TIME
)');//password field coming soon
//self::query('CREATE TABLE...');
//self::query('CREATE TABLE...');
}
private function query($sql, $params = NULL){
$pdoStatement = $this->databaseConnection->prepare($sql);
$pdoStatement->execute(array_values((array) $params));
return $pdoStatement;
}
public function getObjects($objectTable, $searchedForAttribute, $attributeValue){
$pdoStatement = $this->databaseConnection->prepare("SELECT * FROM $objectTable WHERE $searchedForAttribute = ?");
$pdoStatement->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, $objectTable);
$pdoStatement->execute(array($attributeValue));
$resultObjects = array();
while($resultObject = $pdoStatement->fetch()){
array_push($resultObjects, $resultObject);
}
if(empty($resultObjects)){
return false;
}
return $resultObjects;
}
public function getObject($objectTable, $searchedForAttribute, $attributeValue){
//...returns only the first Object from getObjects()
}
public function insertObject($object){
$objectTable = get_class($object);
$objectData = $object->getAttributes();
return $this->query("INSERT INTO $objectTable("
. join(',', array_keys($objectData)) . ")VALUES("
. str_repeat('?,', count($objectData)-1). '?)', $objectData);
}
public function updateAttribute($objectTable, $setData, $searchedAttribute, $searchedAttributeValue){
...
}
public function updateObject($object){
...
}
public function attributeRemoveObject($objectTable, $searchedForAttribute, $attributeValue){
...
}
public function __destruct(){
unset($this->databaseConnection);
}
}
as you can see there is still no data validation for the functions (and no exception handling, work in progress) such like getObjects() so the variables $objectTable, $searchedForAttribute and $attributeValue going direct into the query. This means no protection against SQL injections.
So I thought it would be quite helpful if I use a static function to validate data before inserting into query:
public static function validate($unsafeData){
//validate $unsafeData
return $safeData
}
Because I want to have the ability to search for usernames with similar names and stuff bin2hex() and hex2bin() is a bad choice and for some attributes like the username it is easy to find some starting points for the validation. For instance I would search for empty space, ', " and =...
But how should I validate the content of a forumpost which contains a lot of signs used for SQL queries to? I mean it could also be a a post about sql itself.
I saw a lot of examples for SQL Injections but all of them missing the point that the main manipulation could also be in the content box.
So how does a forum prevent SQL Injections and Errors referring to the content of a post ?