Specific image files breaks form, refusing to post to PHP - php

On my website, I have a form which allows the user to modify a selected item. As a part of this modification, they are allowed the upload (or delete) images associated with the item.
It seems that very specific images are causing my form to not post (I make this assumption because the loading indicator for my browser is pending).
From further inspection, although it does create a file, it's size is 0B. This is concurrent with the fact that the output of $_FILE['tree-photos']['size'][0] is 0. It seems that the image isn't even being attempted to be uploaded as a specific error code is not given by $_FILE['tree-photos']['error'][0] (returns 0).
I have changed all the appropriate file permissions required and the upload_max_size and post_max_size values accordingly. Interestingly, other files from the same folder which follow the exact same naming scheme and are larger upload fine. It seems random which photos trigger the form to not submit, but it is consistent what images do and don't submit.
File extensions are not the problem either, they are consistient.
Here is my code (I have been told off before for not posting all my code so sorry if a lot of it is not required):
<?php
include("../content/head.php");
include("../functions.php");
if (!isset($_SESSION['admin'])) {
header("Location: ../admin/admin.php?page=login");
exit();
}
$id = $_REQUEST['treeID'];
$tree_sql = "SELECT * FROM trees WHERE treeID=" . $id;
$tree_query = mysqli_query($dbconnect, $tree_sql);
$tree_rs = mysqli_fetch_assoc($tree_query);
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$com_name = test_input($_POST['com_name']);
$sci_name = test_input($_POST['sci_name']);
$height = test_input($_POST['height']);
$origin = test_input($_POST['origin']);
$description = test_input($_POST['description']);
$type = test_input($_POST['type']);
if(isset($_FILES['tree-photos']['name'][0])) {
if (!empty($_FILES['tree-photos']['name'][0])) {
for ($i = 0; $i < count($_FILES['tree-photos']['name']); $i++) {
$location = '../images/' . $sci_name .'/' . $sci_name . "_" . uniqid() . "." . strtolower(pathinfo($_FILES['tree-photos']['name'][$i], PATHINFO_EXTENSION));
move_uploaded_file($_FILES['tree-photos']['tmp_name'][$i], $location);
}
}
}
if ($tree_rs["photo"] == "noimage") {
$updatesql = "UPDATE trees SET photo='$sci_name' WHERE treeID=".$id;
}
$_SESSION['err'] = $_FILES['tree-photos']['error'][0];
$updatesql = "UPDATE trees SET com_name='$com_name', sci_name='$sci_name', height='$height', origin='$origin', description='$description', type='$type' WHERE treeID=".$id;
$updatequery = mysqli_query($dbconnect, $updatesql);
}
$tree_sql = "SELECT * FROM trees WHERE treeID=" . $id;
$tree_query = mysqli_query($dbconnect, $tree_sql);
$tree_rs = mysqli_fetch_assoc($tree_query);
include("../content/navigation.php");
?>
<div id="main-container">
Back
<h1><?php echo $_SESSION['err']; ?></h1>
<form action="<?php echo htmlspecialchars($_SERVER['PHP_SELF'])."?treeID=".$id;?>" method="post" enctype="multipart/form-data">
<p>Common Name</p>
<input name="com_name" type="text" value="<?php echo $tree_rs['com_name']; ?>">
<p>Scientific Name</p>
<input name="sci_name" type="text" value="<?php echo $tree_rs['sci_name']; ?>">
<p>Height Name</p>
<input name="height" type="number" value="<?php echo $tree_rs['height']; ?>">
<p>Origin</p>
<input name="origin" type="text" value="<?php echo $tree_rs['origin']; ?>">
<p>Type</p>
<select name="type">
<option value="Deciduous">Deciduous</option>
<option value="Evergreen">Evergreen</option>
</select>
<p>Description</p>
<textarea name="description"><?php echo $tree_rs['description']; ?></textarea>
<p>Add Photos</p>
<input name="tree-photos[]" type="file" multiple>
<?php $tree_rs['photo']; ?>
<?php
if ($tree_rs['photo'] != "noimage") { ?>
<div class="edit-images-container"> <?php
$path = "../images/".$tree_rs['photo']."/";
$images = glob("$path*.{jpg,jpeg,png,gif,bmp}", GLOB_BRACE);
foreach($images as $image) { ?>
<div class="image-editable-container">
<img class="editable-image" data-source="<?php echo $tree_rs['sci_name']; ?>" data-id="<?php echo $tree_rs["treeID"]; ?>" src="<?php echo $image?>" alt="<?php echo $tree_rs['com_name'] . " - " . $tree_rs['description']; ?>">
<img class="editable-image-delete" src="../images/delete.svg" alt="Delete Button">
</div>
<?php } ?> </div> <?php
} else { ?>
<p>No Images Currently</p>
<?php }
?>
<input type="submit" value="Submit">
</form>
</div>
<?php include("../content/footer.php"); ?
Edit: Included some images that work and don't work for me, would be interesting if its the same for you.
Edit 2: It seems that after restarting the server I am able to upload around 15 items, including ones I couldn't before. After that, though new random images are un-uploadable. This might be a config issue.

