homepage Welcome to WebmasterWorld Guest from 54.237.98.229
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Become a Pro Member
Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
Forum Library, Charter, Moderators: coopster & jatar k

PHP Server Side Scripting Forum

    
How To Get Session Array Into Database Query
Also Warning: Cannot modify header
oceanwave

10+ Year Member



 
Msg#: 3360674 posted 1:59 am on Jun 7, 2007 (gmt 0)

Hi,

I found a script to upload photos into a database. Works great. Problem is I can't update my database "users" so that the value from $imagename updates my database field "photo_filename". The previous value for photo_filename remains unchanged.

I tried echo "<pre>"; print_r($_SESSION); to see if the login values were being passed. It gave me:
Array
(
[user] => Jones
[pass] => 123abc
[code] => 1
)
so I know the password and lastname values for the user are being passed to the page. However, I can't get those values in the Update query. I typed 123abc into the query just to see if it works, and photo_filename was immediately updated.

1) How do I get the query to use the array values to SET photo_filename = '$imagename' WHERE password=[pass] and lastname=[user)? How is the query written (I've tried dozens of different ways after searching the Internet, none worked)?

2) When I used echo "<pre>"; print_r($_SESSION); I got a warning.
Warning: Cannot modify header information - headers already sent by (output started at /home/site/public_html/folder/upload.php:5) in /home/site/public_html/folder/upload.php on line....
This line corresponds to:
header('Location: ' . $uploadSuccess);
What do I need to do?

3) The way the script is written, the photo is named something like 1181177664-mypic.jpg. I would prefer if the photos were named according to the userid in a row of the database (ex: 1.jpg, 2.gif) where userid of Jones is 1, userid of Smith is 2. That way the number in the photo name would be unique for each individual member and could be overwritten if that member decides to reupload a new photo. The way the script is written now, one member can upload dozens of photos, and though only the most current name is entered into the database, dozens can be sitting in a folder on my website for each member. How would I change this script to accomplish this?

Thanks so much.

upload.php

<?php
include("security.php");
include("config.php");

// make a note of the current working directory, relative to root.
$directory_self = str_replace(basename($_SERVER['PHP_SELF']), '', $_SERVER['PHP_SELF']);

// make a note of the directory that will recieve the uploaded files
$uploadsDirectory = $_SERVER['DOCUMENT_ROOT'] . $directory_self . 'photos/';

// make a note of the location of the upload form in case we need it
$uploadForm = 'http://' . $_SERVER['HTTP_HOST'] . $directory_self . 'upload.form.php';

// make a note of the location of the success page
$uploadSuccess = 'http://' . $_SERVER['HTTP_HOST'] . $directory_self . 'upload.success.php';

// name of the fieldname used for the file in the HTML form
$fieldname = 'file';

// Now let's deal with the upload

// possible PHP upload errors
$errors = array(1 => 'php.ini max file size exceeded',
2 => 'html form max file size exceeded',
3 => 'file upload was only partial',
4 => 'no file was attached');

// check the upload form was actually submitted else print form
isset($_POST['submit'])
or error('the upload form is neaded', $uploadForm);

// check for standard uploading errors
($_FILES[$fieldname]['error'] == 0)
or error($errors[$_FILES[$fieldname]['error']], $uploadForm);

// check that the file we are working on really was an HTTP upload
@is_uploaded_file($_FILES[$fieldname]['tmp_name'])
or error('not an HTTP upload', $uploadForm);

// validation... since this is an image upload script we
// should run a check to make sure the upload is an image
@getimagesize($_FILES[$fieldname]['tmp_name'])
or error('only image uploads are allowed', $uploadForm);

// make a unique filename for the uploaded file and check it is
// not taken... if it is keep trying until we find a vacant one
$now = time();
while(file_exists($uploadFilename = $uploadsDirectory.$now.'-'.$_FILES[$fieldname]['name']))
{
$now++;
}

//name var for image
$imagename = $now.'-'.$_FILES[$fieldname]['name'];

// now let's move the file to its final and allocate it with the new filename
@move_uploaded_file($_FILES[$fieldname]['tmp_name'], $uploadFilename)
or error('receiving directory insuffiecient permission', $uploadForm);

