Ending a session/clearing cookies - php

Ok, so I've got some legacy code from another company that I have to maintain/repair. One of the features of this code is that there are several sites tied to this one main site, and whenever you navigate from the other sites to this site, a logo from the other site is displayed on the main site (basically this is a service for multiple banks to use, and each bank wants its own branding).
The problem is is that once you navigate from, say, site1 to main site, if you then navigate from site2 to main site, you'll still get site1's branding.
Is there a way to clear a session's cookies? So far they've got code like this, which should THEORETICALLY work:
else
{
setcookie("cuid","",time() - 31536000); //DELETES COOKIE
if( $cuid_demo!="samplecu" && $cuid!="samplecu" )
setcookie("cuid",$cuid,time()+2592000); //2592000 = 1 month
$link=dbconnect();
if(!$link)
die("error: Could not connect to database - ".dberror() );
select_db($link) or die("error: ".dberror() );
if (isset($admin_id))
{
$cuid = $admin_id;
$id = $admin_id;
}
$query="UPDATE cusucceed SET visits=visits+1 WHERE id = '$cuid'";
$result=dbquery($link, $query)or die("Database Server Error 2: ".dberror());
include("index_main.php");
} //END IF/ELSE TO CHECK FOR PREVIOUS VISIT WITH THE PAST MONTH
}
Before it does nothing. Shouldn't setcookie("cuid", "", time() - 31536000); delete the cookie, as the comments say?

You need to set correct domain for cookie when you reset it.
setcookie('name', NULL, -86400, 'cookie_path', 'subdomain.site1.com');

Related

create an action based on specific database information

