Log in

View Full Version : password protected link which leads to different files



HTMLentrant
07-15-2011, 11:32 PM
Hi guys,

I was wondering if there's a way to make the same link to different files.
the catch is that once you've clicked the link a little pop up (in the same page) box asks you for a password (without a username or something like that). different passwords lead you directly to different pdf files (files are not in the same folder).

I've tried to explain that to people but most of them didn't quite understand me:


1 link --> password1 ----> file1.pdf
password2 ----> file2.pdf

The password box will have two buttons: submit and cancel.
needless to say these passwords either encrypted or concealed in the HTML.
I saw there was a script generator and also .htaccess generator but it was a
little bit complicated and not sure it meets the description above. Maybe I'm wrong. anyways,, HELP :) any ideas?

Thanks,
Johnny

jscheuer1
07-15-2011, 11:51 PM
Is PHP available on your host?

djr33
07-16-2011, 12:15 AM
There are a few ways to approach this, but you will need a serverside language. PHP is one option (a good one, in my opinion), or ASP, CGI, JSP, and various others could do the same thing. You could also approach this using .htaccess and mod_rewrite alone, but that's unnecessarily complicated, I think.

There are a few options, depending on how complicated you'd like to make it.

Do you intend to hide the real URL for the files? Can a user who has the right password then have the direct link (and potentially share it with others)?

You can just use a forwarding script. In fact, this could be done even using only Javascript, if you really want a very basic (no security) process, except that they do need to know the URL for the file.
Here's a script to look at as a concept:
http://www.dynamicdrive.com/dynamicindex9/password.htm


If the security is designed to be in users not knowing the password, then that or a similar serverside method should be fine. If you need this to be secure and a link (and password?) that users cannot share with each other, then it gets complicated. Look into user accounts.

Generally, I'm not sure you're approach this in the only way that would work, and not necessarily in the best way. There's nothing wrong with it, but figure out what your requirements are, then think about the technical issues. And go with what's easiest for your goals.

jscheuer1
07-16-2011, 12:32 AM
If you have PHP, this works (just tried it out after tweaking it for multiple passwords). It's a stand alone page and needs to be, though it could perhaps be tweaked and/or combined with javascript to be a part of larger page:


<?php
$passwords = array('joesentme' => 'http://www.google.com/', 'bobsyeruncle' => 'http://www.dynamicdrive.com/');
$thePass = isset($_POST['txtPassword'])? $_POST['txtPassword'] : '';
if (array_key_exists($thePass, $passwords)){
header('Location:' . $passwords[$thePass]);
die();
} else {
?>
<title>Login for Files</title>
<h1>Login for Files</h1>

<form name="form" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">

<p>Password:
<br><input type="password" title="Enter your password" name="txtPassword"></p>

<p><input type="submit" name="Submit" value="Login"></p>

</form>

<?php
die();
}
?>

This is the line to edit to get your passwords and files as you may want them:


$passwords = array('joesentme' => 'http://www.google.com/', 'bobsyeruncle' => 'http://www.dynamicdrive.com/');

The red ones are the passwords and the green ones are the files to go to. You can actually have as many pairs of these as you might like.

HTMLentrant
07-16-2011, 07:00 AM
Hi guys,

Well first of all thank you both for your quick reply :)

At first I wasn't really sure about using PHP since it's supposed to be part of a larger page but I thought I'd give it a try.

