Forum Moderators: coopster

Message Too Old, No Replies

access pdf only when logged in

how to limit access to pdf to users

         

weddingm

10:17 pm on Apr 22, 2009 (gmt 0)

10+ Year Member



Hello,

I want to sell an ebook. I only want people to have access to the pdf who are logged in. I understand the philosophy behind limiting access to a php page with php code. But how do you limit access to a pdf file to those who have logged in?

Thanks,
Matt

rocknbil

10:59 pm on Apr 22, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



In a nutshell (sorry for the cliche,)

- user logs in, every request to your script validates user.
In the logged in area, you output your list index from database entries. An example might be

id.¦.record_id.¦.filename.....¦..title
1..¦.12373.....¦.myfile.pdf...¦..PDF 1
2..¦.34534.....¦.yourfile.pdf.¦..PDF 2

So you output

<ul>
<li><a href="members.php?file=12373">PDF 1</a></li>
<li><a href="members.php?file=34534">PDF 2</a></li>
</ul>

So when clicked, you validate again, so non-logged in users can't access it.

- Open the db, find the corresponding entry,

12373=myfile.pdf

- print a PDF header:

header("content-type: application/pdf\n\n");
Check this mime type, I'm typing off the top of my head, it may be incorrect.

- Using one of the many file open methods, you open the file myfile.pdf from a secure non-public location on your server.

- form a while loop inside the open command, print it to the browser.

AndrewCF

2:23 am on Apr 23, 2009 (gmt 0)

10+ Year Member



If your member area uses HTTP Auth with Apache, you can simply modify the .htaccess file.

If you use PHP Script Auth, follow the rocknbil's method. :)

weddingm

5:04 am on Apr 23, 2009 (gmt 0)

10+ Year Member



awesome, thanks

weddingm

7:18 am on Apr 25, 2009 (gmt 0)

10+ Year Member



Just can't quite get it to work.

I am doing the following in the body of the web page


<?php
if ($xfield!== NULL)
{
$sqlzz="SELECT * FROM table";
$resultzz = @mysql_query( $sqlzz, $connection );

while ($rowzz = mysql_fetch_array($resultzz))
{
$bookname = $rowzz['title'];
$efilename = $rowzz['filename'];}

print "<a href='http://www.sample.com/".$efilename."'>".$bookname."</a>";

header("Content-type:application/pdf");

// It will be called downloaded.pdf
header("Content-Disposition:attachment;filename='".$efilename."'");

// The PDF source is in original.pdf
readfile("http://www.sample.com/".$efilename."");

$fpp = fopen($efilename,"r");
while (!feof($fpp)) {
$buff = fread($fpp,4096);
print $buff;}
}
?>

Thanks,
Matt

weddingm

7:28 am on Apr 25, 2009 (gmt 0)

10+ Year Member



Actually, it works but it clocks forever.

rocknbil

4:22 pm on Apr 25, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I see three things wrong (and a small fourth - since on download you're getting only one record, you do not need while, use if instead, and make sure you have a conditional to manage it if nothing is found.) Might not be all of it, but start with those.

1. You're mixing the two processes. When you generate the page, you want to do ONLY
a. Select all PDF records and generate the link list.
b. Output the list.

The download part should be a separate process. You can do it all in the same script with if/else if/switch conditionals, or two separate scripts, if it works better for you.

The "changes" below are relevant only to the download process.

2. Your while buffer contains the print, all you're getting is the title and file name, close that first, end the mysql query.

3. You're trying to read the file via http, and it should be local, this is the whole point - see my comments in the code below:


<?php
//See comment below
$full_path = '/full/local/server/path/to/non-public/pdf/directory/';

$efilename=NULL; // squelches variable not defined errors if no records found
if ($xfield!== NULL) {
// Not sure if this is correct, but it should be
// some record id - see initial reply
$sqlzz="select filename from table where unique_id=1234";
$resultzz = @mysql_query($sqlzz);
if ($rowzz = mysql_fetch_array($resultzz)) {
// See point #2 above, I don't think there's a need for book name here
$efilename = $rowzz['filename'];}
}
// Close the query, free the memory, what happens if it's blank?
mysql_free_result($resultzz);
if (is_null($filename)) { die{"Oops! No file name!"); }

// It will be called downloaded.pdf
// No - it should be called $filename, if it's
// not, something is going wrong here

//header("Content-type:application/pdf");
// You need to make a choice here. Either you want to display
// the PDF, in which case the previous header is all you need, or
// want to download the file as an attachment, in which
// case the following will work. To force a download,
// which seems to be more difficult for people, you need a few
// other things. I'm leaving this enabled, but
// experiment with both so you know how to manage it.
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.$filename);
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize("$full_path/$efilename"));
// The PDF source is in original.pdf
//readfile("http://www.sample.com/".$efilename."");
// The previous contains a quoting error, (i think,
// or just the two quotes "" are not needed)
// and the whole point is to output a file
// from a non-public location. Use the
// full local server path to open this file
// see line #2 in the code above.

$fpp = fopen("$full_path/$efilename","r");
while (!feof($fpp)) {
$buff = fread($fpp,4096);
print $buff;
}
// This is probably why it's not ending.
// if you don't close the filehandle,
// it won't flush the last buffer
fclose($fpp);

} // end if $xfield
//ALWAYS provide for "what if it doesn't work?"
else { die("OOPS no value for whatever is in $xfield"); }

?>