Hey Everyone it has been awhile wince I've worked with try/catch blocks but I would like to start using them again just for purpose of error handling and proper practices. My code is below,
$email_code = $_REQUEST['code']; //retrive the code from the user clicked link in the email
//database information
$dsn = 'mysql:host=localhost;dbname=primarydb';
$username = 'root';
$password = '';
try {
//option for PDO allows for prepared SQL statements that will mazimize the prevention of sql injections and malicious attacks on the server and databases
$conn = new PDO($dsn, $username, $password); //establish the connection
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); //disable the php parse from parsing the statements.
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); //allow error mode to be active in order to display any errors which may open up holes to attacks
//if the connection fails the try/catch block will pick it up
if (!$conn) {
throw new PDOException('Fatal error on connection');
} else {
//prepare and exexcute the query to match the codes up
$stmt = $conn->prepare("SELECT email_code, active from primarydb.user WHERE email_code = ?");
$stmt->bindParam(1, $email_code, PDO::PARAM_STR, 32);
//check to make sure that the statment executes properly
if (!$stmt->execute()){
throw new PDOException("PDO ERROR ON EXECUTION:\n" . $stmt->errorInfo());
} else { //statement has not failed
//get the row count
$count = $stmt->rowCount();
//traverse the results
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
//there can only be one!
if ($count != 1 || $row['active'] != 0) {
//generate error message
throw new PDOException("Wrong Code");
} else {
echo "working";
//prepare the update statement
$stmt = $conn->prepare("UPDATE primarydb.user SET active = ? WHERE email_code = ?");
$stmt->brindParam(1, 1, PDO::PARAM_INT);
$stmt->bindParam(2, $email_code, PDO::PARAM_STR, 32);
if (!$stmt->execute()) {
throw new PDOException("We're sorry but we can not update your profile at this time, plesae try again later. If this problem persists please contact customer service.");
} else {
print "Your account has now been activated and it is ready to use!";
}
}
}
}
}
} catch(PDOException $e){
//display error message if the database has failed in some manner
echo $e->getMessage();
}
I would like to know why I am not getting any of the error messages, and then how do I fix this problem so that I can avoid making the same problems again in the future. If there is something that is missing or if more information is needed please let me know. Otherwise I think it is pretty straight forward.
ADDITIONAL INFO: I have putt a message that says working at each block of if/else and the one it finally stops showing up at is when I check if($count != 1 || $row['active'] != 0)
UPDATE
<?php
$email_code = $_REQUEST['code']; //retrive the code from the user clicked link in the email
//database information
$dsn = 'mysql:host=localhost;dbname=primarydb';
$username = 'root';
$password = '';
try{
//option for PDO allows for prepared SQL statements that will mazimize the prevention of sql injections and malicious attacks on the server and databases
$conn = new PDO($dsn, $username, $password); //establish the connection
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); //disable the php parse from parsing the statements.
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); //allow error mode to be active in order to display any errors which may open up holes to attacks
//prepare the update statement
$stmt = $conn->prepare("UPDATE primarydb.user SET active = ? WHERE email_code = ?");
$stmt->bindParam('is', $a = 1, $email_code);
if($stmt->execute()){
print "Your account has now been activated and it is ready to use!";
}
} catch(PDOException $e){
//display error message if the database has failed in some manner
echo $e->getMessage();
}
?>
Generated new code, I don't want to get off topic, but I would like a complete solution to this problem. I am now getting the following error
Strict Standards: Only variables should be passed by reference in C:\inetpub\wwwroot\mjsite\login\complete_registration.php on line 14
SQLSTATE[HY000]: General error: 2031
Thoughts?
Please read this first line from the PDOException documentation:
Represents an error raised by PDO. You should not throw a PDOException
from your own code.
Just throw and catch regular old Exceptions. This would also catch a PDOException which inherits from it.
This also gives you a much better way to distinguish between actual exception thrown by PDO and your own exceptions. By the way, it would seem you have a number of cases where you are redundantly throwing exception when PDO would have encountered an error and thrown an exception anyway. Only the first exception will be caught, so in many of those cases, your throw would never be executed.
Also why bother with the SELECT before the update at all? YOu are basically just wasting a query because you aren't doing anything with the selected information. Perhaps just go straigth for update and handle cases where email_code doesn't exist.
Related
I'm fairly new to php and SQL and just can't figure out the problem. Note that this is a school project, therefore the vulnerability to SQL Injections and saving the blank passwords are nothing to worry about.
After the User filled out the Login-form, he's redirected to this page:
[Some html]
<?php
if(isset($_POST['submit']))
{
ConnectSQL();
}
//Retrieve POSTed Login information
$Username = htmlspecialchars($_POST['RegUsername']);
$Email = htmlspecialchars($_POST['RegEmail']);
$Password = htmlspecialchars($_POST['RegPassword']);
function ConnectSQL() {
// SQL Server Extension Sample Code:
// (ConnectionInfo, obviously it's there in the real file)
$conn = sqlsrv_connect($serverName, $connectionInfo);
// PHP Data Objects(PDO) Sample Code:
try {
$conn = new PDO('sqlsrv:server = tcp:xxx.database.windows.net,1433; Database = userdb', 'arechon', '{NotTheRealPassword}');
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Successfully connected to SQL Server and DB";
Register();
}
catch (PDOException $e) {
print('Error connecting to SQL Server.');
die(print_r($e));
}
}
function Register($Username, $Email, $Password) {
$regquery = "INSERT INTO dbo.Users (Username, Email, Password) VALUES ('UsernameTest', 'EmailTest', 'PasswordTest')";
$conn->query($regquery);
echo '<script type="text/javascript">window.open("http://xxx.azurewebsites.net/Login.html", "_self");</script>';
The Code always seems to stop at $conn->query($regquery); and doesn't return any error messages. Sometimes it just stops, when I slightly modify the Code (e.g. replacing $conn->query($regquery); with $conn->exec($regquery); or using " instead of ') I get a HTTP500 error.
I found some similiar questions here on stackoverflow as well as on other plattforms, but none of the provided answers could solve this error. Note that I use SQL and NOT MySQL (though it wouldn't be a lot of work to change that if you think that could solve my problem).
I have successfully made my symfony app connect to a MSSQL database using realestateconz/mssql-bundle and Free TDS.
My problem is that when I try to execute a stored procedure, that procedure throws an exception if something goes wrong, but PDO reports nothing back.
If I do the same thing using mssql_* functions I get a warning with the correct error message from MSSQL.
What is PDO doing differently?
Here are the two samples of code;
//PDO Version
try {
$conn = new PDO($dsn, $user, $pass);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
var_dump($e->getMessage());
die;
}
$stmt = $conn->prepare("INSERT INTO importex_parteneri (id_importex, cif_cnp, denumire) VALUES (1, 9671891, 'Nexus Media')");
$result = $stmt->execute();
var_dump($result); //true
$stmt = $conn->prepare("exec dbo.importex_parteneri_exec 1");
$result = $stmt->execute();
var_dump($result); //true
The mssql_* example
$connection = mssql_connect($server, $user , $pass);
mssql_select_db($nexus_bazadate, $connection);
$result = mssql_query("INSERT INTO importex_parteneri (id_importex, cif_cnp, denumire) VALUES (1, 9671891, 'Nexus Media')");
var_dump($result);
$result = mssql_query("exec dbo.importex_parteneri_exec 1");
var_dump($result);
/*
* The output is
*
* bool(true)
PHP Warning: mssql_query(): message: Error 50000, Level 16, State 1, Procedure importex_parteneri_exec, Line 181, Message: PRT012 - Eroare import par9671891 (severity 16) in /home/vagrant/cv.dev/web/test.php on line 19
PHP Warning: mssql_query(): General SQL Server error: Check messages from the SQL Server (severity 16) in /home/vagrant/cv.dev/web/test.php on line 19
bool(true)
*/
SOLUTION
I ended up adding a wraper around PDO::execute function function
execute(\PDOStatement $stmt, array $params = array())
{
$result = $stmt->execute($params);
$err = $stmt->errorInfo();
switch ($err[0]) {
case '00000':
case '01000':
return true;
default:
//case HY000
return false;
}
}
I may be wrong but I don't recall seeing a native way to handle SQL warnings in PDO in a somehow automated way. According to a user comment you can test manually for the SQLSTATE error code and it'll be:
'00000' (success)
'01000' (success with warning)
If it actually works, it's of course annoying to do by hand. If you have a custom layer on top of PDO you can always do it in your custom exec method.
Found lots of similar problems on this site, but the solutions for those issues don't seem to reply. The user in question has full access to the database, and from what I can tell I'm not missing any commas etc. A second set of eyes would be great.
Submitted signature is in an acceptable formatTrying to open a connectionError!: SQLSTATE[42000] [1044] Access denied for user 'emkinsti_user1'#'localhost' to database 'signatures'
<?php
// Tracks what fields have validation errors
$errors = array();
// Default to showing the form
$show_form = true;
// 1. Get the input from the form
// Using the PHP filters are the most secure way of doing it
$name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_STRING);
$output = filter_input(INPUT_POST, 'output', FILTER_UNSAFE_RAW);
// 2. Confirm the form was submitted before doing anything else
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
// 3. Validate that a name was typed in
if (empty($name)) {
$errors['name'] = true;
}
// 3. Validate that the submitted signature is in an acceptable format
if (!json_decode($output)) {
$errors['output'] = true;
}
}
// No validation errors exist, so we can start the database stuff
if (empty($errors)) {
echo "Submitted signature is in an acceptable format";"<br/>";
$dsn = 'mysql:host=localhost;dbname=signatures';
$user = 'emkinsti_user1';
$pass = '6nqq103t26';
}
// 4. Open a connection to the database using PDO
try {
echo "Trying to open a connection";
$db = new PDO($dsn, $user, $pass);
}
catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
// Make sure we are talking to the database in UTF-8
$db->exec('SET NAMES utf8');
// Create some other pieces of information about the user
// to confirm the legitimacy of their signature
$sig_hash = sha1($output);
$created = time();
$ip = $_SERVER['REMOTE_ADDR'];
// 5. Use PDO prepare to insert all the information into the database
$sql = $db->prepare('INSERT INTO signatures (signator, signature, sig_hash, ip, created)
VALUES (:signator, :signature, :sig_hash, :ip, :created)');
$sql->bindValue(':signator', $name, PDO::PARAM_STR);
$sql->bindValue(':signature', $output, PDO::PARAM_STR);
$sql->bindValue(':sig_hash', $sig_hash, PDO::PARAM_STR);
$sql->bindValue(':ip', $ip, PDO::PARAM_STR);
$sql->bindValue(':created', $created, PDO::PARAM_INT);
$sql->execute();
// 6. Trigger the display of the signature regeneration
$show_form = false;
// mysql_close($db);
$db = null;
?>
emkinsti_user1'#'localhost' to database 'signatures'
if you are using CPanel, CPanel uses prefixes also to the database name:
You used: emkinsti_user1 as users.
You should use: emkinsti_signatures as database name.
Log in into your CPanel and there you will find the database name with prefix
Try http://php.net/manual/en/pdo.getavailabledrivers.php to see if the database is supported by PDO.
<?php
print_r(PDO::getAvailableDrivers());
?>
Just an idea. I would expect another error message when it isn't. So, as far as I can tell, the user has no access when accessing the database from the local host.
Have a look through the code below. This is supposed to check whether or not a database contains a given user. If the it does, it just returns true. If it doesn't, then it returns false.
Anyway, regardless of the user and password existing in the database, for some reason it will not evaluate to true! ! !
function databaseContainsUser($email, $password)
{
include $_SERVER['DOCUMENT_ROOT'].'/includes/db.inc.php';
try
{
$sql = 'SELECT COUNT(*) FROM wl_user
WHERE email = :email AND password = :password';
$s = $pdo->prepare($sql);
$s->bindValue(':email', $email);
$s->bindValue(':password', $password);
$s->execute("USE $dbname");
}
catch (PDOException $e)
{
$error = 'Error searching for user. ' . $e->getMessage();
include $_SERVER['DOCUMENT_ROOT'].'/includes/error.html.php';
exit();
}
$row = $s->fetch(PDO::FETCH_NUM);
if ($row[0] > 0)
{
return TRUE;
}
else
{
return FALSE;
}
}
Any help would be appreciated
For some unknown reason you are passing "USE $dbname" string to execute.
remove that string.
Also, you are trying to catch an exception but apparently don't tell PDO to throw them.
And you are catching it only to echo a message, which is a big no-no.
I've explained the right way recently in this answer
If your problem is different, you have to ask (or better - google for this very problem).
Refer to PDO tag wiki for the proper connect options including database selection and error reporting.
Try this
try
{
$pdo = new PDO('mysql:host=localhost;dbname=yourDbName;', 'root', '',
array(PDO::ATTR_PERSISTENT => true));
$sql = 'SELECT count(*) FROM user WHERE email = :email AND password = :password';
$s = $pdo->prepare($sql);
$s->bindValue(':email', $email);
$s->bindValue(':password', $password);
$s->execute();
}
This is local server example, just change yourDbName to your db name. I just run this code on my local server and it is working.
I am calling a mysql stored procedure using PDO in PHP
try {
$conn = new PDO("mysql:host=$host_db; dbname=$name_db", $user_db, $pass_db);
$stmt = $conn->prepare('CALL sp_user(?,?,#user_id,#product_id)');
$stmt->execute(array("user2", "product2"));
$stmt->setFetchMode(PDO::FETCH_COLUMN, 0);
$errors = $stmt->errorInfo();
if($errors){
echo $errors[2];
}else{
/*Do rest*/
}
}catch(PDOException $e) {
echo "Error : ".$e->getMessage();
}
that return below error because the name of the field in insert query was given wrong
Unknown column 'name1' in 'field list'
So i want to know if this is possible to get detailed error information something like:-
Unknown column 'Tablename.name1' in the 'field list';
that could tell me what column of which table is Unknown.
while creating the pdo connection, pass options like error mode and encoding:
The PDO system consists of 3 classes: PDO, PDOStatement & PDOException. The PDOException class is what you need for error handling.
Here is an example:
try
{
// use the appropriate values …
$pdo = new PDO($dsn, $login, $password);
// any occurring errors wil be thrown as PDOException
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$ps = $pdo->prepare("SELECT `name` FROM `fruits` WHERE `type` = ?");
$ps->bindValue(1, $_GET['type']);
$ps->execute();
$ps->setFetchMode(PDO::FETCH_COLUMN, 0);
$text = "";
foreach ($ps as $row)
{
$text .= $row . "<br>";
}
// a function or method would use a return instead
echo $text;
} catch (Exception $e) {
// apologise
echo '<p class="error">Oops, we have encountered a problem, but we will deal with it. Promised.</p>';
// notify admin
send_error_mail($e->getMessage());
}
// any code that follows here will be executed
I found this to be helpful for me. "error_log" prints to the php error log but you can replace with whatever way you'd like to display the error.
} catch (PDOException $ex){
error_log("MYSQL_ERROR"); //This reminds me what kind of error this actually is
error_log($ex->getTraceAsString()); // will show the php file line (and parameter
// values) so you can figure out which
// query/values caused it
error_log($ex->getMessage()); // will show the actual MYSQL query error
// e.g. constraint issue
}
p.s. I know this is a bit late but maybe it can help someone.