I'be been hunting for ages, obviously any search for a php script with "IP" in it comes up with a LOAD. What I'm after, I want a user to be able to click a link on a section of a website, however once they've clicked that link, they should not be allowed to see that section again for a set amount of time. I'm guessing I'll need to use a database to log the IP and when the link was clicked. So the section on the page will basically need to do the following...? Check IP Check click time variable = "time remaining" If click time <XXX then some variable = yes If click time >XXX then some variable = no Then on the page use an if statement? If some variable = yes show this bit else show "sorry, you cannot view this page for "time remaining" anyone fancy helping me out?
How secure does it need to be? Bearing in mind that it is possible to spoof ip's if needed, you could just go the simple route and make use of a cookie with a time out of whatever you need? This is v raw and will need fixing as my scripts never work first time - probably a semicolon missing somewhere of some other stupid mistake, but it should put you on the right track. I would have tested it myself but too lazy to set up a new database! (note: I didn't write the ip checking function so if that doesn't work just use $_SERVER['REMOTE_ADDR'], it'll do ) PHP: <?php /* this function was taken from http://forums.devshed.com/php-development-5/proxy-servers-64009.html It may or may not work, could just user $_SERVER['REMOTE_ADDR'] but this is more fool proof + accounts for multiple users on same network ......aparently! */ function get_client_ip() { // Get REMOTE_ADDR as the Client IP. $client_ip = ( !empty($_SERVER['REMOTE_ADDR']) ) ? $_SERVER['REMOTE_ADDR'] : ( ( !empty($_ENV['REMOTE_ADDR']) ) ? $_ENV['REMOTE_ADDR'] : $REMOTE_ADDR ); // Check for headers used by proxy servers to send the Client IP. We should look for HTTP_CLIENT_IP before HTTP_X_FORWARDED_FOR. if ($_SERVER["HTTP_CLIENT_IP"]) $proxy_ip = $_SERVER["HTTP_CLIENT_IP"]; elseif ($_SERVER["HTTP_X_FORWARDED_FOR"]) $proxy_ip = $_SERVER["HTTP_X_FORWARDED_FOR"]; // Proxy is used, see if the specified Client IP is valid. Sometimes it's 10.x.x.x or 127.x.x.x... Just making sure. if ($proxy_ip) { if ( preg_match("/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/", $proxy_ip, $ip_list) ) { $private_ip = array('/^0\./', '/^127\.0\.0\.1/', '/^192\.168\..*/', '/^172\.16\..*/', '/^10.\.*/', '/^224.\.*/', '/^240.\.*/'); $client_ip = preg_replace($private_ip, $client_ip, $ip_list[1]); } } // Return the Client IP. return $client_ip; } $ip = get_client_ip(); // get ip addr $time = time(); // current time (in seconds) $timeout = 3600; //timeout in seconds $tc = -1; $mysqli = new mysqli("localhost", "my_user", "my_password", "database"); // connect to db $query = "SELECT time_clicked FROM table WHERE ip = '$ip'"; if (mysqli_connect_errno()) { // if can't connect... printf("Connect failed: %s\n", mysqli_connect_error()); exit(); } if ($result = $mysqli->query($query)) { // check to see if have visted before while ($obj = $result->fetch_object()) { $tc = $obj->time_clicked; // if so, time of last visit is selected } $result->close(); } if ($tc != -1) { // if been here before... $timeleft = $tc + $timeout - $time; if ($timeleft > 0)) { // and still have to wait... echo "sorry, you cannot view this page for ".date("H:i:s",$timeleft); // show this message, } else { echo "Welcome back"; // otherwise show welcome back and update table with new time $mysqli->query("UPDATE table SET time_clicked = '$time' WHERE ip = '$ip'"); } } else { // not been here before?... echo "Welcome, this is your first time here!"; // welcome + add to database $mysqli->query("INSERT INTO table (ip, time_clicked) VALUES ('$ip','$time')"); } $mysqli->close(); // close db conn ?> Hope it helps!
It doesn't need to be superbly secure as the IP's will be tracked throughout the site anyway, and even if someone was to try and force the system a pattern would appear anyway. I'll look into the code you've posted. May need a little bit more help with the code though! I like the first visit function, I could include a link to the FAQ etc on that section, however, I only want the IP logged & blocked after they click on a link and are taken to the next page, so I assume I just put the "Insert into table" code on that page instead. The only reason for the delay is to stop someone using a script to force a row of numbers through a php script thats going to be running on the link.
I get the following error - Fatal error: Cannot instantiate non-existent class: mysqli /public_html/test/sqltest.php on line 45
try removing the 'i' mysqli in PHP 5+ only mysql is the old one I believe the code /should/ still be valid though!
PHP: <? class Session { protected $chrIP = null; // Period between allowed accesses (in seconds) const TIME_LIMIT = 120; protected static $objInstance = null; protected static $arrRestricted = array( 'restricted.php', 'access.php', 'timelog.php' ); protected function __construct() { $this->canAccess(); } # end constructor public function __clone() { throw new Exception('Cannot clone a singleton, duh'); } public static function getInstance() { if ( self::$objInstance === null ) { self::$objInstance = new self; } # end if return self::$objInstance; } # end method protected function canAccess() { if ( in_array( $_SERVER['PHP_SELF'], self::$arrRestricted ) ) { list($intTime) = mysql_fetch_array( mysql_query( " SELECT intTime FROM AccessLog WHERE chrIP = '{$this->getIP()}' " ) ); if ( $intTime > 0 && ( $intTime > ( mktime() - self::TIME_LIMIT ) ) ) { throw new Exception('Error - you cannot access this page for another '.( ( $intTime + self::TIME_LIMIT ) - mktime() ).' seconds.'); } else { mysql_query( " INSERT INTO AccessLog (chrIP, intTime) VALUES ('{$this->getIP()}', '".mktime()."') " ); } # end if } # end if } # end method public function getIP() { if ( $this->chrIP === null ) { // Get REMOTE_ADDR as the Client IP. $client_ip = ( !empty($_SERVER['REMOTE_ADDR']) ) ? $_SERVER['REMOTE_ADDR'] : $_ENV['REMOTE_ADDR']; // Check for headers used by proxy servers to send the Client IP. We should look for HTTP_CLIENT_IP before HTTP_X_FORWARDED_FOR. if ($_SERVER["HTTP_CLIENT_IP"]) { $proxy_ip = $_SERVER["HTTP_CLIENT_IP"]; } elseif ($_SERVER["HTTP_X_FORWARDED_FOR"]) { $proxy_ip = $_SERVER["HTTP_X_FORWARDED_FOR"]; } // Proxy is used, see if the specified Client IP is valid. Sometimes it's 10.x.x.x or 127.x.x.x... Just making sure. if ($proxy_ip) { if ( preg_match("/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/", $proxy_ip, $ip_list) ) { $private_ip = array('/^0\./', '/^127\.0\.0\.1/', '/^192\.168\..*/', '/^172\.16\..*/', '/^10.\.*/', '/^224.\.*/', '/^240.\.*/'); $client_ip = preg_replace($private_ip, $client_ip, $ip_list[1]); } } // Return the Client IP. $this->chrIP = $client_ip; } # end if return $this->chrIP; } # end method } # end class ?> Class based solution. To implement, just stick all that in a file (ie; session.php) and include the file at teh top of the page. Then, just call Session::getInstance(); at the top of your script. Only script defined in the $arrRestricted array will have this time based access security. This means you can just execute this line of code in a single common include in all files and have it only check the ones you want. This is a session class by the way, so anything else to do with the user's session could also be contained within this class, such as login, userid, session string, etc. Might be of some help. Note: getIP() method nicked from eek's solution as it looks good enough. Note: Will probably only work in PHP5.