Related

"Double Load" Issue with PHP isset() and $_POST data

I know I am doing something wrong by using a combination of isset(), $_POST and $_GET but I am wondering what would be the easiest and painless way to tackle my issue.
The issue arises when I submit a HTML form... It reloads the page with the post data. I capture the submit with a php isset() function, process the $_POST data and then run a window.location to refresh the page with some $_GET data.
For example...
//example.php
...
<form action="" method="post">
<input name="stage1name" type="text" class="textfield" size="22" value="<?php echo $ClaimRow['ClaimantName']; ?>">
<input name="VehicleEngine" type="text" class="textfield" size="20" value="<?php echo $vehiclerow['VehicleEngine']; ?>">
<input name="VehicleFuel" type="text" class="textfield" size="20" value="<?php echo $vehiclerow['VehicleFuel']; ?>">
<input name="submitInfo" type="submit" value="<?php echo $LANG_Claims_Change_Info; ?>" />
</form>
...
<?php
if (isset($_POST['submitInfo']))
{
$stage1name= mysqli_real_escape_string($db, $_POST['stage1name']);
$VehicleEngine= mysqli_real_escape_string($db, $_POST['VehicleEngine']);
$VehicleFuel= mysqli_real_escape_string($db, $_POST['VehicleFuel']);
mysqli_query($db, "DO SOME COOL SQL HERE");
//I've done what I need to do so lets reload the page with the updated data
echo "<script>window.location='example.php?vehicle=" . $vehicleID . "&claimTab=Personal'</script>";
}
?>
Like I said before, this method works fine however the user gets the effect of a "double load" and is very epiletic fit inducing.
Any ideas how best to combat this?
Thanks
EDIT - Additional Example
I realised that this one example might not make complete sense so I put together another example which hopefully will.
...
<form action="" method="post">
<select name="addresstype[]" id="multiselectfrom" onchange='this.form.submit();' size="9" style="width:110px; text-align:center;">
<option style="<?php if ($AddType == 'Claimant') { echo'background-color:#9AD3F1 !important;'; } ?>" value="Claimant"><?php echo $LANG_Claims_Claimant; ?></option>
<option style="<?php if ($AddType == 'Vehicle') { echo'background-color:#9AD3F1 !important;'; } ?>" value="Vehicle"><?php echo $LANG_Claims_Vehicle; ?></option>
<option style="<?php if ($AddType == 'Repairer') { echo'background-color:#9AD3F1 !important;'; } ?>" value="Repairer"><?php echo $LANG_Claims_Repairer; ?></option>
<option style="<?php if ($AddType == 'Insurer') { echo'background-color:#9AD3F1 !important;'; } ?>" value="Insurer"><?php echo $LANG_Claims_Insurer; ?></option>
<option style="<?php if ($AddType == 'Fleet') { echo'background-color:#9AD3F1 !important;'; } ?>" value="Fleet"><?php echo $LANG_Claims_Fleet; ?></option>
</select>
</form>
...
<?php
if (isset($_POST['addresstype']))
{
foreach ($_POST['addresstype'] as $addresstype) {
$addresstype2 = $addresstype;
}
echo "<script>window.location='claims.php?claimID=" . $claim . "&claimTab=Addresses&AddressType=" . $addresstype2 . "'</script>";
}
?>
The above example is supposed to take the result of the form and change the window.location depending on the form result. It does work however it loads the page twice in doing so.
Repalace:
echo "<script>window.location='example.php?vehicle=" . $vehicleID . "&claimTab=Personal'</script>";
With:
echo "<META HTTP-EQUIV = 'Refresh' Content = '0; URL =example.php?vehicle=" . $vehicleID . "&claimTab=Personal'>";
After much testing. It turns out CMorriesy was correct. However for future reference you will need to turn output_buffering = on in php.ini and also add <?php ob_start(); ?> to the very first line of your code.
header('Location: example.php?vehicle=' . $vehicleID . '&claimTab=Personal'); die();