UPDATE: Not sure why the answer was removed. But i did receive a solution and for future views I am leaving the original code below. But to make this work we simply needed to change:
if (site_active == 0)
TO:
if ($row['site_active'] == 0)
We also removed the "else exit;" code so if the site was active the page would continue to load like normal. Thank you to whoever posted this answer. Not sure why you deleted it because it worked.
Original Question:
Ok, I am using MYSQL as a database and then php for my script. I am wanting to make a script that checks whether a user's site is "active" or "disabled" this code will be placed at the beginning of each webpage. If the users website is "active" then the website will continue to load normally. If the users website is "disabled" then the website will redirect to an error page that states so.
If my client does not pay the monthly hosting fee then I will set the site to "disabled" in the database and the site will not be accessible until the payment is made. which then I will return it to an "active" state and it will be accessible again. I have came up with the following code so far (I am new to php so if it's stupid don't judge please!) When this code is executed it redirects to the page I have set no matter what rather than displaying the regular site. Any help or suggestions to make this work would be greatly appreciated!
<?php
$con=mysqli_connect("CONNECTION INFO REMOVED FOR SECURITY REASONS");
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$result = mysqli_query($con,"SELECT * FROM mypanda_clients
WHERE id='34'");
while($row = mysqli_fetch_array($result))
{
if (site_active == 0)
{
header('Location: http://www.green-panda.com/');
}
else
{
exit;
}
}
?>
<html>
<h2>Congratulations, your site is active!</h2>
</html>
Give this a try,
if ($row['site_active'] == 0)
{
.....
}

php and mysql session destroyed before update

so im trying to have a table that shows which users are online on my site I have everything working besides the part where if someone closes the site without logging out first they stay on the table as logged in. i'll try to eplain my situation the best I can.
in my database I have a users table in that table is online when you login your online status is set to 1, when you click logout online is set to 0. here is the code im trying to use so that if someone is inactive for 10minutes they will be logged out ( online set to 0 )
<?php
session_start();
$timeout = 10; // Set timeout minutes
$logout_redirect_url = "logout.php"; // Set logout URL
$timeout = $timeout * 60; // Converts minutes to seconds
if (isset($_SESSION['last_activity'])) {
$elapsed_time = time() - $_SESSION['last_activity'];
if ($elapsed_time >= $timeout) {
mysql_query("UPDATE users SET online = 0 WHERE username = '".$_SESSION['username']."'")
or die(mysql_error());
session_destroy();
header("Location: $logout_redirect_url");
}
}
$_SESSION['last_activity'] = time();
?>
This works fine it logs them out if they wait the 10minutes, but if they just close the browser it keeps online = 1 which displays them on the list.
I believe the problem is that when they close the browser that destroys the session before it gets the chance to update the users online and set it to 0
is there anyway around this? help would be very much appreciated thanks :)
btw I know not to use mysql anymore and everything, I will try to switch to something else once I learn more and get everything working first.
The underlying problem is that when a user closes their browser, there's no reliable way to first communicate with your server. [There are things you could try, but in my opinion that's a rabbit hole you shouldn't go down] All you really "know" is how recently the user visited your site logged-in. (in your case $_SESSION['last_activity']).
At a basic level, you will want to start persisting that information in your database, and then have a process kicked off occasionally to cleanup stale sessions.
e.g.
//On page load with a logged-in user
mysql_query("UPDATE `users`
SET `last_activity` = '" . time() . "'
WHERE `username` = '" . mysql_real_escape_string($_SESSION['username']) . "'");
note that assumes you've added an INT column to your table named last_activity
and then in a process that executes, say, every 15 minutes:
mysql_query("UPDATE `users`
SET `online` = 0
WHERE `last_activity` < '" . strtotime('-30 minutes') . "'");
Unix servers have something called cron especially for period tasks/scripts, so that's what I would recommend for kicking off your cleanup script.

PHP: Most efficient way to make multiple fsockopen(); connections?

Hey guys i'm making a website where you submit a server for advertising. When the user goes to the index page of my website it grabs the ip's of all the servers submitted and then tests to see if it is online using fsockopen() like so:
while($row = mysql_fetch_assoc($rs)) {
$ip = $row['ip'];
$info = #fsockopen($ip, 25565, $errno, $errstr, 0.5);
if($info) {
$status = "<div><img width='32px' height='32px'
title='$name is online!' src='images/online.png'/></div>";
$online = true;
} else {
$status = "<div><img width='32px' height='32px'
title='$name is offline!' src='images/offline.png'/></div>";
$online = false;
}
}
}
This way works fine, but the only downside is when you load the site it takes a good 2-4 seconds to start loading the website due to the fsockopen() methods being called. I want to know if there is a better way to do this that will reduce the amount of wait time before the website loads.
Any information will be appreciated, thanks.
Store the online status and last check time in a database, if the last check time is longer than 15 minutes for example, update it. I am pretty sure you don't need to get the status on EVERY pageload? It's the time it takes to connect to each server that slows down the website.
Then again, you would probably wanna move the update process to a cronjob instead of relying on someone visiting your website to update the server statuses.
Looking at your example, I'd make all the $status bits be javascript calls to another php page that checks that individual server.
However, the idea to move the status checks to cron job or use some kind of status caching is very good too. Maybe store statuses in a database only only check the ones that have expired (time limit set by you).

Session Share Across Multiple Domains On Same Server

I heard the best method to share session across multiple domains on same server is to use custom php session handler. (ie, domain name different like abc.com, xyz.com but single application.)
But after i tried it, even custom php session handler that using SAME DATABASE ON 1 SERVER can't share session, when i tried to read cookie value from different domain.
Here's my custom session handler, Please kindly check or fix if something missing here. because i've tried it for a week now. can't get it to work
P.S. To get previous session id, i use link such as: newdomain.com/?ssid=[SESSION_ID]
SESSION_INCLUDE.PHP
<?php
// config
$m_host = "localhost"; //MySQL Host
$m_user = "db_user"; //MySQL User
$m_pass = "db_pass"; //MySQL Pass
$m_db = "db_name"; //MySQL Database
$table = "sess_data";
$session_expire = 600; // Session expire time, in seconds (minutes * 60 = seconds)
$gc_probability = 100; // Probability that the garbage collection function will be called. 50% chance by default
ini_set("session.gc_probability",$gc_probability);
/* Open function; Opens/starts session
Opens a connection to the database and stays open until specifically closed
This function is called first and with each page load */
function open ($s,$n) // do not modify function parameters
{
global $session_connection, $m_host, $m_user, $m_pass, $m_db;
$session_connection = mysql_pconnect($m_host,$m_user,$m_pass);
mysql_select_db($m_db,$session_connection);
return true;
}
/* Read function; downloads data from repository to current session
Queries the mysql database, unencrypts data, and returns it.
This function is called after 'open' with each page load. */
function read ($id) // do not modify function parameters
{
global $session_connection,$session_read,$table;
$query = "SELECT data FROM `$table` WHERE id=\"{$id}\"";
$res = mysql_query($query,$session_connection);
if(mysql_num_rows($res) != 1) return ""; // must return string, not 'false'
else
{
$session_read = mysql_fetch_assoc($res);
$session_read["data"] = base64_decode($session_read["data"]);
return $session_read["data"];
}
}
function write ($id,$data) // do not modify function parameters
{
if(!$data) { return false; }
global $session_connection, $session_read, $session_expire, $table;
$expire = time() + $session_expire;
$data = mysql_real_escape_string(base64_encode($data));
if($session_read) $query = "UPDATE `$table` SET data=\"{$data}\", expire=\"{$expire}\" WHERE id=\"{$id}\"";
else $query = "INSERT INTO sess_data SET id=\"{$id}\", data=\"{$data}\", expire=\"{$expire}\"";
mysql_query($query,$session_connection);
return true;
}
function close ()
{
global $session_connection;
mysql_close($session_connection);
return true;
}
function destroy ($id) // do not modify function parameters
{
global $session_connection,$table;
$query = "DELETE FROM `$table` WHERE id=\"{$id}\"";
mysql_query($query,$session_connection);
return true;
}
function gc ($expire)
{
global $session_connection,$table;
$query = "DELETE FROM `$table` WHERE expire < ".time();
mysql_query($query,$session_connection);
}
// Set custom handlers
session_set_save_handler ("open", "close", "read", "write", "destroy", "gc");
// Start session
session_start();
?>
MySQL Database Description
create table sess_data (
id2 int not null auto_increment,
id text not null,
data text,
expire int not null,
primary key(id2)
);
You can't read cookies from one domain in another domain. That's a security thing implemented in the browser. Using a database for sessions allows you to have multiple servers share sessions on the same domain, but does not allow for multiple domains on the same server to share sessions.
If you want to share sessions between domains, you would need to implement some sort of session transfer method when you switch domains. The simplest way to do this would involve passing the session id as a GET parameter from a page on one domain to a page on the other. Then, on the other domain, you would pick up the session id and create a new session using that ID.
While that is a simple way to do it, it isn't very secure and allows for session hijacking. A better way would be to use the database to create a record with the session id in it, set a short timeout on it, and pass the ID of that record to the other domain. The other domain would then pick up the record from the database and create a session with it. If the record in the database is past it's expiration, it wouldn't pick up the session. This would provide better protection against session hijacking.
This is the purpose of session_name(). Assign a different name to each application's session to avoid collisions between $_SESSION keys. The name will be used as the session cookie's name so although both session cookies will be passed to both applications, only the one matching the application's session_name() will be used to populate $_SESSION.
// App 1
session_name('app1');
session_start();
// App 2
session_name('app2');
session_start();
You really should look into SSO (single sign-on). One option for SSO is to use OpenID (as used on SO), and using it will make your life a lot easier.
Here's an article on it : http://devzone.zend.com/article/3581
the cookies and their visibility is a problem. The browser accessing the new site would not send the session id of the old site to the server.
I think your read() does not use the ssid parameter you provide as session id but as the browser has no session with this domain the system generates one with new id as $id. Have a look if $_REQUEST['ssid'] exist in the database.
Custom session handler might a bit big for this job. You could just check if $_REQUEST['ssid'] exist in the session database and rewrite $_SESSION with it.
I was wondering if anyone could give some suggestions on my method for sharing sessions between domains on same server (same cookie storage folder).
In each pages HEAD tag on all my sites, I call the following PHP code
if(!isset($_SESSION['sso'])) {
require_once('database.php');
$sites = array('http://site1', 'http://site2');
session_regenerate_id(); //Make new session id that will be shared
$session_id = session_id();
foreach($sites as $site) {
if($site != CURRENT_SITE) {
$sesh_key = md5(SALT.$site.$session_id);
$database->insertSessionId($sesh_key, $session_id);
$url = sprintf('%s/sso_set.php?k=%s', $site, $sesh_key);
echo('<link type="text/css" rel="stylesheet" href="'.$url.'" />');
}
}
$_SESSION['sso'] = 'SET';
}
Then on each site I have a file called 'sso_set.php' which contains
<?php
session_start();
if(!isset($_SESSION['sso'])) {
require_once('database.php');
$key = $_GET['k'];
$session_id = $database->getSessionId($key);
if($session_id) {
session_destroy();
session_id($session_id);
session_start();
$database->deleteSessionId($key);
$_SESSION['sso'] = 'SET';
}
}
Is using a text/css link a good idea?
I figured this is always called even if Javascript or Images are disabled?
This code basically makes the first site out of all my sites that gets opened by the user sets the Session ID, and then passes it on to the other sites.
Seems to work pretty well.
You get a slight delay the very first time any of the sites opened and the ID is passed to the sites. But, you could do this via AJAX so the page loads fast. But, then you rely on Javascript being enabled.
Thoughts?

Tracking unique visitors only?

Currently I have a file called "hits.php" and on any page I want to track page hits I just use <?php include("hits.php"); ?>
How can I track unique visitors only though? My hits are false since it can be refreshed by the same person and hits go up.
Here's my source:
<?php
$hits = file_get_contents("./client/hits.txt");
$hits = $hits + 1;
$handle = fopen("./client/hits.txt", "w");
fwrite($handle, $hits);
fclose($handle);
print $hits;
?>
I don't really know how I could do cookie checking... is there a way to check IP's? Or what can I do?
Thanks StackO.
The simplest method would be cookie checking.
A better way would be to create an SQL database and assign the IP address as the primary key. Then whenever a user visits, you would insert that IP into the database.
Create a function included on all pages that checks for $_SESSION['logged'] which you can assign whatever 'flag' you want.
If $_SESSION['logged'] returns 'false' then insert their IP address into the MySQL database.
Set $_SESSION['logged'] to 'true' so you don't waste resources logging the IP multiple times.
Note: When creating the MySQL table, assign the IP address' field as the key.
<?php
session_start();
if (!$_SESSION['status']) {
$connection = mysql_connect("localhost", "user", "password");
mysql_select_db("ip_log", $connection);
$ip = $_SERVER['REMOTE_ADDR'];
mysql_query("INSERT INTO `database`.`table` (IP) VALUES ('$ip')");
mysql_close($connection);
$_SESSION['status'] = true;
}
?>
There isn't a perfect solution, but the first two methods (IP address and/or cookies) are the most reliable, and a combination might be even better.
Rather than reinventing the wheel I used an off the shelf solution. For commercial reasons I avoided Google Analytics (I don't want Google to know my web stats - their best interests are not mine). They're probably fine for non-commercial websites, or if you don't use Google for advertising. There are also dozens of alternatives. Eg I use Getclicky.com
At a basic level, you can get the client's IP address by using the PHP $_SERVER['REMOTE_ADDR'] property
Consider setting a cookie or using a session, though this can be defeated by deletion of a cookie or cookie rejection. See the PHP setcookie docs for more info.
There are other methods for browser fingerprinting - check out all the different data you could conceivably use at https://coveryourtracks.eff.org/
How about google analytics if you cant. you could do a database or create another file with the IPs in it, but it could get complicated with a flat file like that.
I found the solution of very poor quality and just a quick and dirty way of doing it.
I too was developing something similar and formulated a quick method which works without redundancy.
I needed a counter for every time someone accessed another user's profile.
Pseudo:
Create a table with viewer's name and viewee's name (daily_views table).
Check to see if exists the viewer's name with the viewee's name (on the same row).
If they do not exist, update user counter +1 (in users table).
Else do nothing.
Reset entire table values null every 24/12 hours via cron job.
This will deny the same person accessing the same user profile to add 1 to the
counter on refresh for the whole day (or 12 hours) whereas the above solution
by Glenn Nelson would indeed add 1 to the counter, but deny adding to every
user's counter at the same time.
Not only this, but if you were to logoff and log back in to the website, then
it would simply re-add to the counter in which some cases trolls and haxorz
wannabe's will exploit this (as the session is destroyed and started again).
Here are my sample tables:
users
{
user_id INT(8) auto increment, user_name varchar(32), user_counter INT(12)
};
daily_views
{
view_id INT(8) auto increment, viewer_name VARCHAR(32), viewee_name VARCHAR(32)
};
Here is sample code I've written:
<?php
session_start();
$uname = $_SESSION['username'];
$vieweepage = $_GET['name']; //gets the name of the persons page/profile via previous page/form
$connect = mysql_connect("localhost","user","password") or die("Couldn't connect; check your mysql_connect() settings");
$database = mysql_select_db("database") or die("Could not locate database!");
$query = mysql_query("SELECT user_counter from users");
$query = mysql_fetch_row($query);
$counter = $query[0];
$viewcheck = mysql_query("SELECT viewer_name from daily_views WHERE viewee_name='$vieweepage'");
$viewrow = mysql_num_rows($viewcheck);
$newcounter = $counter + 1;
if($viewrow == 0)
{
$update = mysql_query("UPDATE users SET user_counter='$newcounter' WHERE user_name='$vieweepage'");
$insert = mysql_query("INSERT into daily_views (viewer_name, viewee_name) VALUES ('$uname', '$vieweepage')");
}
?>
currently i am using remote address and session ID for visitor.i think its valid visitor because a single user can visit no of times in a days and counter not depends on refresh its only depends on new session.
You could save a timestamp to localStoage in javascript. LocalStoage isn't removed by the browser, so you should be save to check against that. I know that it isn't serverside checking, but it may be helpful anyway.

Categories