12 Replies - 7706 Views - Last Post: 15 June 2011 - 11:22 PM Rate Topic: -----

#1 Downplay  Icon User is offline

  • New D.I.C Head

Reputation: -1
  • View blog
  • Posts: 17
  • Joined: 25-December 10

Prevent PHP script from being run more than once?

Posted 15 June 2011 - 03:57 PM

Hi I would really appreciate if someone could help me out with this. I have this PHP script:

<?php
$ip=$_SERVER['REMOTE_ADDR'];

require_once "class.test.php";

$kg = new test2();
$keepgoing = $kg->keepGoing();

if ($ip==99.99.99.99)
{
	while ($keepgoing)
	{
		$fh = fopen($myfile, 'a') or die("Cannot open file");
		$stringtowrite="this is a test\n";
		fwrite($fh, $stringtowrite);
		fclose($fh);
		sleep(60);
	}
}

else
{
	echo "You do not have access to this script."
}
?>



and here's a portion of class.test.php:

<?php
class test2
{
	public $keepgoing=true;

	function keepGoing() { return $this->keepgoing; }
}
?>



So right now the script will only run a.) when the person's IP address is 99.99.99.99 and b.) when the $keepgoing variable in class.test.php is true. But my problem is preventing that person from opening this script multiple times in their browser. I want to make it so that they can only open it once. So if the script is already open and running from their IP address, it will tell them that they cannot open more than one instance of the script from their IP address. Is this possible? If so, could someone please tell me how I could accomplish this? I greatly appreciate it. Thank you very much.

Is This A Good Question/Topic? 0
  • +

Replies To: Prevent PHP script from being run more than once?

#2 Duckington  Icon User is offline

  • D.I.C Addict

Reputation: 170
  • View blog
  • Posts: 608
  • Joined: 12-October 09

Re: Prevent PHP script from being run more than once?

Posted 15 June 2011 - 04:18 PM

Could use a session.

When they run the script it checks to see if the session is set, if it is then exits, if it isn't then it sets the session and executes the script.
Was This Post Helpful? 0
  • +
  • -

#3 Downplay  Icon User is offline

  • New D.I.C Head

Reputation: -1
  • View blog
  • Posts: 17
  • Joined: 25-December 10

Re: Prevent PHP script from being run more than once?

Posted 15 June 2011 - 04:21 PM

View PostDuckington, on 15 June 2011 - 04:18 PM, said:

Could use a session.

When they run the script it checks to see if the session is set, if it is then exits, if it isn't then it sets the session and executes the script.


So what kind of code would I use for that? Would I write to a file the user's IP address and then somehow remove the IP address when they exit the session? Sorry I'm not familiar with sessions.
Was This Post Helpful? 0
  • +
  • -

#4 Duckington  Icon User is offline

  • D.I.C Addict

Reputation: 170
  • View blog
  • Posts: 608
  • Joined: 12-October 09

Re: Prevent PHP script from being run more than once?

Posted 15 June 2011 - 04:32 PM

Something like:

<?php
session_start();

if(isset($_SESSION['user']))
{
// Session has been set, so don't execute the script
exit();
}
else
{
// Set the session now
$_SESSION['user'] = "whatever";

// Execute the script

// Script here...

// Then when script has finished running, you can unset the session so that the page can be run again
unset($_SESSION['user']);
}
?>


Was This Post Helpful? 0
  • +
  • -

#5 maniacalsounds  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 117
  • View blog
  • Posts: 472
  • Joined: 27-June 10

Re: Prevent PHP script from being run more than once?

Posted 15 June 2011 - 04:32 PM

Are you wanting the person to be able to execute one time at a time (a.k.a. when the script finishes, they can activate it again) or someone can only activate it once from an I.P. address?
Was This Post Helpful? 0
  • +
  • -

#6 Downplay  Icon User is offline

  • New D.I.C Head

Reputation: -1
  • View blog
  • Posts: 17
  • Joined: 25-December 10

Re: Prevent PHP script from being run more than once?

Posted 15 June 2011 - 04:42 PM

Thank you Duckington, that will definitely help.

View Postmaniacalsounds, on 15 June 2011 - 04:32 PM, said:

Are you wanting the person to be able to execute one time at a time (a.k.a. when the script finishes, they can activate it again) or someone can only activate it once from an I.P. address?