Update and delete for specific record

I have written code to retrieve all the images from database for a specific city, and I want to be able to delete a specific image or to change the caption.
The problem is:
the code always work on the last image only!
I hope you guys will be able to help me with this problem.
Retrieve code:
<?php
$City_name=$_REQUEST['id'];
$Image_query = "SELECT * FROM image where City_name ='".$City_name."' ";
$Image_result = mysqli_query($dbcon,$Image_query);
echo "<table>";
while ($row = mysqli_fetch_array($Image_result))
{
$image_id = $row['Image_id'];
$image = $row['Image_url'];
$Caption = $row['Caption'];
echo "<tr style='float:right;'>";
echo "<td>"; ?> <img src="<?php echo $image ; ?>"/> <br>
<input type="text" name="caption" value="<?php echo $Caption ;?>" />
<br> <input name="delete" type="submit" value="Delete picture" />
<br> <input name="Update_caption" type="submit" value="change caption" />
<?php echo "</td>";
echo "<td>"; ?> <input class="input-image" type="hidden" name="id" value="<?php echo $image_id ;?>" />
<?php echo "</td>";
} /* End of while loop */
echo "</tr>";
echo"</table>";
?>
Update code :
if (isset($_POST['Update_caption'])) {
$ImageID = $_POST['id'];
$ImageCaption = $_POST['caption'];
$sql = mysqli_query ($dbcon,"UPDATE `image` SET `Caption`='".$ImageCaption."' WHERE `Image_id`='".$ImageID."' ");
if ($sql) {
echo "done";
} else { echo "error"; }
}
Delete code :
if (isset($_POST['delete'])) {
$ImageID = $_POST['id'];
$sql = mysqli_query ($dbcon,"DELETE FROM `image` where `Image_id` = '".$ImageID."' ");
if ($sql) {
echo "done";
} else { echo "error"; }
}
$_POST['id'] (sql injection alert!) contains the contents of the input element that has a name attribute id.
You are echoing out your input elements in a loop, all with the same name so the last one will overwrite all the previous ones.
You should use an array like for example:
<input class="input-image" type="hidden" name="id[<?php echo $image_id ;?>]" value="<?php echo $image_id ;?>" />
So that your $_POST['id'] is an array containing all elements.
The same applies to other input elements like the caption.
An alternative, especially for your delete option, would be to wrap every image in its own form. But keep in mind that you will need valid html for that to work, you can't have a form that opens in a row element and spans different columns.
And note that you should really use a prepared statement to close the sql injection hole you have now.

Form doesn't work when query involves a variable for the table name -- PHP -- MYSQL

