Just a quick question (maybe not)
I'm looking to add to my website a way for a customer to login and once logged in they are able to select their invoices which i will upload to my server.
My question is what is the best way to go about storing the files and accessing them.
i've done some googling and haven't been able to find much in the way of pointing me in the right direction.
Thanks in advance
Upload them to an unaccessible directory (outside of the www root or protected by htaccess) and serve them with PHP.
This can be done like so:
$file = '/path/to/yourpdf.pdf';
header('Content-type: application/pdf');
header('Content-Length: ' . filesize($file));
readfile($file);
Use PHP and SQL to determine what $file should be and whether or not the user has permission to view the file.
One recommendation I have is to ensure you do not store the actual file in the db. Make sure all you are storing is a pointer (the hyperlink) to a file that is stored somewhere on your network.
Related
Good evening.
I am using Yii framework and mPDF library to generate some PDF files via Ajax script and I need to force "save as" dialogue in users' browsers.
I know how to solve this issue with a single user dowloading a single file.
Does anyone have a tip on how could I make it all work on high-load system (e.g. several users trying to generate and download a PDF will attempt to access one temp file which would cause an error)?
Should I generate a separate file for each session? And which way would be nice for cleaning these temp files?
Thank you for your help.
you should use tempnam http://www.php.net/manual/en/function.tempnam.php to generate the temp files. they'll be uniquely named, so it'll be easy to make one per session. Just delete as normal when you're done with them.
Make an invisible iframe. From JS set that iframe's src to the script on your server that generates the PDF.
<iframe src="http://yoursite.com/download-file.php?report=pdf¶m1=value1¶m2=value2..." width="1" height="1"></iframe>
Then (and I'm not sure how you do this with mPDF) the point is to output the file from script directly into the browser. It's something like this:
<?php
$x = some_function($_GET['param1'],$_GET['param2', ...); // PDF GEN. ROUTINE, BASED ON REQUEST DATA, HOWEVER YOU DO IT
header('Content-type: application/pdf');
echo $x;
That should solve all your concerns.
First of all, I'd recommend you to generate a different temp file for each generated PDF, in order to avoid any possible error like one user downloading somebody else's PDF, etc.
To clean up the temp directory, I'd use a cronjob that deletes all files older than N days.
In order to "force save dialog", you have to set the Content-disposition header to attachment:
header('Content-Disposition: attachment; filename="myfile.pdf"');
I'm building a file sharing site, and I'm thinking, I want my users to be able to upload and share anything.
Sounds dangerous, I know. But, is there a method to allow this to be possible? For example, forcing the download when the user requests the link with a mime type? Rather than "running" something on the page.
Any ideas how to allow any file type without the security issue.
Thanks
Store the file on a location not accessible by the user through the browser. (so above the document root)
when loading a file, use the readfile() function.
Set correct headers, including these:
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=[INSERT FILENAME HERE]");
And also use the correct content-type header for each type of file
If you only want it to be dangerous to other users (as they will be sharing virus ridden files in no time), but provide some protection for your web server from code injection attacks, you might consider storing the uploads in a database BLOB field. That should at least make it harder to inject code that will run on the server.
You can allow users to upload anything by using a simple HTML multipart form along with PHP's $_FILES. Only issue I see is file size limits.
You than can simply post a link to any of these files. It's the user's browsers settings that determine if a file is executed or downloaded, not yours. So you can suggest that they right click on them, and select 'save to', but besides that it's limited.
Any ideas how to allow any filetype without the security issue.
You say it yourself. It's like wanting to make scrambled eggs, without wanting to break the eggs.
I have a file, call it secret.pdf, that I offer for download. However, I would like to keep it from having a URL that can be copied / pasted or typed out like www.website.com/pdf/secret.pdf (no fishing for files!).
For instance, user A clicks on the link, and gets kgsjgldsg.pdf. User B clicks the same link, but gets asadsfsefaw.pdf. The point is, a random filename is used to reference the same file, secret.pdf.
Ive googled php file obfuscator, and joomla filename obfuscator, and have had no luck. Any ideas or a pointer in the right direction would be much appreciated.
You could add a GET variable based on time, that is valid for 1 minute (should be enough).
So your request would be /pdf/getPDF.php?key=xxxxxxxxx
Make key a salted hash based on the current time on your server, for instance the closest number dividable by 5 (when it's 17:17 you'd use 17:15, etc).
Then generations the 'current' hash on your getPDF.php file, and if it is the same, then stream your pdf.
This will NOT stop people from using the link, but the link will only be valid for 5 minutes.
Addendum: You should make sure the pdf is not reachable from outside, but only readable for your pdf-streaming php-file (e.g. outside your /var/www or equivalent directory)
An alternative is to store the pdf file 1 level up from your public_html web folder on your hosting account. You can then use a full path to deliver the file to the user as a download. This way no one can access the file as it is not available on your website. Only the code on your site knows where the file is. I do this for a number of components, see code below relating to Joomla:
$file = '/home/domain/files/secret.pdf'
$filesize = filesize(file );
JResponse::setHeader('Content-Type', 'application/pdf');
JResponse::setHeader('Content-Transfer-Encoding', 'Binary');
JResponse::setHeader('Content-Disposition', 'attachment; filename="'.$file.'"');
JResponse::setHeader('Content-Length', $filesize);
echo JFile::read($file);
Writing a small app that (among other things) lets users upload a file (like an image, a .doc or a text file) as part of their posting/submission.
Our current prototype just dumps the file into /{app_root}/files/, but of course, anyone can get to that even if they are not logged in or using the system. The goal is to only grant access (view access) to the files if user is logged in and does in fact have access to the post that the file belongs to.
So, in short, I am looking for a good way to do this.
I am thinking of either creating a folder outside the /web/ (http) folder and then having PHP render it somehow using header() commans, or, maybe just dumping the file into the database? I have never done either one, however.
While I suspect I can figure it out eventually, there are just too many smart people on here that I was figuring someone will know of some sort of existing class or function library that does this already?
You have to do the following:
Move all the files out of the webroot. You could disable access to the folder with .htaccess, but it is not worth the hassle and potential security risk. Just move it out there.
Keep a table of the files uploaded, storing the user's original file name there. Rename the file to $id.$ext and so on. In short, you don't want to use the user's file name in your system.
Have a script, download.php or whatever, get the file's ID, verify who is logged in, and if everything checks out, fetch the file, read it out to the browser, and send the appropriate download headers.
These headers would be something like:
header('Content-type: application/octet-stream');
header('Content-disposition: attachment; filename=usersuppliedname.txt');
header("Content-Length: " . filesize('../safefiles/1.txt'));
header("Content-Transfer-Encoding: binary");
readfile('../safefiles/1.txt');
exit;
You can then get more fancy if you want to allow resuming files and such, but the above should do it.
I've inherited an application with a glaring security hole.
It has session-based security, but file uploads (which are user specific) are not secured in any way and they are stored in the public file tree.
Filenames do not follow any convention as such, making them hard to guess, but the data is sensitive and thus I need to implement a security measure to prevent unauthorized file access.
Moving the location of the files is not really an option, so I'm looking at a htaccess solution to forward requests to a php handler script.
Does anyone have experience in implementing this type of thing or any good alternative solutions? Specific examples of .htaccess syntax greatly appreciated, as I'm struggling in this area.
Don't really understand why moving them isn't an option, since pushing requests for them to a handler means it no longer matters where they're stored. But you're the man on the scene.
.htaccess looks like:
RewriteEngine on
RewriteRule path/to/where/these/files/live/(.*) /handlerscript.php/$1
Then you pick up the remaining file path and name from $_SERVER['PATH_INFO'].
Well, you could make apache parse .jpg file's for a certain folder adding the following to your .htaccess
AddHandler php5-cgi .jpg
then you could set a file of php to parse the request the way chaos was recomending you and doing a certain validation, then just return jpeg headers along with the correct picture u'd like to display
here's an example
<?php
if($validUser)
{
header("Cache-control: No-cache");
header("Pragma: No-cache");
header("Content-Type: image/jpeg");
//correct picture address
$img = imagecreatefromjpeg("2326_b_lil.jpg");
imagejpeg($img);
}
else
{
//code for error image
}
?>
please let me know if you want a more extensive example
I think you may need to write a script that will serve the images, then use htaccess to completely restrict access to the actual images from a browser.
The script can take in the web path to the image, decide if the user has access, then use something like fpassthru to feed an actual image to the browser.
All references to the images would need to be modified, however, to reference the serving script.
So instead of accessing the images with /images/123/5423453245.jpg,
it would be /image.php?images/123/5423453245.jpg
Or something similar to that.