Here is the code for blocking comments from blocked users. Comments are getting blocked for only the first blocked user in the database table, but i want the comments to be hidden for all the blocked users in database table.
<?php
include_once('adminpanel/dbconnect.php');
$sql_query =mysql_query("SELECT * FROM blocked_accounts WHERE
blocker_id=".$id);
$rr=mysql_fetch_array($sql_query);
if($rr['blocked_id'] == $r['id'] && $rr['blocker_id'] == $id)
{
echo "";
}
else
{ ?>
You need to go through all the records and if any of them match, then this is blocked. This code first sets a flag to say it isn't blocked, then if any of the records match, sets this to true and breaks out of the loop (not worth carrying on)...
<?php
include_once('adminpanel/dbconnect.php');
$sql_query = $conn->prepare( "SELECT * FROM blocked_accounts WHERE
blocker_id= ?");
$sql_query->bind_param("i", $id);
$sql_query->execute();
$blocked = false;
while ($rr=mysqli_fetch_assoc($sql_query)) {
if($rr['blocked_id'] == $r['id'] && $rr['blocker_id'] == $id)
{
$blocked = true;
break;
}
}
if($blocked)
{
echo "";
}
else
{ ?>
As mentioned in the comments, this is update to mysqli_ and prepared statements, you will need to change your connect to use mysqli as well (PHP mysqli connect function may helpd if you are not sure).
Using mysql_* functions is very bad practice because they have been outdated for many years. Since you're in the phase of learning, it's best to focus on learning how to use prepared statements, whether in the form of mysqli or PDO and stick with that.
As to the problem at hand, the code you've given is vague and things that are needed to send the query, such as the connection, are missing. Therefore, my answer aims to guide you into using mysqli prepared statements correctly rather than give you a full-fledged solution.
Code:
<?php
# Establish a connection to the database.
$connection = new mysqli("your host", "your username", "your password", "your db");
# Create a mysqli query.
$query = "SELECT * FROM `blocked_accounts` WHERE `blocker_id` = ?";
# Prepare the query and check whether the operation was successful.
if ($stmt = $connection -> prepare($query)) {
# Bind the parameters to the statement.
$stmt -> bind_param("i", $id); # 'i' means integer
# Execute the statement and check whether the operation was successful.
if ($stmt -> execute()) {
# Get the result out of the statement and cache it.
$result = $stmt -> get_result();
# Close the statement.
$stmt -> close();
# Fetch the first row (use 'while' if you want more).
if ($row = $result -> fetch_assoc()) {
# Check whether the user is blocked...
}
}
}
# Shut down the database connection.
$connection -> close();
?>
Notes:
When you're trying to query the database, remember to use the actual connection you established. In your mysql_query function call, there is not connection passed.
The part && $rr['blocker_id'] == $id in your if check is redundant because the value of $id is the value we used to filter the results returned by the database, so it will be always true.
Related
I have this code:
$host = "127.0.0.1";
$db = "mydb";
$user = "user";
$pass = "pass";
$dbh = new PDO("pgsql:dbname=$db;host=$host", $user, $pass);
$query = "select * from mytable";
$stmt = $dbh->prepare($query);
if ($stmt) {
echo "Query was OK, execute!";
$stmt->execute();
var_dump($stmt->fetchAll());
} else {
echo "Query was NOT OK!";
var_dump($dbh->errorInfo());
}
but it always says
Query was OK, execute
even if the SQL is blatantly wrong (e.g. "bogus SQL" or querying a non-existing table). It always returns a dataset, which is empty when the query is wrong. I know the connection is fine, because a valid query returns valid results.
I do not see any errors anywhere, also not in the logs.
According to the documentation:
Note:
Emulated prepared statements does not communicate with the database server so PDO::prepare() does not check the statement.
So you can write whatever to be prepared, only executing it will check it for validity if emulation is on.
You also don't check the return value of execute() to see if it succeeded and fetchAll() returns an empty array if there are no results by documentation.
According to the documentation:
Note:
Emulated prepared statements does not communicate with the database
server so PDO::prepare() does not check the statement.
So you can write whatever to be prepared, only executing it will check it for validity if emulation is on.
If you want to try if there is any error, you have to excute it then check if the previous was excuted.
$stmt->execute();
if($stmt->errorCode() === '00000'){
// Mean "OK"
var_dump($stmt->fetchAll());
} else {
echo "Query was NOT OK!";
var_dump($dbh->errorInfo());
}
I have a simple question. I'm not too good at programming yet but is this safe and correct?
Currently I am using functions to grab the username, avatars, etc.
Looks like this:
try {
$conn = new PDO("mysql:host=". $mysql_host .";dbname=" . $mysql_db ."", $mysql_username, $mysql_password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}
catch(PDOException $e)
{
echo "Connection failed: " . $e->getMessage();
}
config.php ^^
function getUsername($userid) {
require "config/config.php";
$stmt = $conn->prepare("SELECT username FROM accounts WHERE id = ? LIMIT 1");
$stmt->execute([$userid]);
$name = $stmt->fetch();
return $name["username"];
}
function getProfilePicture($userid) {
require "config/config.php";
$stmt = $conn->prepare("SELECT profilepicture FROM accounts WHERE id = ? LIMIT 1");
$stmt->execute([$userid]);
$image = $stmt->fetch();
return $image["profilepicture"];
}
Is this correct and even more important, is this safe?
Yes, it's safe with respect to SQL injections.
Some other answers are getting off topic into XSS protection, but the code you show doesn't echo anything, it just fetches from the database and returns values from functions. I recommend against pre-escaping values as you return them from functions, because it's not certain that you'll be calling that function with the intention of echoing the result to an HTML response.
It's unnecessary to use is_int() because MySQL will automatically cast to an integer when you use a parameter in a numeric context. A non-numeric string is interpreted as zero. In other words, the following predicates give the same results.
WHERE id = 0
WHERE id = '0'
WHERE id = 'banana'
I recommend against connecting to the database in every function. MySQL's connection code is fairly quick (especially compared to some other RDBMS), but it's still wasteful to make a new connection for every SQL query. Instead, connect to the database once and pass the connection to the function.
When you connect to your database, you catch the exception and echo an error, but then your code is allowed to continue as if the connection succeeded. Instead, you should make your script die if there's a problem. Also, don't output the system error message to users, since they can't do anything with that information and it might reveal too much about your code. Log the error for your own troubleshooting, but output something more general.
You may also consider defining a function for your connection, and a class for your user. Here's an example, although I have not tested it:
function dbConnect() {
try {
$conn = new PDO("mysql:host=". $mysql_host .";dbname=" . $mysql_db ."", $mysql_username, $mysql_password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}
catch(PDOException $e)
{
error_log("PDO connection failed: " . $e->getMessage());
die("Application failure, please contact administrator");
}
}
class User {
protected $row;
public function __construct($userid) {
global $conn;
if (!isset($conn)) {
$conn = dbConnect();
}
$stmt = $conn->prepare("SELECT username, profilepicture FROM accounts WHERE id = ? LIMIT 1");
$stmt->execute([$userid]);
$this->row = $stmt->fetch(PDO::FETCH_ASSOC);
}
function getUsername() {
return $this->row["username"]
}
function getProfilePicture() {
return $this->row["profilepicture"]
}
}
Usage:
$user = new User(123);
$username = $user->getUsername();
$profilePicture = $user->getProfilePicture();
That looks like it would work assuming that your config file is correct. Because it is a prepared statement it looks fine as far as security.
They are only passing in the id. One thing you could do to add some security is ensure that the $userid that is passed in is the proper type. (I am assuming an int).
For example if you are expecting an integer ID coming in and you get a string that might be phishy (possible SQL injection), but if you can confirm that it is an int (perhaps throw an error if it isn't) then you can be sure you are getting what you want.
You can use:
is_int($userid);
To ensure it is an int
More details for is_int() at http://php.net/manual/en/function.is-int.php
Hope this helps.
It is safe (at least this part of the code, I have no idea about the database connection part as pointed out by #icecub), but some things you should pay attention to are:
You only need to require your config.php once on the start of the file
You only need to prepare the statement once then call it on the function, preparing it every time might slow down your script:
The query only needs to be parsed (or prepared) once, but can be executed multiple times with the same or different parameters. When the query is prepared, the database will analyze, compile and optimize its plan for executing the query. - PHP Docs
(Not an error but I personally recommend it) Use Object Orientation to help organize your code better and make easier to mantain/understand
As stated by #BHinkson, you could use is_int to validate the ID of the user (if you are using the IDs as numbers)
Regarding HTML escaping, I'd recommend that you already register your username and etc. HTML escaped.
I'm reaching out after hours of fruitlessly trying to fix a small section of code that just doesnt seem to work regardless of how i try to fetch the value and store.
I will admit I'm not the most experienced and hoping it is a small error on my part that can be easily spotted by someone with more expertise.
All other functions work as expected and fetch all the required value except one, With s the member_id field. This is a linked ID from another table (companies) however in test query the statement works fine.
Whole Code Snippet
<?php
//Error reporting - DEV ONLY
error_reporting(E_ALL);
ini_set('display_errors', 'on');
//New Connection
$mysqli = new mysqli('localhost', 'USER', 'PASSWORD', 'DATABASE');
//Connection Verification
if ($mysqli->connect_errno) {
printf("Connection Failure: %s\n", $mysqli->connect_error);
exit();
}
//Start Session and assign POST values
session_start();
$username = $_POST['username'];
$password1 = $_POST['password'];
//Query prepare, execution and bind
$stmt = $mysqli->prepare("SELECT password FROM user WHERE username='$username'");
$stmt -> execute();
$stmt -> bind_result($result);
/* Fetch the value */
$stmt -> fetch();
/* Close statement */
$stmt -> close();
//Verify password match and direct user according to result
if(password_verify($password1, $result))
{
$stmt = $mysqli->prepare("SELECT member_id FROM user WHERE username='$username'");
$stmt -> execute();
$stmt -> bind_result($company);
$_SESSION['loggedin'] = true;
$_SESSION['username'] = $username;
$_SESSION['company'] = $company;
Header("Location: home.php");
}else{
sleep(5);
Header("Location: index.php");
}
$mysqli->close();
?>
Suspected Issue Code Snippet
if(password_verify($password1, $result))
{
$stmt = $mysqli->prepare("SELECT member_id FROM user WHERE username='$username'");
$stmt -> execute();
$stmt -> bind_result($company);
$_SESSION['loggedin'] = true;
$_SESSION['username'] = $username;
$_SESSION['company'] = $company;
Header("Location: home.php");
}else{
sleep(5);
Header("Location: index.php");
}
Thank you in advance for your help!
EDIT: The issue is, there is no output from:
SELECT member_id FROM user WHERE username='$username
However in a direct query with MySQL it works so feel its a binding issue. this should be bound to $_SESSION['company'].
The other answer is somewhat examplary.
As the question is going to be closed anyway, I'd take a liberty to comment the other answer.
change the name of your second instance of $stmt to something else - $stmtTwo
There is no point in doing that, as previous statement is already closed and cannot interfere in any way.
Would I be writing PHP for 15 years, I would rather suggest to do all the mysql job in one single query, without the need of second statement at all.
add a var_dump($stmtTwo); after binding the result into $company.
That's quite a random poke. Why after binding but not anywhere else?
check your MySQL log for MySQL errors.
For 99% of php users that's mission impossible. Yet it's a matter of only two commands to have the error message right on the screen on the development server.
Is the column member_id in the user table?
That is again a random poke (what about password field?) and it's have to be addressed to the error message discussed in the previous topic anyway. There is no point in asking a programmer for that. One should ask a database, as a way more reliable source.
Add a print output inside it, to show that the password_verify function is working and allowing that code block to execute.
That's the only good point.
Recommendation for using prepared statements is right too, but for some reason it is called "Object style" which is nowhere near the point.
And yes, he finally managed to spot the typo that makes whole question offtopic - fetch() statement is absent.
I suspect that your MySQL is not firing because you're using a PREPARE statement without passing it any values.
Would I be using mysqli myself, I would have known that such a query is all right.
header should be lower case. header() and should be immediately followed by a die or exit command.
Neither is actually true.
Functions in PHP are case insensitive and there is no logic behind this point - so, no manual exit is required.
Stack Overflow is not a code review site either, but nobody cares actually, as one third of answers to those celebrated 10M questions are actually code review answers. So here it goes:
<?php
//Error reporting - ALWAYS PRESENT
error_reporting(E_ALL);
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
//Error displaying - DEV ONLY
ini_set('display_errors', 'on');
//New Connection
$mysqli = new mysqli('localhost', 'USER', 'PASSWORD', 'DATABASE');
//Start Session
session_start();
//Query prepare, bind, execute and fetch
$stmt = $mysqli->prepare("SELECT member_id, password FROM user WHERE username=?");
mysqli->bind_param("s",$_POST['username']);
$stmt->execute();
$stmt->bind_result($member_id, $db_pass);
$stmt->fetch();
if(password_verify($_POST['password'], $db_pass))
{
$_SESSION['username'] = $_POST['username'];
$_SESSION['company'] = $member_id;
Header("Location: home.php");
}else{
Header("Location: index.php");
}
You have not added a Fetch statement after binding the result:
if(password_verify($password1, $result))
{
$stmt = $mysqli->prepare("SELECT member_id FROM user WHERE username='$username'");
$stmt -> execute();
$stmt -> bind_result($company);
$stmt -> fetch();
/* Close statement */
$stmt -> close();
$_SESSION['loggedin'] = true;
$_SESSION['username'] = $username;
$_SESSION['company'] = $company;
Some extra notes:
You are writing your MySQL incorrectly, it is wide open to compromise.
You are using the old MySQL style approach but with the structure of the newer OOP approach, this is just as much as security risk as original MySQL.
Old - procedural- style:
mysqli_query($link, "SELECT poops FROM bathroom WHERE smell = '$bad' LIMIT 1");
New - Object Orientated style:
mysqli->prepare("SELECT poops FROM bathroom WHERE smell = ? LIMIT 1")
mysqli->bind_param("s",$bad); //the value is placed by reference rather than directly
mysqli->execute;
Also:
header should be immediately followed by a die or exit command.
header("Location:blah.php");
exit;
I'm making a forum in php and MySql, so I need to insert and select data from my data base. I'm using mysqli to connect to my db. Something like this:
$link=mysqli_connect("fake_server", "fake_user", "fake_pass", "fake_db");
$user=mysqli_real_escape_string($link, $_POST['user']);
$pass=hash("sha256", mysqli_real_escape_string($link, $_POST['pass']));
$combo=mysqli_fetch_array(mysqli_query($link, "SELECT 1 FROM users WHERE user='$user' AND pwd='$pass'"));
if($combo==0){
// ERROR
} else {
// CORRECT
}
mysqli_close($link);
The problem is the next one:
Everybody say that mysqli_real_escape_string() is MUCH better than addslashes() for insert, but I want users can use single and double quotes in their topics. Myqsli_real_escape_string() removes them but addslashes() doesn't. What can I do in this context?
You should use prepared statements, http://php.net/manual/en/mysqli.quickstart.prepared-statements.php. In the future please provide your code in your question. Here's how you can use your current code with prepared statements:
$link=mysqli_connect("fake_server", "fake_user", "fake_pass", "fake_db");
$user=$_POST['user'];
$pass=hash("sha256", $_POST['pass']);
$stmt = $link->prepare("SELECT 1 FROM users WHERE user = ? AND pwd = ?");
$stmt->bind_param("ss", $user, $pass);
$combo=mysqli_fetch_array($stmt->execute());
if($combo==0){
// ERROR
} else {
// CORRECT
}
mysqli_close($link);
Further reading on the topic:
How can I prevent SQL injection in PHP?mysqli or PDO - what are the pros and cons?
https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet#Defense_Option_1:_Prepared_Statements_.28Parameterized_Queries.29http://php.net/manual/en/mysqlinfo.api.choosing.php
Use a parameterized query with PDO and forget worrying about escaping your queries.
Edit
Your test code:
$link=mysqli_connect("fake_server", "fake_user", "fake_pass", "fake_db");
$user=mysqli_real_escape_string($link, $_POST['user']);
$pass=hash("sha256", mysqli_real_escape_string($link, $_POST['pass']));
$combo=mysqli_fetch_array(mysqli_query($link, "SELECT 1 FROM users WHERE user='$user' AND pwd='$pass'"));
if($combo==0){
// ERROR
} else {
// CORRECT
}
mysqli_close($link);
The PDO version:
$pdo = new PDO('mysql:host=fake_server;dbname=fake_db', 'fake_user', 'fake_pass');
$query = $pdo->prepare("SELECT 1 FROM users WHERE user='?' AND pwd='?'");
$query->execute(array($_POST('user'), hash('sha256', $_POST('pass')));
if ($combo = $query->fetch ()) {
// CORRECT
// $combo would contain an array containing your select fields
} else {
// ERROR
}
Here's PHP code that I'm using:
$query="select * from `myTable` where `email`='$email' limit 0,1";
if(empty($conn))
{
echo "not connected".PHP_EOL;
}
$result = mysql_query($query,$conn);
$row = mysql_fetch_array($result);
if(empty($row))
{
....
When the query is executed in phpmyadmin, I get a single row selected.
However, when I execute the code in php, the row is always empty.
The same goes for several other queries that I've tried to execute. mysql_query always fails.
What could be wrong?
I do not feel there is enough of the code to see what is going on. But based on just what you are showing us, after you get the $result and assign it to $row you have a if statement
if(empty($row)) {...doing something secret...}
which means if something was returned like the row you are expecting NOTHING would happen because (empty($row)) would be false and not execute.
Try this using PDO:
<?php
$email = "example#example.com";
try {
//Instantiate PDO connection
$conn = new PDO("mysql:host=localhost;dbname=db_name", "user", "pass");
//Make PDO errors to throw exceptions, which are easier to handle
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//Make PDO to not emulate prepares, which adds to security
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$query = <<<MySQL
SELECT *
FROM `myTable`
WHERE `email`=:email
LIMIT 0,1;
MySQL;
//Prepare the statement
$stmt = $conn->prepare($query);
$stmt->bindParam(":email", $email, PDO::PARAM_STR);
$stmt->execute();
//Work with results
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
//Do stuff with $row
}
}
catch (PDOException $e) {
//Catch any PDOExceptions errors that were thrown during the operation
die("An error has occurred in the database: " . $e->getMessage());
}
Using mysql_* functions is highly discouraged. It's a guarantee to produce broken code. Please learn PDO or MySQLi from the links in the comment I gave you, and use those instead.
First, confirm $email's value. Echo it right before defining $query to make sure it's what you think it is.
If you've already done that, then you know that's the problem--instead, it's likely that your link identifier $conn is the problem. Instead of using a link identifier, try leaving the second parameter of your query empty, and instead run mysql_connect() at the beginning of your script. That's the best way to do things 99.5% of the time.
See: http://php.net/manual/en/function.mysql-connect.php