PDA

View Full Version : First project, download problem...


Coreyp_1
07-27-2003, 12:14 PM
Hello, All!

I'm new to PHP, and have a question about downloading files through PHP.

My situation is this: I have a collection of PDF files. I have a database for keeping track of the files, their authors, editors, etc.., and I have a working membership system.

I want to be able to allow members to download the PDF files. Since I use a logical naming convention to name my files (so *I* can keep track of them), I want to keep users from simply figuring out the convention and downloading the files on their own without being logged in as a member.

To remedy this, I encrypted the file names on the server, so that no logical method can be used to infer the file names, and short-circuit my system.

I use a file (download.php) which checks the member status, and, if registered, outputs the PDF headers, and then performs a readfile() from the encrypted file name.

I like this because:
(1.) Even though the file name on the server is encrytped, I can still suggest the correct file name using

header("Content-Disposition: attachment; filename=whatever_i_want_it_to_be.pdf"));

(2.) I can fully control whether or not the PDF will be downloaded, because there is no hope of the user being able to figure out the file name on the server (encrypted).

I was happy with this system until I tried to have two downloads going at once, and it didn't work!

In fact, my site does not respond at all until the download is finished, which means if the PDF is 5 megs, then the user cannot browse other parts of my site in the background while that loads, but has to sit there and wait. Worse yet, I'm afraid that if one user is downloading a file, then my site will be temporarily unavailable to ANYONE else (on the internet) until the download is finished and the script is over (although I cannot test this, seeing as I only have one computer and one internet connection.

I'm aware that I could do a simple redirect using

header("Location:encrypted_file_name.PDF");


but this will not allow me to suggest what the real file name should be (as far as I know);

All of that to get to this: Is there a way to allow multiple downloads using PHP as an intermediary?

This is my first PHP project (aside from simple includes on HTML pages).

Thanks for the help!

cbkihong
07-28-2003, 03:33 AM
Unless you are using an antique and crappy Web server, the Web server should be multi-threaded or at least spawns multiple processes to handle multiple simultaneous incoming connections, so you won't be blocking other people's requests while some incoming requests are being served.

Coreyp_1
07-29-2003, 10:38 AM
Well, I've had some interesting developments.

As I stated earlier, when downloading a file being fed through a PHP script, only one file would download at a time. I did some troubleshooting, and these are the symptoms:

1. Only scripts using sessions are affected. Even if one session script is running (like the download), non-session scripts load flawlessly, as do image and HTML files.

2. When the user is downloading a file from a session script, and attempts to access another session script (while the other is still running), the second script will not begin until the first finishes. If the first script is long (like downloading a large file), then the second script may time out waiting for the first to complete.

So it seems that my problem is that I was using sessions to validate the membership status of the person attempting the download. I re-worked the script to use a query string for the validation information, and all of the problems went away.

Looking back, it makes sense that $_SESSION variables can only exist one script at a time. That way, when one script modifies a session variable, then that updated value will be available to the next script. If the scripts were running concurrently, then "the right hand wouldn't know what the left hand is doing."

That's my theory, anyway. I could not find any documentation, though, as to the behavior of session scripts requested in this way. Does anyone have any other insights? It would have saved several days (and a few gray hairs) if I had known this sooner. ;o)

I have a new problem now, though. My original intention for using sessions was to limit access of the files to members only (who have logged in). Now, I did write a fairly strong encryption/decryption routine so that I can safely pass the username, password, and other necessary information through a query string. This allows the script to validate the request. But how can I make sure that the information not only validates, but that the person accessing the file is logged in as well, using the info from a query string and PHP?

The bottom line is that cookies are out, b/c the user may or may not accept them. I liked using sessions, since they only existed as long as the user was logged in, but (as stated earlier) sessions do not allow multiple scripts to be run simultaneously for a single user.

Does anyone have any ideas as to how I can use the query string and PHP to validate the log-in status of a member?

Coreyp_1
07-30-2003, 12:18 PM
Unfortunately, while that approach is simple and would work, it would defeat the purpose of the system.

SITUATION:
Suppose User X becomes a member of the site. User X is presented with a link protected by said system. Since User X is a member, that link is encoded with his username and password. User X copies the link and places it on his website. Person Z comes along and clicks on the link. The link downloads fine, b/c the link validates with User X's username and password.

Bad.

I am attempting to encode a time stamp and the user's IP into the query string. Then, at the download page, I can assure that the link is no more than one hour (30 minutes, whatever) old, and that the person attempting the download is the same person to whom the link was given.

Not completely fool proof, but it is better than nothing.

Coreyp_1
07-31-2003, 02:19 PM
Got it working now!

As to storing the last login time and server info, I am opting to simply pass it encrypted into the URL.

I could put it into a table as you suggested, but it seems as though that would be unnecessary mysql processing. Then again, I'm having to look up their username and password anyway for validation, so I could store it into the same table and have mysql grab it at the same time.

Flip a coin, I guess. Heads, URL Query String, Tails, mySQL.

I think I'll go with storing it in the query string, simply because I don't want to waste storage space on the server.

Thanks for the input. It really helped to talk out the situation!

Now on to graphical design.... Look out, here I come!:cool: