Target Individual Form Instance/Counter Inside A PHP While Loop - php

I have a PDO prepared statement that I use on a single-image page where a user is going to be able to download that specific image. I currently have a counter that increments each time the download button is clicked which updates a counter value in a MySQL database. I'd like to transfer and use the download counter from the single-image page onto an index page that shows multiple images.
Because the form element is inside a while loop when you click the download button, the current functionality updates the counter for all of the images on this page (i.e. everything inside the loop).
Obviously I don't think I can move it outside of the loop because it then won't update anything at all?
How do I get it so the when the download button is clicked for a particular instance of the form, it only updates that specific form elements details?
PHP
<?php
// get username from URL parameter
isset($_GET['username']) ? $username = $_GET['username'] : header("Location: index.php");
// fetch filename details from database
$stmt = $connection->prepare("SELECT * FROM imageposts WHERE username = :username");
$stmt->execute([':username' => $username]);
while ($row = $stmt->fetch()) {
$db_image_filename = htmlspecialchars($row['filename']);
// -- HTML that shows the image file goes here --
// update counter for number of downloads of an image
if (isset($_POST['download'])) {
try {
$sql = "UPDATE imageposts SET downloads = downloads +1 WHERE filename = :filename";
$stmt = $connection->prepare($sql);
$stmt->execute([
':filename' => $db_image_filename
]);
} catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
}
?>
// download button that updates the counter
<form method="post">
<button type="submit" name="download">Download</button>
</form>
<?php } ?>

One way to approach this is to add some PHP outside of your loop, that references a value from a hidden <form> element inside the loop - in this case you have a $db_image_filename value you could use.
<form method="post">
<button type="submit" name="download">Download</button>
<input type="hidden" name="hidden-filename" value="<?php echo $db_image_filename; ?>">
</form>
Then reference this value in PHP:
<?php
if (isset($_POST['download'])) {
// value from hidden form element
$hidden_filename = $_POST['hidden-filename'];
try {
$sql = "UPDATE imageposts SET downloads = downloads +1 WHERE filename = :filename";
$stmt = $connection->prepare($sql);
$stmt->execute([
':filename' => $hidden_filename
]);
header("location: " . $_SERVER['PHP_SELF']);
} catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
}
?>

Related

How can I send information with HTML to PHP without using forms?

