Page 1 of 1

Cookie, Javascript Checking class

Posted: Tue Feb 27, 2007 2:18 pm
by fdan
Here is a little something I have created to check if cookies and javascript are enabled.
Any comments about the algorithm? Is there a better way to achieve this task? Seems to work for me on both Firefox and IE.


Thanks for you comments.

Code: Select all

<?php 
abstract class SessionChecker{

	private static $error_number = 0;

	public static function check()
	{
		
	
		session_start();
		
		$session_ok = self::checkForSession();
		
		//echo $cookies_ok;
		
		if( $session_ok == 1)
		{	
			return 1;
		}
		else
		{
			switch ( $session_ok )
			{
				case 0:
					self::$error_number = 0;
					throw new Exception("Cookies Disabled");
					break;
				case 2:
					self::$error_number = 2;
					throw new Exception("JavaScript Disabled");
					break;
				default:
					return 0;	
					break;
			}
		}
	
	}
	
	private static function checkForSession()
	{
		if (! isset($_POST['test']) ) 
		{
			echo '<script language="JavaScript">
		  	<!--
		  	function submitform()
		  	{
  				document.sessiontest.submit();
		  	}
		  	// -->
		  	</script>'; 
			echo "<form name=\"sessiontest\" action=\"" . $_SERVER['PHP_SELF'] . " \" method=\"post\">";
			echo "<input name=\"test\" type=\"hidden\" value=\"1\" />";
			echo "</form>";
			$_SESSION['SESSION_OK'] = 1;
			echo "<script language=javascript>submitform()</script>";
			return 2;
		} 
		else
		{
			if (isset($_SESSION['SESSION_OK']) && $_SESSION['SESSION_OK'] = 1) 
			{
				return 1; 
			}
			else  
				return 0; 
		
		}
	
	}
	
	public static function getErrorNumber()
	{
		return self::$error_number;
	}

} 
?>
Invoked with:

Code: Select all

try{

	SessionChecker::check();
	
	
}
catch( Exception $e )
{

	system_misconfigured( SessionChecker::getErrorNumber());
	
}

Posted: Tue Feb 27, 2007 3:24 pm
by feyd
if (isset($_SESSION['SESSION_OK']) && $_SESSION['SESSION_OK'] = 1)
Second part will always be true. Was it intended to use assignment?

There is very very very very little reason to ever use $_SERVER['PHP_SELF'] as it directly contains user input opening yourself to very simple injection. In this case you can use "#" instead.

It's typically best to use the correct mapping to the form instead of shortcuts: documment.forms['sessiontest'].submit().

Also it would be good if the output would pass HTML validation. Currently, it will not.

Before calling the session functions, it's probably best to make sure headers haven't been sent using headers_sent().

Why is there an if and switch for $session_ok? It seems odd.


Personal nitpick: consistency in brace placement is important.

Posted: Wed Feb 28, 2007 10:13 am
by fdan
Thanks for all your suggestions. Much appreciated.

I consider myself rather inexperienced with web programming so allow me to elaborate more on some of the things you have pointed out.
There is very very very very little reason to ever use $_SERVER['PHP_SELF'] as it directly contains user input opening yourself to very simple injection. In this case you can use "#" instead.
Would it be ok to do htmlentities($_SERVER['PHP_SELF'], ENT_QUOTES) with PHP_SELF?
Before calling the session functions, it's probably best to make sure headers haven't been sent using headers_sent().
Could you explain this a little more?
Why is there an if and switch for $session_ok? It seems odd.
Thats because I want to find out what went wrong, whether the session or js failed.

The way this script works is rather strange, I have to admit.

The idea is that if there is NO javascript support, the form will not be submitted and exception will be thrown.
If the form is submitted, the exception will be STILL thrown but the newly requested page will execute setting $session_ok to either 1 or 0 indicating whether cookies (or SESSION variables) work.

Do you think this would be a robust solution? What makes me uncomfortable is the fact that during the first run when the form is submitted, both the client and the server run at the same time. The client is submitting the form, the server is throwing an exception and finishing the first page. I am not sure what will happen if, for example ,the connection is slow . I may get the "javascript not enabled" error followed soon by a newly reloaded page saying that everything is fine.

I hope that all this makes sense. let me know what you think

Posted: Wed Feb 28, 2007 10:32 am
by feyd
fdan wrote:Would it be ok to do htmlentities($_SERVER['PHP_SELF'], ENT_QUOTES) with PHP_SELF?
Stick with "#" for the most part. If you absolutely need to URL for some strange reason, search the forums for getURL(). The function has been posted several times.
fdan wrote:Could you explain this a little more?
What's more to explain? To avoid "headers already sent" errors, call headers_sent() and execute accordingly to the information it returns.
fdan wrote:What makes me uncomfortable is the fact that during the first run when the form is submitted, both the client and the server run at the same time.
check() would need to be called at least twice before an exception will throw. The server is normally done processing by the time the user receives any of its output.
fdan wrote:Do you think this would be a robust solution?
Not for myself. If I must detect Javascript (which is rare) I will typically use a very simple check involving an image-serving script. Roughly, Javascript will change the URL of an image on the page to a script. However, because Javascript may be turned on and off at will in some browsers, I typically write my pages to work without Javascript first and foremost, then add Javascript to enhance the experience (but add nothing the user couldn't get to without it.)

Posted: Wed Feb 28, 2007 10:44 am
by Begby
A few things

You should use constants with names that have meaning instead of just numbers, it will make your code a lot more readable than someone wondering what '1' is supposed to represent.

This is probably improper use of exceptions. Exceptions are for exceptional unexpected conditions such as a method receiving a null instead of an array, and in this case its expected that a number of users won't have cookies or javascript enabled. Also, hat happens if your class, or a subroutine within your class, throws a different exception than 'cookies disabled' or 'javascript disabled'? You may want to extend the extension class to a SessionException and only catch that type. Or not even use exceptions.


You can probably just shorten your code to this sans exceptions (where SESSION_OK is a class constant).

Code: Select all

if( SessionChecker::checkForSession() != SessionChecker::SESSION_OK )
{
  system_misconfigured( SessionChecker::getErrorNumber()); 
}