The (main) page already contains JQuery and in order to "create" that pop up box I use the script "Colorbox" (which I'm using anyway on my page for other things).
The point is to stay in the same page and once you hit the login button (like in John's php) you'd be downloading the file directly and return to the same page you were.

"Colorbox is like a "Lightbox", when you click on the "black areas" it fades away to the same original page you were.

So, I saved John's php as an external PHP page and in the main page put it as part of 'class' and it worked fine but the problem is once you put the password it redirects you to a different (outside) page even if it's a specific file, instead of downloading the file (or perhaps getting the Save As window).

Daniel, the idea of all that is to have two different passwords and each person will get a password.
If someone has been given a password to a certain file I wouldn't want him/her to have access to the other file.
It's not gonna be mega secured because I believe those people I'm talking about will not go through viewing the source html and by putting it in a 'class' it's sort of "hiding" the direct URLs even if they have the right password.
By the way, thanks for the link. I've tried it too.

John, Thanks for the great PHP! Is there a way to tweak it even more to what I've described? If so, I'm pretty sure it'll do the trick
Plus, I have tested it and if I click Login without any password it redirects me to the actual php page with the link shown in the address bar and I'd like it to stay within the Lightbox borders. Is that possible?
In other words, in case of wrong password it'll generate a message in the same php page "invalid password" and if someone tries to login without entering a password it'll generate a message saying "password required" and of course it'll stay in the same Lightbox ("Colorbox") borders without redirecting.

Thanks again
Johnny

jscheuer1
07-16-2011, 12:45 PM
OK, if you already use jQuery and ColorBox (with which I'm fairly familiar), it means that if you are using an ordinary link as is usually the case, those with javascript disabled will be taken to the login page, where - also with javascript disabled, unless you have something server side like PHP, they will never be able to get any file.

Incidentally, this would probably work best with ColorBox's iframe mode. Using it's AJAX import might be able to work, but I'm not certain of that. Headers could no longer be employed with AJAX, at least not in the exact way as used in my demo.

We can set it up so that either they need javascript to even see the link or so that things work out acceptably, though less fancily for them when they click it. In the first case you can substitute text that tells them to enable javascript.

Which way we go on that would depend to a degree upon whether or not the rest of the site can function without javascript - no sense making this one feature non-javascript friendly if all the rest of the site is useless or seriously impaired when viewed without javascript.

Back to popping up the PHP page with ColorBox - instead of using a header to switch to the PDF file, which as you know will load the PDF into the ColorBox popup, we could use PHP code to actually pop up the user's browser's open/save dialogue.

We can arrange for various things to happen on wrong password or blank password. By adding a hidden form input we can tell if our PHP page is being submitted or just accessed. If there is no password, but is this hidden value, it has been submitted with a blank password so we can add the 'Password Required' text to the page at that point. If there is a password, and its wrong, we can either use the header at that point to redirect to another page, or to add a 'Password Incorrect' message, still giving them the opportunity to try again. If they have one of the valid passwords we can either load the PDF into the ColorBox, or pop the open/save dialogue, while closing the ColorBox or not, or load the PDF into the main window.

The non-javascript options would be the same, except the user would be looking at the PHP page in their main window from the moment they click on the link. They would then get that same treatment within that main window, needing their back button or a link on the PHP page to get back to the main page. We can even detect lack of javascript on submit and throw them back to the main page after doing whatever we choose to do, if the main page is also PHP, messages could appear there for them.

However, in all of its various permutations, this is pretty complex, so I would need some time to work it all out. And I need to know:


Do we even need a non-javascript pathway?
Is this in fact using the ColorBox iframe option?
Do we want a wrong password to redirect, or just add a message to the PHP page?
Do we want the PDF to appear in the ColorBox, the main window, or pop the open/save dialogue?
If we pop the dialogue, should the ColorBox close or not?

HTMLentrant
07-16-2011, 06:00 PM
Hi John,

I read your post not sure I got it all right and understood but one thing for sure I really really appreciate your willingness to help :)

As for your questions:


Do we even need a non-javascript pathway?
This one is a tough one cause I don't know the answer. I've never had javascript problems before. nor my friends or even co-workers. my guess is we don't need a non-javascript pathway but then again I hope I understand the meaning of a non-javascript pathway :)

Is this in fact using the ColorBox iframe option?
iframe can work too only if it's part of Colorbox. otherwise it looks distorted
if it's used in the main larger page due to different browsers.

Do we want a wrong password to redirect, or just add a message to the PHP page?
No redirections. just adding a message in the same page otherwise it closes the Colorbox and goes to the original page or even outside the website.

Do we want the PDF to appear in the ColorBox, the main window, or pop the open/save dialogue?
Once we put the right password an open/save dialogue will pop and once you click your preferable choice (save/open) hopefully Colorbox will be closed back to the original page since it served its purpose.


Thanks a million,
Johnny

jscheuer1
07-19-2011, 02:29 PM
A non-javascript pathway is for people without javascript enabled. For them colorbox won't open, and they will be taken directly to the login page where they could still download the file if they have the correct password, things just wouldn't be as neat and tidy. I don't have that fully worked out yet, but I think it's possible from some of the things that happened when I was building the javascript assited version with colorbox.

So I've got a working demo on my local PHP server. I don't have access to a live PHP server at the moment , so I'll give you the files. I used ColorBox v1.3.16 and from the demo archive example1 I changed its example7 link:


<a class='example7' href="http://google.com">Outside Webpage (Iframe)</a>

to:


<a class='example7' href="index_3.php">Login (Iframe)</a>

Here's the code for index_3.php:


<?php
$passwords['joesentme'] = '/server/pdf/pdf_1.pdf';
$passwords['bobsyeruncle'] = '/server/pdf/pdf_2.pdf';
$thePass = isset($_POST['txtPassword'])? $_POST['txtPassword'] : '';
$approved = false;
?>
<!DOCTYPE html>
<html>
<head>
<title>Login for Files</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

<?php
if (array_key_exists($thePass, $passwords)){
$approved = true;
?>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/javascript">
jQuery(function($){
$('body').append('<iframe style="display: none;" src="download.php?txtPassword=<?php echo $thePass; ?>" width="0" height="0" scrolling="auto" frameborder="1"></iframe>');
setTimeout(function(){parent.jQuery.colorbox.close();}, 3000);
});
</script>

<?php
}
?>
<style type="text/css">
#required, #wrong {
color: red;
font: bold 90% sans-serif;
}
</style>
</head>
<body>

<h1>Login for Files</h1>

<form name="form" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<p>Password:
<br><input type="password" title="Enter your password" name="txtPassword"></p>
<script type="text/javascript">
document.write('<input type="hidden" name="scripted" value="scripted">');
</script>
<p><input type="submit" name="Submit" value="Login"> <input type="reset" value="Reset"><br><?php
if(!$approved and isset($_POST['Submit'])){
if( $thePass == ''){
echo ' <span id="required">Password Required!</span>';
} else {
echo ' <span id="wrong">Incorrect Password!</span>';
}
} ?><span>&nbsp;</span>
</p>

</form>
</body>
</html>

<?php
die();

?>

The highlighted is where you configure the passwords and files. For added security I placed mine off the parent of the root where they're inaccessible to the browser without the use of these PHP scripts. They can be anywhere on your server.

Also pay attention to the use of jQuery:


<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>

For best results this will point to the same copy of jQuery as is used by the top page, but that's a fine point. It will simply help with load time.

Another file in the same folder which is used is download.php:


<?php
$passwords['joesentme'] = '/server/pdf/pdf_1.pdf';
$passwords['bobsyeruncle'] = '/server/pdf/pdf_2.pdf';
$thePass = isset($_REQUEST['txtPassword'])? $_REQUEST['txtPassword'] : '';
if (array_key_exists($thePass, $passwords)){
$fullPath = $passwords[$thePass];

if ($fd = fopen ($fullPath, "r")) {
$fsize = filesize($fullPath);
$path_parts = pathinfo($fullPath);
$ext = strtolower($path_parts["extension"]);
switch ($ext) {
case "pdf":
header("Content-type: application/pdf"); // add here more headers for diff. extensions
header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\""); // use 'attachment' to force a download
break;
default;
header("Content-type: application/octet-stream");
header("Content-Disposition: filename=\"".$path_parts["basename"]."\"");
}
header("Content-length: $fsize");
header("Cache-control: private"); //use this to open files directly
while(!feof($fd)) {
$buffer = fread($fd, 2048);
echo $buffer;
}
}
fclose ($fd);
}
die();
?>