// If you got this far, everything has worked and the file has been saved.
// We are now going to redirect the client to the success page.

$sql = "UPDATE users SET photo_filename = '$imagename' WHERE password='$password'";
mysql_query($sql);//run the query

header('Location: ' . $uploadSuccess);

// make an error handler which will be used if the upload fails
function error($error, $location, $seconds = 5)
{
header("Refresh: $seconds; URL=\"$location\"");
echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"'."\n".
'"http://www.w3.org/TR/html4/strict.dtd">'."\n\n".
'<html lang="en">'."\n".
'<head>'."\n".
'<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">'."\n\n".
'<link rel="stylesheet" type="text/css" href="stylesheet.css">'."\n\n".
'<title>Upload error</title>'."\n\n".
'</head>'."\n\n".
'<body>'."\n\n".
'<div id="Upload">'."\n\n".
'<h1>Upload failure</h1>'."\n\n".
'<p>An error has occured: '."\n\n".
'<span class="red">' . $error . '...</span>'."\n\n".
' The upload form is reloading</p>'."\n\n".
' </div>'."\n\n".
'</html>';
exit;
} // end error handler
?>

 

Slade

10+ Year Member



 
Msg#: 3360674 posted 2:42 am on Jun 7, 2007 (gmt 0)

Warning: Cannot modify header information - headers already sent by...

This error is unimportant right now, it just means you tried to redirect the user (with the header/Location call) after you had already printed something else(your debug information). When you take the debug print_r out, the error will go away. (just ignore it right now)

My PHP is a little rusty, but I don't see any place where you assigned a value to $password. Are session variables auto-loaded into your local scope? (I'm guessing not.)

Tru changing your mysql_query($sql) line to print($sql) and see what $sql actually has in it. I bet it's not what you think.

After that, I think you have a logic bomb in your sql query. I haven't fully read your code, but I am pretty sure something is wrong with your WHERE clause.

Habtom

WebmasterWorld Senior Member 10+ Year Member



 
Msg#: 3360674 posted 5:03 am on Jun 7, 2007 (gmt 0)

>> I tried echo "<pre>"; print_r($_SESSION); to see if the login values were being passed. It gave me:
Array
(
[user] => Jones
[pass] => 123abc
[code] => 1
)

Password not assigned:

$password = $_SESSION['pass'];
$user_name = $_SESSION['user'];

The query might look similar to the following
$sql = "UPDATE users SET photo_filename = '$imagename' WHERE password='$password' AND username = '$username'";

Habtom

oceanwave

10+ Year Member



 
Msg#: 3360674 posted 1:41 pm on Jun 7, 2007 (gmt 0)

Thank you Slade and Habtom.

Slade, so when I remove the line: echo "<pre>"; print_r($_SESSION); I will no longer have the problem? Good news. I wasn't aware that the error occurs when something is printed. Thanks for educating me.

Habtom, it is nice to hear from you again. As you can see, I actually learned the echo "<pre>"; print_r($_SESSION); trick from you on another post you helped me with. Thanks for teaching me.

Habtom, your code was very similar to something I tried but I can't remember if $_SESSION was part of the line. Anyway, your code worked. I added:

$password = $_SESSION['pass'];
$lastname = $_SESSION['user'];

$sql = "UPDATE users SET photo_filename = '$imagename' WHERE password='$password' AND lastname = '$lastname'";

Lo and behold the photo_filename is now updated. Thank you, thank you. Thanks for being so patient with a php beginner.

Now as for my third question, would I have to pass the userid on login and add $userid = $_SESSION['userid']; to the page? Then I guess I have to change this:

// make a unique filename for the uploaded file and check it is
// not taken... if it is keep trying until we find a vacant one
$now = time();
while(file_exists($uploadFilename = $uploadsDirectory.$now.'-'.$_FILES[$fieldname]['name']))
{
$now++;
}

//name var for image
$imagename = $now.'-'.$_FILES[$fieldname]['name'];

