Link to home
Start Free TrialLog in
Avatar of dmehran
dmehranFlag for United States of America

asked on

redirecting to a folder that does not have public access privilage

Hi, I am trying to set up the following functionality for a website that provides music lessons in the form of video and audio lessons:

Members of the site will login to their account using their un/pw set. Once they login, they can purchase individual lessons and of course a database keeps track of the lessons that this individual has purchased.

Now here is the part that I have problem with and I am hoping that it is possible to do the following: What I like to do is to have these video and audio files residing in a folder with no public access privilege (only owner and group privilege). This way no one can access these files by directly typing the video file address on their browsers and accessing them directly. Meanwhile members who log into their accounts should be able to click on a link in their member area and view the lessons that they have paid for.

thanks in advance
ASKER CERTIFIED SOLUTION
Avatar of Kooroo
Kooroo
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of gruntar
gruntar

This is the right way to do it as Kooroo said. since you're selling stuff you should check;

- if user is logged in (so that you prevent downloading if someone clicks on download.php and is not logged in)
- if user payed for the file that he want to download.

if those two criteria are fulfiled than you output file to download otherwise show error message.

cheers
Kooroo's solution is the core part of how you deliver the file to the user via PHP.
1.  The look of this can be significantly improved however by using the rewritemod in htaccess (assuming you are using apache).

the core file is still Kooroo's variant,
you just would place the following in a directory called "/lessons/"
beneath the web root:

.htaccess:

ReWriteEngine On
RewriteRule ^/?([^/]*\.pdf?|[^\./]*)[:;,\.]*$ /download.php [L,NS]

This in turn would translate any request for a pdf (alter the file type freely)
into a call to the download.php script...


within the script, you can then look at the $_SERVER['REQUEST_URI'] variable to determine the file they are looking for,
download it exactly how Kooroo suggested.
I think that the above is perhaps not the best approach. Rather that accepting a POST with the correct username and password, you should FIRST have a page where the user login details are sorted out, for example the following:

<?php
session_start();

$sql="SELECT password FROM users WHERE username=".mysql_escape_string($_POST['username']);

$res = mysql_query($sql);

if(mysql_num_rows($res)){
    $row=mysql_fetch_assoc($res);
    if($row['password'] == md5($_POST['password'])){
        $_SESSION['loggedin']=1;
        $_SESSION['username']=$_POST['username'];
        print("Please proceed to the <a href="download.php">download page</a>");
    }else{
        die("Password was incorrect");
    }
}else{
    die("Unknown username");
}

?>

Now, the above page will set a SESSION variable which records you current username and the fact that they have logged in. On the download page, you can now show a list of the products which your user has paid for (I won't cover that part here), and you can then provide access to those files only. The user won't have to type in their username and password every time they download a file.

--------------- download.php -------------------
<?php
session_start();
define("DOWNLOAD_DIR","/var/local/download/audiovideodownloaddirectory");

$action="list";
if(isset($_GET['action'])){

$sql="SELECT filename FROM useraccessrights WHERE username=".$_SESSION['username'];
$res=mysql_query($sql);
if(!mysql_num_rows($res)){
    die("You have no entitlements");
}




woops! more to come...

--------------- download.php -------------------
<?php
session_start();
define("DOWNLOAD_DIR","/var/local/download/audiovideodownloaddirectory");

$action="list";
if(isset($_GET['action'])){
   $action=$_GET['action'];
}

switch($action){
    case "list":
         $sql="SELECT filename FROM useraccessrights WHERE username='".$_SESSION['username']."'";
         $res=mysql_query($sql);
         if(!mysql_num_rows($res)){
              die("You have no entitlements");
         }
         while($row=mysql_fetch_assoc()){
             print("<a href=\"?action=fetch&file=".urlencode($row['filename'])."\">".htmlspecialchars($row['filename'])."</a><br>");
         }
         break;
   
    case "fetch":
        $sql="SELECT mimetype,filename FROM useraccessrights WHERE username=".$_SESSION['username']." AND    
               filename='".mysql_escape_string($_GET['filename'])."'";
        $res=mysql_query($sql);
        if(!mysql_num_rows()){
            die("Sorry, access denied");
        }
        $row=mysql_fetch_assoc($res);
        header("Content-Type: ".$row['mimetype']);
        header("Content-Disposition: attachment; filename=".$row['filename']);
        readfile(DOWNLOAD_DIR."/".$row['filename']);
}

?>

This last file does the job of checking that the user is logged in and then checking that they have the rights to access the file in question. The files are stored in a configurable directory of your choosing - off the DocumentRoot, so it's not publically accessible.

Does that help? I can give you the database structure if required.

JP


Avatar of dmehran

ASKER

Hello again and sorry for the late reply. First, thanks for the elaborate explanation and the tips as well as answers from the rest of experts. With a little variation of your solution I got it to work. I changed the MIME type setting from  ... "application/force-download" like kooroo suggested to the following:

header("Content-Type: video/x-ms-wmv");

above changes allows for the user to play the video from the server while downloading it. I had already made use of session variables like the example that 'jdpipe' provided and I didn't have problem setting up the database and verifying/authenticating the user before giving privilege for accessing the video files that are in windows media format.

Ideally it would have been nice if I could come up with an affordable way of preventing the user from downloading the files to their machine and only have them play the video files staight from the server everytime (without being able to download the file).


thanks again
I think that a good way to prevent downloading is to use a flash-based video player. Methods which use RTSP etc are still problematic.
JP
Avatar of dmehran

ASKER

good point 'jdpipe', as a matter of fact I started experimenting with flash video about 2 or 3 weeks ago and I am converting all my .wmv files to .flv formats. It is a lot of work but it does the job.

thanks
dmehran