Hi, I’m trying to implement the following code that I found:
$fileToDownload = "path/to/your_file.zip";
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
header("Content-Type: application/zip"); // you can put here MIME type of your file
header("Content-Disposition: attachment; filename=\\"" . basename($fileToDownload) . "\\";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($fileToDownload));
set_time_limit(0);
readfile("$fileToDownload");
This is a script that supposedly masks the actual URL paths of downloadable files so they can’t be as easily redistributed. I have searched elsewhere on the web and have found many variations of this script.
Unfortunately, none of these scripts worked properly.
The files concerned are ZIP files. When accessing a ZIP file via one of the scripts concerned, it seems to download fine, as the file name and size is retained upon completion of download. However, when attempting to open or extract the ZIP file, error messages pop up noting that the ZIP file is either invalid or empty. (I have tried echoing the actual path to confirm that the download is coming from the correct location, and it is.)
Contrarily, when I download a ZIP file by navigating to the actual URL, the file is extractable and not declared empty.
I have tried on various browsers, including the latest versions of Firefox and Chrome.
Any ideas? Is it perhaps an issue with the hosting service?
There is really no point in “hiding” the URL because you just gave it a second access point (URL) to get the same file from. What you have done doesn’t make it any harder to get the file. Aside from the fact it doesn’t appear to work.
Try opening the zip files you download though the script in a text editor.
There is probably a few PHP errors in there.
I disagree. When the files are outside of public_html its actually very useful.
I’ve had this error frequently myself. What you will probably find is that the file either has html output mixed into it (open it up in notepad++ and look for anything that looks like html or text) OR you have whitespace being output somewhere.
Both are extremely frustrating to track down but it CAN be done.
No you are wrong because while the address to the script is in the address bar the script itself may be relying on tokens in a database. If the token expired the script can deny a download.
Secondly if the file is outside of the public_html folder then the browser can not download it anyway - and how can you see it anyway? - You can’t.
Finally readfile() directly outputs the file as a stream. It doesn’t output a url or a file system file path.
sigh User authentication is one thing, but using this to hide the URL of the file is pointless. Also whether the files is outside of the public root is irrelevant. Regardless, I have access to the file, it is downloaded to my computer just the same. The only thing these scripts do is act as a proxy. They do not hide the files only set an alternate means of accessing the same file. If the sole purpose of this script is to “hide” the file URL, it is 100% pointless.
Second, no where does the original poster mention anything about a database, unless its mention I will not assume there is one or any form of user registration/authentication.
Third, I do not need to be “educated” on this. I’ve been around long enough to implement all of this stuff.
I don’t think anyone is questioning the idea of providing single-use URLs to authorise downloads, just pointing out that this script is definitely not doing anything like that
Yes but even so using headers if a file isnt in public_html it can’t be accessed directly can it. Readfile can access it and still output a stream with a file name in the headers for the browser to save it as.
No I never said THAT script was. I was just pointing out that in theory it can be done because logic_earth is claiming that its pointless and won’t protect anything.
Correct me if I’m wrong because clearly you know how long I’ve been around but didn’t the op say they were trying to implement the code sample? - IE it could be being used in another script? - I agree he doesn’t say it is and he doesn’t say it isn’t but I’m open minded about these things.
Yes, assuming the script doesn’t block you. As I’ve mentioned above, IF you have a larger script which incorporates that code then it may very well refuse a download. Additionally the last time I tried to access a file that was outside of a public_html directory with a browser or download manager I got http error codes. If you know a way around that feel free to tell because MOST people don’t and THAT is what the op is using to their advantage. Most web devs will never beat every single vulnerability but they will try to block as many as they can even if they have to obfuscate things.
Maybe, maybe not. The point is this: The op has asked for help and as of yet I’ve not seen you provide any. Yes you have raised some very valid points and they can be worked around. You seem to be saying that just because that particular code doesn’t do the required job the op should just drop the idea completely. I agree that using THAT code by itself IS pointless without further work to it but we don’t know the ops plans.
Quite right, but we don’t know the ops plans. The op is simply asking for help to get the code working correct?
Try opening the zip files you download though the script in a text editor.
There is probably a few PHP errors in there.
I cannot help further until I know what errors the original poster is getting. As the above code is perfectly valid with no errors.
I cannot magically pull solutions out of my…ahem. I need more information about what is actually wrong.
Well, I plan to implement authentication at a later date but at the moment I just want a method of being notified whenever someone downloads. By having the download occur when a page is landed on rather than by navigating to the direct URL, I can have a PHP mailer on that page send me a notification each time someone downloads. So until I get authentication set up, I’ll at least have a way of knowing when to change the alt access point URL (being after someone downloads).
I opened the file in Notepad++ and sure enough, HTML was mixed in. In fact, it seems that most if not all of the HTML of the webpage that feeds the ZIP file content somehow got mixed into the ZIP file itself.
As I said earlier, readfile() should be able to output files that are stored outside public_html. You might want to consider that in the future when you enable authentication.