I guess I wouldn't need the first paragraph as the userid will already make the photo name unique (examples: 1.jpg, 2.gif).
As far as setting the $imagename, I guess it would = to the passed value of $userid, but what about the extensions? Since they won't be the same each time (gif, jpeg, jpg) how is that coded?

Am I on the right track, or is there a better way?

jatar_k

WebmasterWorld Administrator jatar_k us a WebmasterWorld Top Contributor of All Time 10+ Year Member



 
Msg#: 3360674 posted 12:05 am on Jun 8, 2007 (gmt 0)

you should never need to check if a file already exists if you use something truly unique

a combination of user id with a timestamp it would be fine, the odds that the same user could upload at the exact same second is pretty rare, one would say almost impossible.

oceanwave

10+ Year Member



 
Msg#: 3360674 posted 12:54 pm on Jun 8, 2007 (gmt 0)

Hi jatar_k,

It would be rare, so I completely understand why the timestamp was used in the script I posted. What I am concerned with is that each member can upload dozens of photos (maybe more), even though only one photo name is stored in the database and being used by that member. All of those extra photos will be uploaded to a folder on my site and living there, with no way for me to delete the ones not being used, as I can't identify the used ones from the unused ones. This is because a member is not overwriting their previous photo (since the photo name is not the same each time for that particular member).

jatar_k

WebmasterWorld Administrator jatar_k us a WebmasterWorld Top Contributor of All Time 10+ Year Member



 
Msg#: 3360674 posted 1:32 pm on Jun 8, 2007 (gmt 0)

you could run through the dir and delete the ones that aren't in the db

you could also unlink the previous name found in the db before adding the new name to the db

oceanwave

10+ Year Member



 
Msg#: 3360674 posted 1:37 pm on Jun 8, 2007 (gmt 0)

Could you please explain this a little more? I am new to all of this.

What do you mean by unlink the name in the database? Only one photo filename is in the database for each person (update database takes care of that).

How would I delete the names from the directory that are not in the database?

[edited by: oceanwave at 1:41 pm (utc) on June 8, 2007]

jatar_k

WebmasterWorld Administrator jatar_k us a WebmasterWorld Top Contributor of All Time 10+ Year Member



 
Msg#: 3360674 posted 1:41 pm on Jun 8, 2007 (gmt 0)

originally I thought you wanted to allow multiple images

if not and you only want to store one image per user then it is fairly straight forward

upload new image
get name of old image from the db
unlink the old image
insert the name of the new image into the db

oceanwave

10+ Year Member



 
Msg#: 3360674 posted 1:44 pm on Jun 8, 2007 (gmt 0)

The update database query gets rid of the old name in the database, and adds the new name. My problem is that my image folder on my website is going to be full of images that are not needed.

jatar_k

WebmasterWorld Administrator jatar_k us a WebmasterWorld Top Contributor of All Time 10+ Year Member



 
Msg#: 3360674 posted 1:49 pm on Jun 8, 2007 (gmt 0)

before you update you need to select the old values for that member

phlogit

5+ Year Member



 
Msg#: 3360674 posted 1:53 pm on Jun 8, 2007 (gmt 0)

unlink($filename);
check php manual

deletes a file

oceanwave

10+ Year Member



 
Msg#: 3360674 posted 2:07 pm on Jun 8, 2007 (gmt 0)

Hi phlogit,

I saw this:

unlink
(PHP 4, PHP 5)

unlink Deletes a file

Description
bool unlink ( string $filename [, resource $context] )

-------------

unlink($photo_filename) or print "Unable to unlink $photo_filename ($!)\n" ;

Is this correct? Where do I put this in the script? Where is the file being deleted from? Is it the filename in the database or the file in the folder on the website?

jatar_k

WebmasterWorld Administrator jatar_k us a WebmasterWorld Top Contributor of All Time 10+ Year Member



 
Msg#: 3360674 posted 2:13 pm on Jun 8, 2007 (gmt 0)

that would delete the actual image from the server as long as you pass it the appropriate path to the image