Well both. Basically when an authorized user navigates to the script, I want the while() loop to iterate forever and a session to be set so that the user cannot run the script again and start another while() loop. However, right when the authorized user exits the script (i.e. closes the tab or exits the browser), I want the while loop (which basically contains the whole script) to stop and the session to end so that the user can re-navigate to the script later and start the whole thing over again. So at the end of Duckington's code:

// Then when script has finished running, you can unset the session so that the page can be run again
unset($_SESSION['user']);



I want the script to finish running (and the session to be unset) when the user closes the tab/browser. So just figuring that out would complete my script. Is this possible? Thanks.
Was This Post Helpful? 0
  • +
  • -

#7 maniacalsounds  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 117
  • View blog
  • Posts: 472
  • Joined: 27-June 10

Re: Prevent PHP script from being run more than once?

Posted 15 June 2011 - 04:46 PM

Wait - you WANT an infinite loop? This better be just for practice.

Anyway, his script will work, as desired.

Quote

I want the script to finish running (and the session to be unset) when the user closes the tab/browser. So just figuring that out would complete my script. Is this possible? Thanks.

Yes, I would suggest to move your function into the class test2 if you want that, because you PHP will automatically call any instances of text2 class' __destruct() destructor.

Reading:
http://php.net/manua....oop5.decon.php

Hope I helped!

This post has been edited by maniacalsounds: 15 June 2011 - 04:47 PM

Was This Post Helpful? 0
  • +
  • -

#8 Downplay  Icon User is offline

  • New D.I.C Head

Reputation: -1
  • View blog
  • Posts: 17
  • Joined: 25-December 10

Re: Prevent PHP script from being run more than once?

Posted 15 June 2011 - 04:54 PM

View Postmaniacalsounds, on 15 June 2011 - 04:46 PM, said:

Wait - you WANT an infinite loop? This better be just for practice.

Anyway, his script will work, as desired.

Quote

I want the script to finish running (and the session to be unset) when the user closes the tab/browser. So just figuring that out would complete my script. Is this possible? Thanks.

Yes, I would suggest to move your function into the class test2 if you want that, because you PHP will automatically call any instances of text2 class' __destruct() destructor.

Reading:
http://php.net/manua....oop5.decon.php

Hope I helped!


Yes I want an infinite loop (just for testing purposes) but only until the user closes the browser. Could you explain a bit more how to setup the destruct() so that when the user closes his/her browser, the script stops? Thanks.
Was This Post Helpful? 0
  • +
  • -

#9 Atli  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 3716
  • View blog
  • Posts: 5,976
  • Joined: 08-June 10

Re: Prevent PHP script from being run more than once?

Posted 15 June 2011 - 07:21 PM

Hey.

What you are doing isn't really the "HTTP" way of doing this. An infinite loop in a web request is not the best idea, as the requests generally time out after a certain period. PHP's default timeout period is 30 seconds, and although that can be altered, it's not really that reliable to trust in a HTTP request to be maintained indefinitely.

I would suggest you use AJAX instead. That is, instead of creating a PHP that loops forever, create a PHP that does whatever your loop would do, but only once. Then use Javascript on the client side to call this PHP script via AJAX every 60 seconds (or whatever).

... And seeing as I'm bored waiting for my crappy 10 year old server computer to finish compiling my LAMPP software, I made an example. :)

Assuming that you will be using IP addresses to limit access (which isn't the best method, but that's another topic...), you could create a PHP script like this:
<?php
// Make sure the IP of the user is valid.
$valid_ips = array( "127.0.0.1", "192.168.1.3");
$client_ip = $_SERVER['REMOTE_ADDR'];

if (!in_array($client_ip, $valid_ips)) {
    header("HTTP/1.1 403 Restricted");
    die("Sorry, {$client_ip}, you don't have access to this script.");
}

// Required to use a session.
session_start();

// Set the minimum required wait time in seconds.
$timeout = 20;

// Get the time elapsed since the last time the script was
// accessed by this client.
$elapsed = time();
if (isset($_SESSION['last_trigger_time']))
    $elapsed -= (int)$_SESSION['last_trigger_time'];