I am trying to make an Instagram like website in order to enhance my coding skills. I am echoing the image and a form with a button in it if the posted picture belongs to the logged-in user to delete the posted picture.
Here is the index.php:
<?php
require_once "includes/header.php";
?>
<?php
if (isset($_SESSION["sessionId"])){
echo "<br><br><br>";
$sql="SELECT * FROM post ORDER BY id DESC ";
$stmt=mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt, $sql)){
echo "SQL HATASI. SIÇTIK";
}
else{
mysqli_stmt_execute($stmt);
$result= mysqli_stmt_get_result($stmt);
while ($row=mysqli_fetch_assoc($result)){ //this is where I show the user posted pictures.
$a= $row["file_name"];
$b=$row["username"];
$filepath="file_upload/upload/$a"; //this is where the uploaded pictures are stored.
$postID=$row["id"];
if ($row["username"]==$_SESSION["sessionUser"]){
echo "<img src='$filepath' width='60%' height='40%'>"."<br>"."This picture was posted by ". $b ."<form action='file_upload/delete.php?postid=$postID' method= 'GET'><button type='submit' name='delete'>delete </button></form>".$postID."<hr>";
}
else{
echo "<img src='$filepath' width='60%' height='40%'>"."<br>"."This picture was posted by ". $b ."<hr>";
}
}
}
}
else{
echo "Lütfen giriş yapın.";
require_once "includes/footer.php";
}
?>
What I am trying to do with the:
if ($row["username"]==$_SESSION["sessionUser"]){
echo "<img src='$filepath' width='60%' height='40%'>"."<br>"."This picture was posted by ". $b ."<form action='file_upload/delete.php?postid=$postID' method= 'GET'><button type='submit' name='delete'>delete </button></form>".$postID."<hr>";
}
Part is, I check whether the logged-in user posted that picture by checking if the username from the database equals to the username which is set by the super global SESSION.
Then I am using "<form action='file_upload/delete.php?postid=$postID' and triggering the upload.php while setting the $_GET["postid"]=$postID. What $postID is basically the auto incremented ID which is set while uploading the file and inserting the file name to the database. (Database consists of 3 columns: ID, file_name and username)
I am trying to get the information of which one of the delete buttons is pressed so that I can use that information while I am sending a query in the delete.php thus deleting the correct picture. I am trying to get the information of the ID of the post.
Here is how I am using that information in the delete.php:
<?php
session_start();
require_once "../includes/database.php";
if (isset($_GET["delete"])){
$postid=$_GET["postid"];
$sql="DELETE FROM post WHERE id=?";
$stmt=mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt,$sql)){
header("Location: ../index.php?sqlerror");
exit();
}
else if (empty($postid)){
header("Location: ../index.php?didntwork");
exit();
}
else{
mysqli_stmt_bind_param($stmt,"s",$postid);
mysqli_stmt_execute($stmt);
unset($_GET["postid"]);
header("Location: ../index.php?deletesuccess&$postid");
exit();
}
unset($_GET["postid"]);
}
However, it keeps me redirecting to ../index.php?didntwork because the $postid variable is empty, even though I set it to $postid=$_GET["postid"]. This means I can not get the information of the ID of the post when the user clicks to the delete button, in other words the "<form action='file_upload/delete.php?postid=$postID' part is not working the way I want.
How can I get the information, and is there another way to determine which one of the delete buttons is pressed? I am uploading the image of how the index.php looks like:
here is the image
I'd be tempted, as I mentioned, use AJAX rather than several inline forms - it is easy enough to assign the relevant properties from the recordset to the image and use the image itself ( or other element ) to fire the ajax request. I could not test this but I hope it gives an idea
<?php
session_start();
require_once "includes/header.php";
if( isset(
$_SESSION["sessionId"],
$_SESSION["sessionUser"]
)){
# use a regular query where there are no parameters/variables
$sql="SELECT * FROM post ORDER BY id DESC ";
$res=$conn->query( $sql );
while( $row=$res->fetch_assoc() ){
$filepath="file_upload/upload/" . $row["file_name"];
# default empty values
$postedby='';
$classname='';
$datapid='';
$datauser='';
$bttn='';
# add content to the variables for this user
if( $row["username"]==$_SESSION["sessionUser"] ){
$postedby='<div>This picture was posted by ' . $row["username"] . '</div>';
$classname='class="user-img"';
$bttn=sprintf('<button type="button" data-postid="%s" data-user="%s" value="Delete">', $row["id"], $row["username"] );
}
# print out the image and other stuff
printf('<img src="%s" %s width="60%" height="40%" />%s %s', $filepath, $classname, $postedby, $bttn );
}
} else {
require_once "includes/footer.php";
}
?>
Then bind event handlers to any/all buttons rendered
<script>
let fd=new FormData();
document.querySelectorAll('img.user-img + button[ data-postid ][data-user]').forEach(img=>img.addEventListener('click',function(e){
fd.set('postid',this.dataset.postid);
fd.set('username',this.dataset.user);
fd.set('delete',true);
fetch( 'file_upload/delete.php', { method:'post',body:fd } )
.then( r=>r.text() )
.then( text=>{
alert( text )
})
}))
</script>
And modify the delete.php script to use POST rather than GET.
<?php
session_start();
if (isset(
$_POST['delete'],
$_POST['postid'],
$_POST['username']
)){
require_once '../includes/database.php';
$sql='delete from `post` where `id`=?';
$stmt=$conn->prepare($sql);
$stmt->bind_param('s',$_POST['postid']);
$stmt->execute();
$stmt->close();
exit( header( sprintf('Location: ../index.php?deletesuccess&%s',$postid ) ) );
}
?>

Php UPDATE row function