the steps will be as I mentioned

  • process the new image upload
  • SELECT name of old image from the db, if there isn't one then just carry on with the script
  • use unlink with the old image name from the db to delete the image from the server
  • insert the name of the new image into the db using UPDATE if one existed before or using INSERT if it did not exist
  • phlogit

    5+ Year Member



     
    Msg#: 3360674 posted 2:24 pm on Jun 8, 2007 (gmt 0)

    hi oceanwave i directed you to the unlink in php manual reason being ive only used it once in php myself as i am very new to it. I dont want to mislead you or give you wrong information but i will show you how i used to upload files for project i did before. If i have done something wrong people please let me know as i dont want to mess oceans work up. This is how i used to upload files.

    // you can change this to any directory you want
    // as long as php can write to it
    $uploadDir = 'files/';

    if(isset($_POST['upload']))
    {

    $comments = $_POST['mtxComments'];
    $fileName = $_FILES['userfile']['name'];
    $tmpName = $_FILES['userfile']['tmp_name'];
    $fileSize = $_FILES['userfile']['size'];
    $fileType = $_FILES['userfile']['type'];

    if(!$_POST['mtxComments']) die('Alert: Comments field was blank.');

    // get the file extension first
    $ext = substr(strrchr($fileName, "."), 1);

    // generate the random file name
    $randName = md5(rand() * time());

    // and now we have the unique file name for the upload file
    $filePath = $uploadDir . $randName . '.' . $ext;

    // move the files to the specified directory
    // if the upload directory is not writable or
    // something else went wrong $result will be false
    $result = move_uploaded_file($tmpName, $filePath);
    if (!$result) {
    echo "Error uploading file";
    exit;
    }

    require_once($_SERVER['DOCUMENT_ROOT'].'/db_connect.php');

    if(!get_magic_quotes_gpc())
    {
    $fileName = addslashes($fileName);
    $filePath = addslashes($filePath);
    $comments = addslashes($comments);

    }

    $query = "INSERT INTO tablename (name, size, type, path, comments ) ".
    "VALUES ('$fileName', '$fileSize', '$fileType', '$filePath', '$comments')";

    mysql_query($query) or die('Error, query failed : ' . mysql_error());

    echo "<br>File uploaded<br>";
    }
    ?>

    as it shows i only used to save details of the file on the database but the actual file is saved on the server. when i needed to delete a file i did the following.

    if (isset($_GET['deleteNotes']) && isset($_GET['notes']) ) {
    $id = $_GET['notes'];

    $result = mysql_query("SELECT * FROM tablename WHERE id = $id")
    or die('Delete file failed. ' . mysql_error());
    if (mysql_num_rows($result) == 1) {
    $row = mysql_fetch_assoc($result);
    $name = $row['name'];
    $path = $row['path'];

    unlink($path);

    $result = mysql_query("DELETE FROM tablename
    WHERE id = $id")
    or die('Delete file failed. ' . mysql_error());

    // file deleted successfully, let the user know about it
    echo "<p align=center>File '$name' has been deleted successfully.</p>";
    } else {
    echo "<p align=center>Cannot delete a non-existing file..</p>";
    }
    }

    The above code deletes the row from the table which saved the file details orginally such as size name etc. it then uses the unlink to delete the file from the server.

    The reason i saved files on the server was purely for speed of processing and because i was having problems with saving it in the database.

    Hope this helps mate. Try using bits of it in your code.

    oceanwave

    10+ Year Member



     
    Msg#: 3360674 posted 2:22 am on Jun 9, 2007 (gmt 0)

    I'm sorry everyone. I still can't get this.

    I tried this (with and without the period):

    if (unlink($uploadsDirectory.$photo_filename)) {
    print "Deleted $photo_filename!\n";
    } else {
    print "Delete of $photo_filename failed!\n";
    }

    I tried this (with and without the period):

    unlink($uploadsDirectory.$photo_fileName);

    I tried other bits of code found during my Google searches. Nothing has worked.

    By the way, was I correct to use $uploadsDirectory as the path (based upon the script I posted)?

    Jatar_k has been so patient explaining where in the script to post the unlink code. I'm still not sure where that is in the script I posted. I know I placed the code in the wrong places, because I got an assortment of error messages including "Warning: Division by zero unlink", no such file or directory...., etc.

    Thank you phlogit for posting your code. I will have to study it a bit longer to understand it. I don't want to delete a row in my database - just remove the extra photos in my photos folder. I will try to find the bits of code that apply to my situation. Thanks again.

    I'm sorry to say, I still need help.

    jatar_k

    WebmasterWorld Administrator jatar_k us a WebmasterWorld Top Contributor of All Time 10+ Year Member



     
    Msg#: 3360674 posted 3:16 pm on Jun 9, 2007 (gmt 0)

    this is the part you need to add to

    $sql = "UPDATE users SET photo_filename = '$imagename' WHERE password='$password'";
    mysql_query($sql);//run the query

    that is your update query.

    You will need to add

    a select query to get the name of the old image, if there is one
    use the data from the photo_filename column and build a path to where the image actually lives
    then use that path with unlink to delete the old image

    then carry on with the code as it is now. I don't like it using password as the way to identify the row, is there nothing else unique you could use, like user id? Keep in mind that passwords may not be unique and should never be treated as such. I'll make my example with password but you should really look into that

    all of the above might look something like this

    $q = "select * from users where password='$password'";
    $query = mysql_query($q) or die ('select old image query died: ' . mysql_error());
    // because this should only return a single row I will use an if
    if ($row = mysql_fetch_array($query)) {
    $oldimg = $row['photo_filename'];
    }
    $oldimg = $uploadsDirectory . $oldimg;
    unlink($oldimg);

    $sql = "UPDATE users SET photo_filename = '$imagename' WHERE password='$password'";
    mysql_query($sql);//run the query

    something like that, not totally sure I am using the right things from the right places but it will be pretty close

    oceanwave

    10+ Year Member



     
    Msg#: 3360674 posted 10:18 pm on Jun 9, 2007 (gmt 0)

    Hi jatar_k,

    Your code works perfectly!

    Could you please explain this part:
    ---------
    $oldimg = $row['photo_filename'];
    }
    $oldimg = $uploadsDirectory . $oldimg;
    ---------

    How can $oldimg equal just the filename AND also equal the path with the filename?

    I guess you had to use $row to get the field information from the database. Could you please tell me why this is written in two steps instead of something that combines the two like $uploadsDirectory . $row['photo_filename'];

    I understand your concern about using the password (with lastname). It is bothering me too. I am using a tutorial script that I have been trying to edit. The login page asks for lastname and password. I will have to change the information that is passed into the session to include userid.

    Thank you, thank you jatar_k! I had never heard of "unlink", and had no idea that you could delete files from a website folder while changing your database at the same time. Remarkable!

    Thanks to everyone for their patience.

    Habtom

    WebmasterWorld Senior Member 10+ Year Member



     
    Msg#: 3360674 posted 11:48 am on Jun 10, 2007 (gmt 0)

    $oldimg = $row['photo_filename'];
    }
    $oldimg = $uploadsDirectory . $oldimg;

    :) May be I explain this part for you. The only part I think you have missed is the dot (.) That is like attaching one part of the code to the other. An example:

    $i = "AB";
    $j = "CD";

    $i = $i.$j;

    echo $i; gives you the result "ABCD"

    Habtom

    alfaguru

    5+ Year Member



     
    Msg#: 3360674 posted 3:04 pm on Jun 10, 2007 (gmt 0)

    As a footnote, if you're inserting entered data into SQL, you should always, always, always make sure it's escaped first so malicious users can't use relatively simple means to break into your site.

    Read the PHP manual section on SQL Injection for more information.

    The function mysql_escape_string() does the job for MySQL.

    (Don't rely on magic_quotes, by the way. They're an inelegant hack.)

    oceanwave

    10+ Year Member



     
    Msg#: 3360674 posted 12:55 pm on Jun 13, 2007 (gmt 0)

    Thank you Habtom for the explanation. Your examples made it very clear to understand.

    Alfaguru, thank you for responding. I looked up mysql_escape_string(). One post said to use mysql_real_escape_string instead. Is this true (php5)?

    Would the code look like this in the script? I never know where to put the code - not sure if it should be before or after the query is run - not sure if it should have two )); at the end like the example I found.
    -----
    $sql = "UPDATE users SET photo_filename = '$imagename' WHERE password='$password' AND lastname = '$lastname'";

    mysql_real_escape_string($password),
    mysql_real_escape_string($lastname));


    mysql_query($sql);//run the query

    header('Location: ' . $uploadSuccess);

    Habtom

    WebmasterWorld Senior Member 10+ Year Member



     
    Msg#: 3360674 posted 1:01 pm on Jun 13, 2007 (gmt 0)

    It should go something like:

    $imagename = mysql_real_escape_string(trim($imagename));
    $lastname = mysql_real_escape_string(trim($lastname));
    $password = mysql_real_escape_string(trim($password));

    $sql = "UPDATE users SET photo_filename = '$imagename' WHERE password='$password' AND lastname = '$lastname'";

    mysql_query($sql);//run the query

    header('Location: ' . $uploadSuccess);

    And no, it shouldn't have "))", I don't see any reason for that.

    Habtom

    oceanwave

    10+ Year Member



     
    Msg#: 3360674 posted 1:28 am on Jun 14, 2007 (gmt 0)

    Habtom, I wasn't even close! Thank you so much! The script works fine now.

    My new problem is not with the script, but rather with what I am trying to do. A user enters information in a form, without their image, and submits the info to the database. I originally set the photo_filename field to automatically insert the name soon.jpeg when the form was submitted (there was a soon.jpeg image in a "photos" folder on my website - "photo coming soon"). Everyone initially had the "photo coming soon" image until they went into their user panel and updated their information. Now that worked fine, until I decided I needed to overwrite the extra images in the photos folder so there wouldn't be dozens for each user (the whole reason for posting this thread). I then changed my script (as outlined throughout this thread).

    The problem was when the first user updated their info, the soon.jpeg was deleted from the folder - not good for everyone else. So I then had the form name each person's photo_filename field using the now() function with a .jpeg extension (like 2007-6-13-19-45-43.jpeg). Now everyone has a different photo_filename after they submit the form.

    I bet you can guess the problem. When the user updates/uploads their photo for the first time, the unlink function can't get rid of 2007-6-13-19-45-43.jpeg in the "photos" folder, because it never existed there to begin with. So I now get an error message like:
    -----
    Warning: unlink(/home/mysite/public_html/folder/photos/2007-6-13-19-45-43.jpeg) [function.unlink]: No such file or directory in /home/mysite/public_html/folder/upload.php on line 82

    Warning: Cannot modify header information - headers already sent by (output started at /home/mysite/public_html/folder/upload.php:82) in /home/mysite/public_html/folder/upload.php on line 92
    -----
    However, the new photo_filename name is added to the database and the new photo is uploaded to the photos folder, despite the warnings. Of course, the warnings only happen the first time a user tries to change their photo because after that, the photo actually exists in the folder, and can be overwritten.

    In a nutshell, when the form is submitted an image is not added to the photos folder. Since the image does not exist in the photos folder, it can't be unlinked during the first update.

    I don't want my users to get those nasty warnings. Any suggestions? What exactly do I need to change in the script?

    Habtom

    WebmasterWorld Senior Member 10+ Year Member



     
    Msg#: 3360674 posted 4:49 am on Jun 14, 2007 (gmt 0)

    >> I don't want my users to get those nasty warnings. Any suggestions? What exactly do I need to change in the script?

    The quick way, I think this should do it:

    @unlink($path);
    The "@" suppresses errors.

    The Best Way I think is to check if the file exits, and if it does to unlink:

    if (file_exists($path)) {
    unlink($path);
    }
    Check the file_exists [php.net] function.

    Habtom

    oceanwave

    10+ Year Member



     
    Msg#: 3360674 posted 6:27 pm on Jun 16, 2007 (gmt 0)

    Hi Habtom,

    Right again! Both examples worked perfectly.

    For anyone following this thread, all that was changed was the line:

    unlink($oldimg);

    Just as Habtom said.

    Habtom, I can't thank you enough!

    Global Options:
     top home search open messages active posts  
     

    Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
    rss feed

    All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
    Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
    WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
    © Webmaster World 1996-2014 all rights reserved