I have a few tables with image urls and image ids and I want to be able to delete from each of these tables using one php page and query.
The $tableToDeleteFrom is set as a variable in the url (ex delete.php?table=whatever)
$tableToDeleteFrom = $_GET['table'];
here is my query / php -- it appears this is where the problem may be, for some reason when $tableToDeleteFrom is not a variable, everything works fine. An image is deleted and the redirect brings is back to the correct page. However I need this to be dynamic because the user needs to be able to select which section they want to display in the url.
if (isset($_GET['id'])) {
$id = $_GET['id'];
$query = $pdo->prepare('DELETE FROM '.$tableToDeleteFrom.' WHERE id = ?');
$query->bindValue(1, $id);
$query->execute();
header('Location: img_delete_new.php?table='.$tableToDeleteFrom);
}
here is the php which fetches each line of the table and puts it into array to be accessed in the next bit of code:
class Image {
public function fetch_all() {
global $pdo;
$tableToDeleteFrom = $_GET['table'];
$query = $pdo->prepare("SELECT * FROM ".$tableToDeleteFrom);
$query->execute();
return $query->fetchAll();
}
}
$image = new Image;
$images = $image->fetch_all();
here is the form allowing user to select which image they want to delete:
<form action="img_delete_new.php" method="get">
<?php foreach ($images as $image) { ?>
<div class="delete">
<input type="radio" name="id" value="<?php echo $image['id']; ?>">
<img src="../images/thumbs/<?php echo $image['name']; ?>"><br>
<?php echo $image['desc']; ?>
</div>
<?php } ?>
<input type="submit" value="Delete Image" class="button">
</form>
updated the form to include the hidden variable "table"
<form action="img_delete_new.php" method="get">
<?php foreach ($images as $image) { ?>
<div class="delete">
<input type="hidden" name="table" value="<?php echo $tableToDeleteFrom;?>">
<input type="radio" name="id" value="<?php echo $image['id']; ?>">
<img src="../images/thumbs/<?php echo $image['name']; ?>"><br>
<?php echo $image['desc']; ?>
</div>
<?php } ?>
<input type="submit" value="Delete Image" class="button">
</form>

$_POST variables not stored when large file uploaded

First off, I know similar questions have been asked, however mine doesn't appear to be a server-limited file size....
When using one page with the form below and attempting to send to another file containing the script, it works fine with small files (under 2MB). However, a slightly larger file (around 3MB) it appears to pass the $_POST variables correctly, but the script fails for some unknown reason. Finally, a test file of 9MB fails to send the $_POST variables at all and a print_r($_POST) shows each as undefined.
Here's the form:
<form enctype="multipart/form-data" id="formEditTAPPS" method="POST" action="scripts/editTAPPSprocess.php">
Page ID Number: <? echo $id; ?>
<input type="hidden" name="id" value="<? echo $id; ?>" />
<br />
Page Title: <input type="text" name="newPageTitle" value="<?php echo $row['title']; ?>" style="width:300px;" />
<br />
Number of Pages in PDF: <input type="text" name="newNumberOfPages" value="<?php echo $row['num_pages']; ?>" style="width:30px;" />
<br />
TAPPS Category:
<select name="newCategory">
<? while ($row2 = mysql_fetch_array($data2)) {
$catIDfromCat = $row2['cat_id'];
$catName = $row2['cat_name'];
?><option value="<? echo $catIDfromCat; ?>" <?php if ($catIDfromPages==$catIDfromCat){echo "selected=\"selected\"";} ?> ><? echo $catName; ?></option>
<? } ?>
</select>
<br />
Last Updated: <? echo $row['last_updated']; ?>
<br />
Display Order: <input type="text" name="newDisplayOrder" value="<?php echo $row['display_order']; ?>" />
<br />
Existing PDF: <a href="/files/tapps/<? echo $row['filename']; ?>" /><? echo $row['filename']; ?></a>
<br />
Upload a New PDF: <input name="newPDF" type="file" />
<br />
<input type="submit" name="Submit" value="Update this TAPPS Page" style="margin: 20px 0 0 50px;" />
And here's the processing script:
include_once('../../../common/db/conn.php'); // Connect to the database
// Assigns the variables passed from the form.
$id = $_POST['id'];
$title = $_POST['newPageTitle'];
$num_pages = $_POST['newNumberOfPages'];
$cat_id = $_POST['newCategory'];
$display_order = $_POST['newDisplayOrder'];
$newPDF = basename($_FILES['newPDF']['name']);
// Try to upload the file...
$target = "../../../files/tapps/";
$target = $target . $newPDF;
if(move_uploaded_file($_FILES['newPDF']['tmp_name'], $target)) {
// Saves the data into the correct database table.
$sql = "UPDATE tapps_pages SET title='$title', num_pages='$num_pages', cat_id='$cat_id', display_order='$display_order', filename='$newPDF' WHERE id='$id'";
// Verifies the database stores the form results and sends the user to the "Success" page.
$result = mysql_query($sql);
if($result) {
echo "<meta HTTP-EQUIV=\"REFRESH\" content=\"0; url=../editTAPPSpage.php?id=$id&success=1\">";
} else {
echo "<br /><br />Bummer, something broke. =(<br /><br />";
print_r($_POST);
}
} else {
// Problem uploading the file
echo "<br /><br />Looks like there was a problem uploading the TAPPS page... Better tell Kevin!<br /><br />He's going to want to know this info, so please copy and paste it into the email...<br />";
print_r($_POST);
echo "<br /><br />";
print_r($_SERVER);
echo "<br /><br />";
print_r($_SESSION);
}
Sounds like a upload_max_filesize problem to me, but I've addressed that with a php.ini file:
memory_limit = 128M
max_execution_time = 600
upload_max_filesize = 50M
post_max_size = 64M
And phpinfo() shows that the change stuck, after a reboot of Apache.
Am I missing a setting that could cause a timeout or limit the file size to 2MB? Thanks in advance for any help!