I am trying to allow users to upload a profile image for my site. The file upload part works fine (although there is nothing deterring them form uploading a non-image file). However I can't get it to update the "profile" row in the mysql database. I think it has something to do with the $_SESSION['user_id'] but I'm not sure. Any ideas why it wont update the row?
<?php
if(isset($_POST['submit'])){
$temp = explode(".",$_FILES["file"]["name"]);
$newfilename = ('ProfileImage') . rand(1,99999) . '.' .end($temp);
move_uploaded_file($_FILES['file']['tmp_name'],"images/profile/" . $newfilename);
$con = mysqli_connect("localhost","root","","testsite");
$q = mysqli_query($con,"UPDATE user SET profile = '".$newfilename."' WHERE username = '".$_SESSION['user_id']."'");
}
?>
<form action="" method="post" enctype="multipart/form-data" name="">
<input type="file" name="file" required>
<input type="submit" name="submit" value="Update Image">
</form>
Just in case you need to see this, this is the "functions.php" page where $_SESSION['user_id'] is defined:
<?php
#session_start();
function loggedin(){
if(isset($_SESSION['user_id']) && !empty($_SESSION['user_id'])){
return true;
} else {
return false;
}
}
function getuser($id, $field){
$query = mysql_query("SELECT $field FROM user WHERE UserID='$id'");
$run = mysql_fetch_array($query);
return $run[$field];
}
?>
I am assuming your error is here:
$q = mysqli_query($con,"UPDATE user SET profile = '".$newfilename."' WHERE username = '".$_SESSION['user_id']."'");
And that it should be like this:
$q = mysqli_query($con,"UPDATE user SET profile = '".$newfilename."' WHERE UserID = '".$_SESSION['user_id']."'");
Looks like you switched out UserId with username.
When it comes to the page where you supposedly is setting $_SESSION['user_id'], the code you displayed here does no such thing.
It defines two functions, but does not call them, and does not assign a value to user_id.
So first, update the query as shown above, then do a var_dump of $_SESSION, to see if you have stored anything in it. If not you need to go back a few steps, and make sure you actually set the session variables.

ignoring blank file upload field

