Thanks in advance.
You already have 95% of work done. Now...
Can you use these credentials to protect directories? No, you cannot, as
far as I know. PHP will never handle the directory listings created by
Apache, JPEG files, PDF files, etc.
Can you use these credentials to protect PHP files? Sure. This simpliest
way:
<?
if( !isset($_SESSION['authenticated_user_id']) || $_SESSION['authenticated_user_id']!=666 ){
die('Unauthorized');
}
?>
> How do I protect an authenticated user's files and/or directories?
The typical option is moving them outside the public web directory, where
they cannot be served by Apache. Then do not link the files, link a
download script written in PHP.
--
-+ Álvaro G. Vicario - Burgos, Spain
+- http://www.demogracia.com (la web de humor barnizada para la intemperie)
++ Manda tus dudas al grupo, no a mi buzón
-+ Send your questions to the group, not to my mailbox
--
So that's how it's done. Thanks for the tip.
Here's what I've tried:
The link in the secure (SSL-encrypted) page looks like this:
<a href='../../dlcounter.php?file=somefile.zip|username'>somefile.zip</a>
[dlcounter.php]
$dlfile = trim($_GET[file]);
$dlfile = explode("|", $dlfile);
switch ($dlfile[1])
{
case "thisuser":
$dlpath = '/home/myispacct/thisuser/'.$dlfile[0];
break;
case "thatuser":
$dlpath = '/home/myispacct/thatuser/'.$dlfile[0];
break;
case "otheruser":
$dlpath = '/home/myispacct/otheruser/'.$dlfile[0];
break;
default:
$dlpath = 'http://www.mysite.com/PublicDownload/'.$dlfile[0];
}
[code to record download user and time goes here]
echo $dlpath;
So far so good. But how do I start the download? I hope this is not too
silly a question...
Just be aware that it's awfully easy to rewrite the URL. Get the username
when you validate the user and keep it in a variable session.
> $dlpath = 'http://www.mysite.com/PublicDownload/'.$dlfile[0];
[...]
> So far so good. But how do I start the download?
readfile() will do the trick. You can additionally generate the appropriate
content type header with header('Content-Type: ......').
> I hope this is not too silly a question...
Of course not :)
So, would you suggest something like this:
<a href='../../dlcounter.php?file=$_SESSION['uid']>somefile.zip</a>
The problem with using the session variable is that the session is lost when
going from the SSL-encrypted private user page to the dlcounter.php script.
Is it possible to reference the script like this:
https://www.mysite.com/dlcounter.php
But then the script would have to be in a publicly-accessible area. Is that
a problem?
> readfile() will do the trick. You can additionally generate the
appropriate
> content type header with header('Content-Type: ......').
That's the ticket! Thanks! I got it working with this (stripped down
version of dlcounter.php):
<?php
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=test.txt" );
readfile("/home/myispacct/secure/test.txt");
?>
One more question:
Is is better to use:
header("Content-Type: application/force-download")
or
header("Content-Type: application/octet-stream");
?
I also tried this:
<a href='https://hostname.myisp.com/myacct/dlcounter.php'>somefile.zip</a>
The SSL state appears to be preserved as it goes to dlcounter.php, but I
can't get the SESSION variable value. If I put this in dlcounter.php:
echo $_SESSION['uid'];
exit;
Nothing is echoed on the screen.
I set $SESSION['uid'] on the login page:
$_SESSION['uid'] = $user;
$url="https://hostname.myisp.com/myacct/someuser/privatepage.php";
header('Location: '.$url); //redirect to privatepage.php
echo $_SESSION['uid'] will return the correct value on privatepage.php - but
not on dlcounter.php. Is there some reason why the variable is lost when
clicking on the link in privatepage.php? Do I need to set another Session
variable for the purpose of secure downloading?
oops...
session_start();
echo "SESSION[uid] = ".$_SESSION['uid'];
exit;
now it works :)
---link in privatepage.php---
<a
href='https://hostname.myisp.com/myacct/dlcounter.php?file=test.zip'>test.zi
p</a>
---code in dlcounter---
<?php
session_start();
$dlfile = trim($_GET[file]);
switch ($_SESSION['uid'])
{
case "someuser":
$dlpath = 'home/myacct/someuser/'.$dlfile;
break;
default:
$dlpath = 'http://www.mysite.com/PublicDownload/'.$dlfile;
}
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=".$dlfile);
readfile($dlpath);
The download dialog appears, but the download fails becuase path to the file
is getting screwed up. In the File Download dialog, the File Name appears
not at "test.txt", but as a url to dlcounter.php. Perhaps this is because
it's looking for a SSL-encrypted path? How to get it to go to the correct
path? Is this possible when connecting to an SSL-encrypted dlcounter.php?
Thanks again for the help.
I would suggest NOT doing so. What prevents me from typing any username in
my browser's location bar?
> The problem with using the session variable is that the session is lost when
> going from the SSL-encrypted private user page to the dlcounter.php script.
Then transmit the session ID in the URL when moving to SSL zone. Check
this:
http://es.php.net/manual/en/function.session-id.php
Or you can also use SSL since login.
I'll try to explain myself better. The problem is that you can't password
protect directories. So we've moved files outside the web server root and
we are using a script to download them. If your script loads files from
within the web server root, we're doing nothing! Your users can override
the script and point their browsers to the actual URL. You want your script
to read from the *file system*, from a directory that's hidden to browsers.
10-4.
> > The problem with using the session variable is that the session is lost
when
> > going from the SSL-encrypted private user page to the dlcounter.php
script.
>
> Then transmit the session ID in the URL when moving to SSL zone. Check
> this:
>
> http://es.php.net/manual/en/function.session-id.php
>
> Or you can also use SSL since login.
That would be the best solution, I think.
I understand. In the code snippet above, I switch on user ID - if the user
ID is not set, then the default is to download from the publicDownload
directory. if the user ID *is* set, then /home/myacct/someuser/ is a
directory outside of public_html.
What I'm tying to do (which may be a mistake) is to use the same download
script to log public downloads as well as private downloads. To so this, I
need to pass variables into the script. I was thinking I would pass in the
file name and the user name. But apparently, anyone can send variables into
the script, and potentially guess what the username and/or file is. So I'm
thinking the download script for private files needs to be embedded in the
private, SSL-encrypted page where the links to the private files are. I
will keep working on this...
Thanks again for the help. Your comments have helped a lot.
Yep, you're right, I read the code too quickly. You miss a leading / but
the rest seems okay.
> What I'm tying to do (which may be a mistake) is to use the same download
> script to log public downloads as well as private downloads.
The approach looks good to me.
--
-+ Álvaro G. Vicario - Burgos, Spain
+- http://www.demogracia.com (la web de humor barnizada para la intemperie)
++ No envíes tu dudas a mi correo, publícalas en el grupo
-+ Do not send me your questions, post them to the group
--