WolfRage Posted July 13, 2009 Share Posted July 13, 2009 First Question: Yes that would be secure. Second Question: Yes they are receiving a stream not an actual link to the file being downloaded. I am not completely sure what is wrong with that scrip that you are using, but it appears to be serving the file content in a format that is not valid such as Forced Download. Also it is specifying more than is really necessary, which could be causing trouble. Instead you should use the post fix of the file to determine it's content. All modern browsers support this method. <?php $type=explode('.',$file); $type=$type[1]; header('Content-type: application/'.$type); ?> Quote Link to comment Share on other sites More sharing options...
A JM Posted July 13, 2009 Author Share Posted July 13, 2009 Very strange about the corruption... and stripping the few lines down to what you are using didn't help. <?php $file = $_GET['file']; // the absolute path to your directory storing your files. $path = '/home/claims/'; $download = $file; //header("Pragma: public"); //header("Expires: 0"); //header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); //header("Content-Type: application/force-download"); //header( "Content-Disposition: attachment; filename=".$download); //header( "Content-Description: File Transfer"); //header('Accept-Ranges: bytes'); //header('Content-Length: ' . filesize($file)); //@readfile($file); $type=explode('.',$download); $type=$type[1]; header('Content-type: application/'.$type); header( "Content-Disposition: attachment; filename=".$download); readfile($download); ?> Is there a better way to make this happen - this would be perfect for what I'm needing...? Also, is there a file type that this process is limited to like only .jpg's? Thanks, Quote Link to comment Share on other sites More sharing options...
WolfRage Posted July 13, 2009 Share Posted July 13, 2009 To be honest I am not sure why you are experincing the file corruption. Are you sure the files are intact? Quote Link to comment Share on other sites More sharing options...
A JM Posted July 14, 2009 Author Share Posted July 14, 2009 I pulled them off of the server and they seem to be OK - the file in particular is a PDF. Is there another way that I can make this happen? A JM, Quote Link to comment Share on other sites More sharing options...
A JM Posted July 14, 2009 Author Share Posted July 14, 2009 WolfRage, I may have found the problem.. when I downloaded the file I noticed it was 237K and not 110K like the original, so I opened the downloaded file with a text editor and this is what I found. <br /> <b>Warning</b>: readfile(chart.pdf) [<a href='function.readfile'>function.readfile</a>]: failed to open stream: No such file or directory in <b>/home/mydomain.com/dbpages/download.php</b> on line <b>92</b><br /> My link was setup like this: <a href= http://mydomain.com/dbpages/download.php?file=chart.pdf> testing</a> The file reside in /home/files/ so how do I format the link correctly? A JM, Quote Link to comment Share on other sites More sharing options...
WolfRage Posted July 15, 2009 Share Posted July 15, 2009 Ahh remember when we were talking about hard coding the file location in, well this is where we need to do that. <?php $location=realpath('../../'); $location=$location.'/files/chart.pdf'; /*OR it maybe like this $location.'files/chart.pdf' either way if you run realpath on $location again it should correct it. You can also adjust the above to accept the cleaned get variable instead of the hard coding the pdf file. But make sure this works first.*/ $location=realpath($location); //Then readfile on $location. //Hope all of this solves your problem, let me know what happens. ?> Quote Link to comment Share on other sites More sharing options...
A JM Posted July 15, 2009 Author Share Posted July 15, 2009 If I were to use realpath() like so: $location=realpath('../index.html); print_r($location); exit; What would that look like - /www/index.html ? Quote Link to comment Share on other sites More sharing options...
WolfRage Posted July 15, 2009 Share Posted July 15, 2009 It depends on where you are located on the server. But in this case the "../" signifies to back up in the directory. For instance if you are on a shared server then you are probably under some huge directory list that is broken down usually alphabetically. Might look something like this: "/home/content/a/l/p/alpha/html/mysitefolder/" if you use your code then you would be calling this: "/home/content/a/l/p/alpha/html/index.php" However your code had an error and needs to be like this. <?php $location=realpath('../index.html'); print_r($location); exit; ?> Basically using the real path you can back up as much as you would like then use real path again to proceed down another path in your directory. This was the simplest way for me to figure out how to back up and then move to another location of which was being called dynamically. Quote Link to comment Share on other sites More sharing options...
A JM Posted July 15, 2009 Author Share Posted July 15, 2009 I think this is starting to look like a folder permission issue...? The pathing looks good, but I don't see anything showing up in the logs. I guess it needs to be asked to what permissions should a folder above root be set to? Since PHP is reading and writing the files does that have some impact on that? Thanks, Quote Link to comment Share on other sites More sharing options...
WolfRage Posted July 15, 2009 Share Posted July 15, 2009 Well the question is does PHP have access to folders above the root? usually not. In that case you need to make a folder that is below root but inaccessible via the web. Another words I should not be able to get to that folder via a browser or any type of URL, instead only php should be able to access these areas. Quote Link to comment Share on other sites More sharing options...
A JM Posted July 15, 2009 Author Share Posted July 15, 2009 Right... so how do I do this... this is my dilemma. Any thoughts or suggestions on how to accomplish? A JM, Quote Link to comment Share on other sites More sharing options...
WolfRage Posted July 15, 2009 Share Posted July 15, 2009 .htaccess order deny,allow deny from all Quote Link to comment Share on other sites More sharing options...
A JM Posted July 15, 2009 Author Share Posted July 15, 2009 Doesn't .htaccess only have impact on users that are actually logged into the machine? Since my users are web based and only allowed to login if the have credentials in mysql how can that work? could it be that simple? A JM, Quote Link to comment Share on other sites More sharing options...
WolfRage Posted July 15, 2009 Share Posted July 15, 2009 .htaccess has very little to do with logins unless you are talking about http logins. But other wise .htaccess is all about access control to web users. So yes it could be that simple, now I am not a .htaccess pro so you may want some confirmation. But I am pretty sure that will tell appache to forbide any from viewing that directory. Quote Link to comment Share on other sites More sharing options...
A JM Posted July 16, 2009 Author Share Posted July 16, 2009 OK, .htaccess works 2/3 of the way, I can upload files via php and php can list the files but how do I allow my user(s) to download the file and at some point delete the file? I'm kind of stuck in a catch 22... A JM, Quote Link to comment Share on other sites More sharing options...
A JM Posted July 16, 2009 Author Share Posted July 16, 2009 Well since I was able to upload a file using php I was also assuming I would be able to delete a file using php, not. With an .htaccess file similar to what you posted this is what I get. You don't have permission to access /documents/graph.pdf on this server. Same goes for downloading the file - man this has got me hung up... Essentially I've got everything working working except now I don't have permissions... help... :'( Quote Link to comment Share on other sites More sharing options...
WolfRage Posted July 16, 2009 Share Posted July 16, 2009 OK early on we had made some good progress but it sounds like you may not be putting it all together correctly. You will not be able to supply the user with the files directly, instead you have to perform a readfile for the user through php. If they want to delete the file you have to perform a unlink for the user through php. PHP is not a user it is the system and so it has the permissions to perform these operations. The user is not allowed into this directory at all in any way. Basically PHP must be the interface. Quote Link to comment Share on other sites More sharing options...
A JM Posted July 16, 2009 Author Share Posted July 16, 2009 Wolfrage, I finally got it!!! user error as usual... I wasn't including the path in the readfile() function. <?php $file = $_GET['file']; // the absolute path to your directory storing your files. $path = '/home/download/'; $download = $file; //header("Pragma: public"); //header("Expires: 0"); //header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); //header("Content-Type: application/force-download"); //header( "Content-Disposition: attachment; filename=".$download); //header( "Content-Description: File Transfer"); //header('Accept-Ranges: bytes'); //header('Content-Length: ' . filesize($file)); //@readfile($file); $type=explode('.',$download); $type=$type[1]; header('Content-type: application/'.$type); header( "Content-Disposition: attachment; filename=".$download); readfile($download); ?> NEW <?php $file = $_GET['file']; // the absolute path to your directory storing your files. $path = '/home/download/'; $download = $file; //header("Pragma: public"); //header("Expires: 0"); //header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); //header("Content-Type: application/force-download"); //header( "Content-Disposition: attachment; filename=".$download); //header( "Content-Description: File Transfer"); //header('Accept-Ranges: bytes'); //header('Content-Length: ' . filesize($file)); //@readfile($file); $type=explode('.',$download); $type=$type[1]; header('Content-type: application/'.$type); header( "Content-Disposition: attachment; filename=".$download); readfile($path.$download); ?> I'll now refine the script for my application. Many thanks for all your help, guidance and suggestions with this... A JM, [EDIT] I am still having a slight problem and its with passing variables. This now works perfectly "except" the variable $recordID is not available for use after testing with "if(asset" even though it is gotten originally with $_GET['ID'] and set to $recordID - when I submit the form the variable is blank. I thought every object on the form would be available, what am I missing here? <?php $recordID= $_GET['ID']; $path = "../claims/" . $recordID . "/"; if(isset($_GET['delete']) && $_GET['delete']=='true') { $fname = $_GET['deletefile']; $path = '../claims/' . $recordID . '/'; print_r($path.$fname); exit; //$location=realpath('../claims/' . $recordID . '/'); //chdir($location); //unlink($path.$fname); //header('location: adm_file_list.php'); die(); } ?> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <?php $dir = dir($path); while($file = $dir->read()) { if($file != '.' && $file != '..') { echo "<form method='post' action="?><?php echo $_SERVER['PHP_SELF'].'?delete=true&deletefile='.$file;?> <?php echo" ><a href= /dbpages/download.php?file=$file&recordid=$recordID> $file </a> <input type='submit' value='Delete'></form>"; } } ?> Quote Link to comment Share on other sites More sharing options...
A JM Posted July 17, 2009 Author Share Posted July 17, 2009 Passing the variable through the form again works...? I don't understand that? <?php $dir = dir($path); while($file = $dir->read()) { if($file != '.' && $file != '..') { echo "<form method='post' action="?><?php echo $_SERVER['PHP_SELF'].'?delete=true&recordid='.$recordID.'&deletefile='.$file;?> <?php echo" ><a href= /dbpages/download.php?file=$file&recordid=$recordID> $file </a> <input type='submit' value='Delete'></form>"; } } ?> Quote Link to comment Share on other sites More sharing options...
A JM Posted July 17, 2009 Author Share Posted July 17, 2009 Since I'm working on this at the moment and trying to finish it up I found one last item. Hopefully you'll login tonight Wolfrage... When I uncomment the last 2 lines of the script after deleting the file unlink($path.$fname); header('location: adm_file_list.php'); die(); this is the error that is generated: Warning: Cannot modify header information - headers already sent by (output started at /home/mydomain.com/dbpages/adm_file_list.php:4) in /home/mydomain.com/dbpages/adm_file_list.php on line 15 The issue is somehow related to "adm_file_list.php" being in an iframe and I'm trying to refresh it since it has one less file to delete. I don't understand what I'm doing wrong? This is the last piece to the puzzle andI think this can be put to bed... Thanks. A JM, Quote Link to comment Share on other sites More sharing options...
WolfRage Posted July 17, 2009 Share Posted July 17, 2009 The problem with recieveing this variable $_GET['ID'] is that the form is submitted with POST so the line should look like this: <?php $recordID= $_POST['ID']; ?> The header warning is due to the fact that headers can only be sent prior to any other data that is going to the browser and only once. So before we pick apart the Iframe lets see what is on these two lines: adm_file_list.php: line 4 & line 15 [/] Quote Link to comment Share on other sites More sharing options...
A JM Posted July 18, 2009 Author Share Posted July 18, 2009 Well I think I've resolved all the problems let me know what you think. From the main form I'm setting the variable for $recordID using a $_SESSION and it is retrieved form the actual recordset. $recordID= $_SESSION['port_recordID']; //variable used to carry claimnumber Then in the Iframe I just get the variable from the $_SESSION['port_recordID'] $recordID= $_SESSION['port_recordID']; Using that scenario all my problems disappeared... what do you think? should I run into any problems with the $_SESSION variable; do I need to do anything in particular with it before or after its use? <?php //initialize the session if (!isset($_SESSION)) { session_start(); } $recordID= $_SESSION['port_recordID']; //variable comes from detail page only used to carry claimnumber $path = "../documents/" . $recordID . "/"; if(isset($_GET['delete']) && $_GET['delete']=='true') { $fname = $_GET['deletefile']; $fID = $_GET['recordid']; $path = '../documents/' . $fID . '/'; //print_r($path.$fname); //exit; unlink($path.$fname); header('location: adm_file_list.php'); die(); } ?> <?php $dir = dir($path); while($file = $dir->read()) { if($file != '.' && $file != '..') { echo "<form method='post' action="?><?php echo $_SERVER['PHP_SELF'].'?delete=true&recordid='.$recordID.'&deletefile='.$file;?> <?php echo" ><a href= /dbpages/download.php?file=$file&recordid=$recordID> $file </a> <input type='submit' value='Delete'></form>"; } } ?> Quote Link to comment Share on other sites More sharing options...
WolfRage Posted July 18, 2009 Share Posted July 18, 2009 The only other recommendation I would make is to catch the result of your unlink. So that you can print a confirmation or a failure screen. Although the $_GET variables in this case are not a risk, it is still always a good idea to clean every incoming variable. Good job AJM. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.