// Make sure the min wait time has elapsed
if ($elapsed > $timeout) {
    // Update the session timer, so the next time the script is
    // accessed the elapsed time will be accurate.
    $_SESSION['last_trigger_time'] = time();
    
    // Do whatever you want done here...
    $fh = fopen("random_stuff.txt", 'a');
    if ($fh) {
        fwrite($fh, mt_rand(1, 1000000) . "\n");
        fclose($fh);
    }
    echo "Done";
}
else {
    // Print a message indicating the wait time has not passed.
    // (Note that in the Javascript code, I use the number
    // that I place into this text to reset the AJAX timer.)
    printf("You have to wait %d more seconds", $timeout - $elapsed);
}
?>


Lets call that: trigger.php.
As you can see, this allows a couple of IP addresses to access the script and write a line to a text file, but uses a session value to enforce a 20 second wait period between executions. - The downside to the session method is that the script could still be accessed by multiple separate browsers on the same IP simultaneously. To fix that, you'd have to manually log the IP addresses using either some sort of a log file or custom session handling.

On the client side, you could set up a HTML file like this:
<!DOCTYPE HTML>
<html>
<head>
    <title>Example</title>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <script type="text/javascript" src="trigger.js"></script>
</head>
<body>
    <h1>Example script!</h1>
    <p>This will execute the <em>trigger.php</em> script 
       automatically every 20 seconds.</p>
    <p>Last update: <span id="last_update">Waiting...</span></p>
    <p>Next update in: <span id="update_countdown">Waiting...</span></p>
</body>
</html>


Let's call that: index.html. It simply sets some static HTML elements and calls a Javascript file, trigger.js.

The trigger.js file is where the AJAX calls would be made. That could look like so:
var updateInterval = 20;
var lastUpdate = 0;

// Stores the counter ID so it can be stopped later.
var intervalID = null;

/**
 * Creats a timer that executs a function once a second, which 
 * executes the "updateTrigger" function every 60 seconds and 
 * updates the "Next update in" field in the HTML.
 * 
 * Note that this function is bound to the window.onload event
 * at the bottom of the code, which makes it execute as soon as
 * the page is loaded.
 */
function initTrigger() {
    intervalID = window.setInterval(function() {
        // Calculate what remains of the update wait period.
        var currentTime = new Date().getTime();
        var elapsedSeconds = Math.round((currentTime - lastUpdate) / 1000);
        var timeToUpdate = updateInterval - elapsedSeconds;
        
        // If the timeToUpdate value is less than 0, the wait
        // period is up and it's time to call an update request.
        if (timeToUpdate < 0) {
            updateTrigger();
            timeToUpdate = "Updating...";
        }
        
        // Update the "Next update in" HTML field
        var countdown_elem = document.getElementById('update_countdown');
        if (countdown_elem) {
            countdown_elem.innerHTML = timeToUpdate;
        }
    }, 1000);
}

/**
 * A function that gets called, and which sends the request
 * to have the "trigger.php" file executed.
 */
function updateTrigger() {
    // Create a new AJAX request.
    var xhr = new XMLHttpRequest();
    
    // Set a callback function, to process updates to the request.
    xhr.onreadystatechange = function() {
        if (xhr.readyState == 4) {
            if (xhr.status == 200) {
                // The AJAX request received a message from PHP.
                if (xhr.responseText == "Done") {
                    // The trigger was successfull. Call the "triggerCallback"
                    // function to complete the process on this end.
                    triggerCallback(true, null);
                }
                else {
                    // The trigger wait period wasn't done. Pass the
                    // error message to the "triggerCallback" function
                    // so it can be processed and the wait time updated.
                    triggerCallback(false, xhr.responseText); 
                }
            }
            else if (xhr.status == 403) {
                // The AJAX request returned a "403 Forbidden" header,
                // which means the user is not allowed to use the
                // script.
                // So, stopping the counter and showing a error.
                window.clearInterval(intervalID);
                alert(xhr.responseText);
            }
        }
    }
    
    // Send the request. It works in the background, and the
    // function I defined in the preceeding lines will be called
    // once it is done.
    xhr.open('get', 'trigger.php', true);
    xhr.send(null);
}

/**
 * A function to call when the request has been completed.
 * The parameter will be set to TRUE if the request was
 * completed successfully, otherwise FALSE.
 */