You have to configure the passwords and files in it as well.

That's it, try it out and let me know.

When I have the time, I'll be playing with the non-javascript version and tightening up the code.

HTMLentrant
07-20-2011, 12:29 AM
It looks fantastic, John!

I did everything you said and it worked fine.
I've tested it on several browsers; Surprisingly, I only had problems with Chrome & IE9. After entering the correct password it won't download the file.
It worked well with FF & Safari (also IE7 but the "trick" there is to enter the correct password, then a yellow IE security pops up, repeat the download procedure again with the correct password and then the open/save dialogue pops up).

I must say there is one interesting thing that happens in every browser I've tested.
Once you enter the correct password; I guess, it goes to download.php (which is blank, design wise) and then it goes back to index_3.php, stays on it for several seconds and only then it dissolves/fades out to the original page like in Colorbox.
Is there a way to skip the return to index_3.php after you enter the correct password? it's kinda misleading.

By the way, I saw there's an option to add more download extensions at the header (download.php).
I've only tried out the PDF but I guess it won't matter if I add there also doc & docx extensions. right?

PS- Also wanted to thank you for taking the time to play with the non-javascript version.

jscheuer1
07-21-2011, 04:52 PM
The last question first. I lifted the download code from:

http://www.dynamicdrive.com/forums/showthread.php?t=63292

