473,406 Members | 2,956 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,406 software developers and data experts.

Securely serving files

Hey all,

People on my website register to be allowed access to certain downloads.
I store these files above the document root so that they can't be
accessed by Apache (Only from PHP). I wrote a file serving script which
dumps the correct headers for the download and calls readfile().

I thought everything was going swimmingly until I realized that my
webhost has Safe Mode turned on, and the script execution time is
limited to 30 seconds. If your file takes longer than that to download,
then too bad :).

So how can I do this? The files that I am serving are no larger than
about 2 megabytes.

It seems that one option would be to make a copy of the file I want to
serve, but below the document root so that it is available from the
browser. I'd give the file a randomly generated name that couldn't just
be guessed, and just write a regular link to the browser. Has anyone
tried this, and did it work out okay for you? How did you go about
cleaning up files after the client has downloaded them? Is there a
better option?

Cheers,
Nicholas Sherlock
Feb 11 '06 #1
21 1959
Nicholas Sherlock wrote:
Hey all,

People on my website register to be allowed access to certain downloads.
I store these files above the document root so that they can't be
accessed by Apache (Only from PHP). I wrote a file serving script which
dumps the correct headers for the download and calls readfile().

I thought everything was going swimmingly until I realized that my
webhost has Safe Mode turned on, and the script execution time is
limited to 30 seconds. If your file takes longer than that to download,
then too bad :).

So how can I do this? The files that I am serving are no larger than
about 2 megabytes.

It seems that one option would be to make a copy of the file I want to
serve, but below the document root so that it is available from the
browser. I'd give the file a randomly generated name that couldn't just
be guessed, and just write a regular link to the browser. Has anyone
tried this, and did it work out okay for you? How did you go about
cleaning up files after the client has downloaded them? Is there a
better option?

Cheers,
Nicholas Sherlock


Why not just include() the file?

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
js*******@attglobal.net
==================
Feb 11 '06 #2
Yes actually I've done that before. It works just fine, as for cleaning
the files up afterward you could just use crontab. Assuming your using
Linux. Windows probably has something similar.
Nicholas Sherlock wrote:
Hey all,

People on my website register to be allowed access to certain downloads.
I store these files above the document root so that they can't be
accessed by Apache (Only from PHP). I wrote a file serving script which
dumps the correct headers for the download and calls readfile().

I thought everything was going swimmingly until I realized that my
webhost has Safe Mode turned on, and the script execution time is
limited to 30 seconds. If your file takes longer than that to download,
then too bad :).

So how can I do this? The files that I am serving are no larger than
about 2 megabytes.

It seems that one option would be to make a copy of the file I want to
serve, but below the document root so that it is available from the
browser. I'd give the file a randomly generated name that couldn't just
be guessed, and just write a regular link to the browser. Has anyone
tried this, and did it work out okay for you? How did you go about
cleaning up files after the client has downloaded them? Is there a
better option?

Cheers,
Nicholas Sherlock


Feb 11 '06 #3
On 2006-02-11, Jerry Stuckle <js*******@attglobal.net> wrote:
Why not just include() the file?


not reccomended for binary files - they might have <? in them somewhere...

--

Bye.
Jasen
Feb 11 '06 #4
On 2006-02-11, Nicholas Sherlock <N.********@gmail.com> wrote:
Hey all,

People on my website register to be allowed access to certain downloads.
I store these files above the document root so that they can't be
accessed by Apache (Only from PHP). I wrote a file serving script which
dumps the correct headers for the download and calls readfile().

I thought everything was going swimmingly until I realized that my
webhost has Safe Mode turned on, and the script execution time is
limited to 30 seconds. If your file takes longer than that to download,
then too bad :).

So how can I do this? The files that I am serving are no larger than
about 2 megabytes.

It seems that one option would be to make a copy of the file I want to
serve, but below the document root so that it is available from the
browser.
if it's a *nix server make a link instread of a copy of the file it's much
faster, and uses much less disk space.
I'd give the file a randomly generated name that couldn't just
be guessed, and just write a regular link to the browser. Has anyone
tried this, and did it work out okay for you? How did you go about
cleaning up files after the client has downloaded them? Is there a
better option?


Store the names and delete any that have been sitting there for more than 30
seconds, or spawn a background script that sleeps for 30 seconds and then
deletes the copy.

With unix the download will continue even after the file is no longer present
windows will ( I think) give an error and not delete the file so you'd have
to find a way to detect that, sleep again, and retry.

Bye.
Jasen
Feb 11 '06 #5
Jasen Betts wrote:
On 2006-02-11, Jerry Stuckle <js*******@attglobal.net> wrote:

Why not just include() the file?

not reccomended for binary files - they might have <? in them somewhere...


