From 93fbb254c397794627ba04ced7c5628a9a086eaa Mon Sep 17 00:00:00 2001 From: Peter Adams Date: Mon, 23 Mar 2020 12:08:55 -0700 Subject: [PATCH] Adding support for Composer for package dependancies and updating UA parser to latest version. #477 --- .gitignore | 1 + composer.json | 22 + composer.lock | 132 +++ includes/ua-parser-2.1.1/CHANGELOG | 169 --- includes/ua-parser-2.1.1/LICENSE | 11 - includes/ua-parser-2.1.1/README.md | 125 -- includes/ua-parser-2.1.1/lib/json/JSON.php | 867 -------------- .../ua-parser-2.1.1/lib/json/jsonwrapper.php | 21 - includes/ua-parser-2.1.1/lib/spyc-0.5/COPYING | 21 - includes/ua-parser-2.1.1/lib/spyc-0.5/README | 159 --- .../lib/spyc-0.5/examples/yaml-dump.php | 25 - .../lib/spyc-0.5/examples/yaml-load.php | 21 - .../ua-parser-2.1.1/lib/spyc-0.5/spyc.php | 1046 ----------------- .../ua-parser-2.1.1/lib/spyc-0.5/spyc.yaml | 203 ---- .../lib/spyc-0.5/tests/DumpTest.php | 130 -- .../lib/spyc-0.5/tests/IndentTest.php | 65 - .../lib/spyc-0.5/tests/ParseTest.php | 322 ----- .../lib/spyc-0.5/tests/RoundTripTest.php | 61 - .../lib/spyc-0.5/tests/failing1.yaml | 2 - .../lib/spyc-0.5/tests/indent_1.yaml | 59 - .../lib/spyc-0.5/tests/quotes.yaml | 8 - includes/ua-parser-2.1.1/log/README.md | 1 - .../ua-parser-2.1.1/resources/regexes.json | 1 - .../ua-parser-2.1.1/resources/regexes.yaml | 1002 ---------------- includes/ua-parser-2.1.1/uaparser-cli.php | 279 ----- includes/ua-parser-2.1.1/uaparser.php | 303 ----- modules/base/classes/browscap.php | 22 +- 27 files changed, 167 insertions(+), 4911 deletions(-) create mode 100644 .gitignore create mode 100644 composer.json create mode 100644 composer.lock delete mode 100644 includes/ua-parser-2.1.1/CHANGELOG delete mode 100644 includes/ua-parser-2.1.1/LICENSE delete mode 100644 includes/ua-parser-2.1.1/README.md delete mode 100644 includes/ua-parser-2.1.1/lib/json/JSON.php delete mode 100644 includes/ua-parser-2.1.1/lib/json/jsonwrapper.php delete mode 100644 includes/ua-parser-2.1.1/lib/spyc-0.5/COPYING delete mode 100644 includes/ua-parser-2.1.1/lib/spyc-0.5/README delete mode 100644 includes/ua-parser-2.1.1/lib/spyc-0.5/examples/yaml-dump.php delete mode 100644 includes/ua-parser-2.1.1/lib/spyc-0.5/examples/yaml-load.php delete mode 100644 includes/ua-parser-2.1.1/lib/spyc-0.5/spyc.php delete mode 100644 includes/ua-parser-2.1.1/lib/spyc-0.5/spyc.yaml delete mode 100644 includes/ua-parser-2.1.1/lib/spyc-0.5/tests/DumpTest.php delete mode 100644 includes/ua-parser-2.1.1/lib/spyc-0.5/tests/IndentTest.php delete mode 100644 includes/ua-parser-2.1.1/lib/spyc-0.5/tests/ParseTest.php delete mode 100644 includes/ua-parser-2.1.1/lib/spyc-0.5/tests/RoundTripTest.php delete mode 100644 includes/ua-parser-2.1.1/lib/spyc-0.5/tests/failing1.yaml delete mode 100644 includes/ua-parser-2.1.1/lib/spyc-0.5/tests/indent_1.yaml delete mode 100644 includes/ua-parser-2.1.1/lib/spyc-0.5/tests/quotes.yaml delete mode 100644 includes/ua-parser-2.1.1/log/README.md delete mode 100644 includes/ua-parser-2.1.1/resources/regexes.json delete mode 100644 includes/ua-parser-2.1.1/resources/regexes.yaml delete mode 100644 includes/ua-parser-2.1.1/uaparser-cli.php delete mode 100644 includes/ua-parser-2.1.1/uaparser.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..57872d0f1 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/vendor/ diff --git a/composer.json b/composer.json new file mode 100644 index 000000000..2eb9990f5 --- /dev/null +++ b/composer.json @@ -0,0 +1,22 @@ +{ + "name": "open-web-analytics/open-web-analytics", + "description": "The open source analytics framework.", + "keywords": ["open-web-analytics","owa","web-analytics","analytics"], + "homepage": "https://www.openwebanalytics.com", + "license": "GPL-2.0", + "authors": [ + { + "name": "The OWA Team", + "email": "hello@openwebanalytics.com" + } + ], + + "config": { + "sort-packages": true + }, + + + "require": { + "ua-parser/uap-php": "~3.9.7" + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 000000000..cd7e8fba2 --- /dev/null +++ b/composer.lock @@ -0,0 +1,132 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "7da18c74af1e6314df9ae430964d9d07", + "packages": [ + { + "name": "composer/ca-bundle", + "version": "1.2.6", + "source": { + "type": "git", + "url": "https://github.com/composer/ca-bundle.git", + "reference": "47fe531de31fca4a1b997f87308e7d7804348f7e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/47fe531de31fca4a1b997f87308e7d7804348f7e", + "reference": "47fe531de31fca4a1b997f87308e7d7804348f7e", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "ext-pcre": "*", + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 8", + "psr/log": "^1.0", + "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\CaBundle\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.", + "keywords": [ + "cabundle", + "cacert", + "certificate", + "ssl", + "tls" + ], + "time": "2020-01-13T10:02:55+00:00" + }, + { + "name": "ua-parser/uap-php", + "version": "v3.9.7", + "source": { + "type": "git", + "url": "https://github.com/ua-parser/uap-php.git", + "reference": "7efc2f05b7d9817a59132e5d2e5ca91a1c071f6a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ua-parser/uap-php/zipball/7efc2f05b7d9817a59132e5d2e5ca91a1c071f6a", + "reference": "7efc2f05b7d9817a59132e5d2e5ca91a1c071f6a", + "shasum": "" + }, + "require": { + "composer/ca-bundle": "^1.1", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "<8", + "symfony/console": "^2.0 || ^3.0 || ^4.0", + "symfony/filesystem": "^2.0 || ^3.0 || ^4.0", + "symfony/finder": "^2.0 || ^3.0 || ^4.0", + "symfony/yaml": "^2.0 || ^3.0 || ^4.0" + }, + "suggest": { + "symfony/console": "Required for CLI usage - ^2.0 || ^3.0 || ^4.0", + "symfony/filesystem": "Required for CLI usage - 2.0 || ^3.0 || ^4.0", + "symfony/finder": "Required for CLI usage - ^2.0 || ^3.0 || ^4.0", + "symfony/yaml": "Required for CLI usage - ^4.0 || ^5.0" + }, + "bin": [ + "bin/uaparser" + ], + "type": "library", + "autoload": { + "psr-4": { + "UAParser\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dave Olsen", + "email": "dmolsen@gmail.com" + }, + { + "name": "Lars Strojny", + "email": "lars@strojny.net" + } + ], + "description": "A multi-language port of Browserscope's user agent parser.", + "time": "2020-02-21T09:54:14+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "plugin-api-version": "1.1.0" +} diff --git a/includes/ua-parser-2.1.1/CHANGELOG b/includes/ua-parser-2.1.1/CHANGELOG deleted file mode 100644 index bcecc9411..000000000 --- a/includes/ua-parser-2.1.1/CHANGELOG +++ /dev/null @@ -1,169 +0,0 @@ -THIS CHANGELOG IS AN ATTEMPT TO DOCUMENT CHANGES TO THIS PROJECT. -SUPER MINOR REVISION NUMBERS WON'T SHOW UP IN GITHUB BUT IT'LL HELP -ME ORGANIZE WHEN I MADE A SET OF FIXES - -UAP-2.1.1 - - FIX: making sure patch minor is being populated correctly when showing a mismatch - -UAP-2.1.0 - - ADD: support for custom regexes.json files (via @pravindahal) - - FIX: formerly private vars/functions are now protected (via @pravindahal) - - FIX: command line tool gets 'pretty' option for PHP 5.4 users (via @skyzyx) - - FIX: refactored the regexes.yaml test suite - - FIX: now check to see if allow_url_fopen is set to 'On' before trying to download the YAML file from the command line - - THX: thanks to @pravindahal and @skyzyx for the pull requests - -UAP-2.0.1 - - FIX: renamed uaParser, osParser, & deviceParser to uaParse, osParse, & deviceParse to address a bug with uaParser being recognized as the contruct function for the overall lib - - FIX: updated the test lib so that device failures are properly formatted - -UAP-2.0.0 - - ADD: toString() converts the version bits and family into a simple string - - ADD: toVersionString() converts the version bits into a simple string - - ADD: toFullString() combines the UA and OS family and version bits - - ADD: "convert" flag for uaparser-cli.php - - ADD: "pull & save just regexes.yaml" flag for uaparser-cli.php - - FIX: library is now a dynamic class - - FIX: attributes are now nested & populated like the other ua-parser libraries (e.g. $result->family is now $result->ua->family) - - FIX: uaParser(), osParser(), and deviceParser() are now public functions - - FIX: saves regexes.yaml as JSON for better performance - - FIX: removed the __DIR__ "fix" - - FIX: Apache log parsing now returns results when UA or OS families are set to "Other" and the device is listed as a smartphone or generic feature phone - - FIX: all tabs are now spaces - - FIX: a UA is now run against all three parsers - - FIX: renamed $debug var to $log to better reflect what it does - - DEL: is* boolean attributes (e.g. isMobile) have been removed - - DEL: will no longer auto-parse $_SERVER['HTTP_USER_AGENT'] if available - - DEL: tests no longer run against pgts_browser_list.yaml - - THX: thanks to @rjd22 for the dynamic class code/fix - -UAP-1.5.0 - - ADD: command line interface is now in its own file (via @Synchro) - - ADD: command line utility now supports parsing an Apache log file & recording the results - - ADD: command line utility can now parse a supplied user-agent string and push out a simple list or JSON - - ADD: test suite that uses the ua-parser project's test resources - - FIX: numerous comment & spacing fixes (via @Synchro & @Krinkle) - - FIX: remove PHP4 version of spyc (via @Synchro) - - FIX: remove .svn dirs in spyc (via @lopezdonaque) - - FIX: notes that the PHP 5.2 fix really was for 5.1 (via @Synchro) (knew this, i was lazy) - - FIX: lib now returns an object no matter what. now matches other ua-parser libs (via @Krinkle) - - FIX: checks that $_SERVER attr is set before including it. should be better for command line use. - - FIX: family attr now properly set in an edge case - - FIX: if regexes.yaml picks up bad slashes the PHP lib will account for it (e.g. GoogleTV regex) - - THX: thanks to @Krinkle and @Synchro for the numerous fixes - -UAP-1.4.5 - - FIX: an embarrassing debug print survived the last edit - - THX: thanks to @memakeit for dropping the bug report - -UAP-1.4.4 - - FIX: made sure that the regex file is only loaded once if running the library multiple times. performance boost. - - FIX: added support for identifying various game devices as mobile devices - - THX: thanks to @rjd22 for pointing out the perf issue - -UAP-1.4.3 - - FIX: added support for patch & family attributes to sort of match the other libraries - -UAP-1.4.2 - - FIX: notice if regexes.yaml is missing parens (e.g. match $1) for device & os names - -UAP-1.4.1 - - FIX: notice when using UAParser from the command line - -UAP-1.4.0 - - ADD: silent mode for the UA::get() method - - ADD: nobackup mode for the UA::get() method - - ADD: example of how to do a redirect with ua-parser-php - - The following were changes to regexes.yaml: - ---- ADD: support for Google Earth browser - ---- ADD: another regex for Firefox Mobile - ---- ADD: support for Firefox Alpha builds - ---- ADD: support for Sogou Explorer - ---- ADD: support for the Raven for Mac browser - ---- ADD: support for WebKit Nightly builds (though slightly pointless) - ---- FIX: better pattern matching for the Pale Moon browser - -UAP-v1.3.2 - - FIX: addressed false "tablet" classification for opera mobile & mini on android - - The following were changes to regexes.yaml: - ---- ADD: support for Tizen Browser (aka SLP Browser) from Samsung - ---- FIX: support for a new look Polaris 8.0 user agent string - ---- FIX: modified where the Epiphany Browser check happens - -UAP-v1.3.1 - - FIX: now doing some sanity cleaning on the user agent strings - - FIX: added a smarter default if the user agent isn't recognized at all - -UAP-v1.3.0 - - FIX: now points to Tobie's ua-parser project for the latest greatest YAML file - - FIX: YAML file is now standardized as regexes.yaml instead of user_agents_regex.yaml - - FIX: minor NOTICE issues resolved for very select UAs - -UAP-v1.2.2 - - The following were changes to user_agents_regex.yaml: - ---- ADD: support for UC Browser - -UAP-v1.2.1 - - The following were changes to user_agents_regex.yaml: - ---- ADD: support for android 4 user agents that have a dash in them - -UAP-v1.2.0 - - FIX: should be compatible with PHP 5.2 - - FIX: addressed STRICT mode errors - - FIX: addressed NOTICE for a missing variable - - FIX: if isTablet is set to true then isMobile is set to false (mobile to me means phone) - - THX: Thanks to Mike Bond of WVU Libraries for pointing out the 5.2 incompatibility - -UAP-v1.1.0 - - FIX: a number of fixes from bryan shelton - - The following were changes to user_agents_regex.yaml: - ---- ADD: support for Chrome Mobile - -UAP-v1.0.0 - - just because i don't expect to update this anytime soon and ppl report it's working - -UAP-v0.3.1 - - FIX: swapped nil for null in parse() - - FIX: smarter/saner defaults - - FIX: now using isset() for family_replacement - - THX: thanks to bryan shelton for these fixes - -UAP-v0.3.0 - - ADD: can now supply a specific UA to be checked - - ADD: if the UA contains 'tablet' isTablet is marked true - - ADD: for certain mobile OSs they report a desktop browser. marking them mobile now. - - FIX: tablet listing should now be better - - FIX: the list of mobile browsers was updated - - FIX: made sure that certain checks won't fail as "false" if a version number was a 0 - - FIX: for the device check, if it returns spider as a result it no longer marks it as mobile - - FIX: added more mobile browsers to that specific check - - The following were changes to user_agents_regex.yaml: - ---- ADD: symphony, minimo, teleca, semc, up.browser, bunjaloo, jasmine, & brew browsers supported - ---- ADD: windows mobile 6.5 os support - ---- ADD: amoi, asus, bird, dell, docomo, huawei, i-mate, kyocera, lenovo, lg, microsoft kind, - motorola, philips, samsung, softbank, & sony ericsson device checks - ---- FIX: mobile firefox, opera mobile & mini, obigo, polaris, nokiabrowser, ie mobile, - android, & mobile safari browser checks - ---- FIX: iOS support - ---- FIX: htc, android, palm/hp, kindle, ios, generic feature phones & spider device checks - -UAP-v0.2.0 - - ADD: added isMobile support - - ADD: added isTablet support - - ADD: added isComputer support - - ADD: added isSpider support - -UAP-v0.1.0 - - The following were changes to user_agents_regex.yaml: - ---- expanded support for Symbia & Nokia Devices, - ---- cleaned up some slashies, - ---- added Mobile Safari as the family replacement for iOS devices, - ---- better support for longer HTC device names - ---- added feature phones to the device check - ---- added generic smartphones to the device check - ---- added AvantGo to the ua check - ---- tweaked a lot of the nokia checks - ---- added kindle support to the device section - ---- added a generic catch for android devices. - ---- added support for blackberry devices - ---- changed the blackberry family to 'blackberry webkit' when it's a webkit browser \ No newline at end of file diff --git a/includes/ua-parser-2.1.1/LICENSE b/includes/ua-parser-2.1.1/LICENSE deleted file mode 100644 index 884be7565..000000000 --- a/includes/ua-parser-2.1.1/LICENSE +++ /dev/null @@ -1,11 +0,0 @@ -Copyright (c) 2011-2012 Dave Olsen, http://dmolsen.com -Licensed under the MIT license - -ua-parser-php is a PHP-based pseudo-port of the ua-parser project. Learn more about the ua-parser project at: - -http://code.google.com/p/ua-parser/ - -The user agents data from the ua-parser project is licensed under the Apache license. -spyc-0.5, for loading the YAML, is licensed under the MIT license. -The initial list of generic feature phones & smartphones came from Mobile Web OSP under the MIT license -The initial list of spiders was taken from Yiibu's profile project under the MIT license. \ No newline at end of file diff --git a/includes/ua-parser-2.1.1/README.md b/includes/ua-parser-2.1.1/README.md deleted file mode 100644 index e62fe73ab..000000000 --- a/includes/ua-parser-2.1.1/README.md +++ /dev/null @@ -1,125 +0,0 @@ -# ua-parser PHP Library # - -This is the PHP library for the [ua-parser](https://github.com/tobie/ua-parser) project. - -## v2.0 Changes ## - -v2.0 of the PHP library, released in December 2012, marked a huge transition from the previous pseudo-port of `ua-parser` to a true port that matches up well with the other libraries in the `ua-parser` repo. The primary changes: - -* the `UAParser` class is now dynamic -* properties are nested _(e.g. $result->family is now $result->ua->family)_ -* a user agent string is now required when using `parse()`. the auto-magical "use the server provided UA" is no longer supported. -* `uaParse()`, `osParse()`, and `deviceParse()` are public and can be used to just return those select bits for a given user agent string. -* the `is*` boolean properties _(e.g. isMobile)_ have been dropped. they now exist as part of the `ua-classifier` project. - -Please refer to the `CHANGELOG` for the full list of changes. - -## Demo ## - -You can [test the PHP library](http://uaparser.dmolsen.com/) with your browser. - -## Usage ## - -Straightforward: - -```php -require("uaparser.php"); - -$ua = "Mozilla/5.0 (Macintosh; Intel Ma..."; - -$parser = new UAParser; -$result = $parser->parse($ua); - -print $result->ua->family; // Safari -print $result->ua->major; // 6 -print $result->ua->minor; // 0 -print $result->ua->patch; // 2 -print $result->ua->toString; // Safari 6.0.2 -print $result->ua->toVersionString; // 6.0.2 - -print $result->os->family; // Mac OS X -print $result->os->major; // 10 -print $result->os->minor; // 7 -print $result->os->patch; // 5 -print $result->os->patch_minor; // [null] -print $result->os->toString; // Mac OS X 10.7.5 -print $result->os->toVersionString; // 10.7.5 - -print $result->device->family; // Other - -print $result->toFullString; // Safari 6.0.2/Mac OS X 10.7.5 -print $result->uaOriginal; // Mozilla/5.0 (Macintosh; Intel Ma... -``` - -## Using Your Own Custom regexes.json File ## - -You can use your own `regexes.json` file if you've customized the official file. I *strongly* encourage you to push back any changes you may have so others can benefit. That said, to use your own do the following: - -```php -require("uaparser.php"); - -$parser = new UAParser("path/to/custom/regexes.json"); -``` - -## Using ua-parser PHP Library from the Command Line ## - -A command line utility is now included with the PHP library. The following commands are supported: - -### Get Usage Info - -Provides simple usage information: - - php uaparser-cli.php - -### Update the regexes.json File - -Fetches an updated YAML file for `ua-parser` and overwrites the current JSON file. You can use the following as part of a cron job that runs nightly. - - php uaparser-cli.php -g [-s] [-n] - -By default is verbose. Use `-s` to turn that feature off. By default creates a back-up. Use `-n` to turn that feature off. - -### Convert an Existing regexes.yaml File to regexes.json - -With the change to v2.0 you may have an existing and customized YAML file for `ua-parser`. Use the following to convert it to JSON. - - php uaparser-cli.php -c [-s] [-n] - -By default is verbose. Use `-s` to turn that feature off. By default creates a back-up. Use `-n` to turn that feature off. - -### Grab Just the Latest regexes.yaml File From the Repository - -If you need to add a new UA it's easier to edit the original YAML and then convert it to JSON. - - php uaparser-cli.php -y - -Fetches an updated YAML file. *Warning:* This method overwrites any existing `regexes.yaml` file. - -### Parse an Apache Log File - -Parses the supplied Apache log file to test UAParser.php. Saves the UA to a file when the UA or OS family aren't recognized or when the UA is listed as a generic smartphone or as a generic feature phone. - - php uaparser-cli.php -l "/path/to/apache/logfile" - - -### Parse a Single User Agent String - -Parses a user agent string and dumps the results as a list. - - php uaparser-cli.php [-p] [-j] "your user agent string" - -Use the `-j` flag to print the result as JSON. Use the `-p` flag to pretty print the JSON result when using PHP 5.4+. - -## Credits ## - -Thanks to the [original ua-parser team](http://code.google.com/p/ua-parser/people/list) for making the YAML file available for others to build upon. - -Also, many thanks to the following major contributors to the PHP library: - -* Bryan Shelton -* Michael Bond -* @rjd22 -* Timo Tijhof -* Marcus Bointon -* Ryan Parman -* Pravin Dahal diff --git a/includes/ua-parser-2.1.1/lib/json/JSON.php b/includes/ua-parser-2.1.1/lib/json/JSON.php deleted file mode 100644 index 95a4ccfd4..000000000 --- a/includes/ua-parser-2.1.1/lib/json/JSON.php +++ /dev/null @@ -1,867 +0,0 @@ - - * @author Matt Knapp - * @author Brett Stimmerman - * @copyright 2005 Michal Migurski - * @version CVS: $Id: JSON.php 292911 2010-01-02 04:04:10Z alan_k $ - * @license http://www.opensource.org/licenses/bsd-license.php - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198 - */ - -/** - * Marker constant for Services_JSON::decode(), used to flag stack state - */ -define('SERVICES_JSON_SLICE', 1); - -/** - * Marker constant for Services_JSON::decode(), used to flag stack state - */ -define('SERVICES_JSON_IN_STR', 2); - -/** - * Marker constant for Services_JSON::decode(), used to flag stack state - */ -define('SERVICES_JSON_IN_ARR', 3); - -/** - * Marker constant for Services_JSON::decode(), used to flag stack state - */ -define('SERVICES_JSON_IN_OBJ', 4); - -/** - * Marker constant for Services_JSON::decode(), used to flag stack state - */ -define('SERVICES_JSON_IN_CMT', 5); - -/** - * Behavior switch for Services_JSON::decode() - */ -define('SERVICES_JSON_LOOSE_TYPE', 16); - -/** - * Behavior switch for Services_JSON::decode() - */ -define('SERVICES_JSON_SUPPRESS_ERRORS', 32); - -/** - * Converts to and from JSON format. - * - * Brief example of use: - * - * - * // create a new instance of Services_JSON - * $json = new Services_JSON(); - * - * // convert a complexe value to JSON notation, and send it to the browser - * $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4))); - * $output = $json->encode($value); - * - * print($output); - * // prints: ["foo","bar",[1,2,"baz"],[3,[4]]] - * - * // accept incoming POST data, assumed to be in JSON notation - * $input = file_get_contents('php://input', 1000000); - * $value = $json->decode($input); - * - */ -class Services_JSON -{ - /** - * constructs a new JSON instance - * - * @param int $use object behavior flags; combine with boolean-OR - * - * possible values: - * - SERVICES_JSON_LOOSE_TYPE: loose typing. - * "{...}" syntax creates associative arrays - * instead of objects in decode(). - * - SERVICES_JSON_SUPPRESS_ERRORS: error suppression. - * Values which can't be encoded (e.g. resources) - * appear as NULL instead of throwing errors. - * By default, a deeply-nested resource will - * bubble up with an error, so all return values - * from encode() should be checked with isError() - */ - function Services_JSON($use = 0) - { - $this->use = $use; - } - - /** - * convert a string from one UTF-16 char to one UTF-8 char - * - * Normally should be handled by mb_convert_encoding, but - * provides a slower PHP-only method for installations - * that lack the multibye string extension. - * - * @param string $utf16 UTF-16 character - * @return string UTF-8 character - * @access private - */ - function utf162utf8($utf16) - { - // oh please oh please oh please oh please oh please - if(function_exists('mb_convert_encoding')) { - return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16'); - } - - $bytes = (ord($utf16{0}) << 8) | ord($utf16{1}); - - switch(true) { - case ((0x7F & $bytes) == $bytes): - // this case should never be reached, because we are in ASCII range - // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - return chr(0x7F & $bytes); - - case (0x07FF & $bytes) == $bytes: - // return a 2-byte UTF-8 character - // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - return chr(0xC0 | (($bytes >> 6) & 0x1F)) - . chr(0x80 | ($bytes & 0x3F)); - - case (0xFFFF & $bytes) == $bytes: - // return a 3-byte UTF-8 character - // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - return chr(0xE0 | (($bytes >> 12) & 0x0F)) - . chr(0x80 | (($bytes >> 6) & 0x3F)) - . chr(0x80 | ($bytes & 0x3F)); - } - - // ignoring UTF-32 for now, sorry - return ''; - } - - /** - * convert a string from one UTF-8 char to one UTF-16 char - * - * Normally should be handled by mb_convert_encoding, but - * provides a slower PHP-only method for installations - * that lack the multibye string extension. - * - * @param string $utf8 UTF-8 character - * @return string UTF-16 character - * @access private - */ - function utf82utf16($utf8) - { - // oh please oh please oh please oh please oh please - if(function_exists('mb_convert_encoding')) { - return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8'); - } - - switch(strlen($utf8)) { - case 1: - // this case should never be reached, because we are in ASCII range - // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - return $utf8; - - case 2: - // return a UTF-16 character from a 2-byte UTF-8 char - // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - return chr(0x07 & (ord($utf8{0}) >> 2)) - . chr((0xC0 & (ord($utf8{0}) << 6)) - | (0x3F & ord($utf8{1}))); - - case 3: - // return a UTF-16 character from a 3-byte UTF-8 char - // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - return chr((0xF0 & (ord($utf8{0}) << 4)) - | (0x0F & (ord($utf8{1}) >> 2))) - . chr((0xC0 & (ord($utf8{1}) << 6)) - | (0x7F & ord($utf8{2}))); - } - - // ignoring UTF-32 for now, sorry - return ''; - } - - /** - * encodes an arbitrary variable into JSON format (and sends JSON Header) - * - * @param mixed $var any number, boolean, string, array, or object to be encoded. - * see argument 1 to Services_JSON() above for array-parsing behavior. - * if var is a strng, note that encode() always expects it - * to be in ASCII or UTF-8 format! - * - * @return mixed JSON string representation of input var or an error if a problem occurs - * @access public - */ - function encode($var) - { - header('Content-type: application/json'); - return $this->encodeUnsafe($var); - } - /** - * encodes an arbitrary variable into JSON format without JSON Header - warning - may allow CSS!!!!) - * - * @param mixed $var any number, boolean, string, array, or object to be encoded. - * see argument 1 to Services_JSON() above for array-parsing behavior. - * if var is a strng, note that encode() always expects it - * to be in ASCII or UTF-8 format! - * - * @return mixed JSON string representation of input var or an error if a problem occurs - * @access public - */ - function encodeUnsafe($var) - { - // see bug #16908 - regarding numeric locale printing - $lc = setlocale(LC_NUMERIC, 0); - setlocale(LC_NUMERIC, 'C'); - $ret = $this->_encode($var); - setlocale(LC_NUMERIC, $lc); - return $ret; - - } - /** - * PRIVATE CODE that does the work of encodes an arbitrary variable into JSON format - * - * @param mixed $var any number, boolean, string, array, or object to be encoded. - * see argument 1 to Services_JSON() above for array-parsing behavior. - * if var is a strng, note that encode() always expects it - * to be in ASCII or UTF-8 format! - * - * @return mixed JSON string representation of input var or an error if a problem occurs - * @access public - */ - function _encode($var) - { - - switch (gettype($var)) { - case 'boolean': - return $var ? 'true' : 'false'; - - case 'NULL': - return 'null'; - - case 'integer': - return (int) $var; - - case 'double': - case 'float': - return (float) $var; - - case 'string': - // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT - $ascii = ''; - $strlen_var = strlen($var); - - /* - * Iterate over every character in the string, - * escaping with a slash or encoding to UTF-8 where necessary - */ - for ($c = 0; $c < $strlen_var; ++$c) { - - $ord_var_c = ord($var{$c}); - - switch (true) { - case $ord_var_c == 0x08: - $ascii .= '\b'; - break; - case $ord_var_c == 0x09: - $ascii .= '\t'; - break; - case $ord_var_c == 0x0A: - $ascii .= '\n'; - break; - case $ord_var_c == 0x0C: - $ascii .= '\f'; - break; - case $ord_var_c == 0x0D: - $ascii .= '\r'; - break; - - case $ord_var_c == 0x22: - case $ord_var_c == 0x2F: - case $ord_var_c == 0x5C: - // double quote, slash, slosh - $ascii .= '\\'.$var{$c}; - break; - - case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)): - // characters U-00000000 - U-0000007F (same as ASCII) - $ascii .= $var{$c}; - break; - - case (($ord_var_c & 0xE0) == 0xC0): - // characters U-00000080 - U-000007FF, mask 110XXXXX - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - if ($c+1 >= $strlen_var) { - $c += 1; - $ascii .= '?'; - break; - } - - $char = pack('C*', $ord_var_c, ord($var{$c + 1})); - $c += 1; - $utf16 = $this->utf82utf16($char); - $ascii .= sprintf('\u%04s', bin2hex($utf16)); - break; - - case (($ord_var_c & 0xF0) == 0xE0): - if ($c+2 >= $strlen_var) { - $c += 2; - $ascii .= '?'; - break; - } - // characters U-00000800 - U-0000FFFF, mask 1110XXXX - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $char = pack('C*', $ord_var_c, - @ord($var{$c + 1}), - @ord($var{$c + 2})); - $c += 2; - $utf16 = $this->utf82utf16($char); - $ascii .= sprintf('\u%04s', bin2hex($utf16)); - break; - - case (($ord_var_c & 0xF8) == 0xF0): - if ($c+3 >= $strlen_var) { - $c += 3; - $ascii .= '?'; - break; - } - // characters U-00010000 - U-001FFFFF, mask 11110XXX - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $char = pack('C*', $ord_var_c, - ord($var{$c + 1}), - ord($var{$c + 2}), - ord($var{$c + 3})); - $c += 3; - $utf16 = $this->utf82utf16($char); - $ascii .= sprintf('\u%04s', bin2hex($utf16)); - break; - - case (($ord_var_c & 0xFC) == 0xF8): - // characters U-00200000 - U-03FFFFFF, mask 111110XX - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - if ($c+4 >= $strlen_var) { - $c += 4; - $ascii .= '?'; - break; - } - $char = pack('C*', $ord_var_c, - ord($var{$c + 1}), - ord($var{$c + 2}), - ord($var{$c + 3}), - ord($var{$c + 4})); - $c += 4; - $utf16 = $this->utf82utf16($char); - $ascii .= sprintf('\u%04s', bin2hex($utf16)); - break; - - case (($ord_var_c & 0xFE) == 0xFC): - if ($c+5 >= $strlen_var) { - $c += 5; - $ascii .= '?'; - break; - } - // characters U-04000000 - U-7FFFFFFF, mask 1111110X - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $char = pack('C*', $ord_var_c, - ord($var{$c + 1}), - ord($var{$c + 2}), - ord($var{$c + 3}), - ord($var{$c + 4}), - ord($var{$c + 5})); - $c += 5; - $utf16 = $this->utf82utf16($char); - $ascii .= sprintf('\u%04s', bin2hex($utf16)); - break; - } - } - return '"'.$ascii.'"'; - - case 'array': - /* - * As per JSON spec if any array key is not an integer - * we must treat the the whole array as an object. We - * also try to catch a sparsely populated associative - * array with numeric keys here because some JS engines - * will create an array with empty indexes up to - * max_index which can cause memory issues and because - * the keys, which may be relevant, will be remapped - * otherwise. - * - * As per the ECMA and JSON specification an object may - * have any string as a property. Unfortunately due to - * a hole in the ECMA specification if the key is a - * ECMA reserved word or starts with a digit the - * parameter is only accessible using ECMAScript's - * bracket notation. - */ - - // treat as a JSON object - if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) { - $properties = array_map(array($this, 'name_value'), - array_keys($var), - array_values($var)); - - foreach($properties as $property) { - if(Services_JSON::isError($property)) { - return $property; - } - } - - return '{' . join(',', $properties) . '}'; - } - - // treat it like a regular array - $elements = array_map(array($this, '_encode'), $var); - - foreach($elements as $element) { - if(Services_JSON::isError($element)) { - return $element; - } - } - - return '[' . join(',', $elements) . ']'; - - case 'object': - $vars = get_object_vars($var); - - $properties = array_map(array($this, 'name_value'), - array_keys($vars), - array_values($vars)); - - foreach($properties as $property) { - if(Services_JSON::isError($property)) { - return $property; - } - } - - return '{' . join(',', $properties) . '}'; - - default: - return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS) - ? 'null' - : new Services_JSON_Error(gettype($var)." can not be encoded as JSON string"); - } - } - - /** - * array-walking function for use in generating JSON-formatted name-value pairs - * - * @param string $name name of key to use - * @param mixed $value reference to an array element to be encoded - * - * @return string JSON-formatted name-value pair, like '"name":value' - * @access private - */ - function name_value($name, $value) - { - $encoded_value = $this->_encode($value); - - if(Services_JSON::isError($encoded_value)) { - return $encoded_value; - } - - return $this->_encode(strval($name)) . ':' . $encoded_value; - } - - /** - * reduce a string by removing leading and trailing comments and whitespace - * - * @param $str string string value to strip of comments and whitespace - * - * @return string string value stripped of comments and whitespace - * @access private - */ - function reduce_string($str) - { - $str = preg_replace(array( - - // eliminate single line comments in '// ...' form - '#^\s*//(.+)$#m', - - // eliminate multi-line comments in '/* ... */' form, at start of string - '#^\s*/\*(.+)\*/#Us', - - // eliminate multi-line comments in '/* ... */' form, at end of string - '#/\*(.+)\*/\s*$#Us' - - ), '', $str); - - // eliminate extraneous space - return trim($str); - } - - /** - * decodes a JSON string into appropriate variable - * - * @param string $str JSON-formatted string - * - * @return mixed number, boolean, string, array, or object - * corresponding to given JSON input string. - * See argument 1 to Services_JSON() above for object-output behavior. - * Note that decode() always returns strings - * in ASCII or UTF-8 format! - * @access public - */ - function decode($str) - { - $str = $this->reduce_string($str); - - switch (strtolower($str)) { - case 'true': - return true; - - case 'false': - return false; - - case 'null': - return null; - - default: - $m = array(); - - if (is_numeric($str)) { - // Lookie-loo, it's a number - - // This would work on its own, but I'm trying to be - // good about returning integers where appropriate: - // return (float)$str; - - // Return float or int, as appropriate - return ((float)$str == (integer)$str) - ? (integer)$str - : (float)$str; - - } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) { - // STRINGS RETURNED IN UTF-8 FORMAT - $delim = substr($str, 0, 1); - $chrs = substr($str, 1, -1); - $utf8 = ''; - $strlen_chrs = strlen($chrs); - - for ($c = 0; $c < $strlen_chrs; ++$c) { - - $substr_chrs_c_2 = substr($chrs, $c, 2); - $ord_chrs_c = ord($chrs{$c}); - - switch (true) { - case $substr_chrs_c_2 == '\b': - $utf8 .= chr(0x08); - ++$c; - break; - case $substr_chrs_c_2 == '\t': - $utf8 .= chr(0x09); - ++$c; - break; - case $substr_chrs_c_2 == '\n': - $utf8 .= chr(0x0A); - ++$c; - break; - case $substr_chrs_c_2 == '\f': - $utf8 .= chr(0x0C); - ++$c; - break; - case $substr_chrs_c_2 == '\r': - $utf8 .= chr(0x0D); - ++$c; - break; - - case $substr_chrs_c_2 == '\\"': - case $substr_chrs_c_2 == '\\\'': - case $substr_chrs_c_2 == '\\\\': - case $substr_chrs_c_2 == '\\/': - if (($delim == '"' && $substr_chrs_c_2 != '\\\'') || - ($delim == "'" && $substr_chrs_c_2 != '\\"')) { - $utf8 .= $chrs{++$c}; - } - break; - - case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)): - // single, escaped unicode character - $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2))) - . chr(hexdec(substr($chrs, ($c + 4), 2))); - $utf8 .= $this->utf162utf8($utf16); - $c += 5; - break; - - case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F): - $utf8 .= $chrs{$c}; - break; - - case ($ord_chrs_c & 0xE0) == 0xC0: - // characters U-00000080 - U-000007FF, mask 110XXXXX - //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $utf8 .= substr($chrs, $c, 2); - ++$c; - break; - - case ($ord_chrs_c & 0xF0) == 0xE0: - // characters U-00000800 - U-0000FFFF, mask 1110XXXX - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $utf8 .= substr($chrs, $c, 3); - $c += 2; - break; - - case ($ord_chrs_c & 0xF8) == 0xF0: - // characters U-00010000 - U-001FFFFF, mask 11110XXX - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $utf8 .= substr($chrs, $c, 4); - $c += 3; - break; - - case ($ord_chrs_c & 0xFC) == 0xF8: - // characters U-00200000 - U-03FFFFFF, mask 111110XX - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $utf8 .= substr($chrs, $c, 5); - $c += 4; - break; - - case ($ord_chrs_c & 0xFE) == 0xFC: - // characters U-04000000 - U-7FFFFFFF, mask 1111110X - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $utf8 .= substr($chrs, $c, 6); - $c += 5; - break; - - } - - } - - return $utf8; - - } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) { - // array, or object notation - - if ($str{0} == '[') { - $stk = array(SERVICES_JSON_IN_ARR); - $arr = array(); - } else { - if ($this->use & SERVICES_JSON_LOOSE_TYPE) { - $stk = array(SERVICES_JSON_IN_OBJ); - $obj = array(); - } else { - $stk = array(SERVICES_JSON_IN_OBJ); - $obj = new stdClass(); - } - } - - array_push($stk, array('what' => SERVICES_JSON_SLICE, - 'where' => 0, - 'delim' => false)); - - $chrs = substr($str, 1, -1); - $chrs = $this->reduce_string($chrs); - - if ($chrs == '') { - if (reset($stk) == SERVICES_JSON_IN_ARR) { - return $arr; - - } else { - return $obj; - - } - } - - //print("\nparsing {$chrs}\n"); - - $strlen_chrs = strlen($chrs); - - for ($c = 0; $c <= $strlen_chrs; ++$c) { - - $top = end($stk); - $substr_chrs_c_2 = substr($chrs, $c, 2); - - if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) { - // found a comma that is not inside a string, array, etc., - // OR we've reached the end of the character list - $slice = substr($chrs, $top['where'], ($c - $top['where'])); - array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false)); - //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); - - if (reset($stk) == SERVICES_JSON_IN_ARR) { - // we are in an array, so just push an element onto the stack - array_push($arr, $this->decode($slice)); - - } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) { - // we are in an object, so figure - // out the property name and set an - // element in an associative array, - // for now - $parts = array(); - - if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { - // "name":value pair - $key = $this->decode($parts[1]); - $val = $this->decode($parts[2]); - - if ($this->use & SERVICES_JSON_LOOSE_TYPE) { - $obj[$key] = $val; - } else { - $obj->$key = $val; - } - } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { - // name:value pair, where name is unquoted - $key = $parts[1]; - $val = $this->decode($parts[2]); - - if ($this->use & SERVICES_JSON_LOOSE_TYPE) { - $obj[$key] = $val; - } else { - $obj->$key = $val; - } - } - - } - - } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) { - // found a quote, and we are not inside a string - array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c})); - //print("Found start of string at {$c}\n"); - - } elseif (($chrs{$c} == $top['delim']) && - ($top['what'] == SERVICES_JSON_IN_STR) && - ((strlen(substr($chrs, 0, $c)) - strlen(rtrim(substr($chrs, 0, $c), '\\'))) % 2 != 1)) { - // found a quote, we're in a string, and it's not escaped - // we know that it's not escaped becase there is _not_ an - // odd number of backslashes at the end of the string so far - array_pop($stk); - //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n"); - - } elseif (($chrs{$c} == '[') && - in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { - // found a left-bracket, and we are in an array, object, or slice - array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false)); - //print("Found start of array at {$c}\n"); - - } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) { - // found a right-bracket, and we're in an array - array_pop($stk); - //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); - - } elseif (($chrs{$c} == '{') && - in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { - // found a left-brace, and we are in an array, object, or slice - array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false)); - //print("Found start of object at {$c}\n"); - - } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) { - // found a right-brace, and we're in an object - array_pop($stk); - //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); - - } elseif (($substr_chrs_c_2 == '/*') && - in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { - // found a comment start, and we are in an array, object, or slice - array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false)); - $c++; - //print("Found start of comment at {$c}\n"); - - } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) { - // found a comment end, and we're in one now - array_pop($stk); - $c++; - - for ($i = $top['where']; $i <= $c; ++$i) - $chrs = substr_replace($chrs, ' ', $i, 1); - - //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); - - } - - } - - if (reset($stk) == SERVICES_JSON_IN_ARR) { - return (array)$arr; - - } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) { - return (array)$obj; - - } - - } - } - } - - /** - * @todo Ultimately, this should just call PEAR::isError() - */ - function isError($data, $code = null) - { - if (class_exists('pear')) { - return PEAR::isError($data, $code); - } elseif (is_object($data) && (get_class($data) == 'services_json_error' || - is_subclass_of($data, 'services_json_error'))) { - return true; - } - - return false; - } -} - -if (class_exists('PEAR_Error')) { - - class Services_JSON_Error extends PEAR_Error - { - function Services_JSON_Error($message = 'unknown error', $code = null, - $mode = null, $options = null, $userinfo = null) - { - parent::PEAR_Error($message, $code, $mode, $options, $userinfo); - } - } - -} else { - - /** - * @todo Ultimately, this class shall be descended from PEAR_Error - */ - class Services_JSON_Error - { - function Services_JSON_Error($message = 'unknown error', $code = null, - $mode = null, $options = null, $userinfo = null) - { - - } - } - -} - diff --git a/includes/ua-parser-2.1.1/lib/json/jsonwrapper.php b/includes/ua-parser-2.1.1/lib/json/jsonwrapper.php deleted file mode 100644 index e26950d8f..000000000 --- a/includes/ua-parser-2.1.1/lib/json/jsonwrapper.php +++ /dev/null @@ -1,21 +0,0 @@ -encode($arg); -} - -function json_decode($arg) { - global $services_json; - if (!isset($services_json)) { - $services_json = new Services_JSON(); - } - return $services_json->decode($arg); -} - -?> diff --git a/includes/ua-parser-2.1.1/lib/spyc-0.5/COPYING b/includes/ua-parser-2.1.1/lib/spyc-0.5/COPYING deleted file mode 100644 index 8e7ddbcf6..000000000 --- a/includes/ua-parser-2.1.1/lib/spyc-0.5/COPYING +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License - -Copyright (c) 2011 Vladimir Andersen - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file diff --git a/includes/ua-parser-2.1.1/lib/spyc-0.5/README b/includes/ua-parser-2.1.1/lib/spyc-0.5/README deleted file mode 100644 index 4d7716686..000000000 --- a/includes/ua-parser-2.1.1/lib/spyc-0.5/README +++ /dev/null @@ -1,159 +0,0 @@ -# -# S P Y C -# a simple php yaml class -# -# Load this README! -# >> $readme = Spyc::YAMLLoad('README'); -# ---- %YAML:1.1 -title: Spyc -- a Simple PHP YAML Class -version: 0.5 -authors: [chris wanstrath (chris@ozmm.org), vlad andersen (vlad.andersen@gmail.com)] -websites: [http://www.yaml.org, http://spyc.sourceforge.net] -license: [MIT License, http://www.opensource.org/licenses/mit-license.php] -copyright: "(c) 2005-2006 Chris Wanstrath, 2006-2011 Vlad Andersen" -tested on: [php 5.2.x] - -installation: > - Copy spyc.php to a directory you can - access with your YAML-ready PHP script. - - That's it! - -about: > - From www.yaml.org: - - "YAML(tm) (rhymes with 'camel') is a human-friendly, cross language, - Unicode based data serialization language designed around the common - native data structures of agile programming languages. It is broadly - useful for programming needs ranging from configuration files to - Internet messaging to object persistence to data auditing. Together - with the Unicode standard for characters, the YAML specification provides - all the information necessary to understand YAML Version 1.1 and to - creating programs that process YAML information. - - YAML(tm) is a balance of the following design goals: - - YAML documents are very readable by humans. - - YAML interacts well with scripting languages. - - YAML uses host languages' native data structures. - - YAML has a consistent information model. - - YAML enables stream-based processing. - - YAML is expressive and extensible. - - YAML is easy to implement." - - YAML makes a lot of sense. It's easy to use, easy to learn, and cool. - As the lucky stiff named why once said, "YAML is a beacon of light." - - If you're new to YAML, may we suggest YAML In Five Minutes: - - http://yaml.kwiki.org/?YamlInFiveMinutes - - If you don't have five minutes, realize that this README is a completely - valid YAML document. Dig in, load this or any YAML file into an array - with Spyc and see how easy it is to translate friendly text into usable - data. - - The purpose of Spyc is to provide a pure PHP alternative to Syck, a - simple API for loading and dumping YAML documents, a YAML loader which - understands a usable subset of the YAML spec, and to further spread - the glory of YAML to the PHP masses. - - If you're at all hesitant ("usable subset of YAML?!"), navigate - http://yaml.org/start.html. Spyc completely understands the YAML - document shown there, a document which has features way beyond the - scope of what normal config files might require. Try it for yourself, - and then start enjoying the peace of mind YAML brings to your life. - -meat and a few potatoes: - - concept: Loading a YAML document into PHP - brief: > - $yaml will become an array of all the data in wicked.yaml - code: | - - include('spyc.php'); - - $yaml = Spyc::YAMLLoad('wicked.yaml'); - - - concept: Loading a YAML string into PHP - brief: > - $array will look like this: - array('A YAML','document in a','string') - code: | - - include('spyc.php'); - - $yaml = '- A YAML\n- document in a\n- string.'; - $array = Spyc::YAMLLoad($yaml); - - - concept: Dumping a PHP array to YAML - brief: > - $yaml will become a string of a YAML document created from - $array. - code: | - - include('spyc.php'); - - $array['name'] = 'chris'; - $array['sport'] = 'curbing'; - - $yaml = Spyc::YAMLDump($array); - -prior art: - - who: [Brian Ingerson, Clark Evans, Oren Ben-Kiki] - why?: > - The YAML spec is really a piece of work, and these guys - did a great job on it. A simple and elegant language like - YAML was a long time coming and it's refreshing to know - such able minded individuals took the task to heart and - executed it with cunning and strength. In addition to - their various noteworthy contributions to YAML parsers - and related projects, YAML.pm's README is a treasure trove - of information for knowledge seekers. Thanks, guys. - - - who: why the lucky stiff - why?: > - As the author of Syck, the code used in Ruby for the language's - YAML class and methods, why is indirectly (directly?) responsible - for my first exposure to YAML (as a config file in a Ruby web-app) - and the countless hours I spent playing with this sheik new data - format afterwards. Syck's README is a YAML file and thus the - inspiration for this file and, even, this very piece of software. - - - who: Steve Howell - why?: > - Python's YAML implementation. PyYAML's README file is also YAML, - so it too inspired the YAML format of this README file. - - - who: [Rasmus Lerdorf, Zeev Suraski, Andi Gutmans, et al] - why?: > - PHP is great at what it does best. It's also paid a lot of my bills. - Thanks. - -bugs: - report: > - Please see Spyc's Sourceforge project page for information on reporting bugs. - speed: > - This implementation was not designed for speed. Rather, it - was designed for those who need a pure PHP implementation of - a YAML parser and who are not overly concerned with performance. - If you want speed, check out Syck. - depth: > - This parser is by no means a comprehensive YAML parser. For supported - features and future plans, check the website. - unicode: > - YAML is supposed to be unicode, but for now we're just using ASCII. - PHP has crappy unicode support but who knows what the future holds. - -resources: - - http://www.yaml.org - - http://www.yaml.org/spec/ - - http://yaml.kwiki.org/?YamlInFiveMinutes - - http://www.whytheluckystiff.net/syck/ - - http://yaml4r.sourceforge.net/cookbook/ - -thanks: - - Adam Wood - - Daniel Ferreira - - Aaron Jensen - - Mike Thornton - - Fabien Potencier - - Mustafa Kumas \ No newline at end of file diff --git a/includes/ua-parser-2.1.1/lib/spyc-0.5/examples/yaml-dump.php b/includes/ua-parser-2.1.1/lib/spyc-0.5/examples/yaml-dump.php deleted file mode 100644 index 05a8a2fa5..000000000 --- a/includes/ua-parser-2.1.1/lib/spyc-0.5/examples/yaml-dump.php +++ /dev/null @@ -1,25 +0,0 @@ - 'A sequence','second' => 'of mapped values'); -$array['Mapped'] = array('A sequence','which is mapped'); -$array['A Note'] = 'What if your text is too long?'; -$array['Another Note'] = 'If that is the case, the dumper will probably fold your text by using a block. Kinda like this.'; -$array['The trick?'] = 'The trick is that we overrode the default indent, 2, to 4 and the default wordwrap, 40, to 60.'; -$array['Old Dog'] = "And if you want\n to preserve line breaks, \ngo ahead!"; -$array['key:withcolon'] = "Should support this to"; - -$yaml = Spyc::YAMLDump($array,4,60); \ No newline at end of file diff --git a/includes/ua-parser-2.1.1/lib/spyc-0.5/examples/yaml-load.php b/includes/ua-parser-2.1.1/lib/spyc-0.5/examples/yaml-load.php deleted file mode 100644 index fba95715d..000000000 --- a/includes/ua-parser-2.1.1/lib/spyc-0.5/examples/yaml-load.php +++ /dev/null @@ -1,21 +0,0 @@ -spyc.yaml loaded into PHP:
'; -print_r($array); -echo ''; - - -echo '
YAML Data dumped back:
'; -echo Spyc::YAMLDump($array); -echo '
'; diff --git a/includes/ua-parser-2.1.1/lib/spyc-0.5/spyc.php b/includes/ua-parser-2.1.1/lib/spyc-0.5/spyc.php deleted file mode 100644 index e19d56203..000000000 --- a/includes/ua-parser-2.1.1/lib/spyc-0.5/spyc.php +++ /dev/null @@ -1,1046 +0,0 @@ - - * @author Chris Wanstrath - * @link http://code.google.com/p/spyc/ - * @copyright Copyright 2005-2006 Chris Wanstrath, 2006-2011 Vlad Andersen - * @license http://www.opensource.org/licenses/mit-license.php MIT License - * @package Spyc - */ - -if (!function_exists('spyc_load')) { - /** - * Parses YAML to array. - * @param string $string YAML string. - * @return array - */ - function spyc_load ($string) { - return Spyc::YAMLLoadString($string); - } -} - -if (!function_exists('spyc_load_file')) { - /** - * Parses YAML to array. - * @param string $file Path to YAML file. - * @return array - */ - function spyc_load_file ($file) { - return Spyc::YAMLLoad($file); - } -} - -/** - * The Simple PHP YAML Class. - * - * This class can be used to read a YAML file and convert its contents - * into a PHP array. It currently supports a very limited subsection of - * the YAML spec. - * - * Usage: - * - * $Spyc = new Spyc; - * $array = $Spyc->load($file); - * - * or: - * - * $array = Spyc::YAMLLoad($file); - * - * or: - * - * $array = spyc_load_file($file); - * - * @package Spyc - */ -class Spyc { - - // SETTINGS - - const REMPTY = "\0\0\0\0\0"; - - /** - * Setting this to true will force YAMLDump to enclose any string value in - * quotes. False by default. - * - * @var bool - */ - public $setting_dump_force_quotes = false; - - /** - * Setting this to true will forse YAMLLoad to use syck_load function when - * possible. False by default. - * @var bool - */ - public $setting_use_syck_is_possible = false; - - - - /**#@+ - * @access private - * @var mixed - */ - private $_dumpIndent; - private $_dumpWordWrap; - private $_containsGroupAnchor = false; - private $_containsGroupAlias = false; - private $path; - private $result; - private $LiteralPlaceHolder = '___YAML_Literal_Block___'; - private $SavedGroups = array(); - private $indent; - /** - * Path modifier that should be applied after adding current element. - * @var array - */ - private $delayedPath = array(); - - /**#@+ - * @access public - * @var mixed - */ - public $_nodeId; - -/** - * Load a valid YAML string to Spyc. - * @param string $input - * @return array - */ - public function load ($input) { - return $this->__loadString($input); - } - - /** - * Load a valid YAML file to Spyc. - * @param string $file - * @return array - */ - public function loadFile ($file) { - return $this->__load($file); - } - - /** - * Load YAML into a PHP array statically - * - * The load method, when supplied with a YAML stream (string or file), - * will do its best to convert YAML in a file into a PHP array. Pretty - * simple. - * Usage: - * - * $array = Spyc::YAMLLoad('lucky.yaml'); - * print_r($array); - * - * @access public - * @return array - * @param string $input Path of YAML file or string containing YAML - */ - public static function YAMLLoad($input) { - $Spyc = new Spyc; - return $Spyc->__load($input); - } - - /** - * Load a string of YAML into a PHP array statically - * - * The load method, when supplied with a YAML string, will do its best - * to convert YAML in a string into a PHP array. Pretty simple. - * - * Note: use this function if you don't want files from the file system - * loaded and processed as YAML. This is of interest to people concerned - * about security whose input is from a string. - * - * Usage: - * - * $array = Spyc::YAMLLoadString("---\n0: hello world\n"); - * print_r($array); - * - * @access public - * @return array - * @param string $input String containing YAML - */ - public static function YAMLLoadString($input) { - $Spyc = new Spyc; - return $Spyc->__loadString($input); - } - - /** - * Dump YAML from PHP array statically - * - * The dump method, when supplied with an array, will do its best - * to convert the array into friendly YAML. Pretty simple. Feel free to - * save the returned string as nothing.yaml and pass it around. - * - * Oh, and you can decide how big the indent is and what the wordwrap - * for folding is. Pretty cool -- just pass in 'false' for either if - * you want to use the default. - * - * Indent's default is 2 spaces, wordwrap's default is 40 characters. And - * you can turn off wordwrap by passing in 0. - * - * @access public - * @return string - * @param array $array PHP array - * @param int $indent Pass in false to use the default, which is 2 - * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40) - */ - public static function YAMLDump($array,$indent = false,$wordwrap = false) { - $spyc = new Spyc; - return $spyc->dump($array,$indent,$wordwrap); - } - - - /** - * Dump PHP array to YAML - * - * The dump method, when supplied with an array, will do its best - * to convert the array into friendly YAML. Pretty simple. Feel free to - * save the returned string as tasteful.yaml and pass it around. - * - * Oh, and you can decide how big the indent is and what the wordwrap - * for folding is. Pretty cool -- just pass in 'false' for either if - * you want to use the default. - * - * Indent's default is 2 spaces, wordwrap's default is 40 characters. And - * you can turn off wordwrap by passing in 0. - * - * @access public - * @return string - * @param array $array PHP array - * @param int $indent Pass in false to use the default, which is 2 - * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40) - */ - public function dump($array,$indent = false,$wordwrap = false) { - // Dumps to some very clean YAML. We'll have to add some more features - // and options soon. And better support for folding. - - // New features and options. - if ($indent === false or !is_numeric($indent)) { - $this->_dumpIndent = 2; - } else { - $this->_dumpIndent = $indent; - } - - if ($wordwrap === false or !is_numeric($wordwrap)) { - $this->_dumpWordWrap = 40; - } else { - $this->_dumpWordWrap = $wordwrap; - } - - // New YAML document - $string = "---\n"; - - // Start at the base of the array and move through it. - if ($array) { - $array = (array)$array; - $previous_key = -1; - foreach ($array as $key => $value) { - if (!isset($first_key)) $first_key = $key; - $string .= $this->_yamlize($key,$value,0,$previous_key, $first_key, $array); - $previous_key = $key; - } - } - return $string; - } - - /** - * Attempts to convert a key / value array item to YAML - * @access private - * @return string - * @param $key The name of the key - * @param $value The value of the item - * @param $indent The indent of the current node - */ - private function _yamlize($key,$value,$indent, $previous_key = -1, $first_key = 0, $source_array = null) { - if (is_array($value)) { - if (empty ($value)) - return $this->_dumpNode($key, array(), $indent, $previous_key, $first_key, $source_array); - // It has children. What to do? - // Make it the right kind of item - $string = $this->_dumpNode($key, self::REMPTY, $indent, $previous_key, $first_key, $source_array); - // Add the indent - $indent += $this->_dumpIndent; - // Yamlize the array - $string .= $this->_yamlizeArray($value,$indent); - } elseif (!is_array($value)) { - // It doesn't have children. Yip. - $string = $this->_dumpNode($key, $value, $indent, $previous_key, $first_key, $source_array); - } - return $string; - } - - /** - * Attempts to convert an array to YAML - * @access private - * @return string - * @param $array The array you want to convert - * @param $indent The indent of the current level - */ - private function _yamlizeArray($array,$indent) { - if (is_array($array)) { - $string = ''; - $previous_key = -1; - foreach ($array as $key => $value) { - if (!isset($first_key)) $first_key = $key; - $string .= $this->_yamlize($key, $value, $indent, $previous_key, $first_key, $array); - $previous_key = $key; - } - return $string; - } else { - return false; - } - } - - /** - * Returns YAML from a key and a value - * @access private - * @return string - * @param $key The name of the key - * @param $value The value of the item - * @param $indent The indent of the current node - */ - private function _dumpNode($key, $value, $indent, $previous_key = -1, $first_key = 0, $source_array = null) { - // do some folding here, for blocks - if (is_string ($value) && ((strpos($value,"\n") !== false || strpos($value,": ") !== false || strpos($value,"- ") !== false || - strpos($value,"*") !== false || strpos($value,"#") !== false || strpos($value,"<") !== false || strpos($value,">") !== false || strpos ($value, ' ') !== false || - strpos($value,"[") !== false || strpos($value,"]") !== false || strpos($value,"{") !== false || strpos($value,"}") !== false) || strpos($value,"&") !== false || strpos($value, "'") !== false || strpos($value, "!") === 0 || - substr ($value, -1, 1) == ':') - ) { - $value = $this->_doLiteralBlock($value,$indent); - } else { - $value = $this->_doFolding($value,$indent); - } - - if ($value === array()) $value = '[ ]'; - if (in_array ($value, array ('true', 'TRUE', 'false', 'FALSE', 'y', 'Y', 'n', 'N', 'null', 'NULL'), true)) { - $value = $this->_doLiteralBlock($value,$indent); - } - if (trim ($value) != $value) - $value = $this->_doLiteralBlock($value,$indent); - - if (is_bool($value)) { - $value = ($value) ? "true" : "false"; - } - - if ($value === null) $value = 'null'; - if ($value === "'" . self::REMPTY . "'") $value = null; - - $spaces = str_repeat(' ',$indent); - - //if (is_int($key) && $key - 1 == $previous_key && $first_key===0) { - if (is_array ($source_array) && array_keys($source_array) === range(0, count($source_array) - 1)) { - // It's a sequence - $string = $spaces.'- '.$value."\n"; - } else { - // if ($first_key===0) throw new Exception('Keys are all screwy. The first one was zero, now it\'s "'. $key .'"'); - // It's mapped - if (strpos($key, ":") !== false || strpos($key, "#") !== false) { $key = '"' . $key . '"'; } - $string = rtrim ($spaces.$key.': '.$value)."\n"; - } - return $string; - } - - /** - * Creates a literal block for dumping - * @access private - * @return string - * @param $value - * @param $indent int The value of the indent - */ - private function _doLiteralBlock($value,$indent) { - if ($value === "\n") return '\n'; - if (strpos($value, "\n") === false && strpos($value, "'") === false) { - return sprintf ("'%s'", $value); - } - if (strpos($value, "\n") === false && strpos($value, '"') === false) { - return sprintf ('"%s"', $value); - } - $exploded = explode("\n",$value); - $newValue = '|'; - $indent += $this->_dumpIndent; - $spaces = str_repeat(' ',$indent); - foreach ($exploded as $line) { - $newValue .= "\n" . $spaces . ($line); - } - return $newValue; - } - - /** - * Folds a string of text, if necessary - * @access private - * @return string - * @param $value The string you wish to fold - */ - private function _doFolding($value,$indent) { - // Don't do anything if wordwrap is set to 0 - - if ($this->_dumpWordWrap !== 0 && is_string ($value) && strlen($value) > $this->_dumpWordWrap) { - $indent += $this->_dumpIndent; - $indent = str_repeat(' ',$indent); - $wrapped = wordwrap($value,$this->_dumpWordWrap,"\n$indent"); - $value = ">\n".$indent.$wrapped; - } else { - if ($this->setting_dump_force_quotes && is_string ($value) && $value !== self::REMPTY) - $value = '"' . $value . '"'; - } - - - return $value; - } - -// LOADING FUNCTIONS - - private function __load($input) { - $Source = $this->loadFromSource($input); - return $this->loadWithSource($Source); - } - - private function __loadString($input) { - $Source = $this->loadFromString($input); - return $this->loadWithSource($Source); - } - - private function loadWithSource($Source) { - if (empty ($Source)) return array(); - if ($this->setting_use_syck_is_possible && function_exists ('syck_load')) { - $array = syck_load (implode ('', $Source)); - return is_array($array) ? $array : array(); - } - - $this->path = array(); - $this->result = array(); - - $cnt = count($Source); - for ($i = 0; $i < $cnt; $i++) { - $line = $Source[$i]; - - $this->indent = strlen($line) - strlen(ltrim($line)); - $tempPath = $this->getParentPathByIndent($this->indent); - $line = self::stripIndent($line, $this->indent); - if (self::isComment($line)) continue; - if (self::isEmpty($line)) continue; - $this->path = $tempPath; - - $literalBlockStyle = self::startsLiteralBlock($line); - if ($literalBlockStyle) { - $line = rtrim ($line, $literalBlockStyle . " \n"); - $literalBlock = ''; - $line .= $this->LiteralPlaceHolder; - $literal_block_indent = strlen($Source[$i+1]) - strlen(ltrim($Source[$i+1])); - while (++$i < $cnt && $this->literalBlockContinues($Source[$i], $this->indent)) { - $literalBlock = $this->addLiteralLine($literalBlock, $Source[$i], $literalBlockStyle, $literal_block_indent); - } - $i--; - } - - while (++$i < $cnt && self::greedilyNeedNextLine($line)) { - $line = rtrim ($line, " \n\t\r") . ' ' . ltrim ($Source[$i], " \t"); - } - $i--; - - - - if (strpos ($line, '#')) { - if (strpos ($line, '"') === false && strpos ($line, "'") === false) - $line = preg_replace('/\s+#(.+)$/','',$line); - } - - $lineArray = $this->_parseLine($line); - - if ($literalBlockStyle) - $lineArray = $this->revertLiteralPlaceHolder ($lineArray, $literalBlock); - - $this->addArray($lineArray, $this->indent); - - foreach ($this->delayedPath as $indent => $delayedPath) - $this->path[$indent] = $delayedPath; - - $this->delayedPath = array(); - - } - return $this->result; - } - - private function loadFromSource ($input) { - if (!empty($input) && strpos($input, "\n") === false && file_exists($input)) - return file($input); - - return $this->loadFromString($input); - } - - private function loadFromString ($input) { - $lines = explode("\n",$input); - foreach ($lines as $k => $_) { - $lines[$k] = rtrim ($_, "\r"); - } - return $lines; - } - - /** - * Parses YAML code and returns an array for a node - * @access private - * @return array - * @param string $line A line from the YAML file - */ - private function _parseLine($line) { - if (!$line) return array(); - $line = trim($line); - if (!$line) return array(); - - $array = array(); - - $group = $this->nodeContainsGroup($line); - if ($group) { - $this->addGroup($line, $group); - $line = $this->stripGroup ($line, $group); - } - - if ($this->startsMappedSequence($line)) - return $this->returnMappedSequence($line); - - if ($this->startsMappedValue($line)) - return $this->returnMappedValue($line); - - if ($this->isArrayElement($line)) - return $this->returnArrayElement($line); - - if ($this->isPlainArray($line)) - return $this->returnPlainArray($line); - - - return $this->returnKeyValuePair($line); - - } - - /** - * Finds the type of the passed value, returns the value as the new type. - * @access private - * @param string $value - * @return mixed - */ - private function _toType($value) { - if ($value === '') return null; - $first_character = $value[0]; - $last_character = substr($value, -1, 1); - - $is_quoted = false; - do { - if (!$value) break; - if ($first_character != '"' && $first_character != "'") break; - if ($last_character != '"' && $last_character != "'") break; - $is_quoted = true; - } while (0); - - if ($is_quoted) - return strtr(substr ($value, 1, -1), array ('\\"' => '"', '\'\'' => '\'', '\\\'' => '\'')); - - if (strpos($value, ' #') !== false && !$is_quoted) - $value = preg_replace('/\s+#(.+)$/','',$value); - - if (!$is_quoted) $value = str_replace('\n', "\n", $value); - - if ($first_character == '[' && $last_character == ']') { - // Take out strings sequences and mappings - $innerValue = trim(substr ($value, 1, -1)); - if ($innerValue === '') return array(); - $explode = $this->_inlineEscape($innerValue); - // Propagate value array - $value = array(); - foreach ($explode as $v) { - $value[] = $this->_toType($v); - } - return $value; - } - - if (strpos($value,': ')!==false && $first_character != '{') { - $array = explode(': ',$value); - $key = trim($array[0]); - array_shift($array); - $value = trim(implode(': ',$array)); - $value = $this->_toType($value); - return array($key => $value); - } - - if ($first_character == '{' && $last_character == '}') { - $innerValue = trim(substr ($value, 1, -1)); - if ($innerValue === '') return array(); - // Inline Mapping - // Take out strings sequences and mappings - $explode = $this->_inlineEscape($innerValue); - // Propagate value array - $array = array(); - foreach ($explode as $v) { - $SubArr = $this->_toType($v); - if (empty($SubArr)) continue; - if (is_array ($SubArr)) { - $array[key($SubArr)] = $SubArr[key($SubArr)]; continue; - } - $array[] = $SubArr; - } - return $array; - } - - if ($value == 'null' || $value == 'NULL' || $value == 'Null' || $value == '' || $value == '~') { - return null; - } - - if ( is_numeric($value) && preg_match ('/^(-|)[1-9]+[0-9]*$/', $value) ){ - $intvalue = (int)$value; - if ($intvalue != PHP_INT_MAX) - $value = $intvalue; - return $value; - } - - if (in_array($value, - array('true', 'on', '+', 'yes', 'y', 'True', 'TRUE', 'On', 'ON', 'YES', 'Yes', 'Y'))) { - return true; - } - - if (in_array(strtolower($value), - array('false', 'off', '-', 'no', 'n'))) { - return false; - } - - if (is_numeric($value)) { - if ($value === '0') return 0; - if (rtrim ($value, 0) === $value) - $value = (float)$value; - return $value; - } - - return $value; - } - - /** - * Used in inlines to check for more inlines or quoted strings - * @access private - * @return array - */ - private function _inlineEscape($inline) { - // There's gotta be a cleaner way to do this... - // While pure sequences seem to be nesting just fine, - // pure mappings and mappings with sequences inside can't go very - // deep. This needs to be fixed. - - $seqs = array(); - $maps = array(); - $saved_strings = array(); - - // Check for strings - $regex = '/(?:(")|(?:\'))((?(1)[^"]+|[^\']+))(?(1)"|\')/'; - if (preg_match_all($regex,$inline,$strings)) { - $saved_strings = $strings[0]; - $inline = preg_replace($regex,'YAMLString',$inline); - } - unset($regex); - - $i = 0; - do { - - // Check for sequences - while (preg_match('/\[([^{}\[\]]+)\]/U',$inline,$matchseqs)) { - $seqs[] = $matchseqs[0]; - $inline = preg_replace('/\[([^{}\[\]]+)\]/U', ('YAMLSeq' . (count($seqs) - 1) . 's'), $inline, 1); - } - - // Check for mappings - while (preg_match('/{([^\[\]{}]+)}/U',$inline,$matchmaps)) { - $maps[] = $matchmaps[0]; - $inline = preg_replace('/{([^\[\]{}]+)}/U', ('YAMLMap' . (count($maps) - 1) . 's'), $inline, 1); - } - - if ($i++ >= 10) break; - - } while (strpos ($inline, '[') !== false || strpos ($inline, '{') !== false); - - $explode = explode(', ',$inline); - $stringi = 0; $i = 0; - - while (1) { - - // Re-add the sequences - if (!empty($seqs)) { - foreach ($explode as $key => $value) { - if (strpos($value,'YAMLSeq') !== false) { - foreach ($seqs as $seqk => $seq) { - $explode[$key] = str_replace(('YAMLSeq'.$seqk.'s'),$seq,$value); - $value = $explode[$key]; - } - } - } - } - - // Re-add the mappings - if (!empty($maps)) { - foreach ($explode as $key => $value) { - if (strpos($value,'YAMLMap') !== false) { - foreach ($maps as $mapk => $map) { - $explode[$key] = str_replace(('YAMLMap'.$mapk.'s'), $map, $value); - $value = $explode[$key]; - } - } - } - } - - - // Re-add the strings - if (!empty($saved_strings)) { - foreach ($explode as $key => $value) { - while (strpos($value,'YAMLString') !== false) { - $explode[$key] = preg_replace('/YAMLString/',$saved_strings[$stringi],$value, 1); - unset($saved_strings[$stringi]); - ++$stringi; - $value = $explode[$key]; - } - } - } - - $finished = true; - foreach ($explode as $key => $value) { - if (strpos($value,'YAMLSeq') !== false) { - $finished = false; break; - } - if (strpos($value,'YAMLMap') !== false) { - $finished = false; break; - } - if (strpos($value,'YAMLString') !== false) { - $finished = false; break; - } - } - if ($finished) break; - - $i++; - if ($i > 10) - break; // Prevent infinite loops. - } - - return $explode; - } - - private function literalBlockContinues ($line, $lineIndent) { - if (!trim($line)) return true; - if (strlen($line) - strlen(ltrim($line)) > $lineIndent) return true; - return false; - } - - private function referenceContentsByAlias ($alias) { - do { - if (!isset($this->SavedGroups[$alias])) { echo "Bad group name: $alias."; break; } - $groupPath = $this->SavedGroups[$alias]; - $value = $this->result; - foreach ($groupPath as $k) { - $value = $value[$k]; - } - } while (false); - return $value; - } - - private function addArrayInline ($array, $indent) { - $CommonGroupPath = $this->path; - if (empty ($array)) return false; - - foreach ($array as $k => $_) { - $this->addArray(array($k => $_), $indent); - $this->path = $CommonGroupPath; - } - return true; - } - - private function addArray ($incoming_data, $incoming_indent) { - - // print_r ($incoming_data); - - if (count ($incoming_data) > 1) - return $this->addArrayInline ($incoming_data, $incoming_indent); - - $key = key ($incoming_data); - $value = isset($incoming_data[$key]) ? $incoming_data[$key] : null; - if ($key === '__!YAMLZero') $key = '0'; - - if ($incoming_indent == 0 && !$this->_containsGroupAlias && !$this->_containsGroupAnchor) { // Shortcut for root-level values. - if ($key || $key === '' || $key === '0') { - $this->result[$key] = $value; - } else { - $this->result[] = $value; end ($this->result); $key = key ($this->result); - } - $this->path[$incoming_indent] = $key; - return; - } - - - - $history = array(); - // Unfolding inner array tree. - $history[] = $_arr = $this->result; - foreach ($this->path as $k) { - $history[] = $_arr = $_arr[$k]; - } - - if ($this->_containsGroupAlias) { - $value = $this->referenceContentsByAlias($this->_containsGroupAlias); - $this->_containsGroupAlias = false; - } - - - // Adding string or numeric key to the innermost level or $this->arr. - if (is_string($key) && $key == '<<') { - if (!is_array ($_arr)) { $_arr = array (); } - - $_arr = array_merge ($_arr, $value); - } else if ($key || $key === '' || $key === '0') { - if (!is_array ($_arr)) - $_arr = array ($key=>$value); - else - $_arr[$key] = $value; - } else { - if (!is_array ($_arr)) { $_arr = array ($value); $key = 0; } - else { $_arr[] = $value; end ($_arr); $key = key ($_arr); } - } - - $reverse_path = array_reverse($this->path); - $reverse_history = array_reverse ($history); - $reverse_history[0] = $_arr; - $cnt = count($reverse_history) - 1; - for ($i = 0; $i < $cnt; $i++) { - $reverse_history[$i+1][$reverse_path[$i]] = $reverse_history[$i]; - } - $this->result = $reverse_history[$cnt]; - - $this->path[$incoming_indent] = $key; - - if ($this->_containsGroupAnchor) { - $this->SavedGroups[$this->_containsGroupAnchor] = $this->path; - if (is_array ($value)) { - $k = key ($value); - if (!is_int ($k)) { - $this->SavedGroups[$this->_containsGroupAnchor][$incoming_indent + 2] = $k; - } - } - $this->_containsGroupAnchor = false; - } - - } - - private static function startsLiteralBlock ($line) { - $lastChar = substr (trim($line), -1); - if ($lastChar != '>' && $lastChar != '|') return false; - if ($lastChar == '|') return $lastChar; - // HTML tags should not be counted as literal blocks. - if (preg_match ('#<.*?>$#', $line)) return false; - return $lastChar; - } - - private static function greedilyNeedNextLine($line) { - $line = trim ($line); - if (!strlen($line)) return false; - if (substr ($line, -1, 1) == ']') return false; - if ($line[0] == '[') return true; - if (preg_match ('#^[^:]+?:\s*\[#', $line)) return true; - return false; - } - - private function addLiteralLine ($literalBlock, $line, $literalBlockStyle, $indent = -1) { - $line = self::stripIndent($line, $indent); - if ($literalBlockStyle !== '|') { - $line = self::stripIndent($line); - } - $line = rtrim ($line, "\r\n\t ") . "\n"; - if ($literalBlockStyle == '|') { - return $literalBlock . $line; - } - if (strlen($line) == 0) - return rtrim($literalBlock, ' ') . "\n"; - if ($line == "\n" && $literalBlockStyle == '>') { - return rtrim ($literalBlock, " \t") . "\n"; - } - if ($line != "\n") - $line = trim ($line, "\r\n ") . " "; - return $literalBlock . $line; - } - - function revertLiteralPlaceHolder ($lineArray, $literalBlock) { - foreach ($lineArray as $k => $_) { - if (is_array($_)) - $lineArray[$k] = $this->revertLiteralPlaceHolder ($_, $literalBlock); - else if (substr($_, -1 * strlen ($this->LiteralPlaceHolder)) == $this->LiteralPlaceHolder) - $lineArray[$k] = rtrim ($literalBlock, " \r\n"); - } - return $lineArray; - } - - private static function stripIndent ($line, $indent = -1) { - if ($indent == -1) $indent = strlen($line) - strlen(ltrim($line)); - return substr ($line, $indent); - } - - private function getParentPathByIndent ($indent) { - if ($indent == 0) return array(); - $linePath = $this->path; - do { - end($linePath); $lastIndentInParentPath = key($linePath); - if ($indent <= $lastIndentInParentPath) array_pop ($linePath); - } while ($indent <= $lastIndentInParentPath); - return $linePath; - } - - - private function clearBiggerPathValues ($indent) { - - - if ($indent == 0) $this->path = array(); - if (empty ($this->path)) return true; - - foreach ($this->path as $k => $_) { - if ($k > $indent) unset ($this->path[$k]); - } - - return true; - } - - - private static function isComment ($line) { - if (!$line) return false; - if ($line[0] == '#') return true; - if (trim($line, " \r\n\t") == '---') return true; - return false; - } - - private static function isEmpty ($line) { - return (trim ($line) === ''); - } - - - private function isArrayElement ($line) { - if (!$line) return false; - if ($line[0] != '-') return false; - if (strlen ($line) > 3) - if (substr($line,0,3) == '---') return false; - - return true; - } - - private function isHashElement ($line) { - return strpos($line, ':'); - } - - private function isLiteral ($line) { - if ($this->isArrayElement($line)) return false; - if ($this->isHashElement($line)) return false; - return true; - } - - - private static function unquote ($value) { - if (!$value) return $value; - if (!is_string($value)) return $value; - if ($value[0] == '\'') return trim ($value, '\''); - if ($value[0] == '"') return trim ($value, '"'); - return $value; - } - - private function startsMappedSequence ($line) { - return ($line[0] == '-' && substr ($line, -1, 1) == ':'); - } - - private function returnMappedSequence ($line) { - $array = array(); - $key = self::unquote(trim(substr($line,1,-1))); - $array[$key] = array(); - $this->delayedPath = array(strpos ($line, $key) + $this->indent => $key); - return array($array); - } - - private function returnMappedValue ($line) { - $array = array(); - $key = self::unquote (trim(substr($line,0,-1))); - $array[$key] = ''; - return $array; - } - - private function startsMappedValue ($line) { - return (substr ($line, -1, 1) == ':'); - } - - private function isPlainArray ($line) { - return ($line[0] == '[' && substr ($line, -1, 1) == ']'); - } - - private function returnPlainArray ($line) { - return $this->_toType($line); - } - - private function returnKeyValuePair ($line) { - $array = array(); - $key = ''; - if (strpos ($line, ':')) { - // It's a key/value pair most likely - // If the key is in double quotes pull it out - if (($line[0] == '"' || $line[0] == "'") && preg_match('/^(["\'](.*)["\'](\s)*:)/',$line,$matches)) { - $value = trim(str_replace($matches[1],'',$line)); - $key = $matches[2]; - } else { - // Do some guesswork as to the key and the value - $explode = explode(':',$line); - $key = trim($explode[0]); - array_shift($explode); - $value = trim(implode(':',$explode)); - } - // Set the type of the value. Int, string, etc - $value = $this->_toType($value); - if ($key === '0') $key = '__!YAMLZero'; - $array[$key] = $value; - } else { - $array = array ($line); - } - return $array; - - } - - - private function returnArrayElement ($line) { - if (strlen($line) <= 1) return array(array()); // Weird %) - $array = array(); - $value = trim(substr($line,1)); - $value = $this->_toType($value); - $array[] = $value; - return $array; - } - - - private function nodeContainsGroup ($line) { - $symbolsForReference = 'A-z0-9_\-'; - if (strpos($line, '&') === false && strpos($line, '*') === false) return false; // Please die fast ;-) - if ($line[0] == '&' && preg_match('/^(&['.$symbolsForReference.']+)/', $line, $matches)) return $matches[1]; - if ($line[0] == '*' && preg_match('/^(\*['.$symbolsForReference.']+)/', $line, $matches)) return $matches[1]; - if (preg_match('/(&['.$symbolsForReference.']+)$/', $line, $matches)) return $matches[1]; - if (preg_match('/(\*['.$symbolsForReference.']+$)/', $line, $matches)) return $matches[1]; - if (preg_match ('#^\s*<<\s*:\s*(\*[^\s]+).*$#', $line, $matches)) return $matches[1]; - return false; - - } - - private function addGroup ($line, $group) { - if ($group[0] == '&') $this->_containsGroupAnchor = substr ($group, 1); - if ($group[0] == '*') $this->_containsGroupAlias = substr ($group, 1); - //print_r ($this->path); - } - - private function stripGroup ($line, $group) { - $line = trim(str_replace($group, '', $line)); - return $line; - } -} - -// Enable use of Spyc from command line -// The syntax is the following: php spyc.php spyc.yaml - -define ('SPYC_FROM_COMMAND_LINE', false); - -do { - if (!SPYC_FROM_COMMAND_LINE) break; - if (empty ($_SERVER['argc']) || $_SERVER['argc'] < 2) break; - if (empty ($_SERVER['PHP_SELF']) || $_SERVER['PHP_SELF'] != 'spyc.php') break; - $file = $argv[1]; - printf ("Spyc loading file: %s\n", $file); - print_r (spyc_load_file ($file)); -} while (0); \ No newline at end of file diff --git a/includes/ua-parser-2.1.1/lib/spyc-0.5/spyc.yaml b/includes/ua-parser-2.1.1/lib/spyc-0.5/spyc.yaml deleted file mode 100644 index 930149e22..000000000 --- a/includes/ua-parser-2.1.1/lib/spyc-0.5/spyc.yaml +++ /dev/null @@ -1,203 +0,0 @@ -# -# S P Y C -# a simple php yaml class -# -# authors: [vlad andersen (vlad.andersen@gmail.com), chris wanstrath (chris@ozmm.org)] -# websites: [http://www.yaml.org, http://spyc.sourceforge.net/] -# license: [MIT License, http://www.opensource.org/licenses/mit-license.php] -# copyright: (c) 2005-2006 Chris Wanstrath, 2006-2011 Vlad Andersen -# -# spyc.yml - A file containing the YAML that Spyc understands. - ---- - -# Mappings - with proper types -String: Anyone's name, really. -Int: 13 -True: true -False: false -Zero: 0 -Null: NULL -NotNull: 'null' -NotTrue: 'y' -NotBoolTrue: 'true' -NotInt: '5' -Float: 5.34 -Negative: -90 -SmallFloat: 0.7 -NewLine: \n - -# A sequence -- PHP Class -- Basic YAML Loader -- Very Basic YAML Dumper - -# A sequence of a sequence -- - - YAML is so easy to learn. - - Your config files will never be the same. - -# Sequence of mappings -- - cpu: 1.5ghz - ram: 1 gig - os : os x 10.4.1 - -# Mapped sequence -domains: - - yaml.org - - php.net - -# A sequence like this. -- program: Adium - platform: OS X - type: Chat Client - -# A folded block as a mapped value -no time: > - There isn't any time - for your tricks! - - Do you understand? - -# A literal block as a mapped value -some time: | - There is nothing but time - for your tricks. - -# Crazy combinations -databases: - - name: spartan - notes: - - Needs to be backed up - - Needs to be normalized - type: mysql - -# You can be a bit tricky -"if: you'd": like - -# Inline sequences -- [One, Two, Three, Four] - -# Nested Inline Sequences -- [One, [Two, And, Three], Four, Five] - -# Nested Nested Inline Sequences -- [This, [Is, Getting, [Ridiculous, Guys]], Seriously, [Show, Mercy]] - -# Inline mappings -- {name: chris, age: young, brand: lucky strike} - -# Nested inline mappings -- {name: mark, age: older than chris, brand: [marlboro, lucky strike]} - -# References -- they're shaky, but functional -dynamic languages: &DLANGS - - Perl - - Python - - PHP - - Ruby -compiled languages: &CLANGS - - C/C++ - - Java -all languages: - - *DLANGS - - *CLANGS - -# Added in .2.2: Escaped quotes -- you know, this shouldn't work. but it does. -- 'that''s my value.' -- 'again, that\'s my value.' -- "here's to \"quotes\", boss." - -# added in .2.3 -- {name: "Foo, Bar's", age: 20} - -# Added in .2.4: bug [ 1418193 ] Quote Values in Nested Arrays -- [a, ['1', "2"], b] - -# Added in .2.4: malformed YAML -all - javascripts: [dom1.js, dom.js] - -# Added in .2 -1040: Ooo, a numeric key! # And working comments? Wow! Colons in comments: a menace (0.3). - -hash_1: Hash #and a comment -hash_2: "Hash #and a comment" -"hash#3": "Hash (#) can appear in key too" - -float_test: 1.0 -float_test_with_quotes: '1.0' -float_inverse_test: 001 - -a_really_large_number: 115792089237316195423570985008687907853269984665640564039457584007913129639936 # 2^256 - -int array: [ 1, 2, 3 ] - -array on several lines: - [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 ] - -morelesskey: "" - -array_of_zero: [0] -sophisticated_array_of_zero: {rx: {tx: [0]} } - -switches: - - { row: 0, col: 0, func: {tx: [0, 1]} } - -empty_sequence: [ ] -empty_hash: { } - -special_characters: "[{]]{{]]" - -asterisks: "*" - -empty_key: - : - key: value - -trailing_colon: "foo:" - -multiline_items: - - type: SomeItem - values: [blah, blah, blah, - blah] - ints: [2, 54, 12, - 2143] - -many_lines: | - A quick - fox - - - jumped - over - - - - - - a lazy - - - - dog - - -werte: - 1: nummer 1 - 0: Stunde 0 - -noindent_records: -- record1: value1 -- record2: value2 - -"a:1": [1000] -"a:2": - - 2000 - -# [Endloop] -endloop: | - Does this line in the end indeed make Spyc go to an infinite loop? \ No newline at end of file diff --git a/includes/ua-parser-2.1.1/lib/spyc-0.5/tests/DumpTest.php b/includes/ua-parser-2.1.1/lib/spyc-0.5/tests/DumpTest.php deleted file mode 100644 index 0b9e5fac9..000000000 --- a/includes/ua-parser-2.1.1/lib/spyc-0.5/tests/DumpTest.php +++ /dev/null @@ -1,130 +0,0 @@ -files_to_test = array ('../spyc.yaml', 'failing1.yaml', 'indent_1.yaml', 'quotes.yaml'); - } - - public function testDump() { - foreach ($this->files_to_test as $file) { - $yaml = spyc_load(file_get_contents($file)); - $dump = Spyc::YAMLDump ($yaml); - $yaml_after_dump = Spyc::YAMLLoad ($dump); - $this->assertEquals ($yaml, $yaml_after_dump); - } - } - - public function testDumpWithQuotes() { - $Spyc = new Spyc(); - $Spyc->setting_dump_force_quotes = true; - foreach ($this->files_to_test as $file) { - $yaml = $Spyc->load(file_get_contents($file)); - $dump = $Spyc->dump ($yaml); - $yaml_after_dump = Spyc::YAMLLoad ($dump); - $this->assertEquals ($yaml, $yaml_after_dump); - } - } - - public function testDumpArrays() { - $dump = Spyc::YAMLDump(array ('item1', 'item2', 'item3')); - $awaiting = "---\n- item1\n- item2\n- item3\n"; - $this->assertEquals ($awaiting, $dump); - } - - public function testNull() { - $dump = Spyc::YAMLDump(array('a' => 1, 'b' => null, 'c' => 3)); - $awaiting = "---\na: 1\nb: null\nc: 3\n"; - $this->assertEquals ($awaiting, $dump); - } - - public function testNext() { - $array = array("aaa", "bbb", "ccc"); - #set arrays internal pointer to next element - next($array); - $dump = Spyc::YAMLDump($array); - $awaiting = "---\n- aaa\n- bbb\n- ccc\n"; - $this->assertEquals ($awaiting, $dump); - } - - public function testDumpingMixedArrays() { - $array = array(); - $array[] = 'Sequence item'; - $array['The Key'] = 'Mapped value'; - $array[] = array('A sequence','of a sequence'); - $array[] = array('first' => 'A sequence','second' => 'of mapped values'); - $array['Mapped'] = array('A sequence','which is mapped'); - $array['A Note'] = 'What if your text is too long?'; - $array['Another Note'] = 'If that is the case, the dumper will probably fold your text by using a block. Kinda like this.'; - $array['The trick?'] = 'The trick is that we overrode the default indent, 2, to 4 and the default wordwrap, 40, to 60.'; - $array['Old Dog'] = "And if you want\n to preserve line breaks, \ngo ahead!"; - $array['key:withcolon'] = "Should support this to"; - - $yaml = Spyc::YAMLDump($array,4,60); - } - - public function testMixed() { - $dump = Spyc::YAMLDump(array(0 => 1, 'b' => 2, 1 => 3)); - $awaiting = "---\n0: 1\nb: 2\n1: 3\n"; - $this->assertEquals ($awaiting, $dump); - } - - public function testDumpNumerics() { - $dump = Spyc::YAMLDump(array ('404', '405', '500')); - $awaiting = "---\n- 404\n- 405\n- 500\n"; - $this->assertEquals ($awaiting, $dump); - } - - public function testDumpAsterisks() { - $dump = Spyc::YAMLDump(array ('*')); - $awaiting = "---\n- '*'\n"; - $this->assertEquals ($awaiting, $dump); - } - - public function testDumpAmpersands() { - $dump = Spyc::YAMLDump(array ('some' => '&foo')); - $awaiting = "---\nsome: '&foo'\n"; - $this->assertEquals ($awaiting, $dump); - } - - public function testDumpExclamations() { - $dump = Spyc::YAMLDump(array ('some' => '!foo')); - $awaiting = "---\nsome: '!foo'\n"; - $this->assertEquals ($awaiting, $dump); - } - - public function testDumpExclamations2() { - $dump = Spyc::YAMLDump(array ('some' => 'foo!')); - $awaiting = "---\nsome: foo!\n"; - $this->assertEquals ($awaiting, $dump); - } - - public function testDumpApostrophes() { - $dump = Spyc::YAMLDump(array ('some' => "'Biz' pimpt bedrijventerreinen")); - $awaiting = "---\nsome: \"'Biz' pimpt bedrijventerreinen\"\n"; - $this->assertEquals ($awaiting, $dump); - } - - public function testDumpNumericHashes() { - $dump = Spyc::YAMLDump(array ("titel"=> array("0" => "", 1 => "Dr.", 5 => "Prof.", 6 => "Prof. Dr."))); - $awaiting = "---\ntitel:\n 0:\n 1: Dr.\n 5: Prof.\n 6: Prof. Dr.\n"; - $this->assertEquals ($awaiting, $dump); - } - - public function testEmpty() { - $dump = Spyc::YAMLDump(array("foo" => array())); - $awaiting = "---\nfoo: [ ]\n"; - $this->assertEquals ($awaiting, $dump); - } - - public function testHashesInKeys() { - $dump = Spyc::YAMLDump(array ('#color' => '#ffffff')); - $awaiting = "---\n\"#color\": '#ffffff'\n"; - $this->assertEquals ($awaiting, $dump); - } - -} \ No newline at end of file diff --git a/includes/ua-parser-2.1.1/lib/spyc-0.5/tests/IndentTest.php b/includes/ua-parser-2.1.1/lib/spyc-0.5/tests/IndentTest.php deleted file mode 100644 index 5b6dc8657..000000000 --- a/includes/ua-parser-2.1.1/lib/spyc-0.5/tests/IndentTest.php +++ /dev/null @@ -1,65 +0,0 @@ -Y = Spyc::YAMLLoad("indent_1.yaml"); - } - - public function testIndent_1() { - $this->assertEquals (array ('child_1' => 2, 'child_2' => 0, 'child_3' => 1), $this->Y['root']); - } - - public function testIndent_2() { - $this->assertEquals (array ('child_1' => 1, 'child_2' => 2), $this->Y['root2']); - } - - public function testIndent_3() { - $this->assertEquals (array (array ('resolutions' => array (1024 => 768, 1920 => 1200), 'producer' => 'Nec')), $this->Y['display']); - } - - public function testIndent_4() { - $this->assertEquals (array ( - array ('resolutions' => array (1024 => 768)), - array ('resolutions' => array (1920 => 1200)), - ), $this->Y['displays']); - } - - public function testIndent_5() { - $this->assertEquals (array (array ( - 'row' => 0, - 'col' => 0, - 'headsets_affected' => array ( - array ( - 'ports' => array (0), - 'side' => 'left', - ) - ), - 'switch_function' => array ( - 'ics_ptt' => true - ) - )), $this->Y['nested_hashes_and_seqs']); - } - - public function testIndent_6() { - $this->assertEquals (array ( - 'h' => array ( - array ('a' => 'b', 'a1' => 'b1'), - array ('c' => 'd') - ) - ), $this->Y['easier_nest']); - } - - public function testIndent_space() { - $this->assertEquals ("By four\n spaces", $this->Y['one_space']); - } - - public function testListAndComment() { - $this->assertEquals (array ('one', 'two', 'three'), $this->Y['list_and_comment']); - } - -} \ No newline at end of file diff --git a/includes/ua-parser-2.1.1/lib/spyc-0.5/tests/ParseTest.php b/includes/ua-parser-2.1.1/lib/spyc-0.5/tests/ParseTest.php deleted file mode 100644 index f7045bd44..000000000 --- a/includes/ua-parser-2.1.1/lib/spyc-0.5/tests/ParseTest.php +++ /dev/null @@ -1,322 +0,0 @@ -yaml = spyc_load_file('../spyc.yaml'); - } - - public function testMergeHashKeys() { - $Expected = array ( - array ('step' => array('instrument' => 'Lasik 2000', 'pulseEnergy' => 5.4, 'pulseDuration' => 12, 'repetition' => 1000, 'spotSize' => '1mm')), - array ('step' => array('instrument' => 'Lasik 2000', 'pulseEnergy' => 5.4, 'pulseDuration' => 12, 'repetition' => 1000, 'spotSize' => '2mm')), - ); - $Actual = spyc_load_file ('indent_1.yaml'); - $this->assertEquals ($Expected, $Actual['steps']); - } - - public function testDeathMasks() { - $Expected = array ('sad' => 2, 'magnificent' => 4); - $Actual = spyc_load_file ('indent_1.yaml'); - $this->assertEquals ($Expected, $Actual['death masks are']); - } - - public function testDevDb() { - $Expected = array ('adapter' => 'mysql', 'host' => 'localhost', 'database' => 'rails_dev'); - $Actual = spyc_load_file ('indent_1.yaml'); - $this->assertEquals ($Expected, $Actual['development']); - } - - public function testNumericKey() { - $this->assertEquals ("Ooo, a numeric key!", $this->yaml[1040]); - } - - public function testMappingsString() { - $this->assertEquals ("Anyone's name, really.", $this->yaml['String']); - } - - public function testMappingsInt() { - $this->assertSame (13, $this->yaml['Int']); - } - - public function testMappingsBooleanTrue() { - $this->assertSame (true, $this->yaml['True']); - } - - public function testMappingsBooleanFalse() { - $this->assertSame (false, $this->yaml['False']); - } - - public function testMappingsZero() { - $this->assertSame (0, $this->yaml['Zero']); - } - - public function testMappingsNull() { - $this->assertSame (null, $this->yaml['Null']); - } - - public function testMappingsNotNull() { - $this->assertSame ('null', $this->yaml['NotNull']); - } - - public function testMappingsFloat() { - $this->assertSame (5.34, $this->yaml['Float']); - } - - public function testMappingsNegative() { - $this->assertSame (-90, $this->yaml['Negative']); - } - - public function testMappingsSmallFloat() { - $this->assertSame (0.7, $this->yaml['SmallFloat']); - } - - public function testNewline() { - $this->assertSame ("\n", $this->yaml['NewLine']); - } - - - public function testSeq0() { - $this->assertEquals ("PHP Class", $this->yaml[0]); - } - - public function testSeq1() { - $this->assertEquals ("Basic YAML Loader", $this->yaml[1]); - } - - public function testSeq2() { - $this->assertEquals ("Very Basic YAML Dumper", $this->yaml[2]); - } - - public function testSeq3() { - $this->assertEquals (array("YAML is so easy to learn.", - "Your config files will never be the same."), $this->yaml[3]); - } - - public function testSeqMap() { - $this->assertEquals (array("cpu" => "1.5ghz", "ram" => "1 gig", - "os" => "os x 10.4.1"), $this->yaml[4]); - } - - public function testMappedSequence() { - $this->assertEquals (array("yaml.org", "php.net"), $this->yaml['domains']); - } - - public function testAnotherSequence() { - $this->assertEquals (array("program" => "Adium", "platform" => "OS X", - "type" => "Chat Client"), $this->yaml[5]); - } - - public function testFoldedBlock() { - $this->assertEquals ("There isn't any time for your tricks!\nDo you understand?", $this->yaml['no time']); - } - - public function testLiteralAsMapped() { - $this->assertEquals ("There is nothing but time\nfor your tricks.", $this->yaml['some time']); - } - - public function testCrazy() { - $this->assertEquals (array( array("name" => "spartan", "notes" => - array( "Needs to be backed up", - "Needs to be normalized" ), - "type" => "mysql" )), $this->yaml['databases']); - } - - public function testColons() { - $this->assertEquals ("like", $this->yaml["if: you'd"]); - } - - public function testInline() { - $this->assertEquals (array("One", "Two", "Three", "Four"), $this->yaml[6]); - } - - public function testNestedInline() { - $this->assertEquals (array("One", array("Two", "And", "Three"), "Four", "Five"), $this->yaml[7]); - } - - public function testNestedNestedInline() { - $this->assertEquals (array( "This", array("Is", "Getting", array("Ridiculous", "Guys")), - "Seriously", array("Show", "Mercy")), $this->yaml[8]); - } - - public function testInlineMappings() { - $this->assertEquals (array("name" => "chris", "age" => "young", "brand" => "lucky strike"), $this->yaml[9]); - } - - public function testNestedInlineMappings() { - $this->assertEquals (array("name" => "mark", "age" => "older than chris", - "brand" => array("marlboro", "lucky strike")), $this->yaml[10]); - } - - public function testReferences() { - $this->assertEquals (array('Perl', 'Python', 'PHP', 'Ruby'), $this->yaml['dynamic languages']); - } - - public function testReferences2() { - $this->assertEquals (array('C/C++', 'Java'), $this->yaml['compiled languages']); - } - - public function testReferences3() { - $this->assertEquals (array( - array('Perl', 'Python', 'PHP', 'Ruby'), - array('C/C++', 'Java') - ), $this->yaml['all languages']); - } - - public function testEscapedQuotes() { - $this->assertEquals ("you know, this shouldn't work. but it does.", $this->yaml[11]); - } - - public function testEscapedQuotes_2() { - $this->assertEquals ( "that's my value.", $this->yaml[12]); - } - - public function testEscapedQuotes_3() { - $this->assertEquals ("again, that's my value.", $this->yaml[13]); - } - - public function testQuotes() { - $this->assertEquals ("here's to \"quotes\", boss.", $this->yaml[14]); - } - - public function testQuoteSequence() { - $this->assertEquals ( array( 'name' => "Foo, Bar's", 'age' => 20), $this->yaml[15]); - } - - public function testShortSequence() { - $this->assertEquals (array( 0 => "a", 1 => array (0 => 1, 1 => 2), 2 => "b"), $this->yaml[16]); - } - - public function testHash_1() { - $this->assertEquals ("Hash", $this->yaml['hash_1']); - } - - public function testHash_2() { - $this->assertEquals ('Hash #and a comment', $this->yaml['hash_2']); - } - - public function testHash_3() { - $this->assertEquals ('Hash (#) can appear in key too', $this->yaml['hash#3']); - } - - public function testEndloop() { - $this->assertEquals ("Does this line in the end indeed make Spyc go to an infinite loop?", $this->yaml['endloop']); - } - - public function testReallyLargeNumber() { - $this->assertEquals ('115792089237316195423570985008687907853269984665640564039457584007913129639936', $this->yaml['a_really_large_number']); - } - - public function testFloatWithZeros() { - $this->assertSame ('1.0', $this->yaml['float_test']); - } - - public function testFloatWithQuotes() { - $this->assertSame ('1.0', $this->yaml['float_test_with_quotes']); - } - - public function testFloatInverse() { - $this->assertEquals ('001', $this->yaml['float_inverse_test']); - } - - public function testIntArray() { - $this->assertEquals (array (1, 2, 3), $this->yaml['int array']); - } - - public function testArrayOnSeveralLines() { - $this->assertEquals (array (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19), $this->yaml['array on several lines']); - } - - public function testmoreLessKey() { - $this->assertEquals ('', $this->yaml['morelesskey']); - } - - public function testArrayOfZero() { - $this->assertSame (array(0), $this->yaml['array_of_zero']); - } - - public function testSophisticatedArrayOfZero() { - $this->assertSame (array('rx' => array ('tx' => array (0))), $this->yaml['sophisticated_array_of_zero']); - } - - public function testSwitches() { - $this->assertEquals (array (array ('row' => 0, 'col' => 0, 'func' => array ('tx' => array(0, 1)))), $this->yaml['switches']); - } - - public function testEmptySequence() { - $this->assertSame (array(), $this->yaml['empty_sequence']); - } - - public function testEmptyHash() { - $this->assertSame (array(), $this->yaml['empty_hash']); - } - - public function testEmptykey() { - $this->assertSame (array('' => array ('key' => 'value')), $this->yaml['empty_key']); - } - - public function testMultilines() { - $this->assertSame (array(array('type' => 'SomeItem', 'values' => array ('blah', 'blah', 'blah', 'blah'), 'ints' => array(2, 54, 12, 2143))), $this->yaml['multiline_items']); - } - - public function testManyNewlines() { - $this->assertSame ('A quick -fox - - -jumped -over - - - - - -a lazy - - - -dog', $this->yaml['many_lines']); - } - - public function testWerte() { - $this->assertSame (array ('1' => 'nummer 1', '0' => 'Stunde 0'), $this->yaml['werte']); - } - - /* public function testNoIndent() { - $this->assertSame (array( - array ('record1'=>'value1'), - array ('record2'=>'value2') - ) - , $this->yaml['noindent_records']); - } */ - - public function testColonsInKeys() { - $this->assertSame (array (1000), $this->yaml['a:1']); - } - - public function testColonsInKeys2() { - $this->assertSame (array (2000), $this->yaml['a:2']); - } - - public function testSpecialCharacters() { - $this->assertSame ('[{]]{{]]', $this->yaml['special_characters']); - } - - public function testAngleQuotes() { - $Quotes = Spyc::YAMLLoad('quotes.yaml'); - $this->assertEquals (array ('html_tags' => array ('
', '

'), 'html_content' => array ('

hello world

', 'hello
world'), 'text_content' => array ('hello world')), - $Quotes); - } - - public function testFailingColons() { - $Failing = Spyc::YAMLLoad('failing1.yaml'); - $this->assertSame (array ('MyObject' => array ('Prop1' => array ('key1:val1'))), - $Failing); - } - -} \ No newline at end of file diff --git a/includes/ua-parser-2.1.1/lib/spyc-0.5/tests/RoundTripTest.php b/includes/ua-parser-2.1.1/lib/spyc-0.5/tests/RoundTripTest.php deleted file mode 100644 index 4a906e25c..000000000 --- a/includes/ua-parser-2.1.1/lib/spyc-0.5/tests/RoundTripTest.php +++ /dev/null @@ -1,61 +0,0 @@ - $a))); } - - -class RoundTripTest extends PHPUnit_Framework_TestCase { - - protected function setUp() { - } - - public function testNull() { - $this->assertEquals (array ('x' => null), roundTrip (null)); - } - - public function testY() { - $this->assertEquals (array ('x' => 'y'), roundTrip ('y')); - } - - public function testExclam() { - $this->assertEquals (array ('x' => '!yeah'), roundTrip ('!yeah')); - } - - public function test5() { - $this->assertEquals (array ('x' => '5'), roundTrip ('5')); - } - - public function testSpaces() { - $this->assertEquals (array ('x' => 'x '), roundTrip ('x ')); - } - - public function testApostrophes() { - $this->assertEquals (array ('x' => "'biz'"), roundTrip ("'biz'")); - } - - public function testNewLines() { - $this->assertEquals (array ('x' => "\n"), roundTrip ("\n")); - } - - public function testHashes() { - $this->assertEquals (array ('x' => array ("#color" => '#fff')), roundTrip (array ("#color" => '#fff'))); - } - - public function testWordWrap() { - $this->assertEquals (array ('x' => "aaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"), roundTrip ("aaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")); - } - - public function testABCD() { - $this->assertEquals (array ('a', 'b', 'c', 'd'), Spyc::YAMLLoad(Spyc::YAMLDump(array('a', 'b', 'c', 'd')))); - } - - public function testABCD2() { - $a = array('a', 'b', 'c', 'd'); // Create a simple list - $b = Spyc::YAMLDump($a); // Dump the list as YAML - $c = Spyc::YAMLLoad($b); // Load the dumped YAML - $d = Spyc::YAMLDump($c); // Re-dump the data - $this->assertSame($b, $d); - } - -} \ No newline at end of file diff --git a/includes/ua-parser-2.1.1/lib/spyc-0.5/tests/failing1.yaml b/includes/ua-parser-2.1.1/lib/spyc-0.5/tests/failing1.yaml deleted file mode 100644 index 6906a51c1..000000000 --- a/includes/ua-parser-2.1.1/lib/spyc-0.5/tests/failing1.yaml +++ /dev/null @@ -1,2 +0,0 @@ -MyObject: - Prop1: {key1:val1} \ No newline at end of file diff --git a/includes/ua-parser-2.1.1/lib/spyc-0.5/tests/indent_1.yaml b/includes/ua-parser-2.1.1/lib/spyc-0.5/tests/indent_1.yaml deleted file mode 100644 index 85a0b5919..000000000 --- a/includes/ua-parser-2.1.1/lib/spyc-0.5/tests/indent_1.yaml +++ /dev/null @@ -1,59 +0,0 @@ -root: - child_1: 2 - - child_2: 0 - child_3: 1 - -root2: - child_1: 1 -# A comment - child_2: 2 - -displays: - - resolutions: - 1024: 768 - - resolutions: - 1920: 1200 - -display: - - resolutions: - 1024: 768 - 1920: 1200 - producer: "Nec" - -nested_hashes_and_seqs: - - { row: 0, col: 0, headsets_affected: [{ports: [0], side: left}], switch_function: {ics_ptt: true} } - -easier_nest: { h: [{a: b, a1: b1}, {c: d}] } - -one_space: | - By four - spaces - -steps: - - step: &id001 - instrument: Lasik 2000 - pulseEnergy: 5.4 - pulseDuration: 12 - repetition: 1000 - spotSize: 1mm - - step: - <<: *id001 - spotSize: 2mm - -death masks are: - sad: 2 - <<: {magnificent: 4} - -login: &login - adapter: mysql - host: localhost - -development: - database: rails_dev - <<: *login - -"key": "value:" -colon_only: ":" - -list_and_comment: [one, two, three] # comment \ No newline at end of file diff --git a/includes/ua-parser-2.1.1/lib/spyc-0.5/tests/quotes.yaml b/includes/ua-parser-2.1.1/lib/spyc-0.5/tests/quotes.yaml deleted file mode 100644 index 2ceea86aa..000000000 --- a/includes/ua-parser-2.1.1/lib/spyc-0.5/tests/quotes.yaml +++ /dev/null @@ -1,8 +0,0 @@ -html_tags: - -
- -

-html_content: - -

hello world

- - hello
world -text_content: - - hello world \ No newline at end of file diff --git a/includes/ua-parser-2.1.1/log/README.md b/includes/ua-parser-2.1.1/log/README.md deleted file mode 100644 index 8d5064fdd..000000000 --- a/includes/ua-parser-2.1.1/log/README.md +++ /dev/null @@ -1 +0,0 @@ -If you turn on debug mode this is where your results will be logged. \ No newline at end of file diff --git a/includes/ua-parser-2.1.1/resources/regexes.json b/includes/ua-parser-2.1.1/resources/regexes.json deleted file mode 100644 index 57f68518b..000000000 --- a/includes/ua-parser-2.1.1/resources/regexes.json +++ /dev/null @@ -1 +0,0 @@ -{"user_agent_parsers":[{"regex":"(SeaMonkey|Camino)\/(\\d+)\\.(\\d+)\\.?([ab]?\\d+[a-z]*)"},{"regex":"(Pale[Mm]oon)\/(\\d+)\\.(\\d+)\\.?(\\d+)?","family_replacement":"Pale Moon (Firefox Variant)"},{"regex":"(Fennec)\/(\\d+)\\.(\\d+)\\.?([ab]?\\d+[a-z]*)","family_replacement":"Firefox Mobile"},{"regex":"(Fennec)\/(\\d+)\\.(\\d+)(pre)","family_replacement":"Firefox Mobile"},{"regex":"(Fennec)\/(\\d+)\\.(\\d+)","family_replacement":"Firefox Mobile"},{"regex":"Mobile.*(Firefox)\/(\\d+)\\.(\\d+)","family_replacement":"Firefox Mobile"},{"regex":"(Namoroka|Shiretoko|Minefield)\/(\\d+)\\.(\\d+)\\.(\\d+(?:pre)?)","family_replacement":"Firefox ($1)"},{"regex":"(Firefox)\/(\\d+)\\.(\\d+)(a\\d+[a-z]*)","family_replacement":"Firefox Alpha"},{"regex":"(Firefox)\/(\\d+)\\.(\\d+)(b\\d+[a-z]*)","family_replacement":"Firefox Beta"},{"regex":"(Firefox)-(?:\\d+\\.\\d+)?\/(\\d+)\\.(\\d+)(a\\d+[a-z]*)","family_replacement":"Firefox Alpha"},{"regex":"(Firefox)-(?:\\d+\\.\\d+)?\/(\\d+)\\.(\\d+)(b\\d+[a-z]*)","family_replacement":"Firefox Beta"},{"regex":"(Namoroka|Shiretoko|Minefield)\/(\\d+)\\.(\\d+)([ab]\\d+[a-z]*)?","family_replacement":"Firefox ($1)"},{"regex":"(Firefox).*Tablet browser (\\d+)\\.(\\d+)\\.(\\d+)","family_replacement":"MicroB"},{"regex":"(MozillaDeveloperPreview)\/(\\d+)\\.(\\d+)([ab]\\d+[a-z]*)?"},{"regex":"(Flock)\/(\\d+)\\.(\\d+)(b\\d+?)"},{"regex":"(RockMelt)\/(\\d+)\\.(\\d+)\\.(\\d+)"},{"regex":"(Navigator)\/(\\d+)\\.(\\d+)\\.(\\d+)","family_replacement":"Netscape"},{"regex":"(Navigator)\/(\\d+)\\.(\\d+)([ab]\\d+)","family_replacement":"Netscape"},{"regex":"(Netscape6)\/(\\d+)\\.(\\d+)\\.(\\d+)","family_replacement":"Netscape"},{"regex":"(MyIBrow)\/(\\d+)\\.(\\d+)","family_replacement":"My Internet Browser"},{"regex":"(Opera Tablet).*Version\/(\\d+)\\.(\\d+)(?:\\.(\\d+))?"},{"regex":"(Opera)\/.+Opera Mobi.+Version\/(\\d+)\\.(\\d+)","family_replacement":"Opera Mobile"},{"regex":"Opera Mobi","family_replacement":"Opera Mobile"},{"regex":"(Opera Mini)\/(\\d+)\\.(\\d+)"},{"regex":"(Opera Mini)\/att\/(\\d+)\\.(\\d+)"},{"regex":"(Opera)\/9.80.*Version\/(\\d+)\\.(\\d+)(?:\\.(\\d+))?"},{"regex":"(hpw|web)OS\/(\\d+)\\.(\\d+)(?:\\.(\\d+))?","family_replacement":"webOS Browser"},{"regex":"(luakit)","family_replacement":"LuaKit"},{"regex":"(Snowshoe)\/(\\d+)\\.(\\d+).(\\d+)"},{"regex":"(Lightning)\/(\\d+)\\.(\\d+)([ab]?\\d+[a-z]*)"},{"regex":"(Firefox)\/(\\d+)\\.(\\d+)\\.(\\d+(?:pre)?) \\(Swiftfox\\)","family_replacement":"Swiftfox"},{"regex":"(Firefox)\/(\\d+)\\.(\\d+)([ab]\\d+[a-z]*)? \\(Swiftfox\\)","family_replacement":"Swiftfox"},{"regex":"(rekonq)\/(\\d+)\\.(\\d+) Safari","family_replacement":"Rekonq"},{"regex":"rekonq","family_replacement":"Rekonq"},{"regex":"(conkeror|Conkeror)\/(\\d+)\\.(\\d+)\\.?(\\d+)?","family_replacement":"Conkeror"},{"regex":"(konqueror)\/(\\d+)\\.(\\d+)\\.(\\d+)","family_replacement":"Konqueror"},{"regex":"(WeTab)-Browser"},{"regex":"(Comodo_Dragon)\/(\\d+)\\.(\\d+)\\.(\\d+)","family_replacement":"Comodo Dragon"},{"regex":"(YottaaMonitor|BrowserMob|HttpMonitor|YandexBot|Slurp|BingPreview|PagePeeker|ThumbShotsBot|WebThumb|URL2PNG|ZooShot|GomezA|Catchpoint bot|Willow Internet Crawler|Google SketchUp|Read%20Later)"},{"regex":"(Symphony) (\\d+).(\\d+)"},{"regex":"(Minimo)"},{"regex":"(CrMo)\/(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)","family_replacement":"Chrome Mobile"},{"regex":"(CriOS)\/(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)","family_replacement":"Chrome Mobile iOS"},{"regex":"(Chrome)\/(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+) Mobile","family_replacement":"Chrome Mobile"},{"regex":"(chromeframe)\/(\\d+)\\.(\\d+)\\.(\\d+)","family_replacement":"Chrome Frame"},{"regex":"(UCBrowser)[ \/](\\d+)\\.(\\d+)\\.(\\d+)","family_replacement":"UC Browser"},{"regex":"(UC Browser)[ \/](\\d+)\\.(\\d+)\\.(\\d+)"},{"regex":"(UC Browser|UCBrowser|UCWEB)(\\d+)\\.(\\d+)\\.(\\d+)","family_replacement":"UC Browser"},{"regex":"(SLP Browser)\/(\\d+)\\.(\\d+)","family_replacement":"Tizen Browser"},{"regex":"(Epiphany)\/(\\d+)\\.(\\d+).(\\d+)"},{"regex":"(SE 2\\.X) MetaSr (\\d+)\\.(\\d+)","family_replacement":"Sogou Explorer"},{"regex":"(baidubrowser)[\/\\s](\\d+)","family_replacement":"Baidu Browser"},{"regex":"(FlyFlow)\/(\\d+)\\.(\\d+)","family_replacement":"Baidu Explorer"},{"regex":"(Pingdom.com_bot_version_)(\\d+)\\.(\\d+)","family_replacement":"PingdomBot"},{"regex":"(facebookexternalhit)\/(\\d+)\\.(\\d+)","family_replacement":"FacebookBot"},{"regex":"(Twitterbot)\/(\\d+)\\.(\\d+)","family_replacement":"TwitterBot"},{"regex":"(Rackspace Monitoring)\/(\\d+)\\.(\\d+)","family_replacement":"RackspaceBot"},{"regex":"(PyAMF)\/(\\d+)\\.(\\d+)\\.(\\d+)"},{"regex":"(YaBrowser)\/(\\d+)\\.(\\d+)\\.(\\d+)","family_replacement":"Yandex Browser"},{"regex":"(Chrome)\/(\\d+)\\.(\\d+)\\.(\\d+).* MRCHROME","family_replacement":"Mail.ru Chromium Browser"},{"regex":"(AdobeAIR|Chromium|FireWeb|Jasmine|ANTGalio|Midori|Fresco|Lobo|PaleMoon|Maxthon|Lynx|OmniWeb|Dillo|Camino|Demeter|Fluid|Fennec|Shiira|Sunrise|Chrome|Flock|Netscape|Lunascape|WebPilot|Vodafone|NetFront|Netfront|Konqueror|SeaMonkey|Kazehakase|Vienna|Iceape|Iceweasel|IceWeasel|Iron|K-Meleon|Sleipnir|Galeon|GranParadiso|Opera Mini|iCab|NetNewsWire|ThunderBrowse|Iris|UP\\.Browser|Bunjalloo|Google Earth|Raven for Mac|Openwave)\/(\\d+)\\.(\\d+)\\.(\\d+)"},{"regex":"(Bolt|Jasmine|IceCat|Skyfire|Midori|Maxthon|Lynx|Arora|IBrowse|Dillo|Camino|Shiira|Fennec|Phoenix|Chrome|Flock|Netscape|Lunascape|Epiphany|WebPilot|Opera Mini|Opera|Vodafone|NetFront|Netfront|Konqueror|Googlebot|SeaMonkey|Kazehakase|Vienna|Iceape|Iceweasel|IceWeasel|Iron|K-Meleon|Sleipnir|Galeon|GranParadiso|iCab|NetNewsWire|Space Bison|Stainless|Orca|Dolfin|BOLT|Minimo|Tizen Browser|Polaris|Abrowser|Planetweb|ICE Browser)\/(\\d+)\\.(\\d+)"},{"regex":"(iRider|Crazy Browser|SkipStone|iCab|Lunascape|Sleipnir|Maemo Browser) (\\d+)\\.(\\d+)\\.(\\d+)"},{"regex":"(iCab|Lunascape|Opera|Android|Jasmine|Polaris) (\\d+)\\.(\\d+)\\.?(\\d+)?"},{"regex":"(Kindle)\/(\\d+)\\.(\\d+)"},{"regex":"(Android) Donut","v1_replacement":"1","v2_replacement":"2"},{"regex":"(Android) Eclair","v1_replacement":"2","v2_replacement":"1"},{"regex":"(Android) Froyo","v1_replacement":"2","v2_replacement":"2"},{"regex":"(Android) Gingerbread","v1_replacement":"2","v2_replacement":"3"},{"regex":"(Android) Honeycomb","v1_replacement":"3"},{"regex":"(IEMobile)[ \/](\\d+)\\.(\\d+)","family_replacement":"IE Mobile"},{"regex":"(MSIE) (\\d+)\\.(\\d+).*XBLWP7","family_replacement":"IE Large Screen"},{"regex":"(Firefox)\/(\\d+)\\.(\\d+)\\.(\\d+)"},{"regex":"(Firefox)\/(\\d+)\\.(\\d+)(pre|[ab]\\d+[a-z]*)?"},{"regex":"(Obigo)InternetBrowser"},{"regex":"(Obigo)\\-Browser"},{"regex":"(Obigo|OBIGO)[^\\d]*(\\d+)(?:.(\\d+))?","family_replacement":"Obigo"},{"regex":"(MAXTHON|Maxthon) (\\d+)\\.(\\d+)","family_replacement":"Maxthon"},{"regex":"(Maxthon|MyIE2|Uzbl|Shiira)","v1_replacement":"0"},{"regex":"PLAYSTATION 3.+WebKit","family_replacement":"NetFront NX"},{"regex":"PLAYSTATION 3","family_replacement":"NetFront"},{"regex":"(PlayStation Portable)","family_replacement":"NetFront"},{"regex":"(PlayStation Vita)","family_replacement":"NetFront NX"},{"regex":"AppleWebKit.+ (NX)\/(\\d+)\\.(\\d+)\\.(\\d+)","family_replacement":"NetFront NX"},{"regex":"(Nintendo 3DS)","family_replacement":"NetFront NX"},{"regex":"(BrowseX) \\((\\d+)\\.(\\d+)\\.(\\d+)"},{"regex":"(NCSA_Mosaic)\/(\\d+)\\.(\\d+)","family_replacement":"NCSA Mosaic"},{"regex":"(POLARIS)\/(\\d+)\\.(\\d+)","family_replacement":"Polaris"},{"regex":"(Embider)\/(\\d+)\\.(\\d+)","family_replacement":"Polaris"},{"regex":"(BonEcho)\/(\\d+)\\.(\\d+)\\.(\\d+)","family_replacement":"Bon Echo"},{"regex":"M?QQBrowser","family_replacement":"QQ Browser"},{"regex":"(iPod).+Version\/(\\d+)\\.(\\d+)\\.(\\d+)","family_replacement":"Mobile Safari"},{"regex":"(iPod).*Version\/(\\d+)\\.(\\d+)","family_replacement":"Mobile Safari"},{"regex":"(iPhone).*Version\/(\\d+)\\.(\\d+)\\.(\\d+)","family_replacement":"Mobile Safari"},{"regex":"(iPhone).*Version\/(\\d+)\\.(\\d+)","family_replacement":"Mobile Safari"},{"regex":"(iPad).*Version\/(\\d+)\\.(\\d+)\\.(\\d+)","family_replacement":"Mobile Safari"},{"regex":"(iPad).*Version\/(\\d+)\\.(\\d+)","family_replacement":"Mobile Safari"},{"regex":"(iPod|iPhone|iPad);.*CPU.*OS (\\d+)(?:_\\d+)?_(\\d+).*Mobile","family_replacement":"Mobile Safari"},{"regex":"(iPod|iPhone|iPad)","family_replacement":"Mobile Safari"},{"regex":"(AvantGo) (\\d+).(\\d+)"},{"regex":"(OneBrowser)\/(\\d+).(\\d+)","family_replacement":"ONE Browser"},{"regex":"(Avant)","v1_replacement":"1"},{"regex":"(QtCarBrowser)","v1_replacement":"1"},{"regex":"(iBrowser\/Mini)(\\d+).(\\d+)","family_replacement":"iBrowser Mini"},{"regex":"^(Nokia)","family_replacement":"Nokia Services (WAP) Browser"},{"regex":"(NokiaBrowser)\/(\\d+)\\.(\\d+).(\\d+)\\.(\\d+)","family_replacement":"Nokia Browser"},{"regex":"(NokiaBrowser)\/(\\d+)\\.(\\d+).(\\d+)","family_replacement":"Nokia Browser"},{"regex":"(NokiaBrowser)\/(\\d+)\\.(\\d+)","family_replacement":"Nokia Browser"},{"regex":"(BrowserNG)\/(\\d+)\\.(\\d+).(\\d+)","family_replacement":"Nokia Browser"},{"regex":"(Series60)\/5\\.0","family_replacement":"Nokia Browser","v1_replacement":"7","v2_replacement":"0"},{"regex":"(Series60)\/(\\d+)\\.(\\d+)","family_replacement":"Nokia OSS Browser"},{"regex":"(S40OviBrowser)\/(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)","family_replacement":"Ovi Browser"},{"regex":"(Nokia)[EN]?(\\d+)"},{"regex":"(BB10);","family_replacement":"BlackBerry WebKit"},{"regex":"(PlayBook).+RIM Tablet OS (\\d+)\\.(\\d+)\\.(\\d+)","family_replacement":"BlackBerry WebKit"},{"regex":"(Black[bB]erry).+Version\/(\\d+)\\.(\\d+)\\.(\\d+)","family_replacement":"BlackBerry WebKit"},{"regex":"(Black[bB]erry)\\s?(\\d+)","family_replacement":"BlackBerry"},{"regex":"(OmniWeb)\/v(\\d+)\\.(\\d+)"},{"regex":"(Blazer)\/(\\d+)\\.(\\d+)","family_replacement":"Palm Blazer"},{"regex":"(Pre)\/(\\d+)\\.(\\d+)","family_replacement":"Palm Pre"},{"regex":"(Links) \\((\\d+)\\.(\\d+)"},{"regex":"(QtWeb) Internet Browser\/(\\d+)\\.(\\d+)"},{"regex":"(Silk)\/(\\d+)\\.(\\d+)(?:\\.([0-9\\-]+))?","family_replacement":"Amazon Silk"},{"regex":"(AppleWebKit)\/(\\d+)\\.?(\\d+)?\\+ .* Safari","family_replacement":"WebKit Nightly"},{"regex":"(Version)\/(\\d+)\\.(\\d+)(?:\\.(\\d+))?.*Safari\/","family_replacement":"Safari"},{"regex":"(Safari)\/\\d+"},{"regex":"(OLPC)\/Update(\\d+)\\.(\\d+)"},{"regex":"(OLPC)\/Update()\\.(\\d+)","v1_replacement":"0"},{"regex":"(SEMC\\-Browser)\/(\\d+)\\.(\\d+)"},{"regex":"(Teleca)","family_replacement":"Teleca Browser"},{"regex":"(Phantom)\/V(\\d+)\\.(\\d+)","family_replacement":"Phantom Browser"},{"regex":"(MSIE) (\\d+)\\.(\\d+)","family_replacement":"IE"},{"regex":"(python-requests)\/(\\d+)\\.(\\d+)","family_replacement":"Python Requests"}],"os_parsers":[{"regex":"(Android) (\\d+)\\.(\\d+)(?:[.\\-]([a-z0-9]+))?"},{"regex":"(Android)\\-(\\d+)\\.(\\d+)(?:[.\\-]([a-z0-9]+))?"},{"regex":"(Android) Donut","os_v1_replacement":"1","os_v2_replacement":"2"},{"regex":"(Android) Eclair","os_v1_replacement":"2","os_v2_replacement":"1"},{"regex":"(Android) Froyo","os_v1_replacement":"2","os_v2_replacement":"2"},{"regex":"(Android) Gingerbread","os_v1_replacement":"2","os_v2_replacement":"3"},{"regex":"(Android) Honeycomb","os_v1_replacement":"3"},{"regex":"(Silk-Accelerated=[a-z]{4,5})","os_replacement":"Android"},{"regex":"(Windows (?:NT 5\\.2|NT 5\\.1))","os_replacement":"Windows XP"},{"regex":"(XBLWP7)","os_replacement":"Windows Phone"},{"regex":"(Windows NT 6\\.1)","os_replacement":"Windows 7"},{"regex":"(Windows NT 6\\.0)","os_replacement":"Windows Vista"},{"regex":"(Windows 98|Windows XP|Windows ME|Windows 95|Windows CE|Windows 7|Windows NT 4\\.0|Windows Vista|Windows 2000|Windows 3.1)"},{"regex":"(Windows NT 6\\.2; ARM;)","os_replacement":"Windows RT"},{"regex":"(Windows NT 6\\.2)","os_replacement":"Windows 8"},{"regex":"(Windows NT 5\\.0)","os_replacement":"Windows 2000"},{"regex":"(Windows Phone) (\\d+)\\.(\\d+)"},{"regex":"(Windows Phone) OS (\\d+)\\.(\\d+)"},{"regex":"(Windows ?Mobile)","os_replacement":"Windows Mobile"},{"regex":"(WinNT4.0)","os_replacement":"Windows NT 4.0"},{"regex":"(Win98)","os_replacement":"Windows 98"},{"regex":"(Tizen)\/(\\d+)\\.(\\d+)"},{"regex":"(Mac OS X) (\\d+)[_.](\\d+)(?:[_.](\\d+))?"},{"regex":"Mac_PowerPC","os_replacement":"Mac OS"},{"regex":"(?:PPC|Intel) (Mac OS X)"},{"regex":"(CPU OS|iPhone OS) (\\d+)_(\\d+)(?:_(\\d+))?","os_replacement":"iOS"},{"regex":"(iPhone|iPad|iPod); Opera","os_replacement":"iOS"},{"regex":"(iPhone|iPad|iPod).*Mac OS X.*Version\/(\\d+)\\.(\\d+)","os_replacement":"iOS"},{"regex":"(AppleTV)\/(\\d+)\\.(\\d+)","os_replacement":"ATV OS X","os_v1_replacement":"$1","os_v2_replacement":"$2"},{"regex":"(CrOS) [a-z0-9_]+ (\\d+)\\.(\\d+)(?:\\.(\\d+))?","os_replacement":"Chrome OS"},{"regex":"(Debian)-(\\d+)\\.(\\d+)\\.(\\d+)(?:\\.(\\d+))?"},{"regex":"(Linux Mint)(?:\/(\\d+))?"},{"regex":"(Mandriva)(?: Linux)?\/(\\d+)\\.(\\d+)\\.(\\d+)(?:\\.(\\d+))?"},{"regex":"(Symbian[Oo][Ss])\/(\\d+)\\.(\\d+)","os_replacement":"Symbian OS"},{"regex":"(Symbian\/3).+NokiaBrowser\/7\\.3","os_replacement":"Symbian^3 Anna"},{"regex":"(Symbian\/3).+NokiaBrowser\/7\\.4","os_replacement":"Symbian^3 Belle"},{"regex":"(Symbian\/3)","os_replacement":"Symbian^3"},{"regex":"(Series 60|SymbOS|S60)","os_replacement":"Symbian OS"},{"regex":"(MeeGo)"},{"regex":"Symbian [Oo][Ss]","os_replacement":"Symbian OS"},{"regex":"Series40;","os_replacement":"Nokia Series 40"},{"regex":"(BB10);.+Version\/(\\d+)\\.(\\d+)\\.(\\d+)","os_replacement":"BlackBerry OS"},{"regex":"(Black[Bb]erry)[0-9a-z]+\/(\\d+)\\.(\\d+)\\.(\\d+)(?:\\.(\\d+))?","os_replacement":"BlackBerry OS"},{"regex":"(Black[Bb]erry).+Version\/(\\d+)\\.(\\d+)\\.(\\d+)(?:\\.(\\d+))?","os_replacement":"BlackBerry OS"},{"regex":"(RIM Tablet OS) (\\d+)\\.(\\d+)\\.(\\d+)","os_replacement":"BlackBerry Tablet OS"},{"regex":"(Play[Bb]ook)","os_replacement":"BlackBerry Tablet OS"},{"regex":"(Black[Bb]erry)","os_replacement":"BlackBerry OS"},{"regex":"\\(Mobile;.+Firefox\/\\d+\\.\\d+","os_replacement":"Firefox OS"},{"regex":"(BREW)[ \/](\\d+)\\.(\\d+)\\.(\\d+)"},{"regex":"(BREW);"},{"regex":"(Brew MP|BMP)[ \/](\\d+)\\.(\\d+)\\.(\\d+)","os_replacement":"Brew MP"},{"regex":"BMP;","os_replacement":"Brew MP"},{"regex":"(GoogleTV) (\\d+)\\.(\\d+)\\.(\\d+)"},{"regex":"(GoogleTV)\\\/\\d+"},{"regex":"(WebTV)\/(\\d+).(\\d+)"},{"regex":"(hpw|web)OS\/(\\d+)\\.(\\d+)(?:\\.(\\d+))?","os_replacement":"webOS"},{"regex":"(VRE);"},{"regex":"(SUSE|Fedora|Red Hat|PCLinuxOS)\/(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)"},{"regex":"(SUSE|Fedora|Red Hat|Puppy|PCLinuxOS|CentOS)\/(\\d+)\\.(\\d+)\\.(\\d+)"},{"regex":"(Ubuntu|Kindle|Bada|Lubuntu|BackTrack|Red Hat|Slackware)\/(\\d+)\\.(\\d+)"},{"regex":"(Windows|OpenBSD|FreeBSD|NetBSD|Ubuntu|Kubuntu|Android|Arch Linux|CentOS|WeTab|Slackware)"},{"regex":"(Linux)\/(\\d+)\\.(\\d+)"},{"regex":"(Linux|BSD)"},{"regex":"SunOS","os_replacement":"Solaris"}],"device_parsers":[{"regex":"HTC ([A-Z][a-z0-9]+) Build","device_replacement":"HTC $1"},{"regex":"HTC ([A-Z][a-z0-9 ]+) \\d+\\.\\d+\\.\\d+\\.\\d+","device_replacement":"HTC $1"},{"regex":"HTC_Touch_([A-Za-z0-9]+)","device_replacement":"HTC Touch ($1)"},{"regex":"USCCHTC(\\d+)","device_replacement":"HTC $1 (US Cellular)"},{"regex":"Sprint APA(9292)","device_replacement":"HTC $1 (Sprint)"},{"regex":"HTC ([A-Za-z0-9]+ [A-Z])","device_replacement":"HTC $1"},{"regex":"HTC[-_\/\\s]([A-Za-z0-9]+)","device_replacement":"HTC $1"},{"regex":"(ADR[A-Za-z0-9]+)","device_replacement":"HTC $1"},{"regex":"(HTC)"},{"regex":"(QtCarBrowser)","device_replacement":"Tesla Model S"},{"regex":"(SamsungSGHi560)","device_replacement":"Samsung SGHi560"},{"regex":"SonyEricsson([A-Za-z0-9]+)\/","device_replacement":"Ericsson $1"},{"regex":"PLAYSTATION 3","device_replacement":"PlayStation 3"},{"regex":"(PlayStation Portable)"},{"regex":"(PlayStation Vita)"},{"regex":"(KFOT Build)","device_replacement":"Kindle Fire"},{"regex":"(KFTT Build)","device_replacement":"Kindle Fire HD"},{"regex":"(KFJWI Build)","device_replacement":"Kindle Fire HD 8.9\" WiFi"},{"regex":"(KFJWA Build)","device_replacement":"Kindle Fire HD 8.9\" 4G"},{"regex":"(Kindle Fire)"},{"regex":"(Kindle)"},{"regex":"(Silk)\/(\\d+)\\.(\\d+)(?:\\.([0-9\\-]+))?","device_replacement":"Kindle Fire"},{"regex":"Android[\\- ][\\d]+\\.[\\d]+; [A-Za-z]{2}\\-[A-Za-z]{2}; WOWMobile (.+) Build"},{"regex":"Android[\\- ][\\d]+\\.[\\d]+\\-update1; [A-Za-z]{2}\\-[A-Za-z]{2}; (.+) Build"},{"regex":"Android[\\- ][\\d]+\\.[\\d]+\\.[\\d]+; [A-Za-z]{2}\\-[A-Za-z]{2}; (.+) Build"},{"regex":"Android[\\- ][\\d]+\\.[\\d]+\\.[\\d]+;[A-Za-z]{2}\\-[A-Za-z]{2};(.+) Build"},{"regex":"Android[\\- ][\\d]+\\.[\\d]+; [A-Za-z]{2}\\-[A-Za-z]{2}; (.+) Build"},{"regex":"Android[\\- ][\\d]+\\.[\\d]+\\.[\\d]+; (.+) Build"},{"regex":"Android[\\- ][\\d]+\\.[\\d]+; (.+) Build"},{"regex":"NokiaN([0-9]+)","device_replacement":"Nokia N$1"},{"regex":"NOKIA([A-Za-z0-9\\v-]+)","device_replacement":"Nokia $1"},{"regex":"Nokia([A-Za-z0-9\\v-]+)","device_replacement":"Nokia $1"},{"regex":"NOKIA ([A-Za-z0-9\\-]+)","device_replacement":"Nokia $1"},{"regex":"Nokia ([A-Za-z0-9\\-]+)","device_replacement":"Nokia $1"},{"regex":"Lumia ([A-Za-z0-9\\-]+)","device_replacement":"Lumia $1"},{"regex":"Symbian","device_replacement":"Nokia"},{"regex":"BB10; ([A-Za-z0-9\\- ]+)\\)","device_replacement":"BlackBerry $1"},{"regex":"(PlayBook).+RIM Tablet OS","device_replacement":"BlackBerry Playbook"},{"regex":"Black[Bb]erry ([0-9]+);","device_replacement":"BlackBerry $1"},{"regex":"Black[Bb]erry([0-9]+)","device_replacement":"BlackBerry $1"},{"regex":"Black[Bb]erry;","device_replacement":"BlackBerry"},{"regex":"(Pre)\/(\\d+)\\.(\\d+)","device_replacement":"Palm Pre"},{"regex":"(Pixi)\/(\\d+)\\.(\\d+)","device_replacement":"Palm Pixi"},{"regex":"(Touch[Pp]ad)\/(\\d+)\\.(\\d+)","device_replacement":"HP TouchPad"},{"regex":"HPiPAQ([A-Za-z0-9]+)\/(\\d+).(\\d+)","device_replacement":"HP iPAQ $1"},{"regex":"Palm([A-Za-z0-9]+)","device_replacement":"Palm $1"},{"regex":"Treo([A-Za-z0-9]+)","device_replacement":"Palm Treo $1"},{"regex":"webOS.*(P160UNA)\/(\\d+).(\\d+)","device_replacement":"HP Veer"},{"regex":"(AppleTV)","device_replacement":"AppleTV"},{"regex":"(iPad) Simulator;"},{"regex":"(iPad);"},{"regex":"(iPod);"},{"regex":"(iPhone) Simulator;"},{"regex":"(iPhone);"},{"regex":"acer_([A-Za-z0-9]+)_","device_replacement":"Acer $1"},{"regex":"acer_([A-Za-z0-9]+)_","device_replacement":"Acer $1"},{"regex":"ALCATEL-([A-Za-z0-9]+)","device_replacement":"Alcatel $1"},{"regex":"Alcatel-([A-Za-z0-9]+)","device_replacement":"Alcatel $1"},{"regex":"Amoi\\-([A-Za-z0-9]+)","device_replacement":"Amoi $1"},{"regex":"AMOI\\-([A-Za-z0-9]+)","device_replacement":"Amoi $1"},{"regex":"Asus\\-([A-Za-z0-9]+)","device_replacement":"Asus $1"},{"regex":"ASUS\\-([A-Za-z0-9]+)","device_replacement":"Asus $1"},{"regex":"BIRD\\-([A-Za-z0-9]+)","device_replacement":"Bird $1"},{"regex":"BIRD\\.([A-Za-z0-9]+)","device_replacement":"Bird $1"},{"regex":"BIRD ([A-Za-z0-9]+)","device_replacement":"Bird $1"},{"regex":"Dell ([A-Za-z0-9]+)","device_replacement":"Dell $1"},{"regex":"DoCoMo\/2\\.0 ([A-Za-z0-9]+)","device_replacement":"DoCoMo $1"},{"regex":"([A-Za-z0-9]+)_W\\;FOMA","device_replacement":"DoCoMo $1"},{"regex":"([A-Za-z0-9]+)\\;FOMA","device_replacement":"DoCoMo $1"},{"regex":"Huawei([A-Za-z0-9]+)","device_replacement":"Huawei $1"},{"regex":"HUAWEI-([A-Za-z0-9]+)","device_replacement":"Huawei $1"},{"regex":"vodafone([A-Za-z0-9]+)","device_replacement":"Huawei Vodafone $1"},{"regex":"i\\-mate ([A-Za-z0-9]+)","device_replacement":"i-mate $1"},{"regex":"Kyocera\\-([A-Za-z0-9]+)","device_replacement":"Kyocera $1"},{"regex":"KWC\\-([A-Za-z0-9]+)","device_replacement":"Kyocera $1"},{"regex":"Lenovo\\-([A-Za-z0-9]+)","device_replacement":"Lenovo $1"},{"regex":"Lenovo_([A-Za-z0-9]+)","device_replacement":"Lenovo $1"},{"regex":"LG\/([A-Za-z0-9]+)","device_replacement":"LG $1"},{"regex":"LG-LG([A-Za-z0-9]+)","device_replacement":"LG $1"},{"regex":"LGE-LG([A-Za-z0-9]+)","device_replacement":"LG $1"},{"regex":"LGE VX([A-Za-z0-9]+)","device_replacement":"LG $1"},{"regex":"LG ([A-Za-z0-9]+)","device_replacement":"LG $1"},{"regex":"LGE LG\\-AX([A-Za-z0-9]+)","device_replacement":"LG $1"},{"regex":"LG\\-([A-Za-z0-9]+)","device_replacement":"LG $1"},{"regex":"LGE\\-([A-Za-z0-9]+)","device_replacement":"LG $1"},{"regex":"LG([A-Za-z0-9]+)","device_replacement":"LG $1"},{"regex":"(KIN)\\.One (\\d+)\\.(\\d+)","device_replacement":"Microsoft $1"},{"regex":"(KIN)\\.Two (\\d+)\\.(\\d+)","device_replacement":"Microsoft $1"},{"regex":"(Motorola)\\-([A-Za-z0-9]+)"},{"regex":"MOTO\\-([A-Za-z0-9]+)","device_replacement":"Motorola $1"},{"regex":"MOT\\-([A-Za-z0-9]+)","device_replacement":"Motorola $1"},{"regex":"(Nintendo WiiU)","device_replacement":"Nintendo Wii U"},{"regex":"Nintendo (DS|3DS|DSi|Wii);","device_replacement":"Nintendo $1"},{"regex":"Pantech([A-Za-z0-9]+)","device_replacement":"Pantech $1"},{"regex":"Philips([A-Za-z0-9]+)","device_replacement":"Philips $1"},{"regex":"Philips ([A-Za-z0-9]+)","device_replacement":"Philips $1"},{"regex":"SAMSUNG-([A-Za-z0-9\\-]+)","device_replacement":"Samsung $1"},{"regex":"SAMSUNG\\; ([A-Za-z0-9\\-]+)","device_replacement":"Samsung $1"},{"regex":"Dreamcast","device_replacement":"Sega Dreamcast"},{"regex":"Softbank\/1\\.0\/([A-Za-z0-9]+)","device_replacement":"Softbank $1"},{"regex":"Softbank\/2\\.0\/([A-Za-z0-9]+)","device_replacement":"Softbank $1"},{"regex":"(WebTV)\/(\\d+).(\\d+)"},{"regex":"(hiptop|avantgo|plucker|xiino|blazer|elaine|up.browser|up.link|mmp|smartphone|midp|wap|vodafone|o2|pocket|mobile|pda)","device_replacement":"Generic Smartphone"},{"regex":"^(1207|3gso|4thp|501i|502i|503i|504i|505i|506i|6310|6590|770s|802s|a wa|acer|acs\\-|airn|alav|asus|attw|au\\-m|aur |aus |abac|acoo|aiko|alco|alca|amoi|anex|anny|anyw|aptu|arch|argo|bell|bird|bw\\-n|bw\\-u|beck|benq|bilb|blac|c55\/|cdm\\-|chtm|capi|comp|cond|craw|dall|dbte|dc\\-s|dica|ds\\-d|ds12|dait|devi|dmob|doco|dopo|el49|erk0|esl8|ez40|ez60|ez70|ezos|ezze|elai|emul|eric|ezwa|fake|fly\\-|fly_|g\\-mo|g1 u|g560|gf\\-5|grun|gene|go.w|good|grad|hcit|hd\\-m|hd\\-p|hd\\-t|hei\\-|hp i|hpip|hs\\-c|htc |htc\\-|htca|htcg)","device_replacement":"Generic Feature Phone"},{"regex":"^(htcp|htcs|htct|htc_|haie|hita|huaw|hutc|i\\-20|i\\-go|i\\-ma|i230|iac|iac\\-|iac\/|ig01|im1k|inno|iris|jata|java|kddi|kgt|kgt\/|kpt |kwc\\-|klon|lexi|lg g|lg\\-a|lg\\-b|lg\\-c|lg\\-d|lg\\-f|lg\\-g|lg\\-k|lg\\-l|lg\\-m|lg\\-o|lg\\-p|lg\\-s|lg\\-t|lg\\-u|lg\\-w|lg\/k|lg\/l|lg\/u|lg50|lg54|lge\\-|lge\/|lynx|leno|m1\\-w|m3ga|m50\/|maui|mc01|mc21|mcca|medi|meri|mio8|mioa|mo01|mo02|mode|modo|mot |mot\\-|mt50|mtp1|mtv |mate|maxo|merc|mits|mobi|motv|mozz|n100|n101|n102|n202|n203|n300|n302|n500|n502|n505|n700|n701|n710|nec\\-|nem\\-|newg|neon)","device_replacement":"Generic Feature Phone"},{"regex":"^(netf|noki|nzph|o2 x|o2\\-x|opwv|owg1|opti|oran|ot\\-s|p800|pand|pg\\-1|pg\\-2|pg\\-3|pg\\-6|pg\\-8|pg\\-c|pg13|phil|pn\\-2|pt\\-g|palm|pana|pire|pock|pose|psio|qa\\-a|qc\\-2|qc\\-3|qc\\-5|qc\\-7|qc07|qc12|qc21|qc32|qc60|qci\\-|qwap|qtek|r380|r600|raks|rim9|rove|s55\/|sage|sams|sc01|sch\\-|scp\\-|sdk\/|se47|sec\\-|sec0|sec1|semc|sgh\\-|shar|sie\\-|sk\\-0|sl45|slid|smb3|smt5|sp01|sph\\-|spv |spv\\-|sy01|samm|sany|sava|scoo|send|siem|smar|smit|soft|sony|t\\-mo|t218|t250|t600|t610|t618|tcl\\-|tdg\\-|telm|tim\\-|ts70|tsm\\-|tsm3|tsm5|tx\\-9|tagt)","device_replacement":"Generic Feature Phone"},{"regex":"^(talk|teli|topl|tosh|up.b|upg1|utst|v400|v750|veri|vk\\-v|vk40|vk50|vk52|vk53|vm40|vx98|virg|vite|voda|vulc|w3c |w3c\\-|wapj|wapp|wapu|wapm|wig |wapi|wapr|wapv|wapy|wapa|waps|wapt|winc|winw|wonu|x700|xda2|xdag|yas\\-|your|zte\\-|zeto|aste|audi|avan|blaz|brew|brvw|bumb|ccwa|cell|cldc|cmd\\-|dang|eml2|fetc|hipt|http|ibro|idea|ikom|ipaq|jbro|jemu|jigs|keji|kyoc|kyok|libw|m\\-cr|midp|mmef|moto|mwbp|mywa|newt|nok6|o2im|pant|pdxg|play|pluc|port|prox|rozo|sama|seri|smal|symb|treo|upsi|vx52|vx53|vx60|vx61|vx70|vx80|vx81|vx83|vx85|wap\\-|webc|whit|wmlb|xda\\-|xda_)","device_replacement":"Generic Feature Phone"},{"regex":"(bot|borg|google(^tv)|yahoo|slurp|msnbot|msrbot|openbot|archiver|netresearch|lycos|scooter|altavista|teoma|gigabot|baiduspider|blitzbot|oegp|charlotte|furlbot|http%20client|polybot|htdig|ichiro|mogimogi|larbin|pompos|scrubby|searchsight|seekbot|semanticdiscovery|silk|snappy|speedy|spider|voila|vortex|voyager|zao|zeal|fast\\-webcrawler|converacrawler|dataparksearch|findlinks)","device_replacement":"Spider"}]} \ No newline at end of file diff --git a/includes/ua-parser-2.1.1/resources/regexes.yaml b/includes/ua-parser-2.1.1/resources/regexes.yaml deleted file mode 100644 index 3617a5b26..000000000 --- a/includes/ua-parser-2.1.1/resources/regexes.yaml +++ /dev/null @@ -1,1002 +0,0 @@ -user_agent_parsers: - #### SPECIAL CASES TOP #### - - # must go before Firefox to catch SeaMonkey/Camino - - regex: '(SeaMonkey|Camino)/(\d+)\.(\d+)\.?([ab]?\d+[a-z]*)' - - # Firefox - - regex: '(Pale[Mm]oon)/(\d+)\.(\d+)\.?(\d+)?' - family_replacement: 'Pale Moon (Firefox Variant)' - - regex: '(Fennec)/(\d+)\.(\d+)\.?([ab]?\d+[a-z]*)' - family_replacement: 'Firefox Mobile' - - regex: '(Fennec)/(\d+)\.(\d+)(pre)' - family_replacement: 'Firefox Mobile' - - regex: '(Fennec)/(\d+)\.(\d+)' - family_replacement: 'Firefox Mobile' - - regex: 'Mobile.*(Firefox)/(\d+)\.(\d+)' - family_replacement: 'Firefox Mobile' - - regex: '(Namoroka|Shiretoko|Minefield)/(\d+)\.(\d+)\.(\d+(?:pre)?)' - family_replacement: 'Firefox ($1)' - - regex: '(Firefox)/(\d+)\.(\d+)(a\d+[a-z]*)' - family_replacement: 'Firefox Alpha' - - regex: '(Firefox)/(\d+)\.(\d+)(b\d+[a-z]*)' - family_replacement: 'Firefox Beta' - - regex: '(Firefox)-(?:\d+\.\d+)?/(\d+)\.(\d+)(a\d+[a-z]*)' - family_replacement: 'Firefox Alpha' - - regex: '(Firefox)-(?:\d+\.\d+)?/(\d+)\.(\d+)(b\d+[a-z]*)' - family_replacement: 'Firefox Beta' - - regex: '(Namoroka|Shiretoko|Minefield)/(\d+)\.(\d+)([ab]\d+[a-z]*)?' - family_replacement: 'Firefox ($1)' - - regex: '(Firefox).*Tablet browser (\d+)\.(\d+)\.(\d+)' - family_replacement: 'MicroB' - - regex: '(MozillaDeveloperPreview)/(\d+)\.(\d+)([ab]\d+[a-z]*)?' - - # e.g.: Flock/2.0b2 - - regex: '(Flock)/(\d+)\.(\d+)(b\d+?)' - - # RockMelt - - regex: '(RockMelt)/(\d+)\.(\d+)\.(\d+)' - - # e.g.: Fennec/0.9pre - - regex: '(Navigator)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Netscape' - - - regex: '(Navigator)/(\d+)\.(\d+)([ab]\d+)' - family_replacement: 'Netscape' - - - regex: '(Netscape6)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Netscape' - - - regex: '(MyIBrow)/(\d+)\.(\d+)' - family_replacement: 'My Internet Browser' - - # Opera will stop at 9.80 and hide the real version in the Version string. - # see: http://dev.opera.com/articles/view/opera-ua-string-changes/ - - regex: '(Opera Tablet).*Version/(\d+)\.(\d+)(?:\.(\d+))?' - - regex: '(Opera)/.+Opera Mobi.+Version/(\d+)\.(\d+)' - family_replacement: 'Opera Mobile' - - regex: 'Opera Mobi' - family_replacement: 'Opera Mobile' - - regex: '(Opera Mini)/(\d+)\.(\d+)' - - regex: '(Opera Mini)/att/(\d+)\.(\d+)' - - regex: '(Opera)/9.80.*Version/(\d+)\.(\d+)(?:\.(\d+))?' - - # Opera 14 for Android uses a WebKit render engine. - - regex: '(?:Mobile Safari).*(OPR)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Opera Mobile' - - # Opera 15 for Desktop is similar to Chrome but includes an "OPR" Version string. - - regex: '(?:Chrome).*(OPR)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Opera' - - # Palm WebOS looks a lot like Safari. - - regex: '(hpw|web)OS/(\d+)\.(\d+)(?:\.(\d+))?' - family_replacement: 'webOS Browser' - - # LuaKit has no version info. - # http://luakit.org/projects/luakit/ - - regex: '(luakit)' - family_replacement: 'LuaKit' - - # Snowshoe - - regex: '(Snowshoe)/(\d+)\.(\d+).(\d+)' - - # Lightning (for Thunderbird) - # http://www.mozilla.org/projects/calendar/lightning/ - - regex: '(Lightning)/(\d+)\.(\d+)([ab]?\d+[a-z]*)' - - # Swiftfox - - regex: '(Firefox)/(\d+)\.(\d+)\.(\d+(?:pre)?) \(Swiftfox\)' - family_replacement: 'Swiftfox' - - regex: '(Firefox)/(\d+)\.(\d+)([ab]\d+[a-z]*)? \(Swiftfox\)' - family_replacement: 'Swiftfox' - - # Rekonq - - regex: '(rekonq)/(\d+)\.(\d+)\.?(\d+)? Safari' - family_replacement: 'Rekonq' - - regex: 'rekonq' - family_replacement: 'Rekonq' - - # Conkeror lowercase/uppercase - # http://conkeror.org/ - - regex: '(conkeror|Conkeror)/(\d+)\.(\d+)\.?(\d+)?' - family_replacement: 'Conkeror' - - # catches lower case konqueror - - regex: '(konqueror)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Konqueror' - - - regex: '(WeTab)-Browser' - - - regex: '(Comodo_Dragon)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Comodo Dragon' - - # Bots - - regex: '(YottaaMonitor|BrowserMob|HttpMonitor|YandexBot|Slurp|BingPreview|PagePeeker|ThumbShotsBot|WebThumb|URL2PNG|ZooShot|GomezA|Catchpoint bot|Willow Internet Crawler|Google SketchUp|Read%20Later)' - - - regex: '(Symphony) (\d+).(\d+)' - - - regex: '(Minimo)' - - # Chrome Mobile - - regex: '(CrMo)/(\d+)\.(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Chrome Mobile' - - regex: '(CriOS)/(\d+)\.(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Chrome Mobile iOS' - - regex: '(Chrome)/(\d+)\.(\d+)\.(\d+)\.(\d+) Mobile' - family_replacement: 'Chrome Mobile' - - # Chrome Frame must come before MSIE. - - regex: '(chromeframe)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Chrome Frame' - - # UC Browser - - regex: '(UCBrowser)[ /](\d+)\.(\d+)\.(\d+)' - family_replacement: 'UC Browser' - - regex: '(UC Browser)[ /](\d+)\.(\d+)\.(\d+)' - - regex: '(UC Browser|UCBrowser|UCWEB)(\d+)\.(\d+)\.(\d+)' - family_replacement: 'UC Browser' - - # Tizen Browser (second case included in browser/major.minor regex) - - regex: '(SLP Browser)/(\d+)\.(\d+)' - family_replacement: 'Tizen Browser' - - # Sogou Explorer 2.X - - regex: '(SE 2\.X) MetaSr (\d+)\.(\d+)' - family_replacement: 'Sogou Explorer' - - # Baidu Browsers (desktop spoofs chrome & IE, explorer is mobile) - - regex: '(baidubrowser)[/\s](\d+)' - family_replacement: 'Baidu Browser' - - regex: '(FlyFlow)/(\d+)\.(\d+)' - family_replacement: 'Baidu Explorer' - - # Pingdom - - regex: '(Pingdom.com_bot_version_)(\d+)\.(\d+)' - family_replacement: 'PingdomBot' - - # Facebook - - regex: '(facebookexternalhit)/(\d+)\.(\d+)' - family_replacement: 'FacebookBot' - - # Twitterbot - - regex: '(Twitterbot)/(\d+)\.(\d+)' - family_replacement: 'TwitterBot' - - # Rackspace Monitoring - - regex: '(Rackspace Monitoring)/(\d+)\.(\d+)' - family_replacement: 'RackspaceBot' - - # PyAMF - - regex: '(PyAMF)/(\d+)\.(\d+)\.(\d+)' - - # Yandex Browser - - regex: '(YaBrowser)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Yandex Browser' - - # Mail.ru Amigo/Internet Browser (Chromium-based) - - regex: '(Chrome)/(\d+)\.(\d+)\.(\d+).* MRCHROME' - family_replacement: 'Mail.ru Chromium Browser' - - # AOL Browser (IE-based) - - regex: '(AOL) (\d+)\.(\d+); AOLBuild (\d+)' - - #### END SPECIAL CASES TOP #### - - #### MAIN CASES - this catches > 50% of all browsers #### - - # Browser/major_version.minor_version.beta_version - - regex: '(AdobeAIR|FireWeb|Jasmine|ANTGalio|Midori|Fresco|Lobo|PaleMoon|Maxthon|Lynx|OmniWeb|Dillo|Camino|Demeter|Fluid|Fennec|Epiphany|Shiira|Sunrise|Flock|Netscape|Lunascape|WebPilot|Vodafone|NetFront|Netfront|Konqueror|SeaMonkey|Kazehakase|Vienna|Iceape|Iceweasel|IceWeasel|Iron|K-Meleon|Sleipnir|Galeon|GranParadiso|Opera Mini|iCab|NetNewsWire|ThunderBrowse|Iris|UP\.Browser|Bunjalloo|Google Earth|Raven for Mac|Openwave)/(\d+)\.(\d+)\.(\d+)' - - # Chrome/Chromium/major_version.minor_version.beta_version - - regex: '(Chromium|Chrome)/(\d+)\.(\d+)\.(\d+)' - - # Browser/major_version.minor_version - - regex: '(Bolt|Jasmine|IceCat|Skyfire|Midori|Maxthon|Lynx|Arora|IBrowse|Dillo|Camino|Shiira|Fennec|Phoenix|Chrome|Flock|Netscape|Lunascape|Epiphany|WebPilot|Opera Mini|Opera|Vodafone|NetFront|Netfront|Konqueror|Googlebot|SeaMonkey|Kazehakase|Vienna|Iceape|Iceweasel|IceWeasel|Iron|K-Meleon|Sleipnir|Galeon|GranParadiso|iCab|NetNewsWire|Space Bison|Stainless|Orca|Dolfin|BOLT|Minimo|Tizen Browser|Polaris|Abrowser|Planetweb|ICE Browser)/(\d+)\.(\d+)' - - # Chrome/Chromium/major_version.minor_version - - regex: '(Chromium|Chrome)/(\d+)\.(\d+)' - - # Browser major_version.minor_version.beta_version (space instead of slash) - - regex: '(iRider|Crazy Browser|SkipStone|iCab|Lunascape|Sleipnir|Maemo Browser) (\d+)\.(\d+)\.(\d+)' - # Browser major_version.minor_version (space instead of slash) - - regex: '(iCab|Lunascape|Opera|Android|Jasmine|Polaris) (\d+)\.(\d+)\.?(\d+)?' - - # Kindle WebKit - - regex: '(Kindle)/(\d+)\.(\d+)' - - # weird android UAs - - regex: '(Android) Donut' - v1_replacement: '1' - v2_replacement: '2' - - - regex: '(Android) Eclair' - v1_replacement: '2' - v2_replacement: '1' - - - regex: '(Android) Froyo' - v1_replacement: '2' - v2_replacement: '2' - - - regex: '(Android) Gingerbread' - v1_replacement: '2' - v2_replacement: '3' - - - regex: '(Android) Honeycomb' - v1_replacement: '3' - - # IE Mobile - - regex: '(IEMobile)[ /](\d+)\.(\d+)' - family_replacement: 'IE Mobile' - # desktop mode - # http://www.anandtech.com/show/3982/windows-phone-7-review - - regex: '(MSIE) (\d+)\.(\d+).*XBLWP7' - family_replacement: 'IE Large Screen' - - # AFTER THE EDGE CASES ABOVE! - - regex: '(Firefox)/(\d+)\.(\d+)\.(\d+)' - - regex: '(Firefox)/(\d+)\.(\d+)(pre|[ab]\d+[a-z]*)?' - - #### END MAIN CASES #### - - #### SPECIAL CASES #### - - regex: '(Obigo)InternetBrowser' - - regex: '(Obigo)\-Browser' - - regex: '(Obigo|OBIGO)[^\d]*(\d+)(?:.(\d+))?' - family_replacement: 'Obigo' - - - regex: '(MAXTHON|Maxthon) (\d+)\.(\d+)' - family_replacement: 'Maxthon' - - regex: '(Maxthon|MyIE2|Uzbl|Shiira)' - v1_replacement: '0' - - - regex: 'PLAYSTATION 3.+WebKit' - family_replacement: 'NetFront NX' - - regex: 'PLAYSTATION 3' - family_replacement: 'NetFront' - - regex: '(PlayStation Portable)' - family_replacement: 'NetFront' - - regex: '(PlayStation Vita)' - family_replacement: 'NetFront NX' - - - regex: 'AppleWebKit.+ (NX)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'NetFront NX' - - regex: '(Nintendo 3DS)' - family_replacement: 'NetFront NX' - - - regex: '(BrowseX) \((\d+)\.(\d+)\.(\d+)' - - - regex: '(NCSA_Mosaic)/(\d+)\.(\d+)' - family_replacement: 'NCSA Mosaic' - - # Polaris/d.d is above - - regex: '(POLARIS)/(\d+)\.(\d+)' - family_replacement: 'Polaris' - - regex: '(Embider)/(\d+)\.(\d+)' - family_replacement: 'Polaris' - - - regex: '(BonEcho)/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Bon Echo' - - - regex: 'M?QQBrowser' - family_replacement: 'QQ Browser' - - - regex: '(iPod).+Version/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Mobile Safari' - - regex: '(iPod).*Version/(\d+)\.(\d+)' - family_replacement: 'Mobile Safari' - - regex: '(iPhone).*Version/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Mobile Safari' - - regex: '(iPhone).*Version/(\d+)\.(\d+)' - family_replacement: 'Mobile Safari' - - regex: '(iPad).*Version/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Mobile Safari' - - regex: '(iPad).*Version/(\d+)\.(\d+)' - family_replacement: 'Mobile Safari' - - regex: '(iPod|iPhone|iPad);.*CPU.*OS (\d+)(?:_\d+)?_(\d+).*Mobile' - family_replacement: 'Mobile Safari' - - regex: '(iPod|iPhone|iPad)' - family_replacement: 'Mobile Safari' - - - regex: '(AvantGo) (\d+).(\d+)' - - - regex: '(OneBrowser)/(\d+).(\d+)' - family_replacement: 'ONE Browser' - - - regex: '(Avant)' - v1_replacement: '1' - - # This is the Tesla Model S (see similar entry in device parsers) - - regex: '(QtCarBrowser)' - v1_replacement: '1' - - - regex: '(iBrowser/Mini)(\d+).(\d+)' - family_replacement: 'iBrowser Mini' - # nokia browsers - # based on: http://www.developer.nokia.com/Community/Wiki/User-Agent_headers_for_Nokia_devices - - regex: '^(Nokia)' - family_replacement: 'Nokia Services (WAP) Browser' - - regex: '(NokiaBrowser)/(\d+)\.(\d+).(\d+)\.(\d+)' - family_replacement: 'Nokia Browser' - - regex: '(NokiaBrowser)/(\d+)\.(\d+).(\d+)' - family_replacement: 'Nokia Browser' - - regex: '(NokiaBrowser)/(\d+)\.(\d+)' - family_replacement: 'Nokia Browser' - - regex: '(BrowserNG)/(\d+)\.(\d+).(\d+)' - family_replacement: 'Nokia Browser' - - regex: '(Series60)/5\.0' - family_replacement: 'Nokia Browser' - v1_replacement: '7' - v2_replacement: '0' - - regex: '(Series60)/(\d+)\.(\d+)' - family_replacement: 'Nokia OSS Browser' - - regex: '(S40OviBrowser)/(\d+)\.(\d+)\.(\d+)\.(\d+)' - family_replacement: 'Ovi Browser' - - regex: '(Nokia)[EN]?(\d+)' - - # BlackBerry devices - - regex: '(BB10);' - family_replacement: 'BlackBerry WebKit' - - regex: '(PlayBook).+RIM Tablet OS (\d+)\.(\d+)\.(\d+)' - family_replacement: 'BlackBerry WebKit' - - regex: '(Black[bB]erry).+Version/(\d+)\.(\d+)\.(\d+)' - family_replacement: 'BlackBerry WebKit' - - regex: '(Black[bB]erry)\s?(\d+)' - family_replacement: 'BlackBerry' - - - regex: '(OmniWeb)/v(\d+)\.(\d+)' - - - regex: '(Blazer)/(\d+)\.(\d+)' - family_replacement: 'Palm Blazer' - - - regex: '(Pre)/(\d+)\.(\d+)' - family_replacement: 'Palm Pre' - - # fork of Links - - regex: '(ELinks)/(\d+)\.(\d+)' - - regex: '(ELinks) \((\d+)\.(\d+)' - - regex: '(Links) \((\d+)\.(\d+)' - - - regex: '(QtWeb) Internet Browser/(\d+)\.(\d+)' - - #- regex: '\(iPad;.+(Version)/(\d+)\.(\d+)(?:\.(\d+))?.*Safari/' - # family_replacement: 'iPad' - - # Amazon Silk, should go before Safari - - regex: '(Silk)/(\d+)\.(\d+)(?:\.([0-9\-]+))?' - family_replacement: 'Amazon Silk' - - # Phantomjs, should go before Safari - - regex: '(PhantomJS)/(\d+)\.(\d+)\.(\d+)' - - # WebKit Nightly - - regex: '(AppleWebKit)/(\d+)\.?(\d+)?\+ .* Safari' - family_replacement: 'WebKit Nightly' - - # Safari - - regex: '(Version)/(\d+)\.(\d+)(?:\.(\d+))?.*Safari/' - family_replacement: 'Safari' - # Safari didn't provide "Version/d.d.d" prior to 3.0 - - regex: '(Safari)/\d+' - - - regex: '(OLPC)/Update(\d+)\.(\d+)' - - - regex: '(OLPC)/Update()\.(\d+)' - v1_replacement: '0' - - - regex: '(SEMC\-Browser)/(\d+)\.(\d+)' - - - regex: '(Teleca)' - family_replacement: 'Teleca Browser' - - - regex: '(Phantom)/V(\d+)\.(\d+)' - family_replacement: 'Phantom Browser' - - - regex: '([MS]?IE) (\d+)\.(\d+)' - family_replacement: 'IE' - - - regex: '(python-requests)/(\d+)\.(\d+)' - family_replacement: 'Python Requests' - -os_parsers: - - ########## - # Android - # can actually detect rooted android os. do we care? - ########## - - regex: '(Android) (\d+)\.(\d+)(?:[.\-]([a-z0-9]+))?' - - regex: '(Android)\-(\d+)\.(\d+)(?:[.\-]([a-z0-9]+))?' - - - regex: '(Android) Donut' - os_v1_replacement: '1' - os_v2_replacement: '2' - - - regex: '(Android) Eclair' - os_v1_replacement: '2' - os_v2_replacement: '1' - - - regex: '(Android) Froyo' - os_v1_replacement: '2' - os_v2_replacement: '2' - - - regex: '(Android) Gingerbread' - os_v1_replacement: '2' - os_v2_replacement: '3' - - - regex: '(Android) Honeycomb' - os_v1_replacement: '3' - - ########## - # Kindle Android - ########## - - regex: '(Silk-Accelerated=[a-z]{4,5})' - os_replacement: 'Android' - - ########## - # Windows - # http://en.wikipedia.org/wiki/Windows_NT#Releases - # possibility of false positive when different marketing names share same NT kernel - # e.g. windows server 2003 and windows xp - # lots of ua strings have Windows NT 4.1 !?!?!?!? !?!? !? !????!?! !!! ??? !?!?! ? - # (very) roughly ordered in terms of frequency of occurence of regex (win xp currently most frequent, etc) - ########## - - - regex: '(Windows (?:NT 5\.2|NT 5\.1))' - os_replacement: 'Windows XP' - - # ie mobile des ktop mode - # spoofs nt 6.1. must come before windows 7 - - regex: '(XBLWP7)' - os_replacement: 'Windows Phone' - - - regex: '(Windows NT 6\.1)' - os_replacement: 'Windows 7' - - - regex: '(Windows NT 6\.0)' - os_replacement: 'Windows Vista' - - - regex: '(Win 9x 4\.90)' - os_replacement: 'Windows Me' - - - regex: '(Windows 98|Windows XP|Windows ME|Windows 95|Windows CE|Windows 7|Windows NT 4\.0|Windows Vista|Windows 2000|Windows 3.1)' - - - regex: '(Windows NT 6\.2; ARM;)' - os_replacement: 'Windows RT' - - # is this a spoof or is nt 6.2 out and about in some capacity? - - regex: '(Windows NT 6\.2)' - os_replacement: 'Windows 8' - - - regex: '(Windows NT 5\.0)' - os_replacement: 'Windows 2000' - - - regex: '(Windows Phone) (\d+)\.(\d+)' - - regex: '(Windows Phone) OS (\d+)\.(\d+)' - - regex: '(Windows ?Mobile)' - os_replacement: 'Windows Mobile' - - - regex: '(WinNT4.0)' - os_replacement: 'Windows NT 4.0' - - - regex: '(Win98)' - os_replacement: 'Windows 98' - - ########## - # Tizen OS from Samsung - # spoofs Android so pushing it above - ########## - - regex: '(Tizen)/(\d+)\.(\d+)' - - ########## - # Mac OS - # http://en.wikipedia.org/wiki/Mac_OS_X#Versions - ########## - - regex: '(Mac OS X) (\d+)[_.](\d+)(?:[_.](\d+))?' - - # IE on Mac doesn't specify version number - - regex: 'Mac_PowerPC' - os_replacement: 'Mac OS' - - # builds before tiger don't seem to specify version? - - # ios devices spoof (mac os x), so including intel/ppc prefixes - - regex: '(?:PPC|Intel) (Mac OS X)' - - ########## - # iOS - # http://en.wikipedia.org/wiki/IOS_version_history - ########## - - regex: '(CPU OS|iPhone OS) (\d+)_(\d+)(?:_(\d+))?' - os_replacement: 'iOS' - - # remaining cases are mostly only opera uas, so catch opera as to not catch iphone spoofs - - regex: '(iPhone|iPad|iPod); Opera' - os_replacement: 'iOS' - - # few more stragglers - - regex: '(iPhone|iPad|iPod).*Mac OS X.*Version/(\d+)\.(\d+)' - os_replacement: 'iOS' - - - regex: '(AppleTV)/(\d+)\.(\d+)' - os_replacement: 'ATV OS X' - - ########## - # Chrome OS - # if version 0.0.0, probably this stuff: - # http://code.google.com/p/chromium-os/issues/detail?id=11573 - # http://code.google.com/p/chromium-os/issues/detail?id=13790 - ########## - - regex: '(CrOS) [a-z0-9_]+ (\d+)\.(\d+)(?:\.(\d+))?' - os_replacement: 'Chrome OS' - - ########## - # Linux distros - ########## - - regex: '([Dd]ebian)' - os_replacement: 'Debian' - - regex: '(Linux Mint)(?:/(\d+))?' - - regex: '(Mandriva)(?: Linux)?/(?:[\d.-]+m[a-z]{2}(\d+).(\d))?' - - ########## - # Symbian + Symbian OS - # http://en.wikipedia.org/wiki/History_of_Symbian - ########## - - regex: '(Symbian[Oo][Ss])/(\d+)\.(\d+)' - os_replacement: 'Symbian OS' - - regex: '(Symbian/3).+NokiaBrowser/7\.3' - os_replacement: 'Symbian^3 Anna' - - regex: '(Symbian/3).+NokiaBrowser/7\.4' - os_replacement: 'Symbian^3 Belle' - - regex: '(Symbian/3)' - os_replacement: 'Symbian^3' - - regex: '(Series 60|SymbOS|S60)' - os_replacement: 'Symbian OS' - - regex: '(MeeGo)' - - regex: 'Symbian [Oo][Ss]' - os_replacement: 'Symbian OS' - - regex: 'Series40;' - os_replacement: 'Nokia Series 40' - - ########## - # BlackBerry devices - ########## - - regex: '(BB10);.+Version/(\d+)\.(\d+)\.(\d+)' - os_replacement: 'BlackBerry OS' - - regex: '(Black[Bb]erry)[0-9a-z]+/(\d+)\.(\d+)\.(\d+)(?:\.(\d+))?' - os_replacement: 'BlackBerry OS' - - regex: '(Black[Bb]erry).+Version/(\d+)\.(\d+)\.(\d+)(?:\.(\d+))?' - os_replacement: 'BlackBerry OS' - - regex: '(RIM Tablet OS) (\d+)\.(\d+)\.(\d+)' - os_replacement: 'BlackBerry Tablet OS' - - regex: '(Play[Bb]ook)' - os_replacement: 'BlackBerry Tablet OS' - - regex: '(Black[Bb]erry)' - os_replacement: 'BlackBerry OS' - - ########## - # Firefox OS - ########## - - regex: '\(Mobile;.+Firefox/\d+\.\d+' - os_replacement: 'Firefox OS' - - ########## - # BREW - # yes, Brew is lower-cased for Brew MP - ########## - - regex: '(BREW)[ /](\d+)\.(\d+)\.(\d+)' - - regex: '(BREW);' - - regex: '(Brew MP|BMP)[ /](\d+)\.(\d+)\.(\d+)' - os_replacement: 'Brew MP' - - regex: 'BMP;' - os_replacement: 'Brew MP' - - ########## - # Google TV - ########## - - regex: '(GoogleTV) (\d+)\.(\d+)\.(\d+)' - # Old style - - regex: '(GoogleTV)/[\da-z]+' - - - regex: '(WebTV)/(\d+).(\d+)' - - ########## - # Misc mobile - ########## - - regex: '(hpw|web)OS/(\d+)\.(\d+)(?:\.(\d+))?' - os_replacement: 'webOS' - - regex: '(VRE);' - - ########## - # Generic patterns - # since the majority of os cases are very specific, these go last - ########## - # first.second.third.fourth bits - - regex: '(Fedora|Red Hat|PCLinuxOS)/(\d+)\.(\d+)\.(\d+)\.(\d+)' - - # first.second.third bits - - regex: '(Red Hat|Puppy|PCLinuxOS)/(\d+)\.(\d+)\.(\d+)' - - # first.second bits - - regex: '(Ubuntu|Kindle|Bada|Lubuntu|BackTrack|Red Hat|Slackware)/(\d+)\.(\d+)' - - # just os - - regex: '(Windows|OpenBSD|FreeBSD|NetBSD|Android|WeTab)' - - regex: '(Ubuntu|Kubuntu|Arch Linux|CentOS|Slackware|Gentoo|openSUSE|SUSE|Red Hat|Fedora|PCLinuxOS|Gentoo|Mageia)' - - regex: '(Linux)/(\d+)\.(\d+)' - - regex: '(Linux|BSD)' - - regex: 'SunOS' - os_replacement: 'Solaris' - -device_parsers: - ########## - # incomplete! - # multiple replacement placeholds i.e. ($1) ($2) help solve problem of single device with multiple representations in ua - # e.g. HTC Dream S should parse to the same device as HTC_DreamS - ########## - - ########## - # incomplete! - # HTC - # http://en.wikipedia.org/wiki/List_of_HTC_phones - # this is quickly getting unwieldy - ########## - # example: Mozilla/5.0 (Linux; U; Android 2.3.2; fr-fr; HTC HD2 Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 - - regex: 'HTC ([A-Z][a-z0-9]+) Build' - device_replacement: 'HTC $1' - # example: Mozilla/5.0 (Linux; U; Android 2.1; es-es; HTC Legend 1.23.161.1 Build/ERD79) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17,gzip - - regex: 'HTC ([A-Z][a-z0-9 ]+) \d+\.\d+\.\d+\.\d+' - device_replacement: 'HTC $1' - # example: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; HTC_Touch_Diamond2_T5353; Windows Phone 6.5.3.5) - - regex: 'HTC_Touch_([A-Za-z0-9]+)' - device_replacement: 'HTC Touch ($1)' - # should come after HTC_Touch - - regex: 'USCCHTC(\d+)' - device_replacement: 'HTC $1 (US Cellular)' - - regex: 'Sprint APA(9292)' - device_replacement: 'HTC $1 (Sprint)' - - regex: 'HTC ([A-Za-z0-9]+ [A-Z])' - device_replacement: 'HTC $1' - - regex: 'HTC[-_/\s]([A-Za-z0-9]+)' - device_replacement: 'HTC $1' - - regex: '(ADR[A-Za-z0-9]+)' - device_replacement: 'HTC $1' - - regex: '(HTC)' - - # Tesla Model S - - regex: '(QtCarBrowser)' - device_replacement: 'Tesla Model S' - - # Samsung - - regex: '(SamsungSGHi560)' - device_replacement: 'Samsung SGHi560' - - ######### - # Ericsson - must come before nokia since they also use symbian - ######### - - regex: 'SonyEricsson([A-Za-z0-9]+)/' - device_replacement: 'Ericsson $1' - - ########## - # PlayStation - # The Vita spoofs the Kindle - ########## - - regex: 'PLAYSTATION 3' - device_replacement: 'PlayStation 3' - - regex: '(PlayStation Portable)' - - regex: '(PlayStation Vita)' - - ########## - # incomplete! - # Kindle - # http://amazonsilk.wordpress.com/useful-bits/silk-user-agent/ - ########## - - regex: '(KFOT Build)' - device_replacement: 'Kindle Fire' - - regex: '(KFTT Build)' - device_replacement: 'Kindle Fire HD' - - regex: '(KFJWI Build)' - device_replacement: 'Kindle Fire HD 8.9" WiFi' - - regex: '(KFJWA Build)' - device_replacement: 'Kindle Fire HD 8.9" 4G' - - regex: '(Kindle Fire)' - - regex: '(Kindle)' - - regex: '(Silk)/(\d+)\.(\d+)(?:\.([0-9\-]+))?' - device_replacement: 'Kindle Fire' - - ######### - # Android General Device Matching (far from perfect) - ######### - - regex: 'Android[\- ][\d]+\.[\d]+; [A-Za-z]{2}\-[A-Za-z]{2}; WOWMobile (.+) Build' - - regex: 'Android[\- ][\d]+\.[\d]+\-update1; [A-Za-z]{2}\-[A-Za-z]{2}; (.+) Build' - - regex: 'Android[\- ][\d]+\.[\d]+\.[\d]+; [A-Za-z]{2}\-[A-Za-z]{2}; (.+) Build' - - regex: 'Android[\- ][\d]+\.[\d]+\.[\d]+;[A-Za-z]{2}\-[A-Za-z]{2};(.+) Build' - - regex: 'Android[\- ][\d]+\.[\d]+; [A-Za-z]{2}\-[A-Za-z]{2}; (.+) Build' - - regex: 'Android[\- ][\d]+\.[\d]+\.[\d]+; (.+) Build' - - regex: 'Android[\- ][\d]+\.[\d]+; (.+) Build' - - ########## - # NOKIA - # nokia NokiaN8-00 comes before iphone. sometimes spoofs iphone - ########## - - regex: 'NokiaN([0-9]+)' - device_replacement: 'Nokia N$1' - - regex: 'NOKIA([A-Za-z0-9\v-]+)' - device_replacement: 'Nokia $1' - - regex: 'Nokia([A-Za-z0-9\v-]+)' - device_replacement: 'Nokia $1' - - regex: 'NOKIA ([A-Za-z0-9\-]+)' - device_replacement: 'Nokia $1' - - regex: 'Nokia ([A-Za-z0-9\-]+)' - device_replacement: 'Nokia $1' - - regex: 'Lumia ([A-Za-z0-9\-]+)' - device_replacement: 'Lumia $1' - - regex: 'Symbian' - device_replacement: 'Nokia' - - ########## - # BlackBerry - # http://www.useragentstring.com/pages/BlackBerry/ - ########## - - regex: 'BB10; ([A-Za-z0-9\- ]+)\)' - device_replacement: 'BlackBerry $1' - - regex: '(PlayBook).+RIM Tablet OS' - device_replacement: 'BlackBerry Playbook' - - regex: 'Black[Bb]erry ([0-9]+);' - device_replacement: 'BlackBerry $1' - - regex: 'Black[Bb]erry([0-9]+)' - device_replacement: 'BlackBerry $1' - - regex: 'Black[Bb]erry;' - device_replacement: 'BlackBerry' - - ########## - # PALM / HP - ########## - # some palm devices must come before iphone. sometimes spoofs iphone in ua - - regex: '(Pre)/(\d+)\.(\d+)' - device_replacement: 'Palm Pre' - - regex: '(Pixi)/(\d+)\.(\d+)' - device_replacement: 'Palm Pixi' - - regex: '(Touch[Pp]ad)/(\d+)\.(\d+)' - device_replacement: 'HP TouchPad' - - regex: 'HPiPAQ([A-Za-z0-9]+)/(\d+).(\d+)' - device_replacement: 'HP iPAQ $1' - - regex: 'Palm([A-Za-z0-9]+)' - device_replacement: 'Palm $1' - - regex: 'Treo([A-Za-z0-9]+)' - device_replacement: 'Palm Treo $1' - - regex: 'webOS.*(P160UNA)/(\d+).(\d+)' - device_replacement: 'HP Veer' - - ########## - # AppleTV - # No built in browser that I can tell - # Stack Overflow indicated iTunes-AppleTV/4.1 as a known UA for app available and I'm seeing it in live traffic - ########## - - regex: '(AppleTV)' - device_replacement: 'AppleTV' - - ########## - # Catch the google mobile crawler before checking for iPhones. - ########## - - - regex: 'AdsBot-Google-Mobile' - device_replacement: 'Spider' - - - regex: 'Googlebot-Mobile/(\d+).(\d+)' - device_replacement: 'Spider' - - ########## - # complete but probably catches spoofs - # iSTUFF - ########## - # ipad and ipod must be parsed before iphone - # cannot determine specific device type from ua string. (3g, 3gs, 4, etc) - - regex: '(iPad) Simulator;' - - regex: '(iPad);' - - regex: '(iPod) touch;' - - regex: '(iPod);' - - regex: '(iPhone) Simulator;' - - regex: '(iPhone);' - - ########## - # Acer - ########## - - regex: 'acer_([A-Za-z0-9]+)_' - device_replacement: 'Acer $1' - - regex: 'acer_([A-Za-z0-9]+)_' - device_replacement: 'Acer $1' - - ########## - # Alcatel - ########## - - regex: 'ALCATEL-([A-Za-z0-9]+)' - device_replacement: 'Alcatel $1' - - regex: 'Alcatel-([A-Za-z0-9]+)' - device_replacement: 'Alcatel $1' - - ########## - # Amoi - ########## - - regex: 'Amoi\-([A-Za-z0-9]+)' - device_replacement: 'Amoi $1' - - regex: 'AMOI\-([A-Za-z0-9]+)' - device_replacement: 'Amoi $1' - - ########## - # Amoi - ########## - - regex: 'Asus\-([A-Za-z0-9]+)' - device_replacement: 'Asus $1' - - regex: 'ASUS\-([A-Za-z0-9]+)' - device_replacement: 'Asus $1' - - ########## - # Bird - ########## - - regex: 'BIRD\-([A-Za-z0-9]+)' - device_replacement: 'Bird $1' - - regex: 'BIRD\.([A-Za-z0-9]+)' - device_replacement: 'Bird $1' - - regex: 'BIRD ([A-Za-z0-9]+)' - device_replacement: 'Bird $1' - - ########## - # Dell - ########## - - regex: 'Dell ([A-Za-z0-9]+)' - device_replacement: 'Dell $1' - - ########## - # DoCoMo - ########## - - regex: 'DoCoMo/2\.0 ([A-Za-z0-9]+)' - device_replacement: 'DoCoMo $1' - - regex: '([A-Za-z0-9]+)_W\;FOMA' - device_replacement: 'DoCoMo $1' - - regex: '([A-Za-z0-9]+)\;FOMA' - device_replacement: 'DoCoMo $1' - - ########## - # Huawei - ########## - - regex: 'Huawei([A-Za-z0-9]+)' - device_replacement: 'Huawei $1' - - regex: 'HUAWEI-([A-Za-z0-9]+)' - device_replacement: 'Huawei $1' - - regex: 'vodafone([A-Za-z0-9]+)' - device_replacement: 'Huawei Vodafone $1' - - ########## - # i-mate - ########## - - regex: 'i\-mate ([A-Za-z0-9]+)' - device_replacement: 'i-mate $1' - - ########## - # kyocera - ########## - - regex: 'Kyocera\-([A-Za-z0-9]+)' - device_replacement: 'Kyocera $1' - - regex: 'KWC\-([A-Za-z0-9]+)' - device_replacement: 'Kyocera $1' - - ########## - # lenovo - ########## - - regex: 'Lenovo\-([A-Za-z0-9]+)' - device_replacement: 'Lenovo $1' - - regex: 'Lenovo_([A-Za-z0-9]+)' - device_replacement: 'Lenovo $1' - - ########## - # lg - ########## - - regex: 'LG/([A-Za-z0-9]+)' - device_replacement: 'LG $1' - - regex: 'LG-LG([A-Za-z0-9]+)' - device_replacement: 'LG $1' - - regex: 'LGE-LG([A-Za-z0-9]+)' - device_replacement: 'LG $1' - - regex: 'LGE VX([A-Za-z0-9]+)' - device_replacement: 'LG $1' - - regex: 'LG ([A-Za-z0-9]+)' - device_replacement: 'LG $1' - - regex: 'LGE LG\-AX([A-Za-z0-9]+)' - device_replacement: 'LG $1' - - regex: 'LG\-([A-Za-z0-9]+)' - device_replacement: 'LG $1' - - regex: 'LGE\-([A-Za-z0-9]+)' - device_replacement: 'LG $1' - - regex: 'LG([A-Za-z0-9]+)' - device_replacement: 'LG $1' - - ########## - # kin - ########## - - regex: '(KIN)\.One (\d+)\.(\d+)' - device_replacement: 'Microsoft $1' - - regex: '(KIN)\.Two (\d+)\.(\d+)' - device_replacement: 'Microsoft $1' - - ########## - # motorola - ########## - - regex: '(Motorola)\-([A-Za-z0-9]+)' - - regex: 'MOTO\-([A-Za-z0-9]+)' - device_replacement: 'Motorola $1' - - regex: 'MOT\-([A-Za-z0-9]+)' - device_replacement: 'Motorola $1' - - ########## - # nintendo - ########## - - regex: '(Nintendo WiiU)' - device_replacement: 'Nintendo Wii U' - - regex: 'Nintendo (DS|3DS|DSi|Wii);' - device_replacement: 'Nintendo $1' - - ########## - # pantech - ########## - - regex: 'Pantech([A-Za-z0-9]+)' - device_replacement: 'Pantech $1' - - ########## - # philips - ########## - - regex: 'Philips([A-Za-z0-9]+)' - device_replacement: 'Philips $1' - - regex: 'Philips ([A-Za-z0-9]+)' - device_replacement: 'Philips $1' - - ########## - # Samsung - ########## - - regex: 'SAMSUNG-([A-Za-z0-9\-]+)' - device_replacement: 'Samsung $1' - - regex: 'SAMSUNG\; ([A-Za-z0-9\-]+)' - device_replacement: 'Samsung $1' - - ########## - # Sega - ########## - - regex: 'Dreamcast' - device_replacement: 'Sega Dreamcast' - - ########## - # Softbank - ########## - - regex: 'Softbank/1\.0/([A-Za-z0-9]+)' - device_replacement: 'Softbank $1' - - regex: 'Softbank/2\.0/([A-Za-z0-9]+)' - device_replacement: 'Softbank $1' - - ########## - # WebTV - ########## - - regex: '(WebTV)/(\d+).(\d+)' - - ########## - # Generic Smart Phone - ########## - - regex: '(hiptop|avantgo|plucker|xiino|blazer|elaine|up.browser|up.link|mmp|smartphone|midp|wap|vodafone|o2|pocket|mobile|pda)' - device_replacement: "Generic Smartphone" - - ########## - # Generic Feature Phone - ########## - - regex: '^(1207|3gso|4thp|501i|502i|503i|504i|505i|506i|6310|6590|770s|802s|a wa|acer|acs\-|airn|alav|asus|attw|au\-m|aur |aus |abac|acoo|aiko|alco|alca|amoi|anex|anny|anyw|aptu|arch|argo|bell|bird|bw\-n|bw\-u|beck|benq|bilb|blac|c55/|cdm\-|chtm|capi|comp|cond|craw|dall|dbte|dc\-s|dica|ds\-d|ds12|dait|devi|dmob|doco|dopo|el49|erk0|esl8|ez40|ez60|ez70|ezos|ezze|elai|emul|eric|ezwa|fake|fly\-|fly_|g\-mo|g1 u|g560|gf\-5|grun|gene|go.w|good|grad|hcit|hd\-m|hd\-p|hd\-t|hei\-|hp i|hpip|hs\-c|htc |htc\-|htca|htcg)' - device_replacement: 'Generic Feature Phone' - - regex: '^(htcp|htcs|htct|htc_|haie|hita|huaw|hutc|i\-20|i\-go|i\-ma|i230|iac|iac\-|iac/|ig01|im1k|inno|iris|jata|java|kddi|kgt|kgt/|kpt |kwc\-|klon|lexi|lg g|lg\-a|lg\-b|lg\-c|lg\-d|lg\-f|lg\-g|lg\-k|lg\-l|lg\-m|lg\-o|lg\-p|lg\-s|lg\-t|lg\-u|lg\-w|lg/k|lg/l|lg/u|lg50|lg54|lge\-|lge/|lynx|leno|m1\-w|m3ga|m50/|maui|mc01|mc21|mcca|medi|meri|mio8|mioa|mo01|mo02|mode|modo|mot |mot\-|mt50|mtp1|mtv |mate|maxo|merc|mits|mobi|motv|mozz|n100|n101|n102|n202|n203|n300|n302|n500|n502|n505|n700|n701|n710|nec\-|nem\-|newg|neon)' - device_replacement: 'Generic Feature Phone' - - regex: '^(netf|noki|nzph|o2 x|o2\-x|opwv|owg1|opti|oran|ot\-s|p800|pand|pg\-1|pg\-2|pg\-3|pg\-6|pg\-8|pg\-c|pg13|phil|pn\-2|pt\-g|palm|pana|pire|pock|pose|psio|qa\-a|qc\-2|qc\-3|qc\-5|qc\-7|qc07|qc12|qc21|qc32|qc60|qci\-|qwap|qtek|r380|r600|raks|rim9|rove|s55/|sage|sams|sc01|sch\-|scp\-|sdk/|se47|sec\-|sec0|sec1|semc|sgh\-|shar|sie\-|sk\-0|sl45|slid|smb3|smt5|sp01|sph\-|spv |spv\-|sy01|samm|sany|sava|scoo|send|siem|smar|smit|soft|sony|t\-mo|t218|t250|t600|t610|t618|tcl\-|tdg\-|telm|tim\-|ts70|tsm\-|tsm3|tsm5|tx\-9|tagt)' - device_replacement: 'Generic Feature Phone' - - regex: '^(talk|teli|topl|tosh|up.b|upg1|utst|v400|v750|veri|vk\-v|vk40|vk50|vk52|vk53|vm40|vx98|virg|vite|voda|vulc|w3c |w3c\-|wapj|wapp|wapu|wapm|wig |wapi|wapr|wapv|wapy|wapa|waps|wapt|winc|winw|wonu|x700|xda2|xdag|yas\-|your|zte\-|zeto|aste|audi|avan|blaz|brew|brvw|bumb|ccwa|cell|cldc|cmd\-|dang|eml2|fetc|hipt|http|ibro|idea|ikom|ipaq|jbro|jemu|jigs|keji|kyoc|kyok|libw|m\-cr|midp|mmef|moto|mwbp|mywa|newt|nok6|o2im|pant|pdxg|play|pluc|port|prox|rozo|sama|seri|smal|symb|treo|upsi|vx52|vx53|vx60|vx61|vx70|vx80|vx81|vx83|vx85|wap\-|webc|whit|wmlb|xda\-|xda_)' - device_replacement: 'Generic Feature Phone' - - ########## - # Spiders (this is hack...) - ########## - - regex: '(bot|borg|google(^tv)|yahoo|slurp|msnbot|msrbot|openbot|archiver|netresearch|lycos|scooter|altavista|teoma|gigabot|baiduspider|blitzbot|oegp|charlotte|furlbot|http%20client|polybot|htdig|ichiro|mogimogi|larbin|pompos|scrubby|searchsight|seekbot|semanticdiscovery|silk|snappy|speedy|spider|voila|vortex|voyager|zao|zeal|fast\-webcrawler|converacrawler|dataparksearch|findlinks|crawler)' - device_replacement: 'Spider' - diff --git a/includes/ua-parser-2.1.1/uaparser-cli.php b/includes/ua-parser-2.1.1/uaparser-cli.php deleted file mode 100644 index a85e538eb..000000000 --- a/includes/ua-parser-2.1.1/uaparser-cli.php +++ /dev/null @@ -1,279 +0,0 @@ -parse($ua); - if (($result->ua->family == "Other") && ($result->device->family != "Spider")) { - $output = "UA Not Found: ".$ua." [".$line."]\n"; - $show = "U"; - } else if (($result->os->family == "Other") && ($result->device->family != "Spider")) { - $output = "OS Not Found: ".$ua." [".$line."]\n"; - $show = "O"; - } else if ($result->device->family == "Generic Smartphone") { - $output = "GS: ".$ua." [".$line."]\n"; - $show = "GS"; - } else if ($result->device->family == "Generic Feature Phone") { - $output = "GFP: ".$ua." [".$line."]\n"; - $show = "GFP"; - } - if ((($show == "U") || ($show == "O") || ($show == "GS") || ($show == "GFP")) && !in_array($ua,$saved)) { - fwrite($fp, $output); - $saved[] = $ua; - print $show; - } else { - $i = ($i < 20) ? $i+1 : 0; - if ($i == 0) { - print "."; - } - } - } - } - if (!feof($data)) { - print "Error: unexpected fgets() fail\n"; - } - fclose($fp); - fclose($data); - print "\ncompleted the evaluation of the log file at ".$args["l"]."\n"; - } else { - print "unable to read the file at the supplied path...\n"; - } - - } else if (isset($args["j"]) && $args["j"]) { - - /* Parse the supplied UA from the command line and kick it out as JSON */ - - // load the parser - $parser = new UAParser; - - // parse and encode the results - if (version_compare(PHP_VERSION, '5.4.0', '>=') && isset($args["p"])) { - print json_encode($parser->parse($args["j"]), JSON_PRETTY_PRINT); - } else { - print json_encode($parser->parse($args["j"])); - } - print PHP_EOL; - - } else if (isset($argv[1]) && (($argv[1] != "-j") && ($argv[1] != "-p") && ($argv[1] != "-l") && ($argv[1] != "-s") && ($argv[1] != "-n"))) { - - /* Parse the supplied UA from the command line and kick it out as JSON */ - - // load the parser - $parser = new UAParser; - - // parse and print the results - $result = $parser->parse($argv[1]); - print " ua-parser results for \"".$argv[1]."\"\n"; - foreach ($result as $key => $value) { - if (gettype($value) == "object") { - foreach ($value as $key2 => $value2) { - print " ".$key."->".$key2.": ".$value2."\n"; - } - } else { - print " ".$key.": ".$value."\n"; - } - } - - } else { - - /* Print usage information */ - - print "\n"; - print "Usage:\n"; - print "\n"; - print " php uaparser-cli.php [-p] [-j] \"your user agent string\"\n"; - print " Parses a user agent string and dumps the results as a list.\n"; - print " Use the -j flag to print the result as JSON.\n"; - print " Use the -p flag to pretty print the JSON result when using PHP 5.4+.\n"; - print "\n"; - print " php uaparser-cli.php -g [-s] [-n]\n"; - print " Fetches an updated YAML file for ua-parser and overwrites the current JSON file.\n"; - print " By default is verbose. Use -s to turn that feature off.\n"; - print " By default creates a back-up. Use -n to turn that feature off.\n"; - print "\n"; - print " php uaparser-cli.php -c [-s] [-n]\n"; - print " Converts an existing regexes.yaml file to a regexes.json file.\n"; - print " By default is verbose. Use -s to turn that feature off.\n"; - print " By default creates a back-up. Use -n to turn that feature off.\n"; - print "\n"; - print " php uaparser-cli.php -y\n"; - print " Fetches an updated YAML file. If you need to add a new UA it's easier to edit\n"; - print " the original YAML and then convert it. Warning: This method overwrites any\n"; - print " existing regexes.yaml file.\n"; - print "\n"; - print " php uaparser-cli.php -l \"/path/to/apache/logfile\"\n"; - print " Parses the supplied Apache log file to test UAParser.php. Saves the UA to a file\n"; - print " when the UA or OS family aren't found or when the UA is listed as a generic\n"; - print " smartphone or as a generic feature phone.\n"; - print "\n"; - - } - -} else { - - print "You must run this file from the command line."; - -} diff --git a/includes/ua-parser-2.1.1/uaparser.php b/includes/ua-parser-2.1.1/uaparser.php deleted file mode 100644 index d07555711..000000000 --- a/includes/ua-parser-2.1.1/uaparser.php +++ /dev/null @@ -1,303 +0,0 @@ -regexes - */ - public function __construct($customRegexesFile = null) { - - $regexesFile = ($customRegexesFile !== null) ? $customRegexesFile : dirname(__FILE__).DIRECTORY_SEPARATOR.'resources/regexes.json'; - if (file_exists($regexesFile)) { - $this->regexes = json_decode(file_get_contents($regexesFile)); - } else { - $title = 'Error loading ua-parser'; - if ($customRegexesFile !== null) { - $message = 'ua-parser can\'t find the custom regexes file you supplied ('.$customRegexesFile.'). Please make sure you have the correct path.'; - $instruction1 = ''; - $instruction2 = ''; - } else { - $message = 'Please download the regexes.json file before using uaparser.php. You can type the following at the command line to download the latest version: '; - $instruction1 = '%: cd /path/to/UAParser/'; - $instruction2 = '%: php uaparser-cli.php -g'; - } - - if (php_sapi_name() == 'cli') { - print "\n".$title."\n"; - print $message."\n\n"; - print " ".$instruction2."\n\n"; - } else { - print ''.$title.''; - print '

'.$title.'

'; - print '

'.$message.'

'; - print '
'; - print ''.$instruction1.'
'; - print ''.$instruction2.''; - print '
'; - print ''; - } - - exit; - } - } - - /** - * Sets up some standard variables as well as starts the user agent parsing process - * @param string a user agent string to test, defaults to an empty string - * @return object the result of the user agent parsing - */ - public function parse($ua = '') { - - // build the default obj that will be returned - $result = (object) array( - 'ua' => (object) array(), - 'os' => (object) array(), - 'device' => (object) array(), - 'toFullString' => '', - 'uaOriginal' => $ua - ); - - // figure out the ua, os, and device properties if possible - $result->ua = $this->uaParse($ua); - $result->os = $this->osParse($ua); - $result->device = $this->deviceParse($ua); - - // create a full string version based on the ua and os objects - $result->toFullString = $this->toFullString($result->ua, $result->os); - - // log the results when testing - if ($this->log) { - $this->log($result); - } - - return $result; - - } - - /** - * Attempts to see if the user agent matches a user_agents_parsers regex from regexes.json - * @param string a user agent string to test - * @return object the result of the user agent parsing - */ - public function uaParse($uaString = '') { - - // build the default obj that will be returned - $ua = (object) array( - 'family' => 'Other', - 'major' => null, - 'minor' => null, - 'patch' => null, - 'toString' => '', - 'toVersionString' => '' - ); - - // run the regexes to match things up - $uaRegexes = $this->regexes->user_agent_parsers; - foreach ($uaRegexes as $uaRegex) { - - // tests the supplied regex against the user agent - if (preg_match('/'.str_replace('/','\/',str_replace('\/','/',$uaRegex->regex)).'/i',$uaString,$matches)) { - - // Make sure matches are at least set to null or Other - if (!isset($matches[1])) { $matches[1] = 'Other'; } - if (!isset($matches[2])) { $matches[2] = null; } - if (!isset($matches[3])) { $matches[3] = null; } - if (!isset($matches[4])) { $matches[4] = null; } - - // ua name - $ua->family = isset($uaRegex->family_replacement) ? str_replace('$1',$matches[1],$uaRegex->family_replacement) : $matches[1]; - - // version properties - $ua->major = isset($uaRegex->v1_replacement) ? $uaRegex->v1_replacement : $matches[2]; - $ua->minor = isset($uaRegex->v2_replacement) ? $uaRegex->v2_replacement : $matches[3]; - $ua->patch = isset($uaRegex->v3_replacement) ? $uaRegex->v3_replacement : $matches[4]; - - // extra strings - $ua->toString = $this->toString($ua); - $ua->toVersionString = $this->toVersionString($ua); - - return $ua; - } - - } - - return $ua; - - } - - /** - * Attempts to see if the user agent matches an os_parsers regex from regexes.json - * @param string a user agent string to test - * @return object the result of the os parsing - */ - public function osParse($uaString = '') { - - // build the default obj that will be returned - $os = (object) array( - 'family' => 'Other', - 'major' => null, - 'minor' => null, - 'patch' => null, - 'patch_minor' => null, - 'toString' => '', - 'toVersionString' => '' - ); - - // run the regexes to match things up - $osRegexes = $this->regexes->os_parsers; - foreach ($osRegexes as $osRegex) { - - if (preg_match('/'.str_replace('/','\/',str_replace('\/','/',$osRegex->regex)).'/i',$uaString,$matches)) { - - // Make sure matches are at least set to null or Other - if (!isset($matches[1])) { $matches[1] = 'Other'; } - if (!isset($matches[2])) { $matches[2] = null; } - if (!isset($matches[3])) { $matches[3] = null; } - if (!isset($matches[4])) { $matches[4] = null; } - if (!isset($matches[5])) { $matches[5] = null; } - - // os name - $os->family = isset($osRegex->os_replacement) ? $osRegex->os_replacement : $matches[1]; - - // version properties - $os->major = isset($osRegex->os_v1_replacement) ? $osRegex->os_v1_replacement : $matches[2]; - $os->minor = isset($osRegex->os_v2_replacement) ? $osRegex->os_v2_replacement : $matches[3]; - $os->patch = isset($osRegex->os_v3_replacement) ? $osRegex->os_v3_replacement : $matches[4]; - $os->patch_minor = isset($osRegex->os_v4_replacement) ? $osRegex->os_v4_replacement : $matches[5]; - - // extra strings - $os->toString = $this->toString($os); - $os->toVersionString = $this->toVersionString($os); - - return $os; - } - - } - - return $os; - - } - - /** - * Attempts to see if the user agent matches a device_parsers regex from regexes.json - * @param string a user agent string to test - * @return object the result of the device parsing - */ - public function deviceParse($uaString = '') { - - // build the default obj that will be returned - $device = (object) array( - 'family' => 'Other' - ); - - // run the regexes to match things up - $deviceRegexes = $this->regexes->device_parsers; - foreach ($deviceRegexes as $deviceRegex) { - - if (preg_match('/'.str_replace('/','\/',str_replace('\/','/',$deviceRegex->regex)).'/i',$uaString,$matches)) { - - // Make sure matches are at least set to null or Other - if (!isset($matches[1])) { $matches[1] = 'Other'; } - - // device name - $device->family = isset($deviceRegex->device_replacement) ? str_replace('$1',str_replace("_"," ",$matches[1]),$deviceRegex->device_replacement) : str_replace("_"," ",$matches[1]); - - return $device; - - } - - } - - return $device; - - } - - /** - * Returns a string consisting of the family and full version number based on the provided type - * @param object the object (ua or os) to be used - * @return string the result of combining family and version - */ - public function toString($obj) { - - $versionString = $this->toVersionString($obj); - $string = !empty($versionString) ? $obj->family.' '.$versionString : $obj->family; - - return $string; - } - - /** - * Returns a string consisting of just the full version number based on the provided type - * @param object the obj that contains version number bits - * @return string the result of combining the version number bits together - */ - public function toVersionString($obj) { - - $versionString = isset($obj->major) ? $obj->major : ''; - $versionString = isset($obj->minor) ? $versionString.'.'.$obj->minor : $versionString; - $versionString = isset($obj->patch) ? $versionString.'.'.$obj->patch : $versionString; - $versionString = isset($obj->patch_minor) ? $versionString.'.'.$obj->patch_minor : $versionString; - - return $versionString; - - } - - /** - * Returns a string consistig of the family and full version number for both the browser and os - * @param object the ua object - * @param object the os object - * @return string the result of combining family and version - */ - public function toFullString($ua,$os) { - - $fullString = $this->toString($ua).'/'.$this->toString($os); - - return $fullString; - - } - - /** - * Logs the user agent info - */ - protected function log($data) { - $jsonData = json_encode($data); - $fp = fopen(dirname(__FILE__).DIRECTORY_SEPARATOR.'log/user_agents.log', 'a'); - fwrite($fp, $jsonData."\r\n"); - fclose($fp); - } - -} diff --git a/modules/base/classes/browscap.php b/modules/base/classes/browscap.php index 46010a705..48f251792 100644 --- a/modules/base/classes/browscap.php +++ b/modules/base/classes/browscap.php @@ -16,7 +16,9 @@ // $Id$ // -require_once( OWA_UAPARSER_LIB ); +//require_once( OWA_UAPARSER_LIB ); +require_once ( OWA_VENDOR_DIR . 'autoload.php' ); +use UAParser\Parser; /** * Browscap Class @@ -96,13 +98,13 @@ function lookup( $user_agent ) { if ( ! $cache_obj ) { $custom_db = owa_coreAPI::getSetting('base','ua-regexes'); - + if ( $custom_db ) { - $parser = new UAParser($custom_db); + $parser = Parser::create($custom_db); } else { - $parser = new UAParser; + $parser = Parser::create(); } $cap = $parser->parse( $this->ua ); @@ -197,22 +199,22 @@ function getUaVersionPatch() { function getUaFamilyVersion() { - return $this->browser->ua->toString; + return $this->browser->ua->toVersion(); } function getUaVersion() { - return $this->browser->ua->toVersionString; + return $this->browser->ua->toVersion(); } function getUaOriginal() { - return $this->browser->uaOriginal; + return $this->browser->originalUserAgent; } function getUaOs() { - return $this->browser->toFullString; + return $this->browser->toString(); } function getOsFamily() { @@ -237,12 +239,12 @@ function getOsVersionPatch() { function getOsFamilyVersion() { - return $this->browser->os->toString; + return $this->browser->os->toString(); } function getOsVersion() { - return $this->browser->os->toVersionString; + return $this->browser->os->toVersion(); } }