0

browscap.ini that get_browser() depends on is found at http://browsers.garykeith.com/downloads

Does anyone know how to port the seemingly simple get_browser() to CFML?

Thanks!

Henry
  • 32,689
  • 19
  • 120
  • 221
  • may help: http://stackoverflow.com/questions/6294932/obtaining-browser-and-version-using-coldfusion –  Jun 27 '12 at 22:45
  • @Dagon thx, I relied on `browserDetect()` for storing some visitor stats, but lately it has been returning a lot of (unknown) – Henry Jun 27 '12 at 22:48
  • smart phones/tablets, all the new exciting stuff the kids like perhaps –  Jun 27 '12 at 22:49
  • One attempt: http://forums.adobe.com/thread/620512 – Henry Jun 27 '12 at 23:52
  • 1
    So does that attempt work or not? :/ The answer to _"How to port [any function] from PHP to ColdFusion?"_ is "look at PHP code and write equivalent CFML code." If you want useful help you need to be more precise with what the problem you're having is... – Peter Boughton Jun 28 '12 at 01:50
  • @PeterBoughton yes it works, kind of. I've improved it and posted below in my answer. – Henry Jun 28 '12 at 02:05
  • Turned into a speedy CFC with custom INI parser here: https://github.com/henrylearn2rock/BrowscapCFC – Henry Jun 28 '12 at 21:01
  • `http://tempdownloads.browserscap.com/` has `browscap.ini` but it also has a warning to not use it. – James A Mohler Nov 27 '12 at 22:15

1 Answers1

0

Solved!

This is based on http://forums.adobe.com/thread/620512, and optimized for performance with improved correctness.

It is still quite slow (~1s) because working with ini file with ColdFusion means every getProfileString() is a disk I/O! Might be faster with SSD. :)

function get_browser(user_agent=CGI.HTTP_USER_AGENT, browscap_ini=expandPath("./browscap.ini"))
{
    var result = {};

    // Read wildcard patterns from the INI file
    var browscap_list = getProfileSections(browscap_ini);

    // Seed some variables
    var browser_champion_pattern = "*";

    // Loop through the patterns to find the best match (relative to length of name pattern)
    for (var browser_name_pattern in browscap_list)
    {
        if (len(browser_name_pattern) >= len(browser_champion_pattern))
        {
            // Massage the wildcard into useable regex
            var browser_name_regex = replaceList(browser_name_pattern, ".,*,?,(,),[,]", "\.,.*,.,\(,\),\[,\]");

            if (left(browser_name_pattern, 1) != "*")
                browser_name_regex = "^" & browser_name_regex;

            if (right(browser_name_pattern, 1) != "*")
                browser_name_regex &= "$";

            // Test the resulting regex against the user agent
            if (reFindNoCase(browser_name_regex, user_agent))
                browser_champion_pattern = browser_name_pattern;
        }
    }

    // Set the winning regex patterns
    var browser_name_pattern = browser_champion_pattern;

    // Fetch the winning info
    var keynames = listToArray(browscap_list[browser_champion_pattern]);
    for (var keyname in keynames)
        result[keyname] = getProfileString(browscap_ini, browser_champion_pattern, keyname);

    // Fetch the rest of the info from parents
    while (structKeyExists(result, "parent"))
    {
        var parent = result.parent;

        structDelete(result, "parent");

        var keynames = listToArray(browscap_list[parent]);
        for (var keyname in keynames)
            if (!structKeyExists(result, keyname))
                result[keyname] = getProfileString(browscap_ini, parent, keyname);
    }

    return result;
}
Henry
  • 32,689
  • 19
  • 120
  • 221
  • Turned into a speedy CFC with custom INI parser here: https://github.com/henrylearn2rock/BrowscapCFC – Henry Jun 28 '12 at 20:58
  • This requires `browscap.ini` . The site `http://browsers.garykeith.com/` seems to be down. `github.com` does not have a sample – James A Mohler Nov 27 '12 at 22:13