He didn't say the were binary files.

And even if they were, he'd have exactly the same problem with
readfile() - which he is currently using.

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
js*******@attglobal.net
==================
Feb 11 '06 #6
Jasen Betts wrote:
if it's a *nix server make a link instread of a copy of the file it's much
faster, and uses much less disk space.
The Symlink() command? Awesome!
Store the names and delete any that have been sitting there for more than 30
seconds, or spawn a background script that sleeps for 30 seconds and then
deletes the copy.

With unix the download will continue even after the file is no longer present
windows will ( I think) give an error and not delete the file so you'd have
to find a way to detect that, sleep again, and retry.


I'm on Unix. Thanks, this is an excellent solution.

Cheers,
Nicholas Sherlock
Feb 12 '06 #7
On Sat, 11 Feb 2006 16:56:08 -0500, Jerry Stuckle <js*******@attglobal.net>
wrote:
Jasen Betts wrote:
On 2006-02-11, Jerry Stuckle <js*******@attglobal.net> wrote:
Why not just include() the file?


not reccomended for binary files - they might have <? in them somewhere...


He didn't say the were binary files.

And even if they were, he'd have exactly the same problem with
readfile() - which he is currently using.


No, readfile() doesn't execute the file as PHP. include() does. They're very
different..

--
Andy Hassall :: an**@andyh.co.uk :: http://www.andyh.co.uk
http://www.andyhsoftware.co.uk/space :: disk and FTP usage analysis tool
Feb 12 '06 #8
Andy Hassall wrote:
On Sat, 11 Feb 2006 16:56:08 -0500, Jerry Stuckle <js*******@attglobal.net>
wrote:

Jasen Betts wrote:
On 2006-02-11, Jerry Stuckle <js*******@attglobal.net> wrote:
Why not just include() the file?

not reccomended for binary files - they might have <? in them somewhere...


He didn't say the were binary files.

And even if they were, he'd have exactly the same problem with
readfile() - which he is currently using.

No, readfile() doesn't execute the file as PHP. include() does. They're very
different..


Please read the original post. He is not outputing a php file. It is
text - and would not be executed.
--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
js*******@attglobal.net
==================
Feb 12 '06 #9
On 2006-02-12, Jerry Stuckle <js*******@attglobal.net> wrote:
Andy Hassall wrote:
On Sat, 11 Feb 2006 16:56:08 -0500, Jerry Stuckle <js*******@attglobal.net>
wrote:

Jasen Betts wrote:

On 2006-02-11, Jerry Stuckle <js*******@attglobal.net> wrote:
>Why not just include() the file?

not reccomended for binary files - they might have <? in them somewhere...

He didn't say the were binary files.

And even if they were, he'd have exactly the same problem with
readfile() - which he is currently using.

No, readfile() doesn't execute the file as PHP. include() does. They're very
different..


Please read the original post. He is not outputing a php file. It is
text - and would not be executed.


php files are (usually) text files...
With include() it would be executed if it contained php tags.
The .php filename extension is only significant to the web server.


--

Bye.
Jasen
Feb 12 '06 #10
On 2006-02-12, Nicholas Sherlock <N.********@gmail.com> wrote:
Jasen Betts wrote:
if it's a *nix server make a link instread of a copy of the file it's much
faster, and uses much less disk space.


The Symlink() command? Awesome!


symlinks depend on the apache configuration.

hard links (the link() function) are indistinguishable from
real files.

as long as the file you're linking to is on the same partition as the web
site (and is readable by PHP - you already said it was) link() is probably
the best way to go.
Store the names and delete any that have been sitting there for more than 30
seconds, or spawn a background script that sleeps for 30 seconds and then
deletes the copy.


shell_exec (" ( sleep 30 ; rm '$filename' ) &");

but that doesn't work in safe mode... :( someone else may have an
alternative.
Bye.
Jasen
Feb 12 '06 #11
Jasen Betts wrote:
On 2006-02-12, Nicholas Sherlock <N.********@gmail.com> wrote:
The Symlink() command? Awesome!
symlinks depend on the apache configuration.

hard links (the link() function) are indistinguishable from
real files.

as long as the file you're linking to is on the same partition as the web
site (and is readable by PHP - you already said it was) link() is probably
the best way to go.


I'm using Symlink() right now with success. What is the difference
between hard links and symlinks? Is there any reason to switch?
Store the names and delete any that have been sitting there for more than 30
seconds, or spawn a background script that sleeps for 30 seconds and then
deletes the copy.


shell_exec (" ( sleep 30 ; rm '$filename' ) &");

but that doesn't work in safe mode... :( someone else may have an
alternative.


