End goal:
Click link on page 1, end up with file downloaded and refresh page 1. Using PHP to serve downloads that are not in public html.
Approach:
Page 1.
Link transfers to page 2 with get variable reference of which file I am working with.
Page 2.
Updates relevant SQL databases with information that needs to be updated before refresh of page 1. Set “firstpass” session variable. Set session variable “getvariablereference” from get variable. Redirect to page 1.
Page 1.
If first pass session variable set. Set Second pass session variable. Unset first pass variable. Refresh Page. On reload the page will rebuild using updated SQL database info (changed on page 2.).
Refreshed Page 1.
If second pass session variable set. Run download serving header sequence.
This is page 1. I am not showing the part of page 1 that has the initial link. Since it doesn’t matter.
// REFERSH IF FIRSTPASS IS LIVE
if ($_SESSION["PASS1"] == "YES"){
$_SESSION["PASS1"] = "no";
$_SESSION["PASS2"] = "YES";
echo "<script>document.location.reload();</script>";
}
if ($_SESSION["PASS2"] == "YES"){
// Grab reference data from session:
$id = $_SESSION['passreference'];
// Serve the file download
//First find the file location
$query = "SELECT * from rightplace
WHERE id = '$id'";
$result = mysql_query($query);
$row = mysql_fetch_array($result);
$filename = $row['file'];
$uploader = $row['uploader'];
// Setting up download variables
$string1 = "/home/domain/aboveroot/";
$string2 = $uploader;
$string3 = '/';
$string4 = $filename;
$file= $string1.$string2.$string3.$string4;
$ext = strtolower (end(explode('.', $filename)));
//Finding MIME type
if($ext == "pdf" && file_exists($file)) {
header("Content-disposition: attachment; filename= '$filename'");
header('Content-type: application/pdf');
readfile($file);
}
if($ext == "doc" && file_exists($file)) {
header("Content-disposition: attachment; filename= '$filename'");
header('Content-type: application/msword');
readfile($file);
}
if($ext == "txt" && file_exists($file)) {
header("Content-disposition: attachment; filename= '$filename'");
header('Content-type: text/plain');
readfile($file);
}
if($ext == "rtf" && file_exists($file)) {
header("Content-disposition: attachment; filename= '$filename'");
header('Content-type: application/rtf');
readfile($file);
}
if($ext == "docx" && file_exists($file)) {
header("Content-disposition: attachment; filename= '$filename'");
header('Content-type: application/vnd.openxmlformats-officedocument.wordprocessingml.document');
readfile($file);
}
if($ext == "pptx" && file_exists($file)) {
header("Content-disposition: attachment; filename= '$filename'");
header('Content-type: application/vnd.openxmlformats-officedocument.presentationml.presentation');
readfile($file);
}
if($ext == "ppt" && file_exists($file)) {
header("Content-disposition: attachment; filename= '$filename'");
header('Content-type: application/vnd.ms-powerpoint');
readfile($file);
}
}
The script on page 2 is working correctly. It updates the sql database and redirects to the main page properly. I have also checked that it sets the “$_SESSION[‘passreference’];” correctly and nothing on page 1 would unset it.
So, thats the whole long explanation of the situation. I am stumped. What happens is, as I said page 2 works fine. Then it kicks to page 1, refreshes and then doesnt push any download. I know that the download script works and that the files are there to be downloaded (checked without the whole refresh sequence).
I essentially have two questions:
-
Can anyone spot whats going wrong?
-
Can anyone conceptualize a better approach?
I just reworked your PHP code a bit. Especially you’ll get more information about what’s going wrong. Just try this code and read the following comments, which explain what happend, if you get one of the new error messages. Also read the NOTE part below, which explains why you probably can’t access a file from PHP, even it’s existing and is in the right directory.
So here is the source code:
NOTES:
The file not found error can happen even the file exists. If this happens, this is most probably a security mechanism that prevents the PHP script to access files outside the HTML-root directory. For example php scripts could be executed in a “chrooted” environment, where the root directory “/” is mapped e.g. to “/home/username/”. So if you want to access “/home/username/dir/file” you would need to write “/dir/file” in your PHP script. It can be even worse, if your root is set like “/home/username/html”; then you’ll not be able to access directories below your “html” directory. To work around that, you can create a directory inside the HTML-root and put a file named “.htaccess” there. Write “DENY FROM ALL” in it, which prevents access to the directory by browser request (only scripts can access it). This works for apache servers only. But there are solutions like that for other server software too… More info on this can be found under: http://www.php.net/manual/en/ini.core.php#ini.open-basedir
Another possibility is that your file access right (for uploaded files) are not set in a way, that your script is allowed to access them. With some security settings enabled (on a linux server), your PHP script can only access files owned by the same user as the “owner” set for the script file. After upload via “ftp” this is most probably the usersname of the ftp user. If edited on the shell, this will be the current users username. => But: Uploaded files are sometimes assigned to the user the webserver is running as (e.g. “www-data”, “www-run” or “apache”). So find out which it is and assign your script to this owner.