function triggerCallback(success, message) {
    var currentDate = new Date();
    if (success === true) {
        // Update was successfull! Update the timer and
        // the "Last updated" HTML field.
        lastUpdate = currentDate.getTime();
        var out_elem = document.getElementById('last_update');
        out_elem.innerHTML = currentDate.toLocaleTimeString();
    }
    else {
        // Update failed. Try to extract the number of
        // seconds we need to wait from the error message.
        var extr = /\b(\d+)\b/i.exec(message);
        if (extr) {
            // Use the extracted seconds to reset the lastUpdate
            // value so the script will wait the specified amount
            // before triggering another update.
            var timeToUpdate = parseInt(extr[1]) * 1000;
            var msUI = updateInterval * 1000;
            lastUpdate = currentDate.getTime() - msUI + (msUI - timeToUpdate);
        }
    }
}

/*
 * Set the "initTrigger" function to be executed when teh page loads.
 */
if (window.addEventListener) {
    window.addEventListener('load', initTrigger, true);
}
else {
    window.onload = initTrigger;
}


This will call the trigger.php script every 20 seconds and process what the PHP script prints out and update the HTML accordingly.

Hopefully the code comments can help make sense of what I'm doing :)
Was This Post Helpful? 2
  • +
  • -

#10 Downplay  Icon User is offline

  • New D.I.C Head

Reputation: -1
  • View blog
  • Posts: 17
  • Joined: 25-December 10

Re: Prevent PHP script from being run more than once?

Posted 15 June 2011 - 07:53 PM

Thank you so much Atli for the walk through and the great comments. Your scripts should do the trick!

EDIT: I'm having some trouble getting the session limit to work. Opening multiple instances of the script still works, and adding:

<?php
session_start();
if (isset($_SESSION['used'])) {
    header("HTTP/1.1 403 Restricted");
    die("Sorry, {$client_ip}, you can't run this script again.");
	exit();
}

$_SESSION['used']="cannotdoitagain";
?>



to the beginning of index.html doesn't seem to help stop the script from being run multiple times. Is there a way to fix this?

This post has been edited by Downplay: 15 June 2011 - 08:11 PM

Was This Post Helpful? 0
  • +
  • -

#11 Atli  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 3716
  • View blog
  • Posts: 5,976
  • Joined: 08-June 10

Re: Prevent PHP script from being run more than once?

Posted 15 June 2011 - 09:14 PM

If you want the index file to run PHP code, you need to rename it to index.php. A normal .html file doesn't usually run the PHP code.

However, what you are doing isn't really necessary. The user can open the page multiple times, but it doesn't mean the PHP code will be executing any faster. The trigger.php code limits each browser session to one execution per 20 seconds, and as far as I am aware, browser tabs share a session. So even if you opened 10 tabs with the page on it, it would only execute the PHP code once every 20 seconds.

There is no reliable way to detect when a user leaves a page, so trying to prevent the user from opening the page in two tabs can backfire pretty bad. I mean, say you set a session variable in a tab and then close it. The session variable is still set, so if you try to open the page again in a new tab, you'll be unable to. The PHP code will not be aware the first tab ever closed.

That's why it's better to use AJAX this way, because no matter how many tabs you have open, only the tab who's AJAX request is first to send it's request will trigger the code and get a "Done" message. The others will only ever get "You need to wait" messages.


If you want to protect against the same IP having multiple sessions open, you can't rely on PHP's session handling alone. You'll need to write your own manual IP logging system. Shouldn't be to hard, but as always, using IPs alone is risky. They are unreliable at best.
Was This Post Helpful? 0
  • +
  • -

#12 Downplay  Icon User is offline

  • New D.I.C Head

Reputation: -1
  • View blog
  • Posts: 17
  • Joined: 25-December 10

Re: Prevent PHP script from being run more than once?

Posted 15 June 2011 - 09:51 PM

Ok that makes sense. As for the IP checking, what alternative would you suggest to prevent multiple sessions from being opened? Thanks.
Was This Post Helpful? 0
  • +
  • -

#13 JBrace1990  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 110
  • View blog
  • Posts: 760
  • Joined: 09-March 08

Re: Prevent PHP script from being run more than once?

Posted 15 June 2011 - 11:22 PM

You can't have multiple sessions of the same name on the same computer. So if you name the session "user", you'll only have 1 session and if you try to make a new one, it just changes the value of the old one.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1