0

I've been trying to get this to work properly, but I'm getting an infinite redirect when executed. I've done this in the past, but can't remember exactly how I did it (and I've lost my original files a long time ago).

I have an age gate set up to allow only those over 18 to access content. If they come to my top page (index.php) they'll be asked to enter their birthday (mm-dd-yyyy), and if they meet the age, they will be taken to the next page (home.php). If they aren't of age, then they should be direct to a "sorry" page (message.php). And, if for some reason, they go straight to home.php, they need to be redirected to index.php in order to enter their birthday.

So flow: index.php - home.php (if they pass the age gate)

index. php - message.php (if they don't)

home.php - index.php (if they haven't gone through the age gate yet)

home.php - message.php (if they have gone through the age gate, but failed the check, and are trying to see if they can directly access the page)

(extra) file.php - index.php - file.php (if they haven't gone through the age gate, get redirected to index to do so, then be brought back to file.php once they are pass/checked)

Right now, im getting an infinite loop on the home.php (too many redirects)

my code below:

index.php

<?php
session_start();

if ( isset( $_SESSION[ 'legal' ] ) ) { # Check to see if session has already been set
    $url = ( $_SESSION[ 'legal' ] == 'yes' ) ? 'home.php' : 'message.php';
    header( 'Location: ' . $url );
}

// If visitor hasn't gone through the age gate - Age Gate function and Set Session//
if ( isset( $_POST[ 'checkage' ] ) ) {
    $day = ctype_digit( $_POST[ 'day' ] ) ? $_POST[ 'day' ] : '';
    $month = ctype_digit( $_POST[ 'month' ] ) ? $_POST[ 'month' ] : '';
    $year = ctype_digit( $_POST[ 'year' ] ) ? $_POST[ 'year' ] : '';

    $birthstamp = mktime( 0, 0, 0, $month, $day, $year );
    $diff = time() - $birthstamp;
    $age_years = floor( $diff / 31556926 );
    if ( $age_years >= 18 ) {
        $_SESSION[ 'legal' ] = 'yes';

        $url = 'index.php';
    } else {
        $_SESSION[ 'legal' ] = 'no';

        // If failed the Age Gate go to specific page
        $url = 'message.php';
    }
    header( 'Location: ' . $url );
}


?>
<!doctype html>
<html>

<head>
    <meta charset="utf-8">
    <title>Check</title>
</head>

<body>
    <form method="post" action="index.php" id="checkage">
        <label for="Month">Month:</label>
        <input type="text" name="month" id="month"/>

        <label for="Day">Day:</label>
        <input type="text" name="day" id="day"/>

        <label for="Year">Year:</label>
        <input type="text" name="year" id="year"/>


        <input type="submit" name="checkage" value="Submit" class="submit-button"/>
    </form>
</body>

</html>

home.php

<?php
if (!isset($_SESSION['legal']) || $_SESSION['legal'] == 'no') {
    $_SESSION['target'] = $_SERVER['PHP_SELF'];
    header('Location: index.php');
    return;
}
?>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Home</title>
</head>

<body>
    <p>you are here</p>
</body>
</html>

message.php

<html>
<head>
<meta charset="utf-8">
<title>Sorry</title>
</head>

<body>
    <p>sorry you are not able to see this content</p>
</body>
</html>

Unfortunately, I don't have an external server to test on (or link to)

Keoki
  • 184
  • 4
  • 20
  • It doesn't seem that you're calling `session_start()` at the top of every script. – fubar Mar 06 '18 at 21:48
  • You might find this hard to debug because the page that redirect infinitely has been cached in your browser. Clear the cache every time you make a change to your files. – KIKO Software Mar 06 '18 at 21:49
  • I've done that. cleared cache. php erroring is turned on, but on the infinite redirect page, i can't see what hte issue is. – Keoki Mar 06 '18 at 21:50
  • Have you added `session_start()` to the beginning of all scripts? Because otherwise your `$_SESSION` data is not reinitialised. And I thought `header('Location...')` did a 302 redirect unless otherwise specified. That won't be cached by the browser. – fubar Mar 06 '18 at 21:55
  • thanks fubar. that helped. the issue is that if I go to file.php , I want to go through age check, and then get back to file.php . Is there away to do this? – Keoki Mar 06 '18 at 21:56
  • Yes. You need to change this line `$url = ( $_SESSION[ 'legal' ] == 'yes' ) ? 'home.php' : 'message.php';` to use your `$_SESSION['target']` value, where set. – fubar Mar 06 '18 at 21:58
  • Also, rather than using `yes` or `no` values, you'd likely find it easier to use `true` and `false`. Then you can just perform truthy tests, instead of string comparisons. – fubar Mar 06 '18 at 21:59
  • Fubar can you write it as an answre below. Im not following on the last answer. – Keoki Mar 06 '18 at 22:04
  • @Keoki - I've tried to consolidate what you wrote into a more re-usable structure below. – fubar Mar 06 '18 at 22:51

1 Answers1

1

I have rewritten a lot of what you had, and consolidated the functionality into a single check-age.php include.

// includes/check-age.php
<?php

session_start();

function isLegalAge() 
{
    return ! empty($_SESSION['is_legal']);
}

function hasCheckedLegalAge() 
{
    return isset($_SESSION['is_legal']);
}

function validateLegalAge() 
{
    $day = $_POST['day'] ?? null;
    $month = $_POST['month'] ?? null;
    $year = $_POST['year'] ?? null;

    $dob = new DateTime("{$year}-{$month}-{$day}");
    $age = $dob->diff(new DateTime);

    $_SESSION['is_legal'] = $age->y >= 18;

    redirect();
}

function redirect() 
{
    $validUrl = $_SESSION['redirect_url'] ?? 'home.php';
    $url = isLegalAge() ? $validUrl : 'message.php';

    unset($_SESSION['redirect_url']);

    header("Location: {$url}");
    exit();
}

function forceLegalAgeCheck($redirectUrl = null) 
{
    $_SESSION['redirect_url'] = $redirectUrl;

    header('Location: index.php');
    exit();
}

If you include the check-age.php file at the top of your other files (home.php, file.php), you can then streamline the logic to the following.

// index.php
<?php

require_once('includes/check-age.php');

// Redirect user if they have already confirmed age
if (hasCheckedLegalAge()) redirect();

// Validate user submitted age and redirect accordingly
if ($_POST) validateLegalAge();

// HTML ...


// home.php
<?php

require_once('includes/check-age.php');

// Check if user is of legal age, or force legal age check and return to this page
if (! isLegalAge()) forceLegalAgeCheck();

// HTML ...


// file.php
<?php

require_once('includes/check-age.php');

// Check if user is of legal age, or force legal age check and return to this page
if (! isLegalAge()) forceLegalAgeCheck(__FILE__);

// HTML ...

This is untested, but I think it should work, or at least give you an idea as to how to proceed.

Edit - I have made a couple of amendments to satisfy your new requirement.

  1. Created the hasCheckedLegalAge() function.
  2. Replaced the isLegalAge() call in index.php with hasCheckedLegalAge().

I think this should achieve what you need, but if not, it certainly points you in the right direction again.

fubar
  • 16,918
  • 4
  • 37
  • 43
  • thanks, had to adjust but I'm still getting directed to home.php even though im entering through file.php then directed to index.php for the age gate. – Keoki Mar 06 '18 at 23:42
  • If you `var_dump($url); die;` in the `redirect()` function and try to access `file.php`, what output do you get? – fubar Mar 07 '18 at 00:18
  • nothing. only the html of the page shows up and testing further, its losing its session once I go back to index.php. Its asking to enter the dob again. Once I've passed the age gate once, it should keep the session current, and if by accident someone goes back to index.php (like hitting the back button too many times), it should take them at least to home.php. right now, its asking to enter dob again. – Keoki Mar 07 '18 at 00:31
  • I've added one more line to `index.php` to resolve the back to `index.php` issue. As for losing the session, is the `require_once('includes/check-age.php');` the first thing at the top of each file? No, whitespace, nothing else should be output before hand. – fubar Mar 07 '18 at 00:38
  • yup. no white space. its losing the session. – Keoki Mar 07 '18 at 00:39
  • Give this a read... https://stackoverflow.com/questions/17242346/php-session-lost-after-redirect – fubar Mar 07 '18 at 00:42
  • Im still getting redirected to home.php not back to file.php – Keoki Mar 07 '18 at 00:45
  • Right, it your session is empty, it's not working. Figure out why your sessions are not working. Something is wrong with either your server setup or browser. Read through that other question, and check every item. – fubar Mar 07 '18 at 00:49
  • the session is now being saved, so its working now. I'm not just not redirecting back to file.php – Keoki Mar 07 '18 at 00:50
  • Okay. So if you `var_dump($_SESSION, $url); die;` in the `redirect()` function before the `unset` call, what do you get? – fubar Mar 07 '18 at 00:57
  • goes to after going through the age gate home.php C:\wamp64\www\age\check-age.php:31: array (size=2) 'redirect_url' => null 'is_legal' => boolean true C:\wamp64\www\age\check-age.php:31:string 'home.php' (length=9) going straight to file.php gives me the html of the file. – Keoki Mar 07 '18 at 00:59
  • Wait, if you go to `file.php`, you’re redirected to `index.php`, with the above output on `var_dump()`? If `$_SESSION[‘is_legal’]` per the output, you shouldn’t have been redirected. You should have just been shown the content of `file.php`. Is this what’s happening? – fubar Mar 07 '18 at 01:11
  • If i haven't gone through age gate yet , when hitting file.php it takes me to index.php for the age gate. I go through the age gate, and it takes me to home.php when I want to go back to file.php If ive already passed the age gate, and go straight to file.php , it only displays the content of the page The issue is still present: If I'm on a page that I haven't gone through the age gate yet, it won't return me back to the page when I go through the age gate. – Keoki Mar 07 '18 at 01:18
  • 1
    Just try changing `forceLegalAgeCheck(__FILE__);` to `forceLegalAgeCheck('file.php');` in `file.php`, and `var_dump($_SESSION); die;` in the `forceLegalAgeCheck()` function after the session has been set. – fubar Mar 07 '18 at 01:21
  • that solved it. thanks for helping me work this through! – Keoki Mar 07 '18 at 01:22
  • Hi Fubar, I have a minor issue: if one fails the agecheck, they can hit hte back button to go back to index.php and reenter their DOB in the fields. OF course this isn't acceptable, and defeats the purpose of the agegate/check. What can I put into index.php to redirect back to message so they dont see the date fields to enter thier DOB again? – Keoki Mar 07 '18 at 18:42
  • Whilst you can modify the code, you’re only using the `$_SESSION`, so a user could just close the browser tab, reopen it and try again... this is in no way secure, or foolproof. – fubar Mar 07 '18 at 20:00
  • Yes that is fine. the session must be cleared upon close of browser. Only during current session, they need to not be able to get back to the form to reenter a dob. this is just a requirement needed by a third-party. they don't care if the person closes the browser to clear the session to get around the block. – Keoki Mar 07 '18 at 20:27
  • I don't know what to add to index.php so that if one fails the age check (and go to message.php) that if they hit the back button, they are then sent back to message.php (or if they try to access another file directly, example file.php and even index.php, they are also sent to message.php) Don't know what is being tracked to say "you failed' to call that into redirecting back. – Keoki Mar 07 '18 at 21:02
  • If you need, I've posted the code and pages here : http://www.animation-web.com/age/index.php so right now, if I fail the agegate, it does take me to message.php, however, I can back button it to index.php and re-enter a DOB. Also going to file.php and home.php redirects me back to index.php. So I'm trying to figure out how that if a failed age check is done, it just sends people to message.php – Keoki Mar 07 '18 at 22:27
  • 1
    @Keoki - I have modified my answer to try and help you further. Given the code you'd written originally, if my changes don't solve the issue for you, they should hopefully give you sufficient direction for you to be able to figure out the rest. – fubar Mar 07 '18 at 23:15
  • thanks, but now it just redirects me to message.php can't enter DOB or anything. index.php goes straight to message.php. going to file.php goes to message.php . cleared session and I can't get back to index.php sorry, I can't figure out why this is happening, and based on my old code, the only issue i see is no "values" are being set for the session to weigh on. – Keoki Mar 07 '18 at 23:24
  • 1
    Typo in `hasCheckedLegalAge()` function. – fubar Mar 07 '18 at 23:27
  • thanks! seems to be working correctly now. serioulsy thank you for your time on this! Been dealing with Jquery too much, forgetting my PHP. – Keoki Mar 07 '18 at 23:30