Git Product home page Git Product logo

browscapcfc's People

Contributors

budschneehagen avatar henrylearn2rock avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

browscapcfc's Issues

Nested repetitions *?+ in expression

Using ColdFusion 9 or 10, the CFC regex doesn't work with browscap.ini file (v5029, 5/8/2014) available at http://browscap.org/.

I get the following error:

Malformed regular expression "^Mozilla/5\.0 \(compatible;.*Baiduspider/2\.0;.*+http://www\.baidu\.com/search/spider\.html\)$".

Reason: Nested repetitions *?+ in expression.

The error occurred in compatible;.*Baiduspider/2\.0;.*+http: Line -1 Called from C:\CFusion\cfusion\CustomTags\Browscap.cfc: line 111

ini file very slow to initialize

Hi. I love your cfc. However, since they took much of the functionality out of the default ini file I need the full file. And now that there are close to 150,000 user agent entries in the full file, it take a very long time to initialize the cfc. I've added code to initialize using the browscap.json file which takes about 3 seconds. I was unable to attach the file so here it is below if you want to incorporate it. Thanks again for your work.

/** Detect browser capabilities from user agent string from CGI using browscap.ini.
Download latest browscap.ini at http://browsers.garykeith.com/
/
component
{
/
* parsed browser capabilities from ini */
property struct browserCaps;

/** number of records of browser capabilities */
property numeric browserCapsCount; 

/** sorted from longest to shortest */
property array agentStringPatterns; 

/** parallel array of agentStringPatterns, but turned into RegEX */
property array agentRegexs; 


/**
    @iniFilePath absolute path to `browscap.ini`
*/
function init(string iniFilePath="#expandPath('./browscap.ini')#")
{
    variables.browserCaps = iniToStruct(iniFilePath);

    variables.browserCapsCount = structCount(browserCaps); 

    variables.agentStringPatterns = sortArrayByLen(structKeyArray(browserCaps), "desc");

    variables.agentRegexs = convertPatternToRegex(agentStringPatterns);

    return this;
}


private struct function iniToStruct(required string iniFilePath)
{
    var data = {};
    var file = "";

    /** If iniFilePath is a json file, serialize it and return the data. */
    if (listlast(iniFilePath, ".") is "json")
    {
        return deSerializeJson(fileRead(iniFilePath));
    }

    file = fileOpen(iniFilePath);

    while (!fileIsEOF(file))
    {
        var line = FileReadLine(file);
        var lineLen = len(line); 

        if (lineLen > 0)
        {
            switch (left(line, 1))
            {
                case ";" :
                    continue;
                break;

                case "[" :
                    section = mid(line, 2, lineLen - 2); 
                break;

                default:
                    data[section][listFirst(line, "=")] = listRest(line, "=");  
            }
        }
    }

    fileClose(file);            
    return data;
}


private array function convertPatternToRegex(required array agentStringPatterns)
{
    for (var i = 1; i <= arrayLen(agentStringPatterns); i++)
    {
        var regex = left(agentStringPatterns[i], 1) != "*" ? "^" : "";

        regex &= replaceList(agentStringPatterns[i], ".,*,?,(,),[,],+", "\.,.*,.,\(,\),\[,\],\+");

        if (right(agentStringPatterns[i], 1) != "*")
            regex &= "$";

        agentStringPatterns[i] = regex;
    }

    return agentStringPatterns;
}


/**
    @order ['asc'],'desc'
*/
private array function sortArrayByLen(required array strings, string order="asc")
{
    for (var i = 1; i <= arrayLen(strings); i++)
        local.lengths[i] = len(strings[i]);

    var sortedIndices = structSort(lengths, "numeric", order);
    var results = [];

    for (var index in sortedIndices)
        arrayAppend(results, strings[index]);

    return results;
}


/** @userAgent defaults to `CGI.HTTP_USER_AGENT` */
function getBrowser(string userAgent=CGI.HTTP_USER_AGENT)
{
    // find the longest matched agent, since agent is sorted by len desc, first agent is sufficient 
    var matchedIndex = 1;
    while (matchedIndex < variables.browserCapsCount 
            && !reFindNoCase(variables.agentRegexs[matchedIndex], userAgent))
        ++matchedIndex;

    var matchedStringPattern = agentStringPatterns[matchedIndex];
    var result = {};
    var browserCapsValue = "";
    var parentAgentValue = "";

    /** Place browserCaps[matchedStringPattern] into a variable so we can test for json. */
    browserCapsValue = browserCaps[matchedStringPattern];

    /** If browserCapsValue is json, deserialize it. */
    if (isJson(browserCapsValue)) browserCapsValue = deSerializeJson(browserCapsValue);

    structAppend(result, browserCapsValue);

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

        /** Place browserCaps[parentAgent] into a variable so we can test for json. */
        parentAgentValue = browserCaps[parentAgent];

        /** If parentAgentValue is json, deserialize it. */
        if (isJson(parentAgentValue)) parentAgentValue = deSerializeJson(parentAgentValue);

        structAppend(result, parentAgentValue, false);
    }

    return result;
}

}

Does not work on Lucee

Lucee passes arrays by reference, so convertPatternToRegex() ends up modifying the source array, preventing any matches in getBrowser().

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.