post #5 in that thread. It would probably be best to ask about other extensions there. However, in limited testing I've found that the default section works with .pdf, .gif, and .htm. I have my own questions about the code. Like can the a page be loaded on completion? And it looks like the fclose() is outside the conditional where the fopen() is executed, could that be fixed or would that break it? I have others, I should post to that thread.

Anyways, the delay for closing the colorbox is to make sure the download dialogue (activated by a display none iframe) has time to appear. We can put it on the top page, then we can close the colorbox immediately.

Here's the new index_3.php:


<?php
$passwords['joesentme'] = '/wamp/pdf/pdf_1.pdf';
$passwords['bobsyeruncle'] = '/wamp/pdf/pdf_2.pdf';
$thePass = isset($_POST['txtPassword'])? $_POST['txtPassword'] : '';
$approved = false;
if (array_key_exists($thePass, $passwords) and !isset($_POST['scripted'])){
$fullPath = $passwords[$thePass];

if ($fd = fopen ($fullPath, "r")) {
$fsize = filesize($fullPath);
$path_parts = pathinfo($fullPath);
$ext = strtolower($path_parts["extension"]);
switch ($ext) {
case "pdf":
header("Content-type: application/pdf"); // add here more headers for diff. extensions
header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\""); // use 'attachment' to force a download
break;
default;
header("Content-type: application/octet-stream");
header("Content-Disposition: filename=\"".$path_parts["basename"]."\"");
}
header("Content-length: $fsize");
header("Cache-control: private"); //use this to open files directly
while(!feof($fd)) {
$buffer = fread($fd, 2048);
echo $buffer;
}
}
fclose ($fd);
die();
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Login for Files</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

<?php
if (array_key_exists($thePass, $passwords)){
$approved = true;
?>
<script type="text/javascript">
if(parent.jQuery('iframe[name=filetransferiframe]').size() === 0)
parent.jQuery('<iframe name="filetransferiframe" style="display: none;" src="about:blank" width="0" height="0" scrolling="auto"></iframe>').appendTo('body');
onload = function(){
document.forms.form.setAttribute('target', 'filetransferiframe');
document.forms.form.setAttribute('action', 'download.php');
document.forms.form.txtPassword.setAttribute('value', '<?php echo $thePass; ?>');
document.forms.form.submit();
parent.jQuery.colorbox.close();
}
</script>

<?php
}
?>
<style type="text/css">
#required, #wrong {
color: red;
font: bold 90% sans-serif;
}
</style>
</head>
<body>

<h1>Login for Files</h1>

<form name="form" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<p>Password:
<br><input type="password" title="Enter your password" name="txtPassword"></p>
<script type="text/javascript">
document.write('<input type="hidden" name="scripted" value="scripted">');
</script>
<p><input type="submit" name="Submit" value="Login"> <input type="reset" value="Reset"><br><?php
if(!$approved and isset($_POST['scripted'])){
if( $thePass == ''){
echo ' <span id="required">Password Required!</span>';
} else {
echo ' <span id="wrong">Incorrect Password!</span>';
}
} ?><span>&nbsp;</span><noscript><a href="index.html">Return to Previous Page</a>
</noscript>
</p>
<script type="text/javascript">
document.forms.form.txtPassword.focus();
</script>
</form>
</body>
</html>

<?php
die();

?>

I've also added non-javascript code so that a non-javascript user, if they get to the page and have the password can get the file. In that regard, notice the noscript link:


<noscript><a href="index.html">Return to Previous Page</a>
</noscript>

near the end. that should be to the page that (when javascript is enabled) launches the colorbox, or to the page you want non-javascript users to go to after downloading, or attempting to download.

One other addition - focus automatically goes to the password field when the login page is opened. (javascript only)

About the various browsers, I had no problem in any of them, except that with Chrome and IE the dialogue was at the bottom in a different form than I'm used to. But that appears to be the standard way in those browsers. I didn't have to try twice in any of them.

HTMLentrant
07-23-2011, 10:12 AM
It seems like the new index_3.php works great. I haven't fully tested it though.
Will update my post once I have final results regarding several browsers behavior and other file extensions.

I saw your post at the other thread. I also saw someone answered it and I'm not sure how
or where to put it or if it's even relevant to your code (the other guy was talking about downloads module for his jcow social network)
please let me know if they answered your questions cause it is kinda Gibberish to me with my basic HTML. LOL :D