Trouble getting browscap.ini to tell Safari from Internet Explorer

Hi there, folks. Although this is my first post, I regularly follow Sitepoint articles on the RSS Feed. Also I have more or less learned what I know about PHP from reading countless threads on this forum (and the PHP Manual, of course). Knocking my head gently on the desk sometimes helps.

I felt the need to register and post because of a problem I have with Apple Safari persistently spoofing Internet Explorer on Windows XP. It makes no difference whether I have the browser’s user agent set to default (Automatically chosen) or specifically Safari 5.0.3 - Windows. The browser still behaves as if it were Internet Explorer. Perhaps the problem may be down to how I handle browscap.ini but the argument in the code block below works fine for Firefox, Chrome, Opera and Explorer.

I use the following to detect the user agent and set a patch of javascript if the visitor is using Explorer on a desktop computer:


       if ($configure    ==    'desktop')
            {
                require_once('Content_Arrays.php');
                $explorer    =    null;
                $array        =    new Content_Arrays();
                $jss            =    ($array->sup);
        
                if (!isset($_COOKIE['support']))
                {
                    $browser    =    get_browser(null, true);
                    if (($browser['browser'] = 'MSIE') && ($browser['version'] < 9) || ($browser['browser'] = 'Firefox') && ($browser['version'] < 3.5) || ($browser['browser'] = 'Opera') && ($browser['version'] < 7) || ($browser['browser'] = 'Safari') && ($browser['version'] < 3))
                    {
                        $explorer    =    1;
                        $support    =    $jss[1];
                    }
                    else
                    {
                        $explorer    =    0;
                        $support    =    $jss[0];
                    }
                    setcookie('support', $explorer, time()+3600, '/', 'www.example.com', 0, 1);
                    return $support;
                }
            }

Basically, I am wondering if there might be a more specific way to query browscap that will unmask the Apple browser?

Note: I understand that user agent detection is an imperfect solution but I prefer the method to using javascript for client-side detection. The exception here is a patch to support CSS media queries in older versions of Explorer.

Use conditional comments for old versions of IE not user-agent sniffing. As you found out, sniffing the user-agent is not reliable.

Check out your if statement. You’re using an assignment “=” operator instead of a comparison"==" operator … which will always return true.

@logic_earth : I am aware of conditional comments since I’m a bit of an old lag with HTML. However, since I’m working on a small experimental site of my own, I’m trying to stretch my skills with server side programming and in this particular case study the limits of user agent detection.

@kduv : I have to admit to being somewhat confused here. Initially I tried using the comparison operator (the ‘important’ stickie at the head of this forum on Common PHP Problems warns about this mistake). But the comparison fails for all browsers in this instance. I even tried it again just now to be sure but it failed. The code works as it stands for the other four major browsers but Safari seems to persist in declaring itself as MSIE.

I am wondering if there is another more thorough comparison I might run to get around this issue.

@kduv : My sincerest apologies. I really was confused because in fact the if statement only seemed to be working for me with assignment operators. The actual error in the if statement (properly set as you suggested with comparisons) is that I was checking the browser index for ‘MSIE’ whereas I should have been checking for ‘IE’. It seems that ‘MSIE’ was throwing a positive result for Safari and Explorer by default.


if (($browser['browser'] == 'IE') && ($browser['version'] < 9) || ($browser['browser'] == 'Firefox') && ($browser['version'] < 3.5) || ($browser['browser'] == 'Opera') && ($browser['version'] < 7) || ($browser['browser'] == 'Safari') && ($browser['version'] < 3))

The corrected line above works fine now. Thanks again for the pointer, which made me take a second, third and fourth look at the code as well as a print-out of the browser array - which I should have done at the first hint something was wrong.

@logic_earth : Thank you for the reminder about conditional statements. I will add an exclusion comment around the patch for extra safety.

It’s important to note the difference between using “=” and “==” in your conditional statements. They’re not interchangeable. An if statement evaluates the expression to its boolean value and executes the code accordingly.

A single ‘=’ will assign the variable the value to the right so:


if ($browser['browser'] = 'IE') {

Becomes:


if ('IE') {

Which will evaluate to true.

A ‘==’ will compare the value to the left with the value to the right to see if they are equal. If they are equal, it evaluates as true, otherwise it evaluates to false.

Using OR (or ‘||’) in your if statement will tell PHP to return true if either of these statements are true. As soon as PHP sees it’s first statement that is true, it will stop testing anything else in the if statement.

So if your statement looks like this:


if (($browser['browser'] = 'IE') && ($browser['version'] < 9) || ($browser['browser'] = 'Firefox') && ($browser['version'] < 3.5) || ($browser['browser'] = 'Opera') && ($browser['version'] < 7) || ($browser['browser'] = 'Safari') && ($browser['version'] < 3))

As long as the browser version is less than 9, it will return true because $browser[‘browser’] = ‘IE’ will always evaluate as true. The only time the above example would return false is if the browser version is >= 9.

The only times using ‘=’ will evaluate as false is when the value to the right evaluates as “” (empty string), false, null, 0, or array() (an empty array).

Hope that helps some.

@kduv : Thanks for illustrating the point. Of course your detailed explanation helps: it’s so very easy for beginners to confuse the semantics of the assignment operator. Although the common error must be tiresomely obvious to experienced programmers, the difference can never be over-stressed to a newb like myself.

I had an instinct that I shouldn’t be doing what I did but lacked the confidence to resist making the mistake when it seemed to be getting a result. Instead I could have saved myself a deal of time and trouble if I had tested the output of get_browser() in Explorer to check the index of browser in the array. The PHP Manual even provides a simple code block to cut and paste for that very purpose.

Somehow I made the assumption that ‘MSIE’ would do the trick for Explorer and proceeded to run rings around myself getting nowhere.