Since it isn't that critical when the link expires, I just delete all
previous links every time I create a link. Hopefully there won't be any
concurrency issues there.

In safe mode, the folders that you create with mkdir get Apache's ID,
not the ID of the script, and are therefore not accessible from PHP
scripts. The solution was to use the ftp_* functions of PHP to create a
folder, which then has the correct ID for access.

Cheers,
Nicholas Sherlock

Cheers,
Nicholas Sherlock
Feb 12 '06 #12
Alternatively, you can use chmod() to change the file attributes to
allow reading/writing of the file. Might be faster than the ftp
functions.

Hard links point to the data (ie: they're just a normal file). When
all the hard links to the data are gone, then the data is deleted.
They also cannot cross volumes.

Symlinks point to a file (which points to the data). The effect being,
if you delete the symlink, the original file is still there. They can
cross volumes as they just have a file path they point to.

Apache can be setup to follow, not follow, and change the owner id of
symlinks. Since you said symlinks are apparently working, I don't
think it matters which you choose in this case.

Feb 12 '06 #13
Richard Levasseur wrote:
Alternatively, you can use chmod() to change the file attributes to
allow reading/writing of the file. Might be faster than the ftp
functions.
AFAICS, chmod() isn't the problem. The problem is that when using
Mkdir() the owner of the created folder isn't the same as the owner of
the script, and PHP's safe mode therefore doesn't allow you to access
the created folder (You can't even call Chmod() on it). Creating it
through FTP solves this problem.
Apache can be setup to follow, not follow, and change the owner id of
symlinks. Since you said symlinks are apparently working, I don't
think it matters which you choose in this case.


Thanks.

Cheers,
Nicholas Sherlock
Feb 13 '06 #14
Jasen Betts wrote:
On 2006-02-12, Jerry Stuckle <js*******@attglobal.net> wrote:
Andy Hassall wrote:
On Sat, 11 Feb 2006 16:56:08 -0500, Jerry Stuckle <js*******@attglobal.net>
wrote:

Jasen Betts wrote:
>On 2006-02-11, Jerry Stuckle <js*******@attglobal.net> wrote:
>
>
>
>>Why not just include() the file?
>
>not reccomended for binary files - they might have <? in them somewhere...

He didn't say the were binary files.

And even if they were, he'd have exactly the same problem with
readfile() - which he is currently using.
No, readfile() doesn't execute the file as PHP. include() does. They're very
different..


Please read the original post. He is not outputing a php file. It is
text - and would not be executed.

php files are (usually) text files...
With include() it would be executed if it contained php tags.
The .php filename extension is only significant to the web server.


That's true. But this is NOT php code. This is plain text.

Get me a newspaper and show me where articles have tags such as <?php in
them. Or any other plain text file not about PHP.

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
js*******@attglobal.net
==================
Feb 13 '06 #15
On 2006-02-13, Jerry Stuckle <js*******@attglobal.net> wrote:
Jasen Betts wrote:

php files are (usually) text files...
With include() it would be executed if it contained php tags.
The .php filename extension is only significant to the web server.


That's true. But this is NOT php code. This is plain text.

Get me a newspaper and show me where articles have tags such as <?php in
them. Or any other plain text file not about PHP.


If you can guarantee that the files will never contain
and you (or other resposible people control the content <?php (etc) that'd
work... but it still seems like a problem waiting to happen to me.

Bye.
Jasen
Feb 13 '06 #16
On Sat, 11 Feb 2006 20:13:59 -0500, Jerry Stuckle <js*******@attglobal.net>
wrote:
Andy Hassall wrote:
On Sat, 11 Feb 2006 16:56:08 -0500, Jerry Stuckle <js*******@attglobal.net>
wrote:
Jasen Betts wrote:

On 2006-02-11, Jerry Stuckle <js*******@attglobal.net> wrote:
>Why not just include() the file?

not reccomended for binary files - they might have <? in them somewhere...

He didn't say the were binary files.

And even if they were, he'd have exactly the same problem with
readfile() - which he is currently using.


No, readfile() doesn't execute the file as PHP. include() does. They're very
different..


Please read the original post. He is not outputing a php file. It is
text - and would not be executed.


PHP code _is_ text.

What advantages does include() have over readfile() that makes you suggest it?

It's dangerous and doesn't solve the problem in the original post (which
doesn't actually say anything about what's in the files, or even whether
they're "text" or "binary").

--
Andy Hassall :: an**@andyh.co.uk :: http://www.andyh.co.uk
http://www.andyhsoftware.co.uk/space :: disk and FTP usage analysis tool
Feb 13 '06 #17
Andy Hassall wrote:
On Sat, 11 Feb 2006 20:13:59 -0500, Jerry Stuckle <js*******@attglobal.net>
wrote:

Andy Hassall wrote:
On Sat, 11 Feb 2006 16:56:08 -0500, Jerry Stuckle <js*******@attglobal.net>
wrote:

Jasen Betts wrote:
>On 2006-02-11, Jerry Stuckle <js*******@attglobal.net> wrote:
>
>
>
>>Why not just include() the file?
>
>not reccomended for binary files - they might have <? in them somewhere...

He didn't say the were binary files.

And even if they were, he'd have exactly the same problem with
readfile() - which he is currently using.

No, readfile() doesn't execute the file as PHP. include() does. They're very
different..
Please read the original post. He is not outputing a php file. It is
text - and would not be executed.

PHP code _is_ text.

What advantages does include() have over readfile() that makes you suggest it?


It solves the problem he's having - timeout of the PHP script when
downloading large files.
It's dangerous and doesn't solve the problem in the original post (which
doesn't actually say anything about what's in the files, or even whether
they're "text" or "binary").


Sure it does. And the original post intimated they are text files -
because they are serverd with readfile().

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
js*******@attglobal.net
==================
Feb 14 '06 #18
On 2006-02-14, Jerry Stuckle <js*******@attglobal.net> wrote:
Sure it does. And the original post intimated they are text files -
because they are serverd with readfile().


text/binary makes no difference on unix systems.

<?php
header("Content-type: image/gif");
readfile("example.gif");
?>

Bye.
Jasen
Feb 14 '06 #19
Jasen Betts wrote:
On 2006-02-14, Jerry Stuckle <js*******@attglobal.net> wrote:

Sure it does. And the original post intimated they are text files -
because they are serverd with readfile().

text/binary makes no difference on unix systems.

<?php
header("Content-type: image/gif");
readfile("example.gif");
?>

Bye.
Jasen


Yes, I know there's no difference between text and binary on Linux.
I've probably been using Unix a lot longer than you - and longer than a
lot of people here have been alive.

However - again, he didn't say he was outputting gif's, jpegs or
whatever. Nothing at all about it.

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
js*******@attglobal.net
==================
Feb 14 '06 #20
Please note that include() does not reset or otherwise prevent the
limit on script execution from being enforced (other things can: system
calls, sleep, etc, but include itself is not one of them).

Aside: Including and executing unknown data would open up a potentially
serious security vulnerability. That would be a Bad Thing (tm).

Additional Aside: include() is for including php code, using it in any
other manner would be bad form.

Feb 14 '06 #21
Richard Levasseur wrote:
Please note that include() does not reset or otherwise prevent the
limit on script execution from being enforced (other things can: system
calls, sleep, etc, but include itself is not one of them).

Aside: Including and executing unknown data would open up a potentially
serious security vulnerability. That would be a Bad Thing (tm).


To be clear here, I'm serving user uploaded binary files, so Include()
would indeed be the kiss of death for my whole website.

Cheers,
Nicholas Sherlock
Feb 14 '06 #22

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: John Dalberg | last post by:
With ftp, username and password are transmitted in clear text. I would like to send files using ftp programmatically in a secure way. What's the best way to do this? -- John Dalberg
5
by: Guadala Harry | last post by:
What are my options for *securely* storing/retrieving the ID and password used by an ASP.NET application for accessing a SQL Server (using SQL Server authentication)? Please note that this ID and...
0
by: va | last post by:
I love Web Apps in ASP.NET 2.0 because you can easily deny users access to pages by role or user. But for desktop client to webservice methods, I am not sure what to do.... I am looking for...
2
by: ek1 | last post by:
Hi, I need a method in which to store data securely on windows XP/2003 using C#. By secure I want to a) prevent user reading and changing the data and b) prevent user copying over data I...
3
by: Prash | last post by:
IIS serving javascript files, gives me error 4/21/2006 6:48 AM Guys/Gals, I am using IIS as a server to serve the javascript files. But it is giving me the error as "Object doesn't support this...
0
by: Daniel Di Vita | last post by:
I have three separate applications setup on an IIS server. Let’s call them AppA, AppB, and AppC. On AppA (the Default application) the user is presented with a login window. The login information...
2
by: David T. Ashley | last post by:
I've used Apache with the automatic directory indexes ... works great ... just click on the file name and IE magically figures out how to display it .... if it is a .PDF then Adobe Acrobat runs,...
3
by: Sander Tekelenburg | last post by:
Situation: I store news articles as individual PHP files. Each file contains HTML and now and then some embedded PHP snippets. Serving those news articles on the Web works fine, through...
5
by: xkenneth | last post by:
Hi All, I'll shortly be distributing a number of python applications that use proprietary. The software is part of a much larger system and it will need to be distributed securely. How can i...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.