0

I'm trying to create a counter in PHP that will count how many times within a set timeframe an IP can visit a page and when it hits a download counter within that timeframe it re-directs. The approach I've seen recommended was doing this with a session after referencing several Q&As:

I also looked at:

I do not have much experience with cookies and sessions so I believe that is where I fault in my code. If you have any suggestions on better implementation than what I am doing please advise.

The code:

$jsonFile       = 'foobar.json';
$theJSON        = file_get_contents($jsonFile);  
$jsonArray      = json_decode($theJSON, true);
$theIP          = "123.123.123"; // $_SERVER['REMOTE_ADDR']
$thisTime       = date("H:i");
$addMin         = 1; // set value for testing purposes
$addHour        = 0; // set value for testing purposes
$downloadHits   = 5; // set value for testing purposes
$timeLater      = date("H:i", strtotime($thisTime)+(($addMin*60)+($addHour*60*60)));


if (!empty($theIP) && !empty($jsonArray)) {
    foreach ($jsonArray as $value) {
        if (in_array($theIP, $value, true)) {
            echo "yes"; // header('Location: https://www.url/darthvader.com');
            exit();
        } else {
            if ($thisTime <= $timeLater) { // where my issue starts
                echo $timeLater; // for testing
                session_start();
                $counter = $_SESSION['promo_number'];
                $counter++;
                if ($counter == $downloadHits && file_exists($jsonFile)) {
                    $currentData = file_get_contents($jsonFile);  
                    $currentArray = json_decode($currentData, true); 
                    $theStuff = array(  
                        'ip'    => "123.123.123", // $_SERVER['REMOTE_ADDR']  
                        'date'  => date("H:i"),
                        'time'  => date("m.d.y")
                    );
                    $currentData[] = $theStuff;  
                    $finishData = json_encode($currentData);
                } else {
                    echo 'bar'; // for testing
                    session_unset();
                    session_destroy();
                }
            }
        }
    }
} else {
    echo '<span style="color:red; font-weight:bold;">empty file</span>';
}

What I am trying to do is count the times an IP visits a post within a set time and if it hits that count redirect the IP. I do know that the IP can be spoofed and I am not worried about that plus I would prefer to not use a database at this time. So how can I properly set a session to count the hits and if the IP hits the post in set count it redirects the IP?


EDIT:

After doing some reading and the help from the comment and answer I've made an edit that I hope explains what I am trying to do. After researching further I ran across:

which led me to code:

session_start();
$jsonFile           = 'foobar.json';
$jsonArray          = json_decode(file_get_contents($jsonFile), true);
$theIP              = $_SERVER['REMOTE_ADDR'];
$addMin             = 2; // set value for testing purposes
$addHour            = 0; // set value for testing purposes
$targetedHits       = 1; // set value for testing purposes
$timeLater          = time() + ($addMin*60) + ($addHour*60*60);
$_SESSION['expire'] = $timeLater;

if (!empty($theIP) && !empty($jsonArray)) {
    //look for the $theIP
    if (in_array($theIP,array_column($jsonArray,'ip'))) {
        echo 'IP found in json';
        exit;
    }
    // look at the time the session was set, add to counter or delete session
    if ($_SESSION['count'] = isset($_SESSION['count']) && time() < $_SESSION['expire'] ) {
        echo 'adding to count';
        $_SESSION['count'] + 1;
        // limit reached. Add IP to blacklist
        if ($_SESSION['count'] > $targetedHits) {
            echo 'session count reached max';
            $jsonArray[]=[
                'ip'    => $theIP,
                'date'  => date("H:i"),
                'time'  => date("m.d.y")
            ];
            // save changes
            file_put_contents($jsonFile,json_encode($jsonArray));
            session_destroy();
            exit;
        }       
    } elseif (time() > $_SESSION['expire']) {
        echo 'nuking session and counter';
        session_destroy();
    } else {
        echo 'setting count to 1';
        $_SESSION['count'] = 1;
    }
}
echo '<pre>';
var_dump($_SESSION);
echo '</pre>';

But sadly now the $_SESSION['count'] + 1; no longer increments.

Community
  • 1
  • 1