I've a form with upload field, it works fine. it uploads and everything is good, except that when the upload field is empty. the field in the database table goes blank as well, nothing in it, not even the old image entry!
My Form:
<form enctype="multipart/form-data" action="add.php" method="POST">
Name: <input type="text" name="name"><br>
E-mail: <input type="text" name = "email"><br>
Phone: <input type="text" name = "phone"><br>
Photo: <input type="file" name="site_logo"><br>
<input type="submit" value="Add">
</form>
The PHP code:
<?php
$target = "../upload/";
$target = $target . basename($_FILES['site_logo']['name']);?>
<?php
move_uploaded_file($_FILES['site_logo']['tmp_name'], $target);
// output a list of the fields that had errors
if (!empty($errors)) {
echo "<p class=\"errors\">";
echo "Please review the following fields:<br />";
foreach($errors as $error) {
echo " - " . $error . "<br />";
}
echo "</p>";
}
?>
the query:
$site_logo=($_FILES['site_logo']['name']);
$query = "UPDATE ss_settings SET
site_logo = '{$site_logo}'
WHERE id = 1 ";
$result = mysql_query($query, $connection);
I've set the database connection and the update query and everything. just posted the process code so it be clear to you guys. I just want it to do nothing when the field is empty.
Check out the error messages explained http://www.php.net/manual/en/features.file-upload.errors.php
To check if a file wasn't uploaded:
if ($_FILES['site_logo']['error'] === UPLOAD_ERR_NO_FILE)
A better way, is to check if there were no errors.
if ($_FILES['site_logo']['error'] === UPLOAD_ERR_OK)
If your query is an UPDATE statement you should not change it, also you can try with
<?php
// ...
if($_FILES['site_logo']['name'] == NULL){
// do stuff when no file field is set
}else{
// do stuff when file is set
}
// ...
?>
Personally I would not use an un-sanitized name for a file, but all you need to do in your case, is check for a valid file-upload before you do your query.
So something like (in PDO as the mysql_* functions are deprecated):
// first line borrowed from #DaveChen, +1 for that
if ($_FILES['site_logo']['error'] === UPLOAD_ERR_OK)
{
$stmt = $db->prepare("UPDATE `ss_settings` SET
`site_logo` = :site_logo
WHERE `id` = :id ";
// bind variables
$stmt->bindValue(':site_logo', $_FILES['site_logo']['name'], PDO::PARAM_STR);
$stmt->bindValue(':id', $the_ID, PDO::PARAM_INT);
// execute query
$stmt->execute();
}
Perhaps try something like this to prevent processing of blank uploads:
if($_FILES['site_logo']['error']==0) {
// process
} else {
// handle the error
}
http://php.net/manual/en/features.file-upload.errors.php
Your problem is that you're simply assuming that a successful upload has taken place. NEVER assume success. ALways check for failure. PHP provides the ['error'] parameter in $_FILES for a reason. use it:
if ($_FILES['site_logo']['error'] == UPLOAD_ERR_OK) {
... upload was successful
} else {
die("Upload failed with error code: " . $_FILES['site_logo']['error']);
}
The error codes are defined here: http://www.php.net/manual/en/features.file-upload.errors.php
You'll wan to check for code 4 (UPLOAD_ERR_NO_FILE), which means the user didn't upload anything at all.

How to stop file being inserted into server [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
files get uploaded just before they get cancelled
I have a situation when it comes to cancelling a file upload. What is suppose to happen is that if the user clicks on the "Cancel" button, then it will go to script below and remove the file from the server and delete the file's records from the database:
cancelaudio.php
<?php
session_start();
// connect to the database
include('connect.php');
/* check connection */
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
die();
}
unlink("AudioFiles/" . $_SESSION['AudioFile']); //undefined notice
$delete = $mysqli->prepare('DELETE FROM Audio WHERE AudioId = ?');
$delete->bind_param("i",$_SESSION['lastAudioID']);
$delete->execute();
$deleteaud = $mysqli->prepare('DELETE FROM Audio_Question WHERE AudioId = ?');
$deleteaud->bind_param("i",$_SESSION['lastAudioID']);
$deleteaud->execute();
?>
Now this is the situation I am having:
If I clean my cookies, it means obviously I have no files stored my $_SESSION variable. Now if I try to upload a file (first file) but then cancel it, then I get an undefined index notice for "AudioFile". This is fair as obviously I have no file stored in that $_SESSION variable. But the problem is that it does not perfrom the unlink() and DELETE statement in the code above so it will display the record of the file and still uploads it.
So what is happening is that until I have one file in the server and a file stored in the $_SESSION['AudioFile'], it would not remove the file from the server and and it would delete the record from the database.
So what my question is that what do I need to do so that if there is no file in the $_SESSION['AudioFile'] and the user uploads and then cancels a file, how can I stop it from inserting the file into the server and inserting the database record?
Below is the code where it uploads the files and inserts the data into the database:
audioupload.php
<?php
session_start();
ini_set('display_errors',1);
error_reporting(E_ALL);
// connect to the database
include('connect.php');
/* check connection */
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
die();
}
$result = 0;
if( file_exists("AudioFiles/".$_FILES['fileAudio']['name'])) {
$parts = explode(".",$_FILES['fileAudio']['name']);
$ext = array_pop($parts);
$base = implode(".",$parts);
$n = 2;
while( file_exists("AudioFiles/".$base."_".$n.".".$ext)) $n++;
$_FILES['fileAudio']['name'] = $base."_".$n.".".$ext;
move_uploaded_file($_FILES["fileAudio"]["tmp_name"],
"AudioFiles/" . $_FILES["fileAudio"]["name"]);
$result = 1;
}
else
{
move_uploaded_file($_FILES["fileAudio"]["tmp_name"],
"AudioFiles/" . $_FILES["fileAudio"]["name"]);
$result = 1;
}
$audiosql = "INSERT INTO Audio (AudioFile)
VALUES (?)";
if (!$insert = $mysqli->prepare($audiosql)) {
// Handle errors with prepare operation here
}
//Dont pass data directly to bind_param store it in a variable
$insert->bind_param("s",$aud);
//Assign the variable
$aud = 'AudioFiles/'.$_FILES['fileAudio']['name'];
$insert->execute();
if ($insert->errno) {
// Handle query error here
}
$insert->close();
$lastAudioID = $mysqli->insert_id;
$_SESSION['lastAudioID'] = $lastAudioID;
$_SESSION['AudioFile'] = $_FILES["fileAudio"]["name"];
$audioquestionsql = "INSERT INTO Audio_Question (AudioId, QuestionId)
VALUES (?, ?)";
if (!$insertaudioquestion = $mysqli->prepare($audioquestionsql)) {
// Handle errors with prepare operation here
echo "Prepare statement err audioquestion";
}
$qnum = (int)$_POST['numaudio'];
$insertaudioquestion->bind_param("iii",$lastAudioID, $qnum);
$insertaudioquestion->execute();
if ($insertaudioquestion->errno) {
// Handle query error here
}
$insertaudioquestion->close();
?>
Below is the HTML form for the file input:
<form action='audioupload.php' method='post' enctype='multipart/form-data' target='upload_target_audio' onsubmit='return audioClickHandler(this);' class='audiouploadform' >
Audio File: <input name='fileAudio' type='file' class='fileAudio' /></label><br/><br/><label class='audiolbl'>
<input type='submit' name='submitAudioBtn' class='sbtnaudio' value='Upload' /></label>
<input type='hidden' class='numaudio' name='numaudio' value='" + GetFormAudioCount() + "' />
<label><input type='reset' name='audioCancel' class='audioCancel' value='Cancel' /></label>
<iframe class='upload_target_audio' name='upload_target_audio' src='#' style='width:300px;height:300px;border:0px;solid;#fff;'></iframe></form>
Finally below is the jquery function where if the user clicks on the "Cancel" button while the file is uploading, it will simply change the iframe source to "cancelaudio.php":
function startAudioUpload(audiouploadform){
$(audiouploadform).find('.audiof1_upload_process').css('visibility','visible');
$(audiouploadform).find('.audiof1_upload_form').css('visibility','hidden');
sourceAudioForm = audiouploadform;
$(audiouploadform).find(".audioCancel").on("click", function(event) {
$('.upload_target_audio').get(0).contentwindow
$("iframe[name='upload_target_audio']").attr("src", "cancelaudio.php");
return stopAudioUpload();
});
return true;
}
To get rid of your undefined index stuff, plus make your script a lot more robust, you SHOULD add error checking. Even a simple
if ($_FILES['fileAudio']['error'] === UPLOAD_ERR_OK) {
... successful upload ...
}
would reduce a lot of your problems. Right now your code simply assumes a successful upload, without even bothering to check if an upload was event attempted.
The various error codes for failure are defined here: http://php.net/manual/en/features.file-upload.errors.php

