Okay so I was wondering what is the best way to show a user their own photo and if my way is safe or what should i change.
url:
http://localhost/project/everyone/myphoto.php?num=2
php code:
$user_id = $_SESSION['user_id'];
if (isset($_GET['num'])) {
$num = $_GET['num'];
if ($stmt = $dbconn->prepare("SELECT 1 FROM t_photos WHERE id ='$num' AND user_id ='$user_id' LIMIT 1")) {
$stmt->execute();
$stmt->store_result();
$rows = $stmt->num_rows;
if ($rows === 1) {
$stmt = $dbconn->prepare("SELECT url,uploaddate FROM t_photos WHERE id = ?");
$stmt->bind_param('i', $num); // Bind "$email" to parameter.
$stmt->execute(); // Execute the prepared query.
$stmt->store_result();
$stmt->bind_result($photopath, $uploadtime); // get variables from result.
$stmt->fetch();
} else {
$error2 = "Error 2";
require 'notfound.php';
die();
}
}
}
html & Php code :
<div id="pathwrap">
<div class="photowrap">
<?php if (isset($photopath)) {
echo '<img src="' . $photopath . '">';
} ?>
</div>
</div>
This is how I would do it with PDO and Exception style:
function requestCurrentUserPhoto(){
if( !isset($_GET['num']) ){
throw new Exception('Bad request. The generated link missing get prop num.');
}
if( !isset($_SESSION['user_id']) ){
throw new Exception('Bad request. The generated link linked to a guest.');
}
$sth = $dbh->prepare('SELECT url,uploaddate FROM t_photos WHERE id = :id AND user_id = :user_id LIMIT 1');
$sth->execute(array(
':id' => (int) $_GET['num'],
':user_id' => (int) $_SESSION['user_id']
));
$result = $sth->fetch(PDO::FETCH_ASSOC);
if( $result === false ){
throw new Exception('Bad request. The generated link linked to a non-existence photo or unauthorized user.');
}
//optional...
if( empty($result['url']) || empty($result['uploaddate']) ){
throw new Exception('Bad database table row. There is a invalid photo row in t_photos');
}
return $result;
}
This code should be safe. And it should also check if the code that is related got any errors.
Related
can you help out a beginner trying to learn PHP? I wrote a code for changing password without any validations yet, just to change it and it does not work. It's been days I've been trying and couldn't figure out what's wrong. Thanks in advance.
id is variable name in database where id is kept.
db connection is done with first line and it definitely works.
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
session_start();
print_r($_SESSION);
function changePSW()
{
//$password = $_POST['currPassword']; // required
$newPassword = $_POST['newPassword']; // required
//$newPassword2 = $_POST['NewPassword2']; // required
$newPasswordH = password_hash($newPassword, PASSWORD_DEFAULT);
echo($newPassword);
$id = $_SESSION['userID'];
echo($id);
// create PDO connection object
$dbConn = new DatabaseConnection();
$pdo = $dbConn->getConnection();
try {
$statement = $pdo->prepare("SELECT * FROM `users` WHERE id = :id LIMIT 1");
$statement->bindParam(':id', $id);
$statement->execute();
$result = $statement->fetchAll(PDO::FETCH_ASSOC);
echo "SADASDASD";
// no user matching the email
if (empty($result)) {
$_SESSION['error_message'] = 'Couldnt find user';
header('Location: /Online-store/userForm.php');
return;
}
$sql = "UPDATE users SET password=:newPasswordH WHERE id = :id";
// Prepare statement
$stmt = $pdo->prepare($sql);
echo "AFGHANIKO";
// execute the query
$update_status = $stmt->execute(array(':password' => $newPasswordH, ':id' => $id));
echo "IHAAA";
echo($update_status);
if ($update_status === TRUE) {
echo("Record updated successfully" . "\r\n");
echo nl2br("\nPassword: ");
echo ($newPassword);
echo nl2br("\nHashed Password: ");
echo ($newPasswordH);
return true;
} else {
echo "Error updating record";
die();
}
} catch (PDOException $e) {
// usually this error is logged in application log and we should return an error message that's meaninful to user
return $e->getMessage();
}
}
if($_SESSION['isLoggedIn'] == true) {
require_once("database/DatabaseConnection.php");
unset($_SESSION['success_message']);
unset($_SESSION['error_message']);
changePSW();
}
?>
$update_status = $stmt->execute(array(':newPasswordH' => $newPasswordH, ':id' => $id));
This is what I needed to have instead of
$update_status = $stmt->execute(array(':password' => $newPasswordH, ':id' => $id));
I have a variable $success set to $success = "Successfully Created" but the var $success has no value inside HTML.
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// username and password sent from form
if (isset($_POST['okbutton'])) {
if (isset($_POST['clientuser'], $_POST['clientpass'])) {
$clientuser = $_POST['clientuser'];
$clientpass = $_POST['clientpass'];
$_SESSION['cuser'] = $clientuser;
$_SESSION['cpass'] = $clientpass;
header('Location: trialaccount.php');
die();
}
}
}
try {
if (isset($_SESSION['cuser'])) {
$stmt = $conn->prepare("SELECT user_id FROM user WHERE user_id=:username");
$stmt->bindParam(':username', $_SESSION['cuser']);
$stmt->execute();
$checkdup = $stmt->rowCount();
if ($checkdup == 0) {
$stmt = $conn->prepare("INSERT INTO user (user_id, user_pass, user_online, user_enable, user_start_date, user_end_date, reseller, type) VALUES (:clientuser, :clientpass,0, 1, now(), now() + interval 4 hour, :panelUSER, 'Trial')");
$stmt->bindParam(':clientuser', $_SESSION['cuser']);
$stmt->bindParam(':clientpass', $_SESSION['cpass']);
$stmt->bindParam(':panelUSER', $username);
$stmt->execute();
$success = "Trial Account Created Successfully!";
} else {
$error = "Username '" . $_SESSION['cuser'] . "' is already taken. Try to input unique username." ;
}
}
} catch (PDOException $e) {
echo "Error: Database Error";
}
Inside my HTML, I use echo!
<?php if(isset($success)){ echo $success; } ?>
var $success is returning the value on my personal smartphone,
but no value on other devices.
I dont know what is happening?
Can I use Session instead? ty
Your method does not get the total row count. Therefore, it doesn't go through (if($checkdup == 0)) to set the value for $success. You can try the code below.
Replace:
$stmt = $conn->prepare("SELECT user_id FROM user WHERE user_id=:username");
$stmt->bindParam(':username', $_SESSION['cuser']);
$stmt->execute();
$checkdup = $stmt->rowCount();
With:
$stmt = $conn->prepare("SELECT COUNT(*) FROM user WHERE user_id=:username");
$stmt->bindParam(':username', $_SESSION['cuser']);
$stmt->execute();
$checkdup = $stmt->fetchColumn();
SQL table consist of Id(AI),PID,AID,WEB,ADVERT
My code gets all variables but does not registers anything. But There are two methods of registration.
A. Form includes only to fill PID and Website, where ADVERT is sent hidden.
B. Form includes PID,AID,and website where Advert is sent hidden.
PID is not unique and can be multiple
AID is Unique or 0 if not registered selecting the FORM A in which AID is passed as 0 or NULL
Website is not unique and can be duplicate
If AID is null or 0
IF AID is NULL Check if PID and WEB match [Only Once registered if AID is null]
IF AID is Not NULL Check if AID,PID and WEB is already registered. [Already exist]
LASTLY If Everything is OKAY Register the product in database.
<?php
session_start();
$u = $_SESSION['username']; //GETS Session username to register a product
require('db.php'); //db connection
// ----------------PART A------------
//This gets the ID index Number of user from Member Table
$user = "SELECT id from members WHERE username=?";
$stmt = $ref->prepare($user);
$stmt->bind_param("s", $u);
$rc = $stmt->execute();
if ( false===$rc ) {
die('execute() failed at 1: ' . htmlspecialchars($stmt->error));
}
$stmt->bind_result($ux);
$stmt->fetch();
$stmt->close();
echo "Pass A <br>"; //Testing purpose
// ----------------------------------------------------------
$aid = $_POST['proslot'];
$web = $_POST['web'];
$pid = $_POST['pub'];
$advert = $_POST['advert'];
//-------------INFO DEBUG-----------------
//Testing Codes Variables pass
echo "<br>uid:<br>".$ux; // User ID
echo "<br>advert:<br>".$advert; //Product advertiser
echo "<br>pid:<br>".$pid; //Product id
echo "<br>aid:<br>".$aid; //audit id
echo "<br>web:<br>".$web; //Product website
//------------------------------------------------------
//-------------------PART B-----------------------------
if($_POST['adslot'] != NULL){
//Cheack if AID and WEBSITE matches any existing record.
$valid = "SELECT id from prologger WHERE aid=? AND userweb=?";
$stmt = $ref->prepare($valid);
$stmt->bind_param("is", $aid,$web);
$rc = $stmt->execute();
if ( false===$rc ) {
die('execute() failed at 2: ' . htmlspecialchars($stmt->error));
}
$stmt->store_result();
$val = $stmt->num_rows;
if($val > 0){
echo "Product Already exist :";
$stmt->close();
$ref->close();
exit();
} else{
$stmt->close();
$ref->close();
}
echo "Pass B[1]";
//---------------------PART B[2]-------------------------
} else {
//Cheack if PID,AID and WEBSITE matches any existing record.
$valid = "SELECT id from prologger WHERE pid=? AND aid=? AND userweb=?";
$stmt = $ref->prepare($valid);
$stmt->bind_param("sis", $pid, $aid,$web);
if($_POST['adslot'] == '0' || $_POST['adslot'] == NULL) {
$aid = '0' or $aid = NULL;
} else {
$aid = $_POST['proslot'];
}
$rc = $stmt->execute();
if ( false===$rc ) {
die('execute() failed at 3: ' . htmlspecialchars($stmt->error));
}
$stmt->store_result();
$val2 = $stmt->num_rows;
if($val2 > 0){
echo "Unique product per website Required. This product is already registered to this website:"
$stmt->close();
$ref->close();
exit();
}
$stmt->close();
//------------------------------------------------------
//------------------------PART C------------------------
echo "Pass C";
echo "<br>ROW 1:<br>".$val; //DEBUG VALUE
$sql = "INSERT INTO prologger (uid,advert,pid,aid,userweb) VALUES (?,?,?,?,?)";
$stmt = $ref->prepare($sql) ;
$stmt->bind_param("sssis", $ux , $advert, $pid, $aid , $web); //bind variables
if($_POST['adslot'] == NULL) {
$aid = '0';
} else {
$aid = $_POST['adslot'];
}
$input = $_POST['web'];
$input = trim($input, '/');
// If not have http:// or https:// then prepend it
if (!preg_match('#^http(s)?://#', $input)) {
$input = 'http://' . $input;
}
$urlParts = parse_url($input);
// Remove www.
$web = preg_replace('/^www\./', '', $urlParts['host']);
$rc = $stmt->execute();
if ( false===$rc ) {
die('execute() failed: at 4 ' . htmlspecialchars($stmt->error));
}
$stmt->close();
$ref->close();
echo "Pass Final";
}
//------------------------------------------------------
?>
I fixed it myself. There was an "IF else" Condition that was in this above code Part B
if($_POST['adslot'] != NULL){ //code } else { rest of the code }
where Else needed to be removed
and a $ref->close in the Part B in the else statement of if($val>0) condition which needed to be removed to fix the issue.
I'm sending an array of values from a form. I want to loop through the database table looking for these IDs. As I get this message I understand something is wrong...
Fatal error: Call to a member function bind_param() on a non-object in /home/d15155/tool/pdf.php on line 56
if (count($_POST['q']) == 0){
}
else {
foreach($_POST['q'] as $quality){
# Prepare statement
$stmt = $mysqli->prepare("SELECT the_question, the_sub_questions, the_quality, the_time FROM my_questions WHERE the_category='2' AND the_headline='5' AND quality_id = ? ORDER BY the_sort_order ASC");
$stmt->bind_param('i', $quality);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($the_question, $the_sub_questions, $the_quality, $the_time);
$stmt->fetch();
$konkretaexempel .= utf8_encode($the_question) . " <br />";
}
}
I want to add the results into a long string (then to be used in a PDF).
EDIT
Removed the foreach and the array and it still getting the same error message. I have checked and the database connection is OK.
if (count($_POST['q']) == 0){
}
else {
$stmt = $mysqli->prepare("SELECT the_question, the_sub_questions, the_quality, the_time FROM my_questions WHERE the_category='2' AND the_headline='5' AND quality_id = ? ORDER BY the_sort_order ASC");
$stmt->bind_param('i', '27');
$stmt->execute();
$stmt->bind_result($the_question, $the_sub_questions, $the_quality, $the_time);
$stmt->fetch();
$konkretaexempel .= utf8_encode($the_question) . " <br />";
}
Sean's tip in the comments is probably more than a side note here; it will get rid off the problem: There can be only one active query/statement per connection and after the single ->fetch() the statement is still active (a while-loop would fix that, but no need for that here). When you re-use the $stmt instance as suggested any old result set will be discarded.
Your script currently is like
<?php
$mysqli = setup();
if (count($_POST['q']) == 0){
myErrorHandling();
}
else {
foreach($_POST['q'] as $quality){
$stmt = $mysqli->prepare("SELECT x, y FROM soFoo WHERE id = ?");
if ( !$stmt ) { die('prepare failed'); }
$stmt->bind_param('i', $quality);
$stmt->execute();
$stmt->bind_result($x, $y);
$stmt->fetch();
printf("x=%d,y=%s\r\n", $x, $y);
}
}
function setup() {
// for demonstration purposes only
$_POST = [ 'q'=> [
1,3,5
]];
mysqli_report(MYSQLI_REPORT_STRICT);
$mysqli = new mysqli('localhost', 'localonly', 'localonly', 'test');
$mysqli->query('
CREATE TEMPORARY TABLE soFoo (
id int auto_increment,
x int,
y varchar(32),
primary key(id)
)
');
$stmt = $mysqli->prepare('INSERT INTO soFoo (x,y) VALUES (?,?)');
$stmt->bind_param('ss', $x, $y);
foreach( range('a','z') as $x=>$y ) {
$stmt->execute();
}
return $mysqli;
}
and the output is
x=0,y=a
prepare failed
Now when I move the calls to prepare/bind_param to before the loop
<?php
$mysqli = setup();
if (count($_POST['q']) == 0){
myErrorHandling();
}
else {
$stmt = $mysqli->prepare("SELECT x, y FROM soFoo WHERE id = ?");
if ( !$stmt ) { die('prepare failed'); }
$stmt->bind_param('i', $quality);
foreach($_POST['q'] as $quality){
$stmt->execute();
$stmt->bind_result($x, $y);
$stmt->fetch();
printf("x=%d,y=%s\r\n", $x, $y);
}
}
function setup() {
... same as before...
}
the output is
x=0,y=a
x=2,y=c
x=4,y=e
as expected.
I've made the following script that shows blogposts. $_MULT[0] shows 'blog', $_MULT[1] shows the ID of the blogpost.
I'm wondering:
1) Is this script safe for SQL injection?
2) What if I removed ctype_digit() ? Would it still be safe then?
<?php
error_reporting(E_ALL);
$db = new PDO('mysql:host=localhost;dbname=blablabla','blablabla','passwd');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
echo '<h2>Blog</h2>';
$iTijd = time();
$_MULT = explode("/", $_GET['p']);
if($_MULT[0] == 'blog' AND isset($_MULT[1]))
{
if(ctype_digit($_MULT[1]))
{
// query
$sql = "SELECT Titel, Post, Datum FROM Blog WHERE Id = :Id AND Status = :Status AND Datum < :Tijd LIMIT 1";
// prepare query
$stmt = $db->prepare($sql);
// bind values
$stmt->bindParam(':Id', $a=$_MULT[1], PDO::PARAM_INT);
$stmt->bindParam(':Status', $a='1', PDO::PARAM_INT);
$stmt->bindParam(':Tijd', $a=$iTijd, PDO::PARAM_INT);
// execute query
$stmt->execute();
// select data from db
$aRow = $stmt->fetch(PDO::FETCH_ASSOC);
// show blogpost
echo '<h4>'. $aRow['Titel'] .'</h4><br />';
$datum = $aRow['Datum'];
$datum = date("d-m-Y", $datum);
echo '<i>'. $datum.'</i> - '. $aRow['Post'];
}
else
{
echo "<h2>404 - Pagina niet gevonden</h2>";
}
}
else
{
// query
$sql = "SELECT Id, Titel FROM Blog WHERE Status = :Status AND Datum < :Tijd ORDER BY Id DESC LIMIT 10";
// prepare query
$stmt = $db->prepare($sql);
// bind values
$stmt->bindParam(':Status', $a='1', PDO::PARAM_INT);
$stmt->bindParam(':Tijd', $a=$iTijd, PDO::PARAM_INT);
// execute query
$stmt->execute();
echo '<br /><ul>';
// select data from db
while($aRow = $stmt->fetch(PDO::FETCH_ASSOC))
{
echo '<h4><li>'. $aRow['Titel'] .'</li>
</h4>';
}
echo '</ul>';
if($stmt->rowCount() == 0)
{
echo '<p>Er zijn nog geen blogposts toegevoegd.</p>';
}
}
?>
Is that safe? And what should I do with this? Just leave it?
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
Strange code, but if You want use it change if statement to:
if($_MULT[0] == 'blog' && ! empty($_MULT[1])) { ... }
if(ctype_digit( (string) $_MULT[1])) { ... }