php $_GET issue - updated

thanks now I have a error code HY093 Invalid parameter number after using the renameit SUBMIT button. Any idea why? thanks
Any help would be appreciated. Thanks a lot.
<?php
// init
include("db_con1.php");
require("menu.php");
// modify distribution list name
if(is_numeric($_GET['gid'])) {
$g_id=$_GET['gid'];
$one = $pdo->prepare('SELECT * FROM contactgroups WHERE id=:gid');
$one->bindParam(':gid', $g_id, PDO::PARAM_INT);
if( $one->execute(array(':gid' => $_GET['gid'])) ) {
$result = $one->fetch();
}
}
// distribution list query
$queryl = $pdo->prepare('SELECT id, gr_name FROM contactgroups WHERE status=1 ORDER BY gr_name ASC');
$queryl->execute();
// Members list query
if (isset($_GET['gid'])) {
$g_id=$_GET['gid'];
$querym = $pdo->prepare('SELECT STRAIGHT_JOIN gm.linktype, if( gm.linktype = "group", cg.gr_name, cm.contact_sur ) mname FROM groupmembers gm LEFT JOIN contactgroups cg ON gm.link_id = cg.id LEFT JOIN contactmain cm ON gm.link_id = cm.id WHERE gm.group_id =:gid ORDER BY mname ASC');
$querym->bindParam(':gid', $g_id, PDO::PARAM_INT);
$querym->execute();
}
// distribution list query
$queryr = $pdo->prepare('SELECT * FROM contactmain WHERE status=1 ORDER BY contact_sur ASC');
$queryr->execute();
This is what should but does not work...
if (isset($_POST['renameit'])) {
$ren = htmlspecialchars($_POST['rename']);
$g_id = $_GET['gid'];
if ($g_id !== '' && is_numeric($g_id)) { // Change that first to == if gid != 0 as well
$sqlren = "UPDATE contactgroups SET gr_name = :rename WHERE id = :gid";
$sqlren = $pdo->prepare($sqlren);
$sqlren->bindValue(':rname', $ren); // <<< Is this supposed to be :ren?
$sqlren->bindValue(':gid', $g_id);
if ($sqlren->execute()) {
echo "<meta http-equiv=\"refresh\" content=\"0;URL=groups.php\">";
} else {
//Query failed.
$errorcode = $sqlren->errorCode();
echo $errorcode;
}
} else {
echo 'gid not provided'; // Or something
}
}
?>
and this is the HTML bit:
<form id="group-in" method="post" action="groups.php">
Add new Distribution group: <input type="text" name="newgroup" placeholder="name..."> <input type="submit" name="createit" value="Create new">
Rename groupname: <input type="text" name="rename" value="<?php echo $result['gr_name']; ?>"> <input type="submit" name="renameit" value="Rename">
</form>
<!-- Distribution list -->
<div id="left"><label class="header">Distribution list</label>
<ul>
<?php foreach ($queryl as $i => $rowl) { ?>
<li >
<?php if ($i)?>
<input name="checkbox1_add[]" id="dist_<?php echo $i ?>" type="checkbox" value="<? echo $rowl['id']; ?>" />
<label for="groups_<?php echo $i ?>">
<a href="groups.php?gid=<?php echo $rowl['id']; ?>" <?php $g_id=$_GET['gid']; if ($g_id==$rowl['id']) echo 'class="bold"'; ?> >
<?php echo $rowl['gr_name']; ?>
</a></label>
</li>
<?php } ?>
</ul>
</div>
sorry for the long code but I think I loose this $_GET somehow after selecting the distribution item.
Shouldn't you be doing something like this?
if (isset($_POST['renameit'])) {
$ren = htmlspecialchars($_POST['rename']);
$g_id = $_GET['gid'];
if ($g_id !== '' && is_numeric($g_id)) { // Change that first to == if gid != 0 as well
$sqlren = "UPDATE contactgroups SET gr_name = :ren WHERE id = :gid";
$sqlren = $pdo->prepare($sqlren);
$sqlren->bindValue(':rname', $ren); // <<< Is this supposed to be :ren?
$sqlren->bindValue(':gid', $g_id);
if ($sqlren->execute()) {
echo "<meta http-equiv=\"refresh\" content=\"0;URL=groups.php\">";
} else {
//Query failed.
$errorcode = $sqlren->errorCode();
echo $errorcode;
}
} else {
echo 'gid not provided'; // Or something
}
}
Also, if it's always going to be an integer, you could use:
$g_id = (int)$_GET['gid'];
But you would need to be careful with things that evaluate to 0 and check for it in your if statement:
if ($g_id > 0) {
Assuming 0 is not a valid gid value.
EDIT
Looking at your markup and form, this all seems confused.
For instance, your PHP code is using GET, but your code here is not including the gid in the ACTION attribute. (Also, you really should use two different forms for this, IMO.)
<form id="group-in" method="post" action="groups.php?gid=<?php echo $g_id;?>">
Add new Distribution group:
<input type="text" name="newgroup" placeholder="name...">
<input type="submit" name="createit" value="Create new">
</form>
<form id="group-in" method="post" action="groups.php?gid=<?php echo $g_id;?>">
Rename groupname:
<input type="text" name="rename" value="<?php echo $result['gr_name']; ?>">
<input type="submit" name="renameit" value="Rename">
</form>
However, your comment seems to suggest that multiple checkboxes can be checked to rename a group? But then you don't have a FORM tag around it:
<!-- Distribution list -->
<div id="left"><label class="header">Distribution list</label>
<form id="group-in" method="post" action="groups.php">
<ul>
<?php foreach ($queryl as $i => $rowl) { ?>
<li >
<?php if ($i)?>
<input name="checkbox1_add[]" id="dist_<?php echo $i ?>" type="checkbox" value="<? echo $rowl['id']; ?>" />
<label for="groups_<?php echo $i ?>">
<a href="groups.php?gid=<?php echo $rowl['id']; ?>" <?php $g_id=$_GET['gid']; if ($g_id==$rowl['id']) echo 'class="bold"'; ?> >
<?php echo $rowl['gr_name']; ?>
</a></label>
</li>
<?php } ?>
</ul>
</form>
</div>
The challenge that you're going to have here is that you need to loop through that $_POST['gid'] array, whereas the first single group rename you key off of the gid in the GET. I would suggest organizing your code into a Group/Groups object(s) and use a Model/View/Controller (MVC) pattern to organize your code.
Are you saying that you can't get $_GET['gid'] after you submit the group-in form?
Because if that's the case, what you have to do is create a hidden input with your gid value so it can be available in $_POST.
Without putting much thought to what you're trying to do, I can tell you that you simply can't have code using $_GET and $_POST simultaneously.
Update: I don't think you understood what I meant. But Jared is already doing a better job explaining what is wrong with your code, so I guess I won't repeat it.

Categories