how to avoid Form Re submission in php

I have a form in dashboard.php to create invoice and this is submitted to invoice.php
Now my invoice.php inserts the Invoice and the customer into the database and then shows me a invoice order filling form.
if i refresh this page, it inserts a new invoice for the same customer, how do i avoid this.
I was reading that we could avoid it by redirection, but in my case how do i use it. Some thing like a PRG(post/redirect/get) how to use it?
Do i need to make an intermediate page before going to insert items to invoice
The pattern you've heard about is this: Post/Redirect/Get.
In general, POST is for actions, GET is for views. So you never show a user a page on a POST request. Instead, you redirect them to a page they'll request with GET, which will not cause any changes in your database.
after successful form submission do a redirect to the same page and optionally indicate that the submission was successful
Example: invoice.php
if (count($_POST)) {
if (/*post data is valid*/) {
/*do whatever is needed*/
header('Location: invoice.php?success');
}
} else if (isset($_GET['success'])) {
echo "Form successfuly submitted";
}
Let dashboard.php post the form data to insert.php, which will process the data and then forward to invoice.php. Use sessions to transport the data from one file to another. Here is insert.php:
<?php
session_start();
if (session_is_registered("invoiceVars"))
session_unregister("invoiceVars");
if (!session_is_registered("errors"))
session_register("errors");
$errors = array();
if (!session_is_registered("formVars"))
session_register("formVars");
foreach($_POST as $f_varname => $f_value)
$formVars[$varname] = trim(EscapeShellCmd(stripslashes($value)));
// process your data and write it to the database or return to dashboard.php with errors, then:
session_unregister("errors");
session_register("invoiceVars");
$invoiceVars = array();
foreach ($formVars as $i_varname => $i_value)
$invoiceVars[$i_varname] = $i_value;
session_unregister("formVars");
// add additional variables
$invoiceVars["coupon"] = 'unique_coupon_code';
// invoice.php will process the data and display it
// it has session_start(); at the top, to have $invoiceVars available
header('Location: invoice.php');
exit();
?>
header(); and exit(); will flush $_POST, so it is no longer available when the user hits back on his browser.
Here is an example code for you:
# database.php
$db = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
session_start();
# dashboard.php
require_once("database.php");
function getSavedValue() {
global $db;
$sql = "SELECT input_text FROM temp_table WHERE sess_key='?'";
$query = $db->prepare($sql);
$query->bindParam(session_id());
$query->execute();
if ($query->rowCount() == 1)
return $query->fetch();
else
return " ";
}
<form action="invoice.php" method="POST">
<input type="text" name="getThisInfo" value="<?php echo getSavedValue(); ?>"/>
<input type="submit" value="Send"/>
</form>
# invoice.php
if (isset($_POST["getThisInfo"]) && /* validation check */ 1) {
require_once("database.php");
$textInput = $_POST["getThisInfo"];
$sql = "INSERT INTO perm_table(invoice_info) VALUES('?');";
$query = $db->prepare($sql);
$query->bindParam($textInput);
$query->execute();
$rows = $query->rowCount();
echo "$rows invoices were inserted.";
unset($_POST["getThisInfo"]);
header("success.php");
} else {
header("dashboard.php");
}

Categories