DᴀʀᴛʜVᴀᴅᴇʀ
  • 7,681
  • 17
  • 73
  • 127
  • In the above you have consecutive lines `session_start(); $counter = $_SESSION['promo_number'];` - where then is `$_SESSION['promo_number'];` defined?? That doesn't seem to make sense – Professor Abronsius Aug 05 '16 at 22:38
  • That must be where my issue falls. I'm still researching about sessions and ended testing several Q&As approach to the session. – DᴀʀᴛʜVᴀᴅᴇʀ Aug 05 '16 at 22:39
  • Also you should not start a new session in every iteration of the loop, once at the top of every page is sufficient ~ though perhaps you have a cunning plan because of the condition `if ($counter == $downloadHits && file_exists($jsonFile)) {` is not met you destroy the session variable... – Professor Abronsius Aug 05 '16 at 22:44

2 Answers2

1

Darth_Vader you're almost there. There are a couple of issues with your script.

  • You never save the count in session, so you have no way to retrieve it later
  • You start your session late in the script. This is poor practice because it will break as soon as you echo something higher up or forget and try to use $_SESSION higher up
  • You read your JSON file and decode it twice unnecessarily, wasting system memory
  • You never save the changes you make to the JSON
  • You call session_unset() and session_destroy() after a successful download, so the count would be lost even if you were trying to save it properly

My modifications:

session_start();    
$jsonFile       = 'foobar.json';
$jsonArray = json_decode(file_get_contents($jsonFile), true);
$theIP          = $_SERVER['REMOTE_ADDR'];
$thisTime       = time();
$addMin         = 1; // set value for testing purposes
$addHour        = 0; // set value for testing purposes
$downloadHits   = 5; // set value for testing purposes
$timeLater      = $thisTime + ($addMin*60) + ($addHour*60*60);    
if(empty($theIP)){
    echo 'empty file';
    exit;
}
//look for the $theIP in the 'ip' column
if(in_array($theIP,array_column($jsonArray,'ip'))){
    echo 'IP found in json';
    exit;
}    
if($thisTime > $timeLater){//not sure what you want to do here
    exit;
}
//increment the count, or set it to 1 to begin
$_SESSION['count'] = isset($_SESSION['count'])? $_SESSION['count']+1 : 1;

if($_SESSION['count']>=$downloadHits){//limit reached. Add IP to blacklist
    $jsonArray[]=[
        'ip'    => $theIP,
        'date'  => date("H:i"),
        'time'  => date("m.d.y")
    ];
    //save changes
    file_put_contents($jsonFile,json_encode($jsonArray));
    exit;
}        
echo 'good to go!'; //allow the download

Happy coding.

BeetleJuice
  • 39,516
  • 19
  • 105
  • 165
0

Figured it out after spending some time under the session tag. These two questions were helpful:

Which led me to code:

session_start();
$jsonFile           = 'foobar.json';
$jsonArray          = json_decode(file_get_contents($jsonFile), true);
$theIP              = $_SERVER['REMOTE_ADDR'];
$addMin             = 1; // set value for testing purposes
$addHour            = 0; // set value for testing purposes
$targetedHits       = 5; // set value for testing purposes
$timeLater          = time() + ($addMin*60) + ($addHour*60*60);
if (empty($_SESSION['count'])) {
    $_SESSION['expire'] = $timeLater;
}
if (!empty($theIP) && !empty($jsonArray)) {
    // look for the $theIP
    if (in_array($theIP,array_column($jsonArray,'ip'))) {
        $_SESSION['count'] = 0;
        session_destroy();
        echo 'IP found in json';
        exit;
    }
    if (time() < $_SESSION['expire']) {
        echo 'below the time ';
        $_SESSION['count'] = isset($_SESSION['count'])? $_SESSION['count'] + 1 : 1;
        if ($_SESSION['count'] > $targetedHits) {
            echo 'session count reached max ';
            $jsonArray[] = [
                'ip'    => $theIP,
                'date'  => date("H:i"),
                'time'  => date("m.d.y")
            ];
            // save changes
            file_put_contents($jsonFile,json_encode($jsonArray));
            unset($_SESSION['count']);
            session_destroy();
            exit;
        }       
    } elseif (time() > $_SESSION['expire']) {
        echo 'nuking session and counter';
        $_SESSION['count'] = 0;
        unset($_SESSION['expire']);
    }   
}
echo '<pre>';
var_dump($_SESSION);
echo '</pre>';

I hope the above helps the next person because I didn't really know anything about sessions and it has been an adventure getting this to work this evening.

Community
  • 1
  • 1
DᴀʀᴛʜVᴀᴅᴇʀ
  • 7,681
  • 17
  • 73
  • 127