I am trying to create something like a lock and unlock pages feature. The user has to go thorugh the pages in this order:
$steps = array(1 =>'create_session.php',2 => 'QandATable.php',3 => 'individualmarks.php',4 => 'penalty.php',5 => 'penaltymarks',6 => 'complete.php');
So what should happen is that if the user is on a page a they SHOULD BE on, then that page shold be unlocked (or in other words the if statement is met where it shows the page's code), if the user accesses a page which they should not be on, then that page beocmes locked (the else statement is met where it displays the div with the Continue hyperlink`).
The problem is that even though the user is on the correct page, the page is still "locked" when it should be unlocked so the user can use the page. At moment all pages accessed are locked so my question is that how can I unlock a page when the user is on a correct page?
Below is an example create_session.php:
<?php
session_start();
include ('steps.php'); //exteranlised steps.php
?>
<head>
...
</head>
<body>
<?php
if ((isset($username)) && (isset($userid))) { //checks if user is logged in
if (allowed_in() === "Allowed") {
//create_session.php code:
} else {
$page = allowed_in() + 1;
?>
<div class="boxed">
Continue with Current Assessment
<?php
}
} else {
echo "Please Login to Access this Page | <a href='./teacherlogin.php'>Login</a>";
//show above echo if user is not logged in
}
?>
Below is the full steps.php:
<?php
$steps = array(1 =>'create_session.php',2 => 'QandATable.php',3 => 'individualmarks.php',4 => 'penalty.php',5 => 'penaltymarks',6 => 'complete.php');
function allowed_in($steps = array()){
// Track $latestStep in either a session variable
// $currentStep will be dependent upon the page you're on
if(isset($_SESSION['latestStep'])){
$latestStep = $_SESSION['latestStep'];
}
else{
$latestStep = 0;
}
$currentStep = basename(__FILE__);
$currentIdx = array_search($currentStep, $steps);
$latestIdx = array_search($latestStep, $steps);
if ($currentIdx - $latestIdx == 1 )
{
$currentIdx = $_SESSION['latestStep'];
return 'Allowed';
}
return $latestIdx;
}
?>
Something like this, though this probably won't work as is:
$allowed_page = $_SESSION['latestStep'];
if ($steps[$allowed_page] == $_SERVER['SCRIPT_NAME']) {
... allowed to be here ...
}
Basically, given your array of "steps", you store the index of the allowed page in the session as you. As they complete a page and "unlock" the next page, you increment that index value in your session and redirect to the next page in the sequence.
if ($page_is_done) {
$_SESSION['latestStep']++;
header("Location: " . $steps[$_SESSION['latestStep']]);
}
Keep it simple, seems that you are over complicating the goal. It seems like you simply want to ensure that the user completes previous steps of a process before they can continue on to the next. Why not try something more like...
// General Idea
$completedArr = array('1' => false, '2' => false ...);
$pageMap = array('page1.php' => '1', 'page2.php' => '2' ...);
// On Page1
$completedArr = $_SESSION['completedArr'];
$locked = true;
$currentStep = $pageMap[$_SERVER['SCRIPT_NAME']]; // '1'
if($currentStep > 1)
{
if($completedArr[$currentStep - 1] === true)
$locked = false;
}
else
{
$locked = false;
}
$completedArr[$currentStep] = true;
$_SESSION['completedArr'] = $completedArr;
Use this as needed for continuous pages also. The idea is that the pageMap you would define to give index numbers to script names. Then you would simply check to see that the previous index was marked as completed before "unlocking" this page.
Related
I have page with 4 links, when someone clicks on one of the links I want to set a cookie to store the selected link, then when they return to the site, the cookie redirects them to the link they previously selected. Since I only want the 4 links to set a cookie I'm using a query string (?sel=p1) in the link and checking for that to set the cookie.
function set_pref_cookie(){
if (isset($_GET['sel'])) {
$root = $_GET['sel'];
if ($root = 'p1'){
$cookie_var = '/page1/';
} else if ($root = 'p2'){
$cookie_var = '/page2/';
} else if ($root = 'p3'){
$cookie_var = '/page3/';
} else if ($root = 'p4'){
$cookie_var = '/page4/';
}
} else {
$root = '';
}
if ($root !=''){
setcookie('pref_sel',$_COOKIE['sel'] = $cookie_var, time()+60*60*24*5, "/");
}
if (isset($_COOKIE['pref_sel']) && $_COOKIE['pref_sel'] != ''){
header('Location:' . $_COOKIE['pref_sel']);
exit;
}
}
add_action('init','set_pref_cookie');
The issue is, all 4 links set the same value in the cookie /page1/
, and, on return to the site, I'm getting a redirect loop.
I've also tried checking for an empty cookie
if (isset($_COOKIE['pref_sel']) && !empty($_COOKIE['pref_sel']) ){
but same result.
To refer to all the comments in your first ticket, and this one (please don't use 2 questions for the same problem)
=> Redirection with cookie without loop : ok fixed by the correction i gave you and explained to you in the first question.
=> second problem : you're always redirected to page-1.
=> please fix this part of you're code like this :
if ($root == 'p1'){
$cookie_var = '/page1/';
} else if ($root == 'p2'){
$cookie_var = '/page2/';
} else if ($root == 'p3'){
$cookie_var = '/page3/';
} else if ($root == 'p4'){
$cookie_var = '/page4/';
}
You also should add an else case cause your $cookie_var could have sometimes empty value.
=> third, what do you want to achieve with your setcookie with an affectation ?
setcookie('pref_sel',$_COOKIE['sel'] = $cookie_var, time()+60*60*24*5, "/");
you should only do this :
setcookie('pref_sel', $cookie_var, time()+60*60*24*5, "/");
=> to debug, comment you're redirection and replace it by
echo $_COOKIE['pref_sel'];
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:
PHP function to increment variable by 1 each time
How to not increase page/post view count with refresh?
php increment variable value with 1 when submit
I also looked at:
How do I count unique visitors to my site?
adding counter to php page to count the unique visitors
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:
session_destroy() after certain amount of time in PHP
How do I expire a PHP session after 30 minutes?
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.
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.
Figured it out after spending some time under the session tag. These two questions were helpful:
How do check if a PHP session is empty?
How can I clear my php session data correctly?
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.
So, I made a PHP page/link checker, which should not allow an user to visit/redirect to a page if isn't passed certain minutes from last visit/redirect.
The problem is, the user is being redirected to the page ALWAYS even if he already did it 1 min ago and the timer is 7 min (example). The timer is setted into MySQL as minutes.
can't figure out what is wrong in the code
this is the first page:
<?php
session_start();
$sql = "SELECT * FROM table_records";
$result = mysql_query($sql);
$records = array();
while ($row = mysql_fetch_assoc($result)) {
$records[] = $row;
}
foreach ($records as $record) {
$now = new DateTime();
if (!array_key_exists($record, $_SESSION['records']) || ($now->getTimestamp()-$_SESSION['records'][$record]) <= 600) {
echo "<td><center>".$record['id']."</center></td>";
echo "<td><center>".$record['name']."</center></td>";
echo "<td><center>".$record['link']."</center></td>";
echo "<td><center>".$record['delay']."</center></td>";`
} else {
// link disabled
}
}
?>
and this is the page the users are redirected to, to check the timer, and in case redirect them to the link.
$waiting_time = $delay * 60; //calculate delay time in seconds
if (!array_key_exists($id, $_SESSION['records'])) {
$_SESSION['records'][$id] = $now->getTimestamp();
header("Location: $link");
exit();
} elseif (array_key_exists($id, $_SESSION['records']) && ($now->getTimestamp()-$_SESSION['records'][$id]) >= $waiting_time) {
echo "Looks like you already visited this page";
} elseif (array_key_exists($id, $_SESSION['records']) && ($now->getTimestamp()-$_SESSION['records'][$id]) < $waiting_time) {
$_SESSION['records'][$id] = $now->getTimestamp();
header("Location: $link");
exit();
}
The problem is, the user is being redirected to the $link ALWAYS, even if he already visited, and the time of delay isn't passed.
What is wrong with the code?
DRY, you can write your if/elseif statements much easier:
if (array_key_exists($id, $_SESSION['records']) && ($now->getTimestamp()-$_SESSION['records'][$id]) < $waiting_time) {
echo "Looks like you already visited this page";
} else {
$_SESSION['records'][$id] = $now->getTimestamp();
header("Location: $link");
exit();
}
Now, if you look at it you'll see there are two things to check at first:
Is $_SESSION['records'] not empty (maybe session wasn't intialized on second page?) - var_dump ($_SESSION['records']) - what's in there?
what's the result of ($now->getTimestamp()-$_SESSION['records'][$id]) and what's in $waiting_time variable - var_dump it
Don't forget to call exit() after dumping the code and before redirection or simply comment location () lines, otherwise you'll see nothing
Third possibility (you'll know this is the case if you don't see var_dump printout) is that your browser remembers 301 redirection and when you go second time to same address it redirects automatically without calling your script - restart your browser or try different one.
When I navigate to a page which is locked (in other words when the box which states you have to Continue appears, I am getting undefined $_SESSION variables. Before I included the if (allowed_in()=== "Allowed"){ statement, I was not getting any undefined $_SESSION variables but as now need that if statement, Im starting to get those variable errors.
For the $_SESSION undefined errors, is it because I am placing the $_SESSION variables in the wrong place?
Below is an example QandATable.php order of code looks like:
<?php
ini_set('session.gc_maxlifetime',12*60*60);
ini_set('session.gc_divisor', '1');
ini_set('session.gc_probability', '1');
ini_set('session.cookie_lifetime', '0');
require_once 'init.php';
//12 hours sessions
session_start();
include('steps.php'); //exteranlised steps.php
?>
<head>
<?php
if (isset($_POST['id'])) {
$_SESSION['id'] = $_POST['id'];
}
if(isset($_POST['sessionNum'])){
//Declare my counter for the first time
$_SESSION['initial_count'] = $_POST['sessionNum'];
$_SESSION['sessionNum'] = intval($_POST['sessionNum']);
$_SESSION['sessionCount'] = 1;
}
elseif (isset($_POST['submitDetails']) && $_SESSION['sessionCount'] < $_SESSION['sessionNum']) {
$_SESSION['sessionCount']++;
}
?>
</head>
<body>
<?php
//once session is expired, it should log the user out, but at mo this isn't happening
if ((isset($username)) && (isset($userid))){ //checks if user is logged in
if (allowed_in()=== "Allowed"){
//QandATable.php code:
}else{
$page = allowed_in()+1;
?>
<div class="boxed">
Continue with Current Assessment
<?php
}
}else{
echo "Please Login to Access this Page | <a href='./teacherlogin.php'>Login</a>";
//show above echo if user is not logged in
}
?>
Below is the full steps.php:
<?php
$steps = array(1 =>'create_session.php',2 => 'QandATable.php',3 => 'individualmarks.php',4 => 'penalty.php',5 => 'penaltymarks',6 => 'complete.php');
function allowed_in($steps = array()){
// Track $latestStep in either a session variable
// $currentStep will be dependent upon the page you're on
if(isset($_SESSION['latestStep'])){
$latestStep = $_SESSION['latestStep'];
}
else{
$latestStep = 0;
}
$currentStep = basename(__FILE__);
$currentIdx = array_search($currentStep, $steps);
$latestIdx = array_search($latestStep, $steps);
if ($currentIdx - $latestIdx == 1 )
{
$currentIdx = $_SESSION['latestStep'];
return 'Allowed';
}
return $latestIdx;
}
?>
session_start() must go before any content.
Note:
To use cookie-based sessions, session_start() must be called before
outputing anything to the browser.
http://php.net/manual/en/function.session-start.php
I have an index view that lists items, and it's a long list so I use Paginator to limit items to 50-to-a-view.
Each item has an "edit" link that goes to an edit view with inputs/validations/etc. When that form is submitted, I redirect the use back to the index view.
So far so good, but here's the rub:
If a user is on page N of the index and they click edit and edit an item, I want them to be redirected back to page N of the index. If I knew the page number, I could just stick "/page:N" on to end of the URL, but I have no idea how I can get the page number. (N could be any page number, but especially >=2)
Any ideas would be appreciated.
The page number should be part of the $params var in the list view. Just tack it onto the end of the edit link and handle it from there. On the edit page you will need a way to take in the optional page number, store it during any form submission, and forward back to the list with the same page number.
I created a component that saves the page in the session. Then in the app_controller.php, I check to see if there is anything in the session for the particular model being used and then add that to the url. If you are interested in the code for the component, message me. I also store the order, if the user changed the sort order in the index page before editing.
See here for the source:
http://github.com/jimiyash/cake-pluggables/blob/a0c3774982c19d02cfdd19a2977eabe046a4b294/controllers/components/memory.php
Here is the gist of what I am doing.
//controller or component code
if(!empty($params['named']) && !empty($params['controller']) && $params['action'] == 'admin_index'){
$this->Session->write("Pagem.{$params['controller']}", $params['named']);
}
//app_controller.php
$redirectNew = "";
if(is_array($redirectTo)){
if(!empty($params['prefix']) && $params['prefix'] == 'admin'){
$redirectNew .= '/admin';
}
if(!empty($params['controller'])){
$redirectNew .= "/" . $params['controller'];
}
if(!empty($redirectTo['action'])){
$redirectNew .= "/" . $redirectTo['action'];
}
} else {
$redirectNew = $redirectTo;
}
$controller = $params['controller'];
if($this->Session->check("Pagem.$controller")){
$settings = $this->Session->read("Pagem.$controller");
$append = array();
foreach($settings as $key=>$value){
$append[] = "$key:$value";
}
return $redirectNew . "/" . join("/", $append);
} else {
return $redirectNew;
}
If I understand correctly, the above is fine for editing, but not for adding. This solution should work for both situations:
In your controllers or your /app/app_controller.php, put in something like this for adding:
$insertID = $this->{$this->modelClass}->getLastInsertID();
$page = $this->{$this->modelClass}->getPageNumber($insertID, $this->paginate['limit']);
$this->redirect("/admin/{$controllerName}/index/page:{$page}");
...and something like this for editing:
$page = $this->{$this->modelClass}->getPageNumber($id, $this->paginate['limit']);
$this->redirect("/admin/{$controllerName}/index/page:{$page}");
In your /app/app_model.php, put in this:
/**
* Work out which page a record is on, so the user can be redirected to
* the correct page. (Not necessarily the page she came from, as this
* could be a new record.)
*/
function getPageNumber($id, $rowsPerPage) {
$result = $this->find('list'); // id => name
$resultIDs = array_keys($result); // position - 1 => id
$resultPositions = array_flip($resultIDs); // id => position - 1
$position = $resultPositions[$id] + 1; // Find the row number of the record
$page = ceil($position / $rowsPerPage); // Find the page of that row number
return $page;
}
Hope that helps!
Does a simple
$this->redirect($this->referer());
works?
In view with paginator:
<?php
if ($this->Paginator->hasPage(null, 2)) {
$pag_Start = $this->Paginator->counter('{:start}');
$pag_End = $this->Paginator->counter('{:end}');
if( $pag_Start == $pag_End ){
$pageToRedirect = $this->Paginator->current('Posts');
}else{
$pageToRedirect= '';
}}?>
Then link to edit page
<?php
echo $this->Form->postLink(
'Edit',
array('action' => 'edit', $subscription['Post']['id']));
?>
In controller:
public function edit($post_id, $pageToRedirect = false){
//after all editing its done redirect
if($pageToRedirect){
// if record was last in pagination page redirect to previous page
$pageToRedirect = $pageToRedirect -1;
return $this->redirect(array('action' => 'index/page:'.$pageToRedirect ));
}else{
// else redirect to the same pagination page
$this->redirect($this->referer());
}
}