summaryrefslogtreecommitdiffstats
path: root/vendor
diff options
context:
space:
mode:
Diffstat (limited to 'vendor')
-rw-r--r--vendor/github.com/avct/uasurfer/.gitignore56
-rw-r--r--vendor/github.com/avct/uasurfer/.travis.yml11
-rw-r--r--vendor/github.com/avct/uasurfer/LICENSE192
-rw-r--r--vendor/github.com/avct/uasurfer/README.md169
-rw-r--r--vendor/github.com/avct/uasurfer/browser.go192
-rw-r--r--vendor/github.com/avct/uasurfer/const_string.go49
-rw-r--r--vendor/github.com/avct/uasurfer/device.go60
-rw-r--r--vendor/github.com/avct/uasurfer/system.go336
-rw-r--r--vendor/github.com/avct/uasurfer/uasurfer.go227
-rw-r--r--vendor/github.com/avct/uasurfer/uasurfer_test.go1074
-rw-r--r--vendor/github.com/mssola/user_agent/.travis.yml13
-rw-r--r--vendor/github.com/mssola/user_agent/LICENSE20
-rw-r--r--vendor/github.com/mssola/user_agent/README.md51
-rw-r--r--vendor/github.com/mssola/user_agent/all_test.go594
-rw-r--r--vendor/github.com/mssola/user_agent/bot.go123
-rw-r--r--vendor/github.com/mssola/user_agent/browser.go140
-rw-r--r--vendor/github.com/mssola/user_agent/operating_systems.go359
-rw-r--r--vendor/github.com/mssola/user_agent/user_agent.go174
18 files changed, 2366 insertions, 1474 deletions
diff --git a/vendor/github.com/avct/uasurfer/.gitignore b/vendor/github.com/avct/uasurfer/.gitignore
new file mode 100644
index 000000000..35ba52a16
--- /dev/null
+++ b/vendor/github.com/avct/uasurfer/.gitignore
@@ -0,0 +1,56 @@
+# Compiled bin #
+###################
+
+
+# Compiled source #
+###################
+*.dll
+*.exe
+*.o
+*.so
+
+# Packages #
+############
+# it's better to unpack these files and commit the raw source
+# git has its own built in compression methods
+*.7z
+*.dmg
+*.gz
+*.iso
+*.jar
+*.rar
+*.tar
+*.zip
+
+# Configuration Files #
+#######################
+*.cfg
+
+# Logs and databases #
+######################
+*.log
+*.sql
+*.sqlite
+logs
+coverage.html
+coverage.out
+
+# Test Files #
+#######################
+*.test
+
+# OS generated files #
+######################
+.DS_Store
+.DS_Store?
+.Spotlight-V100
+.Trashes
+ehthumbs.db
+Thumbs.db
+
+# go.rice generated files
+*.rice-box.go
+
+# Dev Tools #
+######################
+.vagrant \ No newline at end of file
diff --git a/vendor/github.com/avct/uasurfer/.travis.yml b/vendor/github.com/avct/uasurfer/.travis.yml
new file mode 100644
index 000000000..77b64e6f2
--- /dev/null
+++ b/vendor/github.com/avct/uasurfer/.travis.yml
@@ -0,0 +1,11 @@
+sudo: false
+
+language: go
+
+go:
+ - 1.9.x
+ - 1.8.x
+ - 1.7.x
+
+script:
+ - go test
diff --git a/vendor/github.com/avct/uasurfer/LICENSE b/vendor/github.com/avct/uasurfer/LICENSE
new file mode 100644
index 000000000..a092343b2
--- /dev/null
+++ b/vendor/github.com/avct/uasurfer/LICENSE
@@ -0,0 +1,192 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ Copyright 2015 Avocet Systems Ltd.
+ http://avocet.io/opensource
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ Copyright 2015 Avocet Systems Ltd.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License. \ No newline at end of file
diff --git a/vendor/github.com/avct/uasurfer/README.md b/vendor/github.com/avct/uasurfer/README.md
new file mode 100644
index 000000000..2a4ab608d
--- /dev/null
+++ b/vendor/github.com/avct/uasurfer/README.md
@@ -0,0 +1,169 @@
+[![Build Status](https://travis-ci.org/avct/uasurfer.svg?branch=master)](https://travis-ci.org/avct/uasurfer) [![GoDoc](https://godoc.org/github.com/avct/uasurfer?status.svg)](https://godoc.org/github.com/avct/uasurfer) [![Go Report Card](https://goreportcard.com/badge/github.com/avct/uasurfer)](https://goreportcard.com/report/github.com/avct/uasurfer)
+
+# uasurfer
+
+![uasurfer-100px](https://cloud.githubusercontent.com/assets/597902/16172506/9debc136-357a-11e6-90fb-c7c46f50dff0.png)
+
+**User Agent Surfer** (uasurfer) is a lightweight Golang package that parses and abstracts [HTTP User-Agent strings](https://en.wikipedia.org/wiki/User_agent) with particular attention to device type.
+
+The following information is returned by uasurfer from a raw HTTP User-Agent string:
+
+| Name | Example | Coverage in 192,792 parses |
+|----------------|---------|--------------------------------|
+| Browser name | `chrome` | 99.85% |
+| Browser version | `53` | 99.17% |
+| Platform | `ipad` | 99.97% |
+| OS name | `ios` | 99.96% |
+| OS version | `10` | 98.81% |
+| Device type | `tablet` | 99.98% |
+
+Layout engine, browser language, and other esoteric attributes are not parsed.
+
+Coverage is estimated from a random sample of real UA strings collected across thousands of sources in US and EU mid-2016.
+
+## Usage
+
+### Parse(ua string) Function
+
+The `Parse()` function accepts a user agent `string` and returns UserAgent struct with named constants and integers for versions (minor, major and patch separately), and the full UA string that was parsed (lowercase). A string can be retrieved by adding `.String()` to a variable, such as `uasurfer.BrowserName.String()`.
+
+```
+// Define a user agent string
+myUA := "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36"
+
+// Parse() returns all attributes, including returning the full UA string last
+ua, uaString := uasurfer.Parse(myUA)
+```
+
+where example UserAgent is:
+```
+{
+ Browser {
+ BrowserName: BrowserChrome,
+ Version: {
+ Major: 45,
+ Minor: 0,
+ Patch: 2454,
+ },
+ },
+ OS {
+ Platform: PlatformMac,
+ Name: OSMacOSX,
+ Version: {
+ Major: 10,
+ Minor: 10,
+ Patch: 5,
+ },
+ },
+ DeviceType: DeviceComputer,
+}
+```
+
+**Usage note:** There are some OSes that do not return a version, see docs below. Linux is typically not reported with a specific Linux distro name or version.
+
+#### Browser Name
+* `BrowserChrome` - Google [Chrome](https://en.wikipedia.org/wiki/Google_Chrome), [Chromium](https://en.wikipedia.org/wiki/Chromium_(web_browser))
+* `BrowserSafari` - Apple [Safari](https://en.wikipedia.org/wiki/Safari_(web_browser)), Google Search ([GSA](https://itunes.apple.com/us/app/google/id284815942))
+* `BrowserIE` - Microsoft [Internet Explorer](https://en.wikipedia.org/wiki/Internet_Explorer), [Edge](https://en.wikipedia.org/wiki/Microsoft_Edge)
+* `BrowserFirefox` - Mozilla [Firefox](https://en.wikipedia.org/wiki/Firefox), GNU [IceCat](https://en.wikipedia.org/wiki/GNU_IceCat), [Iceweasel](https://en.wikipedia.org/wiki/Mozilla_Corporation_software_rebranded_by_the_Debian_project#Iceweasel), [Seamonkey](https://en.wikipedia.org/wiki/SeaMonkey)
+* `BrowserAndroid` - Android [WebView](https://developer.chrome.com/multidevice/webview/overview) (Android OS <4.4 only)
+* `BrowserOpera` - [Opera](https://en.wikipedia.org/wiki/Opera_(web_browser))
+* `BrowserUCBrowser` - [UC Browser](https://en.wikipedia.org/wiki/UC_Browser)
+* `BrowserSilk` - Amazon [Silk](https://en.wikipedia.org/wiki/Amazon_Silk)
+* `BrowserSpotify` - [Spotify](https://en.wikipedia.org/wiki/Spotify#Clients) desktop client
+* `BrowserBlackberry` - RIM [BlackBerry](https://en.wikipedia.org/wiki/BlackBerry)
+* `BrowserUnknown` - Unknown
+
+#### Browser Version
+
+Browser version returns an `unint8` of the major version attribute of the User-Agent String. For example Chrome 45.0.23423 would return `45`. The intention is to support math operators with versions, such as "do XYZ for Chrome version >23".
+
+Unknown version is returned as `0`.
+
+#### Platform
+* `PlatformWindows` - Microsoft Windows
+* `PlatformMac` - Apple Macintosh
+* `PlatformLinux` - Linux, including Android and other OSes
+* `PlatformiPad` - Apple iPad
+* `PlatformiPhone` - Apple iPhone
+* `PlatformBlackberry` - RIM Blackberry
+* `PlatformWindowsPhone` Microsoft Windows Phone & Mobile
+* `PlatformKindle` - Amazon Kindle & Kindle Fire
+* `PlatformPlaystation` - Sony Playstation, Vita, PSP
+* `PlatformXbox` - Microsoft Xbox - `PlatformXbox`
+* `PlatformNintendo` - Nintendo DS, Wii, etc.
+* `PlatformUnknown` - Unknown
+
+#### OS Name
+* `OSWindows`
+* `OSMacOSX` - includes "macOS Sierra"
+* `OSiOS`
+* `OSAndroid`
+* `OSChromeOS`
+* `OSWebOS`
+* `OSLinux`
+* `OSPlaystation`
+* `OSXbox`
+* `OSNintendo`
+* `OSUnknown`
+
+#### OS Version
+
+OS X major version is alway 10 with consecutive minor versions indicating release releases (10 - Yosemite, 11 - El Capitain, 12 Sierra, etc). Windows version is NT version. `Version{0, 0, 0}` indicated version is unknown or not evaluated.
+Versions can be compared using `Less` function: `if ver1.Less(ver2) {}`
+
+Here are some examples across the platform, os.name, and os.version:
+
+* For Windows XP (Windows NT 5.1), "`PlatformWindows`" is the platform, "`OSWindows`" is the name, and `{5, 1, 0}` the version.
+* For OS X 10.5.1, "`PlatformMac`" is the platform, "`OSMacOSX`" the name, and `{10, 5, 1}` the version.
+* For Android 5.1, "`PlatformLinux`" is the platform, "`OSAndroid`" is the name, and `{5, 1, 0}` the version.
+* For iOS 5.1, "`PlatformiPhone`" or "`PlatformiPad`" is the platform, "`OSiOS`" is the name, and `{5, 1, 0}` the version.
+
+###### Windows Version Guide
+
+* Windows 10 - `{10, 0, 0}`
+* Windows 8.1 - `{6, 3, 0}`
+* Windows 8 - `{6, 2, 0}`
+* Windows 7 - `{6, 1, 0}`
+* Windows Vista - `{6, 0, 0}`
+* Windows XP - `{5, 1, 0}` or `{5, 2, 0}`
+* Windows 2000 - `{5, 0, 0}`
+
+Windows 95, 98, and ME represent 0.01% of traffic worldwide and are not available through this package at this time.
+
+#### DeviceType
+DeviceType is typically quite accurate, though determining between phones and tablets on Android is not always possible due to how some vendors design their UA strings. A mobile Android device without tablet indicator defaults to being classified as a phone. DeviceTV supports major brands such as Philips, Sharp, Vizio and steaming boxes such as Apple, Google, Roku, Amazon.
+
+* `DeviceComputer`
+* `DevicePhone`
+* `DeviceTablet`
+* `DeviceTV`
+* `DeviceConsole`
+* `DeviceWearable`
+* `DeviceUnknown`
+
+## Example Combinations of Attributes
+* Surface RT -> `OSWindows8`, `DeviceTablet`, OSVersion >= `6`
+* Android Tablet -> `OSAndroid`, `DeviceTablet`
+* Microsoft Edge -> `BrowserIE`, BrowserVersion >= `12.0.0`
+
+## To do
+
+* Remove compiled regexp in favor of string.Contains wherever possible (lowers mem/alloc)
+* Better version support on Firefox derivatives (e.g. SeaMonkey)
+* Potential additional browser support:
+ * "NetFront" (1% share in India)
+ * "QQ Browser" (6.5% share in China)
+ * "Sogou Explorer" (5% share in China)
+ * "Maxthon" (1.5% share in China)
+ * "Nokia"
+* Potential additional OS support:
+ * "Nokia" (5% share in India)
+ * "Series 40" (5.5% share in India)
+ * Windows 2003 Server
+* iOS safari browser identification based on iOS version
+* Add android version to browser identification
+* old Macs
+ * "opera/9.64 (macintosh; ppc mac os x; u; en) presto/2.1.1"
+* old Windows
+ * "mozilla/5.0 (windows nt 4.0; wow64) applewebkit/537.36 (khtml, like gecko) chrome/37.0.2049.0 safari/537.36"
diff --git a/vendor/github.com/avct/uasurfer/browser.go b/vendor/github.com/avct/uasurfer/browser.go
new file mode 100644
index 000000000..e156818ab
--- /dev/null
+++ b/vendor/github.com/avct/uasurfer/browser.go
@@ -0,0 +1,192 @@
+package uasurfer
+
+import (
+ "strings"
+)
+
+// Browser struct contains the lowercase name of the browser, along
+// with its browser version number. Browser are grouped together without
+// consideration for device. For example, Chrome (Chrome/43.0) and Chrome for iOS
+// (CriOS/43.0) would both return as "chrome" (name) and 43.0 (version). Similarly
+// Internet Explorer 11 and Edge 12 would return as "ie" and "11" or "12", respectively.
+// type Browser struct {
+// Name BrowserName
+// Version struct {
+// Major int
+// Minor int
+// Patch int
+// }
+// }
+
+// Retrieve browser name from UA strings
+func (u *UserAgent) evalBrowserName(ua string) bool {
+ // Blackberry goes first because it reads as MSIE & Safari
+ if strings.Contains(ua, "blackberry") || strings.Contains(ua, "playbook") || strings.Contains(ua, "bb10") || strings.Contains(ua, "rim ") {
+ u.Browser.Name = BrowserBlackberry
+ return u.isBot()
+ }
+
+ if strings.Contains(ua, "applewebkit") {
+ switch {
+ case strings.Contains(ua, "opr/") || strings.Contains(ua, "opios/"):
+ u.Browser.Name = BrowserOpera
+
+ case strings.Contains(ua, "silk/"):
+ u.Browser.Name = BrowserSilk
+
+ case strings.Contains(ua, "edge/") || strings.Contains(ua, "iemobile/") || strings.Contains(ua, "msie "):
+ u.Browser.Name = BrowserIE
+
+ case strings.Contains(ua, "ucbrowser/") || strings.Contains(ua, "ucweb/"):
+ u.Browser.Name = BrowserUCBrowser
+
+ // Edge, Silk and other chrome-identifying browsers must evaluate before chrome, unless we want to add more overhead
+ case strings.Contains(ua, "chrome/") || strings.Contains(ua, "crios/") || strings.Contains(ua, "chromium/") || strings.Contains(ua, "crmo/"):
+ u.Browser.Name = BrowserChrome
+
+ case strings.Contains(ua, "android") && !strings.Contains(ua, "chrome/") && strings.Contains(ua, "version/") && !strings.Contains(ua, "like android"):
+ // Android WebView on Android >= 4.4 is purposefully being identified as Chrome above -- https://developer.chrome.com/multidevice/webview/overview
+ u.Browser.Name = BrowserAndroid
+
+ case strings.Contains(ua, "fxios"):
+ u.Browser.Name = BrowserFirefox
+
+ case strings.Contains(ua, " spotify/"):
+ u.Browser.Name = BrowserSpotify
+
+ // AppleBot uses webkit signature as well
+ case strings.Contains(ua, "applebot"):
+ u.Browser.Name = BrowserAppleBot
+
+ // presume it's safari unless an esoteric browser is being specified (webOSBrowser, SamsungBrowser, etc.)
+ case strings.Contains(ua, "like gecko") && strings.Contains(ua, "mozilla/") && strings.Contains(ua, "safari/") && !strings.Contains(ua, "linux") && !strings.Contains(ua, "android") && !strings.Contains(ua, "browser/") && !strings.Contains(ua, "os/"):
+ u.Browser.Name = BrowserSafari
+
+ // if we got this far and the device is iPhone or iPad, assume safari. Some agents don't actually contain the word "safari"
+ case strings.Contains(ua, "iphone") || strings.Contains(ua, "ipad"):
+ u.Browser.Name = BrowserSafari
+
+ // Google's search app on iPhone, leverages native Safari rather than Chrome
+ case strings.Contains(ua, " gsa/"):
+ u.Browser.Name = BrowserSafari
+
+ default:
+ goto notwebkit
+
+ }
+ return u.isBot()
+ }
+
+notwebkit:
+ switch {
+ case strings.Contains(ua, "msie") || strings.Contains(ua, "trident"):
+ u.Browser.Name = BrowserIE
+
+ case strings.Contains(ua, "gecko") && (strings.Contains(ua, "firefox") || strings.Contains(ua, "iceweasel") || strings.Contains(ua, "seamonkey") || strings.Contains(ua, "icecat")):
+ u.Browser.Name = BrowserFirefox
+
+ case strings.Contains(ua, "presto") || strings.Contains(ua, "opera"):
+ u.Browser.Name = BrowserOpera
+
+ case strings.Contains(ua, "ucbrowser"):
+ u.Browser.Name = BrowserUCBrowser
+
+ case strings.Contains(ua, "applebot"):
+ u.Browser.Name = BrowserAppleBot
+
+ case strings.Contains(ua, "baiduspider"):
+ u.Browser.Name = BrowserBaiduBot
+
+ case strings.Contains(ua, "adidxbot") || strings.Contains(ua, "bingbot") || strings.Contains(ua, "bingpreview"):
+ u.Browser.Name = BrowserBingBot
+
+ case strings.Contains(ua, "duckduckbot"):
+ u.Browser.Name = BrowserDuckDuckGoBot
+
+ case strings.Contains(ua, "facebot") || strings.Contains(ua, "facebookexternalhit"):
+ u.Browser.Name = BrowserFacebookBot
+
+ case strings.Contains(ua, "googlebot"):
+ u.Browser.Name = BrowserGoogleBot
+
+ case strings.Contains(ua, "linkedinbot"):
+ u.Browser.Name = BrowserLinkedInBot
+
+ case strings.Contains(ua, "msnbot"):
+ u.Browser.Name = BrowserMsnBot
+
+ case strings.Contains(ua, "pingdom.com_bot"):
+ u.Browser.Name = BrowserPingdomBot
+
+ case strings.Contains(ua, "twitterbot"):
+ u.Browser.Name = BrowserTwitterBot
+
+ case strings.Contains(ua, "yandex") || strings.Contains(ua, "yadirectfetcher"):
+ u.Browser.Name = BrowserYandexBot
+
+ case strings.Contains(ua, "yahoo"):
+ u.Browser.Name = BrowserYahooBot
+
+ case strings.Contains(ua, "phantomjs"):
+ u.Browser.Name = BrowserBot
+
+ default:
+ u.Browser.Name = BrowserUnknown
+
+ }
+
+ return u.isBot()
+}
+
+// Retrieve browser version
+// Methods used in order:
+// 1st: look for generic version/#
+// 2nd: look for browser-specific instructions (e.g. chrome/34)
+// 3rd: infer from OS (iOS only)
+func (u *UserAgent) evalBrowserVersion(ua string) {
+ // if there is a 'version/#' attribute with numeric version, use it -- except for Chrome since Android vendors sometimes hijack version/#
+ if u.Browser.Name != BrowserChrome && u.Browser.Version.findVersionNumber(ua, "version/") {
+ return
+ }
+
+ switch u.Browser.Name {
+ case BrowserChrome:
+ // match both chrome and crios
+ _ = u.Browser.Version.findVersionNumber(ua, "chrome/") || u.Browser.Version.findVersionNumber(ua, "crios/") || u.Browser.Version.findVersionNumber(ua, "crmo/")
+
+ case BrowserIE:
+ if u.Browser.Version.findVersionNumber(ua, "msie ") || u.Browser.Version.findVersionNumber(ua, "edge/") {
+ return
+ }
+
+ // get MSIE version from trident version https://en.wikipedia.org/wiki/Trident_(layout_engine)
+ if u.Browser.Version.findVersionNumber(ua, "trident/") {
+ // convert trident versions 3-7 to MSIE version
+ if (u.Browser.Version.Major >= 3) && (u.Browser.Version.Major <= 7) {
+ u.Browser.Version.Major += 4
+ }
+ }
+
+ case BrowserFirefox:
+ _ = u.Browser.Version.findVersionNumber(ua, "firefox/") || u.Browser.Version.findVersionNumber(ua, "fxios/")
+
+ case BrowserSafari: // executes typically if we're on iOS and not using a familiar browser
+ u.Browser.Version = u.OS.Version
+ // early Safari used a version number +1 to OS version
+ if (u.Browser.Version.Major <= 3) && (u.Browser.Version.Major >= 1) {
+ u.Browser.Version.Major++
+ }
+
+ case BrowserUCBrowser:
+ _ = u.Browser.Version.findVersionNumber(ua, "ucbrowser/")
+
+ case BrowserOpera:
+ _ = u.Browser.Version.findVersionNumber(ua, "opr/") || u.Browser.Version.findVersionNumber(ua, "opios/") || u.Browser.Version.findVersionNumber(ua, "opera/")
+
+ case BrowserSilk:
+ _ = u.Browser.Version.findVersionNumber(ua, "silk/")
+
+ case BrowserSpotify:
+ _ = u.Browser.Version.findVersionNumber(ua, "spotify/")
+ }
+}
diff --git a/vendor/github.com/avct/uasurfer/const_string.go b/vendor/github.com/avct/uasurfer/const_string.go
new file mode 100644
index 000000000..2fa21d86d
--- /dev/null
+++ b/vendor/github.com/avct/uasurfer/const_string.go
@@ -0,0 +1,49 @@
+// Code generated by "stringer -type=DeviceType,BrowserName,OSName,Platform -output=const_string.go"; DO NOT EDIT.
+
+package uasurfer
+
+import "fmt"
+
+const _DeviceType_name = "DeviceUnknownDeviceComputerDeviceTabletDevicePhoneDeviceConsoleDeviceWearableDeviceTV"
+
+var _DeviceType_index = [...]uint8{0, 13, 27, 39, 50, 63, 77, 85}
+
+func (i DeviceType) String() string {
+ if i < 0 || i >= DeviceType(len(_DeviceType_index)-1) {
+ return fmt.Sprintf("DeviceType(%d)", i)
+ }
+ return _DeviceType_name[_DeviceType_index[i]:_DeviceType_index[i+1]]
+}
+
+const _BrowserName_name = "BrowserUnknownBrowserChromeBrowserIEBrowserSafariBrowserFirefoxBrowserAndroidBrowserOperaBrowserBlackberryBrowserUCBrowserBrowserSilkBrowserNokiaBrowserNetFrontBrowserQQBrowserMaxthonBrowserSogouExplorerBrowserSpotifyBrowserBotBrowserAppleBotBrowserBaiduBotBrowserBingBotBrowserDuckDuckGoBotBrowserFacebookBotBrowserGoogleBotBrowserLinkedInBotBrowserMsnBotBrowserPingdomBotBrowserTwitterBotBrowserYandexBotBrowserYahooBot"
+
+var _BrowserName_index = [...]uint16{0, 14, 27, 36, 49, 63, 77, 89, 106, 122, 133, 145, 160, 169, 183, 203, 217, 227, 242, 257, 271, 291, 309, 325, 343, 356, 373, 390, 406, 421}
+
+func (i BrowserName) String() string {
+ if i < 0 || i >= BrowserName(len(_BrowserName_index)-1) {
+ return fmt.Sprintf("BrowserName(%d)", i)
+ }
+ return _BrowserName_name[_BrowserName_index[i]:_BrowserName_index[i+1]]
+}
+
+const _OSName_name = "OSUnknownOSWindowsPhoneOSWindowsOSMacOSXOSiOSOSAndroidOSBlackberryOSChromeOSOSKindleOSWebOSOSLinuxOSPlaystationOSXboxOSNintendoOSBot"
+
+var _OSName_index = [...]uint8{0, 9, 23, 32, 40, 45, 54, 66, 76, 84, 91, 98, 111, 117, 127, 132}
+
+func (i OSName) String() string {
+ if i < 0 || i >= OSName(len(_OSName_index)-1) {
+ return fmt.Sprintf("OSName(%d)", i)
+ }
+ return _OSName_name[_OSName_index[i]:_OSName_index[i+1]]
+}
+
+const _Platform_name = "PlatformUnknownPlatformWindowsPlatformMacPlatformLinuxPlatformiPadPlatformiPhonePlatformiPodPlatformBlackberryPlatformWindowsPhonePlatformPlaystationPlatformXboxPlatformNintendoPlatformBot"
+
+var _Platform_index = [...]uint8{0, 15, 30, 41, 54, 66, 80, 92, 110, 130, 149, 161, 177, 188}
+
+func (i Platform) String() string {
+ if i < 0 || i >= Platform(len(_Platform_index)-1) {
+ return fmt.Sprintf("Platform(%d)", i)
+ }
+ return _Platform_name[_Platform_index[i]:_Platform_index[i+1]]
+}
diff --git a/vendor/github.com/avct/uasurfer/device.go b/vendor/github.com/avct/uasurfer/device.go
new file mode 100644
index 000000000..70c00b112
--- /dev/null
+++ b/vendor/github.com/avct/uasurfer/device.go
@@ -0,0 +1,60 @@
+package uasurfer
+
+import (
+ "strings"
+)
+
+func (u *UserAgent) evalDevice(ua string) {
+ switch {
+
+ case u.OS.Platform == PlatformWindows || u.OS.Platform == PlatformMac || u.OS.Name == OSChromeOS:
+ if strings.Contains(ua, "mobile") || strings.Contains(ua, "touch") {
+ u.DeviceType = DeviceTablet // windows rt, linux haxor tablets
+ return
+ }
+ u.DeviceType = DeviceComputer
+
+ case u.OS.Platform == PlatformiPad || u.OS.Platform == PlatformiPod || strings.Contains(ua, "tablet") || strings.Contains(ua, "kindle/") || strings.Contains(ua, "playbook"):
+ u.DeviceType = DeviceTablet
+
+ case u.OS.Platform == PlatformiPhone || u.OS.Platform == PlatformBlackberry || strings.Contains(ua, "phone"):
+ u.DeviceType = DevicePhone
+
+ // long list of smarttv and tv dongle identifiers
+ case strings.Contains(ua, "tv") || strings.Contains(ua, "crkey") || strings.Contains(ua, "googletv") || strings.Contains(ua, "aftb") || strings.Contains(ua, "adt-") || strings.Contains(ua, "roku") || strings.Contains(ua, "viera") || strings.Contains(ua, "aquos") || strings.Contains(ua, "dtv") || strings.Contains(ua, "appletv") || strings.Contains(ua, "smarttv") || strings.Contains(ua, "tuner") || strings.Contains(ua, "smart-tv") || strings.Contains(ua, "hbbtv") || strings.Contains(ua, "netcast") || strings.Contains(ua, "vizio"):
+ u.DeviceType = DeviceTV
+
+ case u.OS.Name == OSAndroid:
+ // android phones report as "mobile", android tablets should not but often do -- http://android-developers.blogspot.com/2010/12/android-browser-user-agent-issues.html
+ if strings.Contains(ua, "mobile") {
+ u.DeviceType = DevicePhone
+ return
+ }
+
+ if strings.Contains(ua, "tablet") || strings.Contains(ua, "nexus 7") || strings.Contains(ua, "nexus 9") || strings.Contains(ua, "nexus 10") || strings.Contains(ua, "xoom") {
+ u.DeviceType = DeviceTablet
+ return
+ }
+
+ u.DeviceType = DevicePhone // default to phone
+
+ case u.OS.Platform == PlatformPlaystation || u.OS.Platform == PlatformXbox || u.OS.Platform == PlatformNintendo:
+ u.DeviceType = DeviceConsole
+
+ case strings.Contains(ua, "glass") || strings.Contains(ua, "watch") || strings.Contains(ua, "sm-v"):
+ u.DeviceType = DeviceWearable
+
+ // specifically above "mobile" string check as Kindle Fire tablets report as "mobile"
+ case u.Browser.Name == BrowserSilk || u.OS.Name == OSKindle && !strings.Contains(ua, "sd4930ur"):
+ u.DeviceType = DeviceTablet
+
+ case strings.Contains(ua, "mobile") || strings.Contains(ua, "touch") || strings.Contains(ua, " mobi") || strings.Contains(ua, "webos"): //anything "mobile"/"touch" that didn't get captured as tablet, console or wearable is presumed a phone
+ u.DeviceType = DevicePhone
+
+ case u.OS.Name == OSLinux: // linux goes last since it's in so many other device types (tvs, wearables, android-based stuff)
+ u.DeviceType = DeviceComputer
+
+ default:
+ u.DeviceType = DeviceUnknown
+ }
+}
diff --git a/vendor/github.com/avct/uasurfer/system.go b/vendor/github.com/avct/uasurfer/system.go
new file mode 100644
index 000000000..e823c9cc7
--- /dev/null
+++ b/vendor/github.com/avct/uasurfer/system.go
@@ -0,0 +1,336 @@
+package uasurfer
+
+import (
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+var (
+ amazonFireFingerprint = regexp.MustCompile("\\s(k[a-z]{3,5}|sd\\d{4}ur)\\s") //tablet or phone
+)
+
+func (u *UserAgent) evalOS(ua string) bool {
+
+ s := strings.IndexRune(ua, '(')
+ e := strings.IndexRune(ua, ')')
+ if s > e {
+ s = 0
+ e = len(ua)
+ }
+ if e == -1 {
+ e = len(ua)
+ }
+
+ agentPlatform := ua[s+1 : e]
+ specsEnd := strings.Index(agentPlatform, ";")
+ var specs string
+ if specsEnd != -1 {
+ specs = agentPlatform[:specsEnd]
+ } else {
+ specs = agentPlatform
+ }
+
+ //strict OS & version identification
+ switch specs {
+ case "android":
+ u.evalLinux(ua, agentPlatform)
+
+ case "bb10", "playbook":
+ u.OS.Platform = PlatformBlackberry
+ u.OS.Name = OSBlackberry
+
+ case "x11", "linux":
+ u.evalLinux(ua, agentPlatform)
+
+ case "ipad", "iphone", "ipod touch", "ipod":
+ u.evaliOS(specs, agentPlatform)
+
+ case "macintosh":
+ u.evalMacintosh(ua)
+
+ default:
+ switch {
+ // Blackberry
+ case strings.Contains(ua, "blackberry") || strings.Contains(ua, "playbook"):
+ u.OS.Platform = PlatformBlackberry
+ u.OS.Name = OSBlackberry
+
+ // Windows Phone
+ case strings.Contains(agentPlatform, "windows phone "):
+ u.evalWindowsPhone(agentPlatform)
+
+ // Windows, Xbox
+ case strings.Contains(ua, "windows ") || strings.Contains(ua, "microsoft-cryptoapi"):
+ u.evalWindows(ua)
+
+ // Kindle
+ case strings.Contains(ua, "kindle/") || amazonFireFingerprint.MatchString(agentPlatform):
+ u.OS.Platform = PlatformLinux
+ u.OS.Name = OSKindle
+
+ // Linux (broader attempt)
+ case strings.Contains(ua, "linux"):
+ u.evalLinux(ua, agentPlatform)
+
+ // WebOS (non-linux flagged)
+ case strings.Contains(ua, "webos") || strings.Contains(ua, "hpwos"):
+ u.OS.Platform = PlatformLinux
+ u.OS.Name = OSWebOS
+
+ // Nintendo
+ case strings.Contains(ua, "nintendo"):
+ u.OS.Platform = PlatformNintendo
+ u.OS.Name = OSNintendo
+
+ // Playstation
+ case strings.Contains(ua, "playstation") || strings.Contains(ua, "vita") || strings.Contains(ua, "psp"):
+ u.OS.Platform = PlatformPlaystation
+ u.OS.Name = OSPlaystation
+
+ // Android
+ case strings.Contains(ua, "android"):
+ u.evalLinux(ua, agentPlatform)
+
+ // Apple CFNetwork
+ case strings.Contains(ua, "cfnetwork") && strings.Contains(ua, "darwin"):
+ u.evalMacintosh(ua)
+
+ default:
+ u.OS.Platform = PlatformUnknown
+ u.OS.Name = OSUnknown
+ }
+ }
+
+ return u.isBot()
+}
+
+func (u *UserAgent) isBot() bool {
+
+ if u.OS.Platform == PlatformBot || u.OS.Name == OSBot {
+ u.DeviceType = DeviceComputer
+ return true
+ }
+
+ if u.Browser.Name >= BrowserBot && u.Browser.Name <= BrowserYahooBot {
+ u.OS.Platform = PlatformBot
+ u.OS.Name = OSBot
+ u.DeviceType = DeviceComputer
+ return true
+ }
+
+ return false
+}
+
+// evalLinux returns the `Platform`, `OSName` and Version of UAs with
+// 'linux' listed as their platform.
+func (u *UserAgent) evalLinux(ua string, agentPlatform string) {
+
+ switch {
+ // Kindle Fire
+ case strings.Contains(ua, "kindle") || amazonFireFingerprint.MatchString(agentPlatform):
+ // get the version of Android if available, though we don't call this OSAndroid
+ u.OS.Platform = PlatformLinux
+ u.OS.Name = OSKindle
+ u.OS.Version.findVersionNumber(agentPlatform, "android ")
+
+ // Android, Kindle Fire
+ case strings.Contains(ua, "android") || strings.Contains(ua, "googletv"):
+ // Android
+ u.OS.Platform = PlatformLinux
+ u.OS.Name = OSAndroid
+ u.OS.Version.findVersionNumber(agentPlatform, "android ")
+
+ // ChromeOS
+ case strings.Contains(ua, "cros"):
+ u.OS.Platform = PlatformLinux
+ u.OS.Name = OSChromeOS
+
+ // WebOS
+ case strings.Contains(ua, "webos") || strings.Contains(ua, "hpwos"):
+ u.OS.Platform = PlatformLinux
+ u.OS.Name = OSWebOS
+
+ // Linux, "Linux-like"
+ case strings.Contains(ua, "x11") || strings.Contains(ua, "bsd") || strings.Contains(ua, "suse") || strings.Contains(ua, "debian") || strings.Contains(ua, "ubuntu"):
+ u.OS.Platform = PlatformLinux
+ u.OS.Name = OSLinux
+
+ default:
+ u.OS.Platform = PlatformLinux
+ u.OS.Name = OSLinux
+ }
+}
+
+// evaliOS returns the `Platform`, `OSName` and Version of UAs with
+// 'ipad' or 'iphone' listed as their platform.
+func (u *UserAgent) evaliOS(uaPlatform string, agentPlatform string) {
+
+ switch uaPlatform {
+ // iPhone
+ case "iphone":
+ u.OS.Platform = PlatformiPhone
+ u.OS.Name = OSiOS
+ u.OS.getiOSVersion(agentPlatform)
+
+ // iPad
+ case "ipad":
+ u.OS.Platform = PlatformiPad
+ u.OS.Name = OSiOS
+ u.OS.getiOSVersion(agentPlatform)
+
+ // iPod
+ case "ipod touch", "ipod":
+ u.OS.Platform = PlatformiPod
+ u.OS.Name = OSiOS
+ u.OS.getiOSVersion(agentPlatform)
+
+ default:
+ u.OS.Platform = PlatformiPad
+ u.OS.Name = OSUnknown
+ }
+}
+
+func (u *UserAgent) evalWindowsPhone(agentPlatform string) {
+ u.OS.Platform = PlatformWindowsPhone
+
+ if u.OS.Version.findVersionNumber(agentPlatform, "windows phone os ") || u.OS.Version.findVersionNumber(agentPlatform, "windows phone ") {
+ u.OS.Name = OSWindowsPhone
+ } else {
+ u.OS.Name = OSUnknown
+ }
+}
+
+func (u *UserAgent) evalWindows(ua string) {
+
+ switch {
+ //Xbox -- it reads just like Windows
+ case strings.Contains(ua, "xbox"):
+ u.OS.Platform = PlatformXbox
+ u.OS.Name = OSXbox
+ if !u.OS.Version.findVersionNumber(ua, "windows nt ") {
+ u.OS.Version.Major = 6
+ u.OS.Version.Minor = 0
+ u.OS.Version.Patch = 0
+ }
+
+ // No windows version
+ case !strings.Contains(ua, "windows "):
+ u.OS.Platform = PlatformWindows
+ u.OS.Name = OSUnknown
+
+ case strings.Contains(ua, "windows nt ") && u.OS.Version.findVersionNumber(ua, "windows nt "):
+ u.OS.Platform = PlatformWindows
+ u.OS.Name = OSWindows
+
+ case strings.Contains(ua, "windows xp"):
+ u.OS.Platform = PlatformWindows
+ u.OS.Name = OSWindows
+ u.OS.Version.Major = 5
+ u.OS.Version.Minor = 1
+ u.OS.Version.Patch = 0
+
+ default:
+ u.OS.Platform = PlatformWindows
+ u.OS.Name = OSUnknown
+
+ }
+}
+
+func (u *UserAgent) evalMacintosh(uaPlatformGroup string) {
+ u.OS.Platform = PlatformMac
+ if i := strings.Index(uaPlatformGroup, "os x 10"); i != -1 {
+ u.OS.Name = OSMacOSX
+ u.OS.Version.parse(uaPlatformGroup[i+5:])
+
+ return
+ }
+ u.OS.Name = OSUnknown
+}
+
+func (v *Version) findVersionNumber(s string, m string) bool {
+ if ind := strings.Index(s, m); ind != -1 {
+ return v.parse(s[ind+len(m):])
+ }
+ return false
+}
+
+// getiOSVersion accepts the platform portion of a UA string and returns
+// a Version.
+func (o *OS) getiOSVersion(uaPlatformGroup string) {
+ if i := strings.Index(uaPlatformGroup, "cpu iphone os "); i != -1 {
+ o.Version.parse(uaPlatformGroup[i+14:])
+ return
+ }
+
+ if i := strings.Index(uaPlatformGroup, "cpu os "); i != -1 {
+ o.Version.parse(uaPlatformGroup[i+7:])
+ return
+ }
+
+ o.Version.parse(uaPlatformGroup)
+}
+
+// strToInt simply accepts a string and returns a `int`,
+// with '0' being default.
+func strToInt(str string) int {
+ i, _ := strconv.Atoi(str)
+ return i
+}
+
+// strToVer accepts a string and returns a Version,
+// with {0, 0, 0} being default.
+func (v *Version) parse(str string) bool {
+ if len(str) == 0 || str[0] < '0' || str[0] > '9' {
+ return false
+ }
+ for i := 0; i < 3; i++ {
+ empty := true
+ val := 0
+ l := len(str) - 1
+
+ for k, c := range str {
+ if c >= '0' && c <= '9' {
+ if empty {
+ val = int(c) - 48
+ empty = false
+ if k == l {
+ str = str[:0]
+ }
+ continue
+ }
+
+ if val == 0 {
+ if c == '0' {
+ if k == l {
+ str = str[:0]
+ }
+ continue
+ }
+ str = str[k:]
+ break
+ }
+
+ val = 10*val + int(c) - 48
+ if k == l {
+ str = str[:0]
+ }
+ continue
+ }
+ str = str[k+1:]
+ break
+ }
+
+ switch i {
+ case 0:
+ v.Major = val
+
+ case 1:
+ v.Minor = val
+
+ case 2:
+ v.Patch = val
+ }
+ }
+ return true
+}
diff --git a/vendor/github.com/avct/uasurfer/uasurfer.go b/vendor/github.com/avct/uasurfer/uasurfer.go
new file mode 100644
index 000000000..15aac6d40
--- /dev/null
+++ b/vendor/github.com/avct/uasurfer/uasurfer.go
@@ -0,0 +1,227 @@
+// Package uasurfer provides fast and reliable abstraction
+// of HTTP User-Agent strings. The philosophy is to identify
+// technologies that holds >1% market share, and to avoid
+// expending resources and accuracy on guessing at esoteric UA
+// strings.
+package uasurfer
+
+import "strings"
+
+//go:generate stringer -type=DeviceType,BrowserName,OSName,Platform -output=const_string.go
+
+// DeviceType (int) returns a constant.
+type DeviceType int
+
+// A complete list of supported devices in the
+// form of constants.
+const (
+ DeviceUnknown DeviceType = iota
+ DeviceComputer
+ DeviceTablet
+ DevicePhone
+ DeviceConsole
+ DeviceWearable
+ DeviceTV
+)
+
+// BrowserName (int) returns a constant.
+type BrowserName int
+
+// A complete list of supported web browsers in the
+// form of constants.
+const (
+ BrowserUnknown BrowserName = iota
+ BrowserChrome
+ BrowserIE
+ BrowserSafari
+ BrowserFirefox
+ BrowserAndroid
+ BrowserOpera
+ BrowserBlackberry
+ BrowserUCBrowser
+ BrowserSilk
+ BrowserNokia
+ BrowserNetFront
+ BrowserQQ
+ BrowserMaxthon
+ BrowserSogouExplorer
+ BrowserSpotify
+ BrowserBot // Bot list begins here
+ BrowserAppleBot
+ BrowserBaiduBot
+ BrowserBingBot
+ BrowserDuckDuckGoBot
+ BrowserFacebookBot
+ BrowserGoogleBot
+ BrowserLinkedInBot
+ BrowserMsnBot
+ BrowserPingdomBot
+ BrowserTwitterBot
+ BrowserYandexBot
+ BrowserYahooBot // Bot list ends here
+)
+
+// OSName (int) returns a constant.
+type OSName int
+
+// A complete list of supported OSes in the
+// form of constants. For handling particular versions
+// of operating systems (e.g. Windows 2000), see
+// the README.md file.
+const (
+ OSUnknown OSName = iota
+ OSWindowsPhone
+ OSWindows
+ OSMacOSX
+ OSiOS
+ OSAndroid
+ OSBlackberry
+ OSChromeOS
+ OSKindle
+ OSWebOS
+ OSLinux
+ OSPlaystation
+ OSXbox
+ OSNintendo
+ OSBot
+)
+
+// Platform (int) returns a constant.
+type Platform int
+
+// A complete list of supported platforms in the
+// form of constants. Many OSes report their
+// true platform, such as Android OS being Linux
+// platform.
+const (
+ PlatformUnknown Platform = iota
+ PlatformWindows
+ PlatformMac
+ PlatformLinux
+ PlatformiPad
+ PlatformiPhone
+ PlatformiPod
+ PlatformBlackberry
+ PlatformWindowsPhone
+ PlatformPlaystation
+ PlatformXbox
+ PlatformNintendo
+ PlatformBot
+)
+
+type Version struct {
+ Major int
+ Minor int
+ Patch int
+}
+
+func (v Version) Less(c Version) bool {
+ if v.Major < c.Major {
+ return true
+ }
+
+ if v.Major > c.Major {
+ return false
+ }
+
+ if v.Minor < c.Minor {
+ return true
+ }
+
+ if v.Minor > c.Minor {
+ return false
+ }
+
+ return v.Patch < c.Patch
+}
+
+type UserAgent struct {
+ Browser Browser
+ OS OS
+ DeviceType DeviceType
+}
+
+type Browser struct {
+ Name BrowserName
+ Version Version
+}
+
+type OS struct {
+ Platform Platform
+ Name OSName
+ Version Version
+}
+
+// Reset resets the UserAgent to it's zero value
+func (ua *UserAgent) Reset() {
+ ua.Browser = Browser{}
+ ua.OS = OS{}
+ ua.DeviceType = DeviceUnknown
+}
+
+// Parse accepts a raw user agent (string) and returns the UserAgent.
+func Parse(ua string) *UserAgent {
+ dest := new(UserAgent)
+ parse(ua, dest)
+ return dest
+}
+
+// ParseUserAgent is the same as Parse, but populates the supplied UserAgent.
+// It is the caller's responsibility to call Reset() on the UserAgent before
+// passing it to this function.
+func ParseUserAgent(ua string, dest *UserAgent) {
+ parse(ua, dest)
+}
+
+func parse(ua string, dest *UserAgent) {
+ ua = normalise(ua)
+ switch {
+ case len(ua) == 0:
+ dest.OS.Platform = PlatformUnknown
+ dest.OS.Name = OSUnknown
+ dest.Browser.Name = BrowserUnknown
+ dest.DeviceType = DeviceUnknown
+
+ // stop on on first case returning true
+ case dest.evalOS(ua):
+ case dest.evalBrowserName(ua):
+ default:
+ dest.evalBrowserVersion(ua)
+ dest.evalDevice(ua)
+ }
+}
+
+// normalise normalises the user supplied agent string so that
+// we can more easily parse it.
+func normalise(ua string) string {
+ if len(ua) <= 1024 {
+ var buf [1024]byte
+ ascii := copyLower(buf[:len(ua)], ua)
+ if !ascii {
+ // Fall back for non ascii characters
+ return strings.ToLower(ua)
+ }
+ return string(buf[:len(ua)])
+ }
+ // Fallback for unusually long strings
+ return strings.ToLower(ua)
+}
+
+// copyLower copies a lowercase version of s to b. It assumes s contains only single byte characters
+// and will panic if b is nil or is not long enough to contain all the bytes from s.
+// It returns early with false if any characters were non ascii.
+func copyLower(b []byte, s string) bool {
+ for j := 0; j < len(s); j++ {
+ c := s[j]
+ if c > 127 {
+ return false
+ }
+
+ if 'A' <= c && c <= 'Z' {
+ c += 'a' - 'A'
+ }
+
+ b[j] = c
+ }
+ return true
+}
diff --git a/vendor/github.com/avct/uasurfer/uasurfer_test.go b/vendor/github.com/avct/uasurfer/uasurfer_test.go
new file mode 100644
index 000000000..7a4688bb2
--- /dev/null
+++ b/vendor/github.com/avct/uasurfer/uasurfer_test.go
@@ -0,0 +1,1074 @@
+package uasurfer
+
+import "testing"
+
+var testUAVars = []struct {
+ UA string
+ UserAgent
+}{
+ // Empty
+ {"",
+ UserAgent{}},
+
+ // Single char
+ {"a",
+ UserAgent{}},
+
+ // Some random string
+ {"some random string",
+ UserAgent{}},
+
+ // Potentially malformed ua
+ {")(",
+ UserAgent{}},
+
+ // iPhone
+ {"Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X) AppleWebKit/546.10 (KHTML, like Gecko) Version/6.0 Mobile/7E18WD Safari/8536.25",
+ UserAgent{
+ Browser{BrowserSafari, Version{6, 0, 0}}, OS{PlatformiPhone, OSiOS, Version{7, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (iPhone; CPU iPhone OS 8_0_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12A405 Safari/600.1.4",
+ UserAgent{
+ Browser{BrowserSafari, Version{8, 0, 0}}, OS{PlatformiPhone, OSiOS, Version{8, 0, 2}}, DevicePhone}},
+
+ // iPad
+ {"Mozilla/5.0(iPad; U; CPU iPhone OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B314 Safari/531.21.10",
+ UserAgent{
+ Browser{BrowserSafari, Version{4, 0, 4}}, OS{PlatformiPad, OSiOS, Version{3, 2, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (iPad; CPU OS 9_0 like Mac OS X) AppleWebKit/601.1.17 (KHTML, like Gecko) Version/8.0 Mobile/13A175 Safari/600.1.4",
+ UserAgent{
+ Browser{BrowserSafari, Version{8, 0, 0}}, OS{PlatformiPad, OSiOS, Version{9, 0, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (iPhone; CPU iPhone OS 10_0 like Mac OS X) AppleWebKit/602.1.32 (KHTML, like Gecko) Version/10.0 Mobile/14A5261v Safari/602.1",
+ UserAgent{
+ Browser{BrowserSafari, Version{10, 0, 0}}, OS{PlatformiPhone, OSiOS, Version{10, 0, 0}}, DevicePhone}},
+
+ // Chrome
+ {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36",
+ UserAgent{
+ Browser{BrowserChrome, Version{43, 0, 2357}}, OS{PlatformMac, OSMacOSX, Version{10, 10, 4}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; en) AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60 Mobile/9B206 Safari/534.48.3",
+ UserAgent{
+ Browser{BrowserChrome, Version{19, 0, 1084}}, OS{PlatformiPhone, OSiOS, Version{5, 1, 1}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; Android 6.0; Nexus 5X Build/MDB08L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.76 Mobile Safari/537.36",
+ UserAgent{
+ Browser{BrowserChrome, Version{46, 0, 2490}}, OS{PlatformLinux, OSAndroid, Version{6, 0, 0}}, DevicePhone}},
+
+ // Chromium (Chrome)
+ {"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.19 (KHTML, like Gecko) Ubuntu/11.10 Chromium/18.0.1025.142 Chrome/18.0.1025.142 Safari/535.19",
+ UserAgent{
+ Browser{BrowserChrome, Version{18, 0, 1025}}, OS{PlatformLinux, OSLinux, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36",
+ UserAgent{
+ Browser{BrowserChrome, Version{45, 0, 2454}}, OS{PlatformMac, OSMacOSX, Version{10, 11, 0}}, DeviceComputer}},
+
+ //TODO: refactor "getVersion()" to handle this device/chrome version douchebaggery
+ // {"Mozilla/5.0 (Linux; Android 4.4.2; en-gb; SAMSUNG SM-G800F Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Version/1.6 Chrome/28.0.1500.94 Mobile Safari/537.36",
+ // UserAgent{
+ // Browser{BrowserChrome, Version{28,0,1500}, OS{PlatformLinux, OSAndroid, Version{4,4,2}}, DevicePhone}},
+
+ // Safari
+ {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/600.7.12 (KHTML, like Gecko) Version/8.0.7 Safari/600.7.12",
+ UserAgent{
+ Browser{BrowserSafari, Version{8, 0, 7}}, OS{PlatformMac, OSMacOSX, Version{10, 10, 4}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_5; en-us) AppleWebKit/525.26.2 (KHTML, like Gecko) Version/3.2 Safari/525.26.12",
+ UserAgent{
+ Browser{BrowserSafari, Version{3, 2, 0}}, OS{PlatformMac, OSMacOSX, Version{10, 5, 5}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12) AppleWebKit/602.1.32 (KHTML, like Gecko) Version/10.0 Safari/602.1.32", // macOS Sierra dev beta
+ UserAgent{
+ Browser{BrowserSafari, Version{10, 0, 0}}, OS{PlatformMac, OSMacOSX, Version{10, 12, 0}}, DeviceComputer}},
+
+ // Firefox
+ {"Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) FxiOS/1.0 Mobile/12F69 Safari/600.1.4",
+ UserAgent{
+ Browser{BrowserFirefox, Version{1, 0, 0}}, OS{PlatformiPhone, OSiOS, Version{8, 3, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Android 4.4; Tablet; rv:41.0) Gecko/41.0 Firefox/41.0",
+ UserAgent{
+ Browser{BrowserFirefox, Version{41, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{4, 4, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (Android; Mobile; rv:40.0) Gecko/40.0 Firefox/40.0",
+ UserAgent{
+ Browser{BrowserFirefox, Version{40, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{0, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0",
+ UserAgent{
+ Browser{BrowserFirefox, Version{38, 0, 0}}, OS{PlatformLinux, OSLinux, Version{0, 0, 0}}, DeviceComputer}},
+
+ // Silk
+ {"Mozilla/5.0 (Linux; U; Android 4.4.3; de-de; KFTHWI Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.47 like Chrome/37.0.2026.117 Safari/537.36",
+ UserAgent{
+ Browser{BrowserSilk, Version{3, 47, 0}}, OS{PlatformLinux, OSKindle, Version{4, 4, 3}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (Linux; U; en-us; KFJWI Build/IMM76D) AppleWebKit/535.19 (KHTML like Gecko) Silk/2.4 Safari/535.19 Silk-Acceleratedtrue",
+ UserAgent{
+ Browser{BrowserSilk, Version{2, 4, 0}}, OS{PlatformLinux, OSKindle, Version{0, 0, 0}}, DeviceTablet}},
+
+ // Opera
+ {"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36 OPR/18.0.1284.68",
+ UserAgent{
+ Browser{BrowserOpera, Version{18, 0, 1284}}, OS{PlatformWindows, OSWindows, Version{6, 1, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (iPhone; CPU iPhone OS 8_4 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) OPiOS/10.2.0.93022 Mobile/12H143 Safari/9537.53",
+ UserAgent{
+ Browser{BrowserOpera, Version{10, 2, 0}}, OS{PlatformiPhone, OSiOS, Version{8, 4, 0}}, DevicePhone}},
+
+ // Internet Explorer -- https://msdn.microsoft.com/en-us/library/hh869301(v=vs.85).aspx
+ {"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.123",
+ UserAgent{
+ Browser{BrowserIE, Version{12, 123, 0}}, OS{PlatformWindows, OSWindows, Version{10, 0, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)",
+ UserAgent{
+ Browser{BrowserIE, Version{10, 0, 0}}, OS{PlatformWindows, OSWindows, Version{6, 2, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Windows NT 6.3; Trident/7.0; .NET4.0E; .NET4.0C; rv:11.0) like Gecko",
+ UserAgent{
+ Browser{BrowserIE, Version{11, 0, 0}}, OS{PlatformWindows, OSWindows, Version{6, 3, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; DEVICE INFO) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Mobile Safari/537.36 Edge/12.123",
+ UserAgent{
+ Browser{BrowserIE, Version{12, 123, 0}}, OS{PlatformWindowsPhone, OSWindowsPhone, Version{10, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 520) like iPhone OS 7_0_3 Mac OS X AppleWebKit/537 (KHTML, like Gecko) Mobile Safari/537",
+ UserAgent{
+ Browser{BrowserIE, Version{11, 0, 0}}, OS{PlatformWindowsPhone, OSWindowsPhone, Version{8, 1, 0}}, DevicePhone}},
+
+ {"Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.3705; .NET CLR 2.0.50727)",
+ UserAgent{
+ Browser{BrowserIE, Version{5, 0, 1}}, OS{PlatformWindows, OSWindows, Version{5, 0, 0}}, DeviceComputer}},
+
+ {"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; GTB6.4; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; OfficeLiveConnector.1.3; OfficeLivePatch.0.0; .NET CLR 1.1.4322)",
+ UserAgent{
+ Browser{BrowserIE, Version{7, 0, 0}}, OS{PlatformWindows, OSWindows, Version{6, 1, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; ARM; Trident/6.0; Touch)", //Windows Surface RT tablet
+ UserAgent{
+ Browser{BrowserIE, Version{10, 0, 0}}, OS{PlatformWindows, OSWindows, Version{6, 2, 0}}, DeviceTablet}},
+
+ // UC Browser
+ {"Mozilla/5.0 (Linux; U; Android 2.3.4; en-US; MT11i Build/4.0.2.A.0.62) AppleWebKit/534.31 (KHTML, like Gecko) UCBrowser/9.0.1.275 U3/0.8.0 Mobile Safari/534.31",
+ UserAgent{
+ Browser{BrowserUCBrowser, Version{9, 0, 1}}, OS{PlatformLinux, OSAndroid, Version{2, 3, 4}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 4.0.4; en-US; Micromax P255 Build/IMM76D) AppleWebKit/534.31 (KHTML, like Gecko) UCBrowser/9.2.0.308 U3/0.8.0 Mobile Safari/534.31",
+ UserAgent{
+ Browser{BrowserUCBrowser, Version{9, 2, 0}}, OS{PlatformLinux, OSAndroid, Version{4, 0, 4}}, DevicePhone}},
+
+ {"UCWEB/2.0 (Java; U; MIDP-2.0; en-US; MicromaxQ5) U2/1.0.0 UCBrowser/9.4.0.342 U2/1.0.0 Mobile",
+ UserAgent{
+ Browser{BrowserUCBrowser, Version{9, 4, 0}}, OS{PlatformUnknown, OSUnknown, Version{0, 0, 0}}, DevicePhone}},
+
+ // Nokia Browser
+ // {"Mozilla/5.0 (Series40; Nokia501/14.0.4/java_runtime_version=Nokia_Asha_1_2; Profile/MIDP-2.1 Configuration/CLDC-1.1) Gecko/20100401 S40OviBrowser/4.0.0.0.45",
+ // UserAgent{
+ // Browser{BrowserUnknown, Version{4,0,0}}, OS{PlatformUnknown, OSUnknown, Version{0,0,0}}, DevicePhone}},
+
+ // {"Mozilla/5.0 (Symbian/3; Series60/5.3 NokiaN8-00/111.040.1511; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/535.1 (KHTML, like Gecko) NokiaBrowser/8.3.1.4 Mobile Safari/535.1",
+ // UserAgent{
+ // Browser{BrowserUnknown, Version{8,0,0}}, OS{PlatformUnknown, OSUnknown, Version{0,0,0}}, DevicePhone}},
+
+ // {"NokiaN97/21.1.107 (SymbianOS/9.4; Series60/5.0 Mozilla/5.0; Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebkit/525 (KHTML, like Gecko) BrowserNG/7.1.4",
+ // BrowserUnknown, Version{7,0,0}}, OS{PlatformUnknown, OSUnknown, Version{0,0,0}}, DevicePhone}},
+
+ // ChromeOS
+ {"Mozilla/5.0 (X11; U; CrOS i686 9.10.0; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Chrome/4.0.253.0 Safari/532.5",
+ UserAgent{
+ Browser{BrowserChrome, Version{4, 0, 253}}, OS{PlatformLinux, OSChromeOS, Version{0, 0, 0}}, DeviceComputer}},
+
+ // iPod, iPod Touch
+ {"mozilla/5.0 (ipod touch; cpu iphone os 9_3_3 like mac os x) applewebkit/601.1.46 (khtml, like gecko) version/9.0 mobile/13g34 safari/601.1",
+ UserAgent{
+ Browser{BrowserSafari, Version{9, 0, 0}}, OS{PlatformiPod, OSiOS, Version{9, 3, 3}}, DeviceTablet}},
+
+ {"mozilla/5.0 (ipod; cpu iphone os 6_1_6 like mac os x) applewebkit/536.26 (khtml, like gecko) version/6.0 mobile/10b500 safari/8536.25",
+ UserAgent{
+ Browser{BrowserSafari, Version{6, 0, 0}}, OS{PlatformiPod, OSiOS, Version{6, 1, 6}}, DeviceTablet}},
+
+ // WebOS
+ {"Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.0; U; de-DE) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/233.70 Safari/534.6 TouchPad/1.0",
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformLinux, OSWebOS, Version{0, 0, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (webOS/1.4.1.1; U; en-US) AppleWebKit/532.2 (KHTML, like Gecko) Version/1.0 Safari/532.2 Pre/1.0",
+ UserAgent{
+ Browser{BrowserUnknown, Version{1, 0, 0}}, OS{PlatformLinux, OSWebOS, Version{0, 0, 0}}, DevicePhone}},
+
+ // Android WebView (Android <= 4.3)
+ {"Mozilla/5.0 (Linux; U; Android 2.2; en-us; DROID2 GLOBAL Build/S273) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{2, 2, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 4.0.3; de-ch; HTC Sensation Build/IML74K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari53/4.30",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{4, 0, 3}}, DevicePhone}},
+
+ // BlackBerry
+ {"Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML, like Gecko) Version/7.2.1.0 Safari/536.2+",
+ UserAgent{
+ Browser{BrowserBlackberry, Version{7, 2, 1}}, OS{PlatformBlackberry, OSBlackberry, Version{0, 0, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (BB10; Kbd) AppleWebKit/537.35+ (KHTML, like Gecko) Version/10.2.1.1925 Mobile Safari/537.35+",
+ UserAgent{
+ Browser{BrowserBlackberry, Version{10, 2, 1}}, OS{PlatformBlackberry, OSBlackberry, Version{0, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) BlackBerry8703e/4.1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/104",
+ UserAgent{
+ Browser{BrowserBlackberry, Version{0, 0, 0}}, OS{PlatformBlackberry, OSBlackberry, Version{0, 0, 0}}, DevicePhone}},
+
+ // Windows Phone
+ {"Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 625; ANZ941)",
+ UserAgent{
+ Browser{BrowserIE, Version{10, 0, 0}}, OS{PlatformWindowsPhone, OSWindowsPhone, Version{8, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; NOKIA; Lumia 900)",
+ UserAgent{
+ Browser{BrowserIE, Version{9, 0, 0}}, OS{PlatformWindowsPhone, OSWindowsPhone, Version{7, 5, 0}}, DevicePhone}},
+
+ // Kindle eReader
+ {"Mozilla/5.0 (Linux; U; en-US) AppleWebKit/528.5+ (KHTML, like Gecko, Safari/528.5+) Version/4.0 Kindle/3.0 (screen 600×800; rotate)",
+ UserAgent{
+ Browser{BrowserUnknown, Version{4, 0, 0}}, OS{PlatformLinux, OSKindle, Version{0, 0, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (X11; U; Linux armv7l like Android; en-us) AppleWebKit/531.2+ (KHTML, like Gecko) Version/5.0 Safari/533.2+ Kindle/3.0+",
+ UserAgent{
+ Browser{BrowserUnknown, Version{5, 0, 0}}, OS{PlatformLinux, OSKindle, Version{0, 0, 0}}, DeviceTablet}},
+
+ // Amazon Fire
+ {"Mozilla/5.0 (Linux; U; Android 4.4.3; de-de; KFTHWI Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.67 like Chrome/39.0.2171.93 Safari/537.36",
+ UserAgent{
+ Browser{BrowserSilk, Version{3, 67, 0}}, OS{PlatformLinux, OSKindle, Version{4, 4, 3}}, DeviceTablet}}, // Fire tablet
+
+ {"Mozilla/5.0 (Linux; U; Android 4.2.2; en­us; KFTHWI Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.22 like Chrome/34.0.1847.137 Mobile Safari/537.36",
+ UserAgent{
+ Browser{BrowserSilk, Version{3, 22, 0}}, OS{PlatformLinux, OSKindle, Version{4, 2, 2}}, DeviceTablet}}, // Fire tablet, but with "Mobile"
+
+ {"Mozilla/5.0 (Linux; Android 4.4.4; SD4930UR Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/34.0.0.0 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/35.0.0.48.273;]",
+ UserAgent{
+ Browser{BrowserChrome, Version{34, 0, 0}}, OS{PlatformLinux, OSKindle, Version{4, 4, 4}}, DevicePhone}}, // Facebook app on Fire Phone
+
+ {"mozilla/5.0 (linux; android 4.4.3; kfthwi build/ktu84m) applewebkit/537.36 (khtml, like gecko) version/4.0 chrome/34.0.0.0 safari/537.36 [pinterest/android]",
+ UserAgent{
+ Browser{BrowserChrome, Version{34, 0, 0}}, OS{PlatformLinux, OSKindle, Version{4, 4, 3}}, DeviceTablet}}, // Fire tablet running pinterest
+
+ // extra logic to identify phone when using silk has not been added
+ // {"Mozilla/5.0 (Linux; Android 4.4.4; SD4930UR Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.67 like Chrome/39.0.2171.93 Mobile Safari/537.36",
+ // UserAgent{
+ // Browser{BrowserSilk, Version{3,0,0}}, OS{PlatformLinux, OSKindle, Version{4,0,0}}, DevicePhone}}, // Silk on Fire Phone
+
+ // Nintendo
+ {"Opera/9.30 (Nintendo Wii; U; ; 2047-7; fr)",
+ UserAgent{
+ Browser{BrowserOpera, Version{9, 30, 0}}, OS{PlatformNintendo, OSNintendo, Version{0, 0, 0}}, DeviceConsole}},
+
+ {"Mozilla/5.0 (Nintendo WiiU) AppleWebKit/534.52 (KHTML, like Gecko) NX/2.1.0.8.21 NintendoBrowser/1.0.0.7494.US",
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformNintendo, OSNintendo, Version{0, 0, 0}}, DeviceConsole}},
+
+ // Xbox
+ {"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; Xbox)", //Xbox 360
+ UserAgent{
+ Browser{BrowserIE, Version{9, 0, 0}}, OS{PlatformXbox, OSXbox, Version{6, 1, 0}}, DeviceConsole}},
+
+ // Playstation
+ {"Mozilla/5.0 (PlayStation 4 4.50) AppleWebKit/601.2 (KHTML, like Gecko)",
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformPlaystation, OSPlaystation, Version{0, 0, 0}}, DeviceConsole}},
+
+ {"Mozilla/5.0 (Playstation Vita 1.61) AppleWebKit/531.22.8 (KHTML, like Gecko) Silk/3.2",
+ UserAgent{
+ Browser{BrowserSilk, Version{3, 2, 0}}, OS{PlatformPlaystation, OSPlaystation, Version{0, 0, 0}}, DeviceConsole}},
+
+ // Smart TVs and TV dongles
+ {"Mozilla/5.0 (CrKey armv7l 1.4.15250) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.0 Safari/537.36", // Chromecast
+ UserAgent{
+ Browser{BrowserChrome, Version{31, 0, 1650}}, OS{PlatformUnknown, OSUnknown, Version{0, 0, 0}}, DeviceTV}},
+
+ {"Mozilla/5.0 (Linux; GoogleTV 3.2; VAP430 Build/MASTER) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.77 Safari/534.24", // Google TV
+ UserAgent{
+ Browser{BrowserChrome, Version{11, 0, 696}}, OS{PlatformLinux, OSAndroid, Version{0, 0, 0}}, DeviceTV}},
+
+ {"Mozilla/5.0 (Linux; Android 5.0; ADT-1 Build/LPX13D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.89 Mobile Safari/537.36", // Android TV
+ UserAgent{
+ Browser{BrowserChrome, Version{40, 0, 2214}}, OS{PlatformLinux, OSAndroid, Version{5, 0, 0}}, DeviceTV}},
+
+ {"Mozilla/5.0 (Linux; Android 4.2.2; AFTB Build/JDQ39) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.173 Mobile Safari/537.22", // Amazon Fire
+ UserAgent{
+ Browser{BrowserChrome, Version{25, 0, 1364}}, OS{PlatformLinux, OSAndroid, Version{4, 2, 2}}, DeviceTV}},
+
+ {"Mozilla/5.0 (Unknown; Linux armv7l) AppleWebKit/537.1+ (KHTML, like Gecko) Safari/537.1+ LG Browser/6.00.00(+mouse+3D+SCREEN+TUNER; LGE; GLOBAL-PLAT5; 03.07.01; 0x00000001;); LG NetCast.TV-2013/03.17.01 (LG, GLOBAL-PLAT4, wired)", // LG TV
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformLinux, OSLinux, Version{0, 0, 0}}, DeviceTV}},
+
+ {"Mozilla/5.0 (X11; FreeBSD; U; Viera; de-DE) AppleWebKit/537.11 (KHTML, like Gecko) Viera/3.10.0 Chrome/23.0.1271.97 Safari/537.11", // Panasonic Viera
+ UserAgent{
+ Browser{BrowserChrome, Version{23, 0, 1271}}, OS{PlatformLinux, OSLinux, Version{0, 0, 0}}, DeviceTV}},
+
+ // TODO: not catching "browser/" and reporting as safari -- ua string not being fully checked?
+ // {"Mozilla/5.0 (DTV) AppleWebKit/531.2+ (KHTML, like Gecko) Espial/6.1.5 AQUOSBrowser/2.0 (US01DTV;V;0001;0001)", // Sharp Aquos
+ // BrowserUnknown, Version{0,0,0}}, OS{PlatformUnknown, OSUnknown, Version{0,0,0}}, DeviceTV}},
+
+ {"Roku/DVP-5.2 (025.02E03197A)", // Roku
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformUnknown, OSUnknown, Version{0, 0, 0}}, DeviceTV}},
+
+ {"mozilla/5.0 (smart-tv; linux; tizen 2.3) applewebkit/538.1 (khtml, like gecko) samsungbrowser/1.0 tv safari/538.1", // Samsung SmartTV
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformLinux, OSLinux, Version{0, 0, 0}}, DeviceTV}},
+
+ {"mozilla/5.0 (linux; u) applewebkit/537.36 (khtml, like gecko) version/4.0 mobile safari/537.36 smarttv/6.0 (netcast)",
+ UserAgent{
+ Browser{BrowserUnknown, Version{4, 0, 0}}, OS{PlatformLinux, OSLinux, Version{0, 0, 0}}, DeviceTV}},
+
+ // Google search app (GSA) for iOS -- it's Safari in disguise as of v6
+ {"Mozilla/5.0 (iPad; CPU OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) GSA/6.0.51363 Mobile/12F69 Safari/600.1.4",
+ UserAgent{
+ Browser{BrowserSafari, Version{8, 3, 0}}, OS{PlatformiPad, OSiOS, Version{8, 3, 0}}, DeviceTablet}},
+
+ // Spotify (applicable for advertising applications)
+ {"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Spotify/1.0.9.133 Safari/537.36",
+ UserAgent{
+ Browser{BrowserSpotify, Version{1, 0, 9}}, OS{PlatformWindows, OSWindows, Version{5, 1, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Spotify/1.0.9.133 Safari/537.36",
+ UserAgent{
+ Browser{BrowserSpotify, Version{1, 0, 9}}, OS{PlatformMac, OSMacOSX, Version{10, 10, 2}}, DeviceComputer}},
+
+ // OCSP fetchers
+ {"Microsoft-CryptoAPI/10.0",
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformWindows, OSUnknown, Version{0, 0, 0}}, DeviceComputer}},
+ {"trustd (unknown version) CFNetwork/811.7.2 Darwin/16.7.0 (x86_64)",
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformMac, OSUnknown, Version{0, 0, 0}}, DeviceComputer}},
+ {"ocspd (unknown version) CFNetwork/520.5.3 Darwin/11.4.2 (x86_64)(MacBookAir5%2C2)",
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformMac, OSUnknown, Version{0, 0, 0}}, DeviceComputer}},
+ // Bots
+ {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/600.2.5 (KHTML, like Gecko) Version/8.0.2 Safari/600.2.5 (Applebot/0.1; +http://www.apple.com/go/applebot)",
+ UserAgent{
+ Browser{BrowserAppleBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{10, 10, 1}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)",
+ UserAgent{
+ Browser{BrowserBaiduBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)",
+ UserAgent{
+ Browser{BrowserBingBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"DuckDuckBot/1.0; (+http://duckduckgo.com/duckduckbot.html)",
+ UserAgent{
+ Browser{BrowserDuckDuckGoBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)",
+ UserAgent{
+ Browser{BrowserFacebookBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"Facebot/1.0",
+ UserAgent{
+ Browser{BrowserFacebookBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
+ UserAgent{
+ Browser{BrowserGoogleBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"LinkedInBot/1.0 (compatible; Mozilla/5.0; Jakarta Commons-HttpClient/3.1 +http://www.linkedin.com)",
+ UserAgent{
+ Browser{BrowserLinkedInBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"msnbot/2.0b (+http://search.msn.com/msnbot.htm)",
+ UserAgent{
+ Browser{BrowserMsnBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"Pingdom.com_bot_version_1.4_(http://www.pingdom.com/)",
+ UserAgent{
+ Browser{BrowserPingdomBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"Twitterbot/1.0",
+ UserAgent{
+ Browser{BrowserTwitterBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)",
+ UserAgent{
+ Browser{BrowserYandexBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)",
+ UserAgent{
+ Browser{BrowserYahooBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{0, 0, 0}}, DeviceComputer}},
+
+ // {"Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
+ // BrowserBot, Version{0,0,0}}, OS{PlatformBot, OSBot, Version{6,0,0}}, DeviceComputer}},
+
+ {"mozilla/5.0 (unknown; linux x86_64) applewebkit/538.1 (khtml, like gecko) phantomjs/2.1.1 safari/538.1",
+ UserAgent{
+ Browser{BrowserBot, Version{0, 0, 0}}, OS{PlatformBot, OSBot, Version{0, 0, 0}}, DeviceComputer}},
+
+ // Unknown or partially handled
+ {"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.1b3pre) Gecko/20090223 SeaMonkey/2.0a3", //Seamonkey (~FF)
+ UserAgent{
+ Browser{BrowserFirefox, Version{0, 0, 0}}, OS{PlatformMac, OSMacOSX, Version{10, 4, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en; rv:1.9.0.8pre) Gecko/2009022800 Camino/2.0b3pre", //Camino (~FF)
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformMac, OSMacOSX, Version{10, 5, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Mobile; rv:26.0) Gecko/26.0 Firefox/26.0", //firefox OS
+ UserAgent{
+ Browser{BrowserFirefox, Version{26, 0, 0}}, OS{PlatformUnknown, OSUnknown, Version{0, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.45 Safari/535.19", //chrome for android having requested desktop site
+ UserAgent{
+ Browser{BrowserChrome, Version{18, 0, 1025}}, OS{PlatformLinux, OSLinux, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"Opera/9.80 (S60; SymbOS; Opera Mobi/352; U; de) Presto/2.4.15 Version/10.00",
+ UserAgent{
+ Browser{BrowserOpera, Version{10, 0, 0}}, OS{PlatformUnknown, OSUnknown, Version{0, 0, 0}}, DevicePhone}},
+
+ // BrowserQQ
+ // {"Mozilla/5.0 (Windows NT 6.2; WOW64; Trident/7.0; Touch; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729; InfoPath.3; Tablet PC 2.0; QQBrowser/7.6.21433.400; rv:11.0) like Gecko",
+ // UserAgent{
+ // Browser{BrowserQQ, Version{7,0,0}}, OS{PlatformWindows, OSWindows, Version{8,0,0}}, DeviceTablet}},
+
+ // {"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36 QQBrowser/9.0.2191.400",
+ // UserAgent{
+ // Browser{BrowserQQ, Version{9,0,0}}, OS{PlatformWindows, OSWindows, Version{7,0,0}}, DeviceComputer}},
+
+ // ANDROID TESTS
+
+ {"Mozilla/5.0 (Linux; U; Android 1.0; en-us; dream) AppleWebKit/525.10+ (KHTML,like Gecko) Version/3.0.4 Mobile Safari/523.12.2",
+ UserAgent{
+ Browser{BrowserAndroid, Version{3, 0, 4}}, OS{PlatformLinux, OSAndroid, Version{1, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 1.0; en-us; generic) AppleWebKit/525.10 (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2",
+ UserAgent{
+ Browser{BrowserAndroid, Version{3, 0, 4}}, OS{PlatformLinux, OSAndroid, Version{1, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 1.0.3; de-de; A80KSC Build/ECLAIR) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{1, 0, 3}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 1.5; en-gb; T-Mobile G1 Build/CRC1) AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1",
+ UserAgent{
+ Browser{BrowserAndroid, Version{3, 1, 2}}, OS{PlatformLinux, OSAndroid, Version{1, 5, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 1.5; es-; FBW1_4 Build/MASTER) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2",
+ UserAgent{
+ Browser{BrowserAndroid, Version{3, 0, 4}}, OS{PlatformLinux, OSAndroid, Version{1, 5, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux U; Android 1.5 en-us hero) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2",
+ UserAgent{
+ Browser{BrowserAndroid, Version{3, 0, 4}}, OS{PlatformLinux, OSAndroid, Version{1, 5, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 1.5; en-us; Opus One Build/RBE.00.00) AppleWebKit/528.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile Safari/525.20.1",
+ UserAgent{
+ Browser{BrowserAndroid, Version{3, 1, 1}}, OS{PlatformLinux, OSAndroid, Version{1, 5, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 1.6; ar-us; SonyEricssonX10i Build/R2BA026) AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1",
+ UserAgent{
+ Browser{BrowserAndroid, Version{3, 1, 2}}, OS{PlatformLinux, OSAndroid, Version{1, 6, 0}}, DevicePhone}},
+
+ // TODO: support names of Android OS?
+ //{"Mozilla/5.0 (Linux; U; Android Donut; de-de; HTC Tattoo 1.52.161.1 Build/Donut) AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1",
+ // UserAgent{
+ // Browser{BrowserAndroid, Version{3, 1, 2}}, OS{PlatformLinux, OSAndroid, Version{1, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 1.6; en-gb; HTC Tattoo Build/DRC79) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2",
+ UserAgent{
+ Browser{BrowserAndroid, Version{3, 0, 4}}, OS{PlatformLinux, OSAndroid, Version{1, 6, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 1.6; ja-jp; Docomo HT-03A Build/DRD08) AppleWebKit/525.10 (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2",
+ UserAgent{
+ Browser{BrowserAndroid, Version{3, 0, 4}}, OS{PlatformLinux, OSAndroid, Version{1, 6, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 2.1; en-us; Nexus One Build/ERD62) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{2, 1, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 2.1-update1; en-au; HTC_Desire_A8183 V1.16.841.1 Build/ERE27) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{2, 1, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 2.1; en-us; generic) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2",
+ UserAgent{
+ Browser{BrowserAndroid, Version{3, 0, 4}}, OS{PlatformLinux, OSAndroid, Version{2, 1, 0}}, DevicePhone}},
+
+ // TODO support named versions of Android?
+ {"Mozilla/5.0 (Linux; U; Android Eclair; en-us; sholes) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2",
+ UserAgent{
+ Browser{BrowserAndroid, Version{3, 0, 4}}, OS{PlatformLinux, OSAndroid, Version{0, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 2.2; en-sa; HTC_DesireHD_A9191 Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{2, 2, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 2.2.1; en-gb; HTC_DesireZ_A7272 Build/FRG83D) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{2, 2, 1}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 2.3.3; en-us; Sensation_4G Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/5.0 Safari/533.16",
+ UserAgent{
+ Browser{BrowserAndroid, Version{5, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{2, 3, 3}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 2.3.5; ko-kr; SHW-M250S Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{2, 3, 5}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 2.3.7; ja-jp; L-02D Build/GWK74) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{2, 3, 7}}, DevicePhone}},
+
+ // TODO: is tablet, not phone
+ {"Mozilla/5.0 (Linux; U; Android 3.0; xx-xx; Transformer TF101 Build/HRI66) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{3, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{3, 0, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (Linux; U; Android 4.0.1; en-us; sdk Build/ICS_MR0) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{4, 0, 1}}, DevicePhone}},
+
+ // TODO support "android-" version prefix
+ // However, can't find reference to this naming scheme in real-world UA gathering
+ // {"Mozilla/5.0 (Linux; U; Android-4.0.3; en-us; Galaxy Nexus Build/IML74K) AppleWebKit/535.7 (KHTML, like Gecko) CrMo/16.0.912.75 Mobile Safari/535.7",
+ // UserAgent{
+ // Browser{BrowserChrome, Version{16,0,0}}, OS{PlatformLinux, OSAndroid, Version{4,0,0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 4.1.1; en-us; Nexus S Build/JRO03E) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{4, 1, 1}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 4.1; en-gb; Build/JRN84D) AppleWebKit/534.30 (KHTML like Gecko) Version/4.0 Mobile Safari/534.30",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{4, 1, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 4.1.1; el-gr; MB525 Build/JRO03H; CyanogenMod-10) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{4, 1, 1}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 4.1.1; fr-fr; MB525 Build/JRO03H; CyanogenMod-10) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{4, 1, 1}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; U; Android 4.2; en-us; Nexus 10 Build/JVP15I) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{4, 2, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (Linux; U; Android 4.2; ro-ro; LT18i Build/4.1.B.0.431) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
+ UserAgent{
+ Browser{BrowserAndroid, Version{4, 0, 0}}, OS{PlatformLinux, OSAndroid, Version{4, 2, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; Android 4.3; Nexus 7 Build/JWR66D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.111 Safari/537.36",
+ UserAgent{
+ Browser{BrowserChrome, Version{27, 0, 1453}}, OS{PlatformLinux, OSAndroid, Version{4, 3, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (Linux; Android 4.4; Nexus 7 Build/KOT24) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.105 Safari/537.36",
+ UserAgent{
+ Browser{BrowserChrome, Version{30, 0, 1599}}, OS{PlatformLinux, OSAndroid, Version{4, 4, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (Linux; Android 4.4; Nexus 4 Build/KRT16E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.105 Mobile Safari",
+ UserAgent{
+ Browser{BrowserChrome, Version{30, 0, 1599}}, OS{PlatformLinux, OSAndroid, Version{4, 4, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; Android 6.0.1; SM-G930V Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.98 Mobile Safari/537.36",
+ UserAgent{
+ Browser{BrowserChrome, Version{52, 0, 2743}}, OS{PlatformLinux, OSAndroid, Version{6, 0, 1}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; Android 7.0; Nexus 5X Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.98 Mobile Safari/537.36",
+ UserAgent{
+ Browser{BrowserChrome, Version{52, 0, 2743}}, OS{PlatformLinux, OSAndroid, Version{7, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Linux; Android 7.0; Nexus 6P Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/52.0.2743.98 Mobile Safari/537.36",
+ UserAgent{
+ Browser{BrowserChrome, Version{52, 0, 2743}}, OS{PlatformLinux, OSAndroid, Version{7, 0, 0}}, DevicePhone}},
+
+ // BLACKBERRY TESTS
+
+ {"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) BlackBerry8703e/4.1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/104",
+ UserAgent{
+ Browser{BrowserBlackberry, Version{0, 0, 0}}, OS{PlatformBlackberry, OSBlackberry, Version{0, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/10.1.0.4633 Mobile Safari/537.10+",
+ UserAgent{
+ Browser{BrowserBlackberry, Version{10, 1, 0}}, OS{PlatformBlackberry, OSBlackberry, Version{0, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (BB10; Kbd) AppleWebKit/537.35+ (KHTML, like Gecko) Version/10.2.1.1925 Mobile Safari/537.35+",
+ UserAgent{
+ Browser{BrowserBlackberry, Version{10, 2, 1}}, OS{PlatformBlackberry, OSBlackberry, Version{0, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (PlayBook; U; RIM Tablet OS 1.0.0; en-US) AppleWebKit/534.11 (KHTML, like Gecko) Version/7.1.0.7 Safari/534.11",
+ UserAgent{
+ Browser{BrowserBlackberry, Version{7, 1, 0}}, OS{PlatformBlackberry, OSBlackberry, Version{0, 0, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML, like Gecko) Version/7.2.1.0 Safari/536.2+",
+ UserAgent{
+ Browser{BrowserBlackberry, Version{7, 2, 1}}, OS{PlatformBlackberry, OSBlackberry, Version{0, 0, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (X11; U; CrOS i686 9.10.0; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Chrome/4.0.253.0 Safari/532.5",
+ UserAgent{
+ Browser{BrowserChrome, Version{4, 0, 253}}, OS{PlatformLinux, OSChromeOS, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (X11; CrOS armv7l 5500.100.6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.120 Safari/537.36",
+ UserAgent{
+ Browser{BrowserChrome, Version{34, 0, 1847}}, OS{PlatformLinux, OSChromeOS, Version{0, 0, 0}}, DeviceComputer}},
+
+ // {"Mozilla/5.0 (Mobile; rv:14.0) Gecko/14.0 Firefox/14.0",
+ // UserAgent{
+ // Browser{BrowserFirefox, 14, OSFirefoxOS, 14}, DevicePhone}},
+
+ // {"Mozilla/5.0 (Mobile; rv:17.0) Gecko/17.0 Firefox/17.0",
+ // UserAgent{
+ // Browser{BrowserFirefox, , OSFirefoxOS}, DevicePhone}},
+
+ // {"Mozilla/5.0 (Mobile; rv:18.1) Gecko/18.1 Firefox/18.1",
+ // UserAgent{
+ // Browser{BrowserFirefox, , OSFirefoxOS}, DevicePhone}},
+
+ // {"Mozilla/5.0 (Tablet; rv:18.1) Gecko/18.1 Firefox/18.1",
+ // UserAgent{
+ // Browser{BrowserFirefox, , OSFirefoxOS}, DevicePhone}},
+
+ // {"Mozilla/5.0 (Mobile; LG-D300; rv:18.1) Gecko/18.1 Firefox/18.1",
+ // UserAgent{
+ // Browser{BrowserFirefox, , OSFirefoxOS}, DevicePhone}},
+
+ {"Mozilla/5.0(iPad; U; CPU iPhone OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B314 Safari/531.21.10",
+ UserAgent{
+ Browser{BrowserSafari, Version{4, 0, 4}}, OS{PlatformiPad, OSiOS, Version{3, 2, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7",
+ UserAgent{
+ Browser{BrowserSafari, Version{4, 0, 5}}, OS{PlatformiPhone, OSiOS, Version{4, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3",
+ UserAgent{
+ Browser{BrowserSafari, Version{5, 1, 0}}, OS{PlatformiPhone, OSiOS, Version{5, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (iPad; CPU OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3",
+ UserAgent{
+ Browser{BrowserSafari, Version{5, 1, 0}}, OS{PlatformiPad, OSiOS, Version{5, 0, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25",
+ UserAgent{
+ Browser{BrowserSafari, Version{6, 0, 0}}, OS{PlatformiPad, OSiOS, Version{6, 0, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X) AppleWebKit/546.10 (KHTML, like Gecko) Version/6.0 Mobile/7E18WD Safari/8536.25",
+ UserAgent{
+ Browser{BrowserSafari, Version{6, 0, 0}}, OS{PlatformiPhone, OSiOS, Version{7, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (iPad; CPU OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53",
+ UserAgent{
+ Browser{BrowserSafari, Version{7, 0, 0}}, OS{PlatformiPad, OSiOS, Version{7, 0, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (iPad; CPU OS 7_0_2 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A501 Safari/9537.53",
+ UserAgent{
+ Browser{BrowserSafari, Version{7, 0, 0}}, OS{PlatformiPad, OSiOS, Version{7, 0, 2}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (iPhone; CPU iPhone OS 10_2_1 like Mac OS X) AppleWebKit/602.4.6 (KHTML, like Gecko) Mobile/14D27 [FBAN/FBIOS;FBAV/86.0.0.48.52;FBBV/53842252;FBDV/iPhone9,1;FBMD/iPhone;FBSN/iOS;FBSV/10.2.1;FBSS/2;FBCR/Verizon;FBID/phone;FBLC/en_US;FBOP/5;FBRV/0]",
+ UserAgent{
+ Browser{BrowserSafari, Version{10, 2, 1}}, OS{PlatformiPhone, OSiOS, Version{10, 2, 1}}, DevicePhone}},
+
+ // TODO handle default browser based on iOS version
+ // {"Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/538.34.9 (KHTML, like Gecko) Mobile/12A4265u",
+ // UserAgent{
+ // Browser{BrowserSafari, Version{8,0,0}}, OS{PlatformiPhone, OSiOS, Version{8,0,0}}, DevicePhone}},
+
+ // TODO extrapolate browser from iOS version
+ // {"Mozilla/5.0 (iPad; CPU OS 8_0 like Mac OS X) AppleWebKit/538.34.9 (KHTML, like Gecko) Mobile/12A4265u",
+ // UserAgent{
+ // Browser{BrowserSafari, Version{8,0,0}}, OS{PlatformiPad, OSiOS, Version{8,0,0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (iPhone; CPU iPhone OS 8_0_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12A405 Safari/600.1.4",
+ UserAgent{
+ Browser{BrowserSafari, Version{8, 0, 0}}, OS{PlatformiPhone, OSiOS, Version{8, 0, 2}}, DevicePhone}},
+
+ {"Mozilla/5.0 (X11; U; Linux x86_64; en; rv:1.9.0.14) Gecko/20080528 Ubuntu/9.10 (karmic) Epiphany/2.22 Firefox/3.0",
+ UserAgent{
+ Browser{BrowserFirefox, Version{3, 0, 0}}, OS{PlatformLinux, OSLinux, Version{0, 0, 0}}, DeviceComputer}},
+
+ // Can't parse browser due to limitation of user agent library
+ {"Mozilla/5.0 (X11; U; Linux x86_64; zh-TW; rv:1.9.0.8) Gecko/2009032712 Ubuntu/8.04 (hardy) Firefox/3.0.8 GTB5",
+ UserAgent{
+ Browser{BrowserFirefox, Version{3, 0, 8}}, OS{PlatformLinux, OSLinux, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (compatible; Konqueror/3.5; Linux; x86_64) KHTML/3.5.5 (like Gecko) (Debian)",
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformLinux, OSLinux, Version{0, 0, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.1.5) Gecko/20091112 Iceweasel/3.5.5 (like Firefox/3.5.5; Debian-3.5.5-1)",
+ UserAgent{
+ Browser{BrowserFirefox, Version{3, 5, 5}}, OS{PlatformLinux, OSLinux, Version{0, 0, 0}}, DeviceComputer}},
+
+ // TODO consider bot?
+ // {"Miro/2.0.4 (http://www.getmiro.com/; Darwin 10.3.0 i386)",
+ // UserAgent{
+ // Browser{BrowserUnknown, Version{0,0,0}}, OS{PlatformMac, OSMacOSX, Version{3,0,0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.1b3pre) Gecko/20090223 SeaMonkey/2.0a3",
+ UserAgent{
+ Browser{BrowserFirefox, Version{0, 0, 0}}, OS{PlatformMac, OSMacOSX, Version{10, 4, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_5; en-us) AppleWebKit/525.26.2 (KHTML, like Gecko) Version/3.2 Safari/525.26.12",
+ UserAgent{
+ Browser{BrowserSafari, Version{3, 2, 0}}, OS{PlatformMac, OSMacOSX, Version{10, 5, 5}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en; rv:1.9.0.8pre) Gecko/2009022800 Camino/2.0b3pre",
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformMac, OSMacOSX, Version{10, 5, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_2; en-US) AppleWebKit/533.1 (KHTML, like Gecko) Chrome/5.0.329.0 Safari/533.1",
+ UserAgent{
+ Browser{BrowserChrome, Version{5, 0, 329}}, OS{PlatformMac, OSMacOSX, Version{10, 6, 2}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 (.NET CLR 3.5.30729)",
+ UserAgent{
+ Browser{BrowserFirefox, Version{3, 5, 6}}, OS{PlatformMac, OSMacOSX, Version{10, 6, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/534.52.7 (KHTML, like Gecko) Version/5.1.2 Safari/534.52.7",
+ UserAgent{
+ Browser{BrowserSafari, Version{5, 1, 2}}, OS{PlatformMac, OSMacOSX, Version{10, 7, 2}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:9.0) Gecko/20111222 Thunderbird/9.0.1",
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformMac, OSMacOSX, Version{10, 7, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.75 Safari/535.7",
+ UserAgent{
+ Browser{BrowserChrome, Version{16, 0, 912}}, OS{PlatformMac, OSMacOSX, Version{10, 7, 2}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8) AppleWebKit/535.18.5 (KHTML, like Gecko) Version/5.2 Safari/535.18.5",
+ UserAgent{
+ Browser{BrowserSafari, Version{5, 2, 0}}, OS{PlatformMac, OSMacOSX, Version{10, 8, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_8; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Chrome/4.0.249.0 Safari/532.5",
+ UserAgent{
+ Browser{BrowserChrome, Version{4, 0, 249}}, OS{PlatformMac, OSMacOSX, Version{10, 8, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9) AppleWebKit/537.35.1 (KHTML, like Gecko) Version/6.1 Safari/537.35.1",
+ UserAgent{
+ Browser{BrowserSafari, Version{6, 1, 0}}, OS{PlatformMac, OSMacOSX, Version{10, 9, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10) AppleWebKit/538.34.48 (KHTML, like Gecko) Version/8.0 Safari/538.35.8",
+ UserAgent{
+ Browser{BrowserSafari, Version{8, 0, 0}}, OS{PlatformMac, OSMacOSX, Version{10, 10, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10) AppleWebKit/538.32 (KHTML, like Gecko) Version/7.1 Safari/538.4",
+ UserAgent{
+ Browser{BrowserSafari, Version{7, 1, 0}}, OS{PlatformMac, OSMacOSX, Version{10, 10, 0}}, DeviceComputer}},
+
+ {"Opera/9.80 (S60; SymbOS; Opera Mobi/352; U; de) Presto/2.4.15 Version/10.00",
+ UserAgent{
+ Browser{BrowserOpera, Version{10, 0, 0}}, OS{PlatformUnknown, OSUnknown, Version{0, 0, 0}}, DevicePhone}},
+
+ {"Opera/9.80 (S60; SymbOS; Opera Mobi/352; U; de) Presto/2.4.15 Version/10.00",
+ UserAgent{
+ Browser{BrowserOpera, Version{10, 0, 0}}, OS{PlatformUnknown, OSUnknown, Version{0, 0, 0}}, DevicePhone}},
+
+ // TODO: support OneBrowser? https://play.google.com/store/apps/details?id=com.tencent.ibibo.mtt&hl=en_GB
+ // {"OneBrowser/3.1 (NokiaN70-1/5.0638.3.0.1)",
+ // UserAgent{
+ // Browser{BrowserUnknown, Version{0,0,0}}, OS{PlatformUnknown, OSUnknown, Version{0,0,0}}, DevicePhone}},
+
+ // WebOS reports itself as safari :(
+ {"Mozilla/5.0 (webOS/1.0; U; en-US) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/1.0 Safari/525.27.1 Pre/1.0",
+ UserAgent{
+ Browser{BrowserUnknown, Version{1, 0, 0}}, OS{PlatformLinux, OSWebOS, Version{0, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (webOS/1.4.1.1; U; en-US) AppleWebKit/532.2 (KHTML, like Gecko) Version/1.0 Safari/532.2 Pre/1.0",
+ UserAgent{
+ Browser{BrowserUnknown, Version{1, 0, 0}}, OS{PlatformLinux, OSWebOS, Version{0, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.0; U; de-DE) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/233.70 Safari/534.6 TouchPad/1.0",
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformLinux, OSWebOS, Version{0, 0, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.2; U; en-US) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/234.40.1 Safari/534.6 TouchPad/1.0",
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformLinux, OSWebOS, Version{0, 0, 0}}, DeviceTablet}},
+
+ {"Opera/9.30 (Nintendo Wii; U; ; 2047-7; fr)",
+ UserAgent{
+ Browser{BrowserOpera, Version{9, 30, 0}}, OS{PlatformNintendo, OSNintendo, Version{0, 0, 0}}, DeviceConsole}},
+
+ {"Mozilla/5.0 (Nintendo WiiU) AppleWebKit/534.52 (KHTML, like Gecko) NX/2.1.0.8.21 NintendoBrowser/1.0.0.7494.US",
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformNintendo, OSNintendo, Version{0, 0, 0}}, DeviceConsole}},
+
+ {"Mozilla/5.0 (Nintendo WiiU) AppleWebKit/536.28 (KHTML, like Gecko) NX/3.0.3.12.6 NintendoBrowser/2.0.0.9362.US",
+ UserAgent{
+ Browser{BrowserUnknown, Version{0, 0, 0}}, OS{PlatformNintendo, OSNintendo, Version{0, 0, 0}}, DeviceConsole}},
+
+ // TODO fails to get opera first -- but is this a real UA string or an uncommon spoof?
+ // {"Mozilla/4.0 (compatible; MSIE 5.0; Windows 2000) Opera 6.0 [en]",
+ // BrowserIE, Version{5,0,0}}, OS{PlatformWindows, OSWindows, Version{4,0,0}}, DeviceComputer}},
+
+ {"Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.3705; .NET CLR 2.0.50727)",
+ UserAgent{
+ Browser{BrowserIE, Version{5, 0, 1}}, OS{PlatformWindows, OSWindows, Version{5, 0, 0}}, DeviceComputer}},
+
+ {"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; GTB6.4; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; OfficeLiveConnector.1.3; OfficeLivePatch.0.0; .NET CLR 1.1.4322)",
+ UserAgent{
+ Browser{BrowserIE, Version{7, 0, 0}}, OS{PlatformWindows, OSWindows, Version{6, 1, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Windows; U; Windows NT 6.1; sk; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7",
+ UserAgent{
+ Browser{BrowserFirefox, Version{3, 5, 7}}, OS{PlatformWindows, OSWindows, Version{6, 1, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)",
+ UserAgent{
+ Browser{BrowserIE, Version{10, 0, 0}}, OS{PlatformWindows, OSWindows, Version{6, 2, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/536.5 (KHTML, like Gecko) YaBrowser/1.0.1084.5402 Chrome/19.0.1084.5402 Safari/536.5",
+ UserAgent{
+ Browser{BrowserChrome, Version{19, 0, 1084}}, OS{PlatformWindows, OSWindows, Version{6, 2, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.15 (KHTML, like Gecko) Chrome/24.0.1295.0 Safari/537.15",
+ UserAgent{
+ Browser{BrowserChrome, Version{24, 0, 1295}}, OS{PlatformWindows, OSWindows, Version{6, 2, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; rv:11.0) like Gecko",
+ UserAgent{
+ Browser{BrowserIE, Version{11, 0, 0}}, OS{PlatformWindows, OSWindows, Version{6, 3, 0}}, DeviceTablet}},
+
+ {"Mozilla/5.0 (IE 11.0; Windows NT 6.3; Trident/7.0; .NET4.0E; .NET4.0C; rv:11.0) like Gecko",
+ UserAgent{
+ Browser{BrowserIE, Version{11, 0, 0}}, OS{PlatformWindows, OSWindows, Version{6, 3, 0}}, DeviceComputer}},
+
+ // {"Mozilla/4.0 (compatible; MSIE 4.01; Windows 95)",
+ // UserAgent{
+ // Browser{BrowserIE, Version{5,0,0}}, OS{PlatformWindows, OSWindows95, Version{5,0,0}}, DeviceComputer}},
+
+ // {"Mozilla/4.0 (compatible; MSIE 5.0; Windows 95) Opera 6.02 [en]",
+ // UserAgent{
+ // Browser{BrowserIE, Version{5,0,0}}, OS{PlatformWindows, OSWindows95, Version{5,0,0}}, DeviceComputer}},
+
+ // {"Mozilla/4.0 (compatible; MSIE 6.0b; Windows 98; YComp 5.0.0.0)",
+ // UserAgent{
+ // Browser{BrowserIE, Version{6,0,0}}, OS{PlatformWindows, OSWindows98, Version{5,0,0}}, DeviceComputer}},
+
+ // {"Mozilla/4.0 (compatible; MSIE 4.01; Windows 98)",
+ // UserAgent{
+ // Browser{BrowserIE, Version{4,0,0}}, OS{PlatformWindows, OSWindows98, Version{5,0,0}}, DeviceComputer}},
+
+ // {"Mozilla/5.0 (Windows; U; Windows 98; en-US; rv:1.8.1.8pre) Gecko/20071019 Firefox/2.0.0.8 Navigator/9.0.0.1",
+ // UserAgent{
+ // Browser{BrowserFirefox, Version{2,0,0}}, OS{PlatformWindows, OSWindows98, Version{5,0,0}}, DeviceComputer}},
+
+ //Can't parse due to limitation of user agent library
+ // {"Mozilla/5.0 (Windows; U; Windows CE 5.1; rv:1.8.1a3) Gecko/20060610 Minimo/0.016",
+ // UserAgent{
+ // Browser{ BrowserUnknown, Version{0,0,0}}, OS{PlatformWindowsPhone, OSWindowsPhone, Version{0,0,0}}, DevicePhone}},
+
+ // {"Mozilla/4.0 (compatible; MSIE 4.01; Windows CE; 176x220)",
+ // UserAgent{
+ // Browser{BrowserIE, Version{4,0,0}}, OS{PlatformWindowsPhone, OSWindowsPhone, Version{0,0,0}}, DevicePhone}},
+
+ // Can't parse browser due to limitation of user agent library
+ // {"Mozilla/4.0 (compatible; MSIE 5.0; Windows ME) Opera 6.0 [de]",
+ // UserAgent{
+ // Browser{BrowserUnknown, OSWindowsME}, DeviceComputer}},
+
+ {"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 1.1.4322; InfoPath.2; .NET CLR 3.5.21022; .NET CLR 3.5.30729; MS-RTC LM 8; OfficeLiveConnector.1.4; OfficeLivePatch.1.3; .NET CLR 3.0.30729)",
+ UserAgent{
+ Browser{BrowserIE, Version{8, 0, 0}}, OS{PlatformWindows, OSWindows, Version{6, 0, 0}}, DeviceComputer}},
+
+ {"Mozilla/5.0 (Windows; U; Windows NT 5.1; cs; rv:1.9.1.8) Gecko/20100202 Firefox/3.5.8",
+ UserAgent{
+ Browser{BrowserFirefox, Version{3, 5, 8}}, OS{PlatformWindows, OSWindows, Version{5, 1, 0}}, DeviceComputer}},
+
+ {"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; )",
+ UserAgent{
+ Browser{BrowserIE, Version{7, 0, 0}}, OS{PlatformWindows, OSWindows, Version{5, 1, 0}}, DeviceComputer}},
+
+ // Can't parse due to limitation of user agent library
+ {"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Windows Phone 6.5.3.5)",
+ UserAgent{
+ Browser{BrowserIE, Version{6, 0, 0}}, OS{PlatformWindowsPhone, OSWindowsPhone, Version{6, 5, 3}}, DevicePhone}},
+
+ // desktop mode for Windows Phone 7
+ {"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; XBLWP7; ZuneWP7)",
+ UserAgent{
+ Browser{BrowserIE, Version{7, 0, 0}}, OS{PlatformWindows, OSWindows, Version{6, 1, 0}}, DeviceComputer}},
+
+ // mobile mode for Windows Phone 7
+ {"Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0; HTC; T8788)",
+ UserAgent{
+ Browser{BrowserIE, Version{7, 0, 0}}, OS{PlatformWindowsPhone, OSWindowsPhone, Version{7, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0)",
+ UserAgent{
+ Browser{BrowserIE, Version{9, 0, 0}}, OS{PlatformWindowsPhone, OSWindowsPhone, Version{7, 5, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 920)",
+ UserAgent{
+ Browser{BrowserIE, Version{10, 0, 0}}, OS{PlatformWindowsPhone, OSWindowsPhone, Version{8, 0, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Windows Phone 8.1; ARM; Trident/7.0; Touch IEMobile/11.0; HTC; Windows Phone 8S by HTC) like Gecko",
+ UserAgent{
+ Browser{BrowserIE, Version{11, 0, 0}}, OS{PlatformWindowsPhone, OSWindowsPhone, Version{8, 1, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (Windows Phone 8.1; ARM; Trident/7.0; Touch IEMobile/11.0; NOKIA; 909) like Gecko",
+ UserAgent{
+ Browser{BrowserIE, Version{11, 0, 0}}, OS{PlatformWindowsPhone, OSWindowsPhone, Version{8, 1, 0}}, DevicePhone}},
+
+ {"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; Xbox)",
+ UserAgent{
+ Browser{BrowserIE, Version{9, 0, 0}}, OS{PlatformXbox, OSXbox, Version{6, 1, 0}}, DeviceConsole}},
+}
+
+func TestAgentSurfer(t *testing.T) {
+ for _, determined := range testUAVars {
+ t.Run("", func(t *testing.T) {
+ testFuncs := []func(string) *UserAgent{
+ Parse,
+ func(ua string) *UserAgent {
+ u := new(UserAgent)
+ ParseUserAgent(ua, u)
+ return u
+ },
+ }
+
+ for _, f := range testFuncs {
+ ua := f(determined.UA)
+
+ if ua.Browser.Name != determined.Browser.Name {
+ t.Errorf("browserName: got %v, wanted %v", ua.Browser.Name, determined.Browser.Name)
+ t.Logf("agent: %s", determined.UA)
+ }
+
+ if ua.Browser.Version != determined.Browser.Version {
+ t.Errorf("browser version: got %d, wanted %d", ua.Browser.Version, determined.Browser.Version)
+ t.Logf("agent: %s", determined.UA)
+ }
+
+ if ua.OS.Platform != determined.OS.Platform {
+ t.Errorf("platform: got %v, wanted %v", ua.OS.Platform, determined.OS.Platform)
+ t.Logf("agent: %s", determined.UA)
+ }
+
+ if ua.OS.Name != determined.OS.Name {
+ t.Errorf("os: got %s, wanted %s", ua.OS.Name, determined.OS.Name)
+ t.Logf("agent: %s", determined.UA)
+ }
+
+ if ua.OS.Version != determined.OS.Version {
+ t.Errorf("os version: got %d, wanted %d", ua.OS.Version, determined.OS.Version)
+ t.Logf("agent: %s", determined.UA)
+ }
+
+ if ua.DeviceType != determined.DeviceType {
+ t.Errorf("device type: got %v, wanted %v", ua.DeviceType, determined.DeviceType)
+ t.Logf("agent: %s", determined.UA)
+ }
+ }
+ })
+ }
+}
+
+func BenchmarkAgentSurfer(b *testing.B) {
+ num := len(testUAVars)
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ Parse(testUAVars[i%num].UA)
+ }
+}
+
+func BenchmarkAgentSurferReuse(b *testing.B) {
+ dest := new(UserAgent)
+ num := len(testUAVars)
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ dest.Reset()
+ ParseUserAgent(testUAVars[i%num].UA, dest)
+ }
+}
+
+func BenchmarkEvalSystem(b *testing.B) {
+ num := len(testUAVars)
+ v := UserAgent{}
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.evalOS(testUAVars[i%num].UA)
+ }
+}
+
+func BenchmarkEvalBrowserName(b *testing.B) {
+ num := len(testUAVars)
+ v := UserAgent{}
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.evalBrowserName(testUAVars[i%num].UA)
+ }
+}
+
+func BenchmarkEvalBrowserVersion(b *testing.B) {
+ num := len(testUAVars)
+ v := UserAgent{}
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.Browser.Name = testUAVars[i%num].Browser.Name
+ v.evalBrowserVersion(testUAVars[i%num].UA)
+ }
+}
+
+func BenchmarkEvalDevice(b *testing.B) {
+ num := len(testUAVars)
+ v := UserAgent{}
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ v.OS.Name = testUAVars[i%num].OS.Name
+ v.OS.Platform = testUAVars[i%num].OS.Platform
+ v.Browser.Name = testUAVars[i%num].Browser.Name
+ v.evalDevice(testUAVars[i%num].UA)
+ }
+}
+
+// Chrome for Mac
+func BenchmarkParseChromeMac(b *testing.B) {
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ Parse("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36")
+ }
+}
+
+// Chrome for Windows
+func BenchmarkParseChromeWin(b *testing.B) {
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ Parse("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36")
+ }
+}
+
+// Chrome for Android
+func BenchmarkParseChromeAndroid(b *testing.B) {
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ Parse("Mozilla/5.0 (Linux; Android 4.4.2; GT-P5210 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.93 Safari/537.36")
+ }
+}
+
+// Safari for Mac
+func BenchmarkParseSafariMac(b *testing.B) {
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ Parse("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/600.7.12 (KHTML, like Gecko) Version/8.0.7 Safari/600.7.12")
+ }
+}
+
+// Safari for iPad
+func BenchmarkParseSafariiPad(b *testing.B) {
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ Parse("Mozilla/5.0 (iPad; CPU OS 8_1_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B440 Safari/600.1.4")
+ }
+}
diff --git a/vendor/github.com/mssola/user_agent/.travis.yml b/vendor/github.com/mssola/user_agent/.travis.yml
deleted file mode 100644
index 96f43d112..000000000
--- a/vendor/github.com/mssola/user_agent/.travis.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-language: go
-go:
- - 1.4.x
- - 1.5.x
- - 1.6.x
- - 1.7.x
- - 1.8.x
- - 1.9.x
- - 1.x
- - tip
-matrix:
- allow_failures:
- - go: tip
diff --git a/vendor/github.com/mssola/user_agent/LICENSE b/vendor/github.com/mssola/user_agent/LICENSE
deleted file mode 100644
index 1c42691ce..000000000
--- a/vendor/github.com/mssola/user_agent/LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-Copyright (c) 2012-2018 Miquel Sabaté Solà
-
-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.
diff --git a/vendor/github.com/mssola/user_agent/README.md b/vendor/github.com/mssola/user_agent/README.md
deleted file mode 100644
index 60427ec53..000000000
--- a/vendor/github.com/mssola/user_agent/README.md
+++ /dev/null
@@ -1,51 +0,0 @@
-
-# UserAgent [![Build Status](https://travis-ci.org/mssola/user_agent.png?branch=master)](https://travis-ci.org/mssola/user_agent) [![GoDoc](https://godoc.org/github.com/mssola/user_agent?status.png)](http://godoc.org/github.com/mssola/user_agent)
-
-
-UserAgent is a Go library that parses HTTP User Agents.
-
-## Usage
-
-~~~ go
-package main
-
-import (
- "fmt"
-
- "github.com/mssola/user_agent"
-)
-
-func main() {
- // The "New" function will create a new UserAgent object and it will parse
- // the given string. If you need to parse more strings, you can re-use
- // this object and call: ua.Parse("another string")
- ua := user_agent.New("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.97 Safari/537.11")
-
- fmt.Printf("%v\n", ua.Mobile()) // => false
- fmt.Printf("%v\n", ua.Bot()) // => false
- fmt.Printf("%v\n", ua.Mozilla()) // => "5.0"
-
- fmt.Printf("%v\n", ua.Platform()) // => "X11"
- fmt.Printf("%v\n", ua.OS()) // => "Linux x86_64"
-
- name, version := ua.Engine()
- fmt.Printf("%v\n", name) // => "AppleWebKit"
- fmt.Printf("%v\n", version) // => "537.11"
-
- name, version = ua.Browser()
- fmt.Printf("%v\n", name) // => "Chrome"
- fmt.Printf("%v\n", version) // => "23.0.1271.97"
-
- // Let's see an example with a bot.
-
- ua.Parse("Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)")
-
- fmt.Printf("%v\n", ua.Bot()) // => true
-
- name, version = ua.Browser()
- fmt.Printf("%v\n", name) // => Googlebot
- fmt.Printf("%v\n", version) // => 2.1
-}
-~~~
-
-Copyright &copy; 2012-2018 Miquel Sabaté Solà, released under the MIT License.
diff --git a/vendor/github.com/mssola/user_agent/all_test.go b/vendor/github.com/mssola/user_agent/all_test.go
deleted file mode 100644
index a5d5ee648..000000000
--- a/vendor/github.com/mssola/user_agent/all_test.go
+++ /dev/null
@@ -1,594 +0,0 @@
-// Copyright (C) 2012-2018 Miquel Sabaté Solà <mikisabate@gmail.com>
-// This file is licensed under the MIT license.
-// See the LICENSE file.
-
-package user_agent
-
-import (
- "fmt"
- "reflect"
- "testing"
-)
-
-// Slice that contains all the tests. Each test is contained in a struct
-// that groups the title of the test, the User-Agent string to be tested and the expected value.
-var uastrings = []struct {
- title string
- ua string
- expected string
- expectedOS *OSInfo
-}{
- // Bots
- {
- title: "GoogleBot",
- ua: "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
- expected: "Mozilla:5.0 Browser:Googlebot-2.1 Bot:true Mobile:false",
- },
- {
- title: "GoogleBotSmartphone (iPhone)",
- ua: "Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
- expected: "Mozilla:5.0 Browser:Googlebot-2.1 Bot:true Mobile:true",
- },
- {
- title: "GoogleBotSmartphone (Android)",
- ua: "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.96 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
- expected: "Mozilla:5.0 Browser:Googlebot-2.1 Bot:true Mobile:true",
- },
- {
- title: "BingBot",
- ua: "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)",
- expected: "Mozilla:5.0 Browser:bingbot-2.0 Bot:true Mobile:false",
- },
- {
- title: "BaiduBot",
- ua: "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)",
- expected: "Mozilla:5.0 Browser:Baiduspider-2.0 Bot:true Mobile:false",
- },
- {
- title: "Twitterbot",
- ua: "Twitterbot",
- expected: "Browser:Twitterbot Bot:true Mobile:false",
- },
- {
- title: "YahooBot",
- ua: "Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)",
- expected: "Mozilla:5.0 Browser:Yahoo! Slurp Bot:true Mobile:false",
- },
- {
- title: "FacebookExternalHit",
- ua: "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)",
- expected: "Browser:facebookexternalhit-1.1 Bot:true Mobile:false",
- },
- {
- title: "FacebookPlatform",
- ua: "facebookplatform/1.0 (+http://developers.facebook.com)",
- expected: "Browser:facebookplatform-1.0 Bot:true Mobile:false",
- },
- {
- title: "FaceBot",
- ua: "Facebot",
- expected: "Browser:Facebot Bot:true Mobile:false",
- },
- {
- title: "NutchCVS",
- ua: "NutchCVS/0.8-dev (Nutch; http://lucene.apache.org/nutch/bot.html; nutch-agent@lucene.apache.org)",
- expected: "Browser:NutchCVS Bot:true Mobile:false",
- },
- {
- title: "MJ12bot",
- ua: "Mozilla/5.0 (compatible; MJ12bot/v1.2.4; http://www.majestic12.co.uk/bot.php?+)",
- expected: "Mozilla:5.0 Browser:MJ12bot-v1.2.4 Bot:true Mobile:false",
- },
- {
- title: "MJ12bot",
- ua: "MJ12bot/v1.0.8 (http://majestic12.co.uk/bot.php?+)",
- expected: "Browser:MJ12bot Bot:true Mobile:false",
- },
- {
- title: "AhrefsBot",
- ua: "Mozilla/5.0 (compatible; AhrefsBot/4.0; +http://ahrefs.com/robot/)",
- expected: "Mozilla:5.0 Browser:AhrefsBot-4.0 Bot:true Mobile:false",
- },
-
- // Internet Explorer
- {
- title: "IE10",
- ua: "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)",
- expected: "Mozilla:5.0 Platform:Windows OS:Windows 8 Browser:Internet Explorer-10.0 Engine:Trident Bot:false Mobile:false",
- expectedOS: &OSInfo{"Windows 8", "Windows", "8"},
- },
- {
- title: "Tablet",
- ua: "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; ARM; Trident/6.0; Touch; .NET4.0E; .NET4.0C; Tablet PC 2.0)",
- expected: "Mozilla:4.0 Platform:Windows OS:Windows 8 Browser:Internet Explorer-10.0 Engine:Trident Bot:false Mobile:false",
- },
- {
- title: "Touch",
- ua: "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; ARM; Trident/6.0; Touch)",
- expected: "Mozilla:5.0 Platform:Windows OS:Windows 8 Browser:Internet Explorer-10.0 Engine:Trident Bot:false Mobile:false",
- },
- {
- title: "Phone",
- ua: "Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0; SAMSUNG; SGH-i917)",
- expected: "Mozilla:4.0 Platform:Windows OS:Windows Phone OS 7.0 Browser:Internet Explorer-7.0 Engine:Trident Bot:false Mobile:true",
- expectedOS: &OSInfo{"Windows Phone OS 7.0", "Windows Phone OS", "7.0"},
- },
- {
- title: "IE6",
- ua: "Mozilla/4.0 (compatible; MSIE6.0; Windows NT 5.0; .NET CLR 1.1.4322)",
- expected: "Mozilla:4.0 Platform:Windows OS:Windows 2000 Browser:Internet Explorer-6.0 Engine:Trident Bot:false Mobile:false",
- expectedOS: &OSInfo{"Windows 2000", "Windows", "2000"},
- },
- {
- title: "IE8Compatibility",
- ua: "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; InfoPath.3; MS-RTC LM 8)",
- expected: "Mozilla:4.0 Platform:Windows OS:Windows 7 Browser:Internet Explorer-8.0 Engine:Trident Bot:false Mobile:false",
- expectedOS: &OSInfo{"Windows 7", "Windows", "7"},
- },
- {
- title: "IE10Compatibility",
- ua: "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; InfoPath.3; MS-RTC LM 8)",
- expected: "Mozilla:4.0 Platform:Windows OS:Windows 7 Browser:Internet Explorer-10.0 Engine:Trident Bot:false Mobile:false",
- },
- {
- title: "IE11Win81",
- ua: "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko",
- expected: "Mozilla:5.0 Platform:Windows OS:Windows 8.1 Browser:Internet Explorer-11.0 Engine:Trident Bot:false Mobile:false",
- expectedOS: &OSInfo{"Windows 8.1", "Windows", "8.1"},
- },
- {
- title: "IE11Win7",
- ua: "Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko",
- expected: "Mozilla:5.0 Platform:Windows OS:Windows 7 Browser:Internet Explorer-11.0 Engine:Trident Bot:false Mobile:false",
- },
- {
- title: "IE11b32Win7b64",
- ua: "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko",
- expected: "Mozilla:5.0 Platform:Windows OS:Windows 7 Browser:Internet Explorer-11.0 Engine:Trident Bot:false Mobile:false",
- },
- {
- title: "IE11b32Win7b64MDDRJS",
- ua: "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; MDDRJS; rv:11.0) like Gecko",
- expected: "Mozilla:5.0 Platform:Windows OS:Windows 7 Browser:Internet Explorer-11.0 Engine:Trident Bot:false Mobile:false",
- },
- {
- title: "IE11Compatibility",
- ua: "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; Trident/7.0)",
- expected: "Mozilla:4.0 Platform:Windows OS:Windows 8.1 Browser:Internet Explorer-7.0 Engine:Trident Bot:false Mobile:false",
- },
-
- // Microsoft Edge
- {
- title: "EdgeDesktop",
- ua: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240",
- expected: "Mozilla:5.0 Platform:Windows OS:Windows 10 Browser:Edge-12.10240 Engine:EdgeHTML Bot:false Mobile:false",
- expectedOS: &OSInfo{"Windows 10", "Windows", "10"},
- },
- {
- title: "EdgeMobile",
- ua: "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; DEVICE INFO) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Mobile Safari/537.36 Edge/12.10240",
- expected: "Mozilla:5.0 Platform:Windows OS:Windows Phone 10.0 Browser:Edge-12.10240 Engine:EdgeHTML Bot:false Mobile:true",
- },
-
- // Gecko
- {
- title: "FirefoxMac",
- ua: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0b8) Gecko/20100101 Firefox/4.0b8",
- expected: "Mozilla:5.0 Platform:Macintosh OS:Intel Mac OS X 10.6 Browser:Firefox-4.0b8 Engine:Gecko-20100101 Bot:false Mobile:false",
- expectedOS: &OSInfo{"Intel Mac OS X 10.6", "Mac OS X", "10.6"},
- },
- {
- title: "FirefoxMacLoc",
- ua: "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13",
- expected: "Mozilla:5.0 Platform:Macintosh OS:Intel Mac OS X 10.6 Localization:en-US Browser:Firefox-3.6.13 Engine:Gecko-20101203 Bot:false Mobile:false",
- expectedOS: &OSInfo{"Intel Mac OS X 10.6", "Mac OS X", "10.6"},
- },
- {
- title: "FirefoxLinux",
- ua: "Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20100101 Firefox/17.0",
- expected: "Mozilla:5.0 Platform:X11 OS:Linux x86_64 Browser:Firefox-17.0 Engine:Gecko-20100101 Bot:false Mobile:false",
- expectedOS: &OSInfo{"Linux x86_64", "Linux", ""},
- },
- {
- title: "FirefoxLinux - Ubuntu V50",
- ua: "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:50.0) Gecko/20100101 Firefox/50.0",
- expected: "Mozilla:5.0 Platform:X11 OS:Ubuntu Browser:Firefox-50.0 Engine:Gecko-20100101 Bot:false Mobile:false",
- expectedOS: &OSInfo{"Ubuntu", "Ubuntu", ""},
- },
- {
- title: "FirefoxWin",
- ua: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14",
- expected: "Mozilla:5.0 Platform:Windows OS:Windows XP Localization:en-US Browser:Firefox-2.0.0.14 Engine:Gecko-20080404 Bot:false Mobile:false",
- expectedOS: &OSInfo{"Windows XP", "Windows", "XP"},
- },
- {
- title: "Firefox29Win7",
- ua: "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0",
- expected: "Mozilla:5.0 Platform:Windows OS:Windows 7 Browser:Firefox-29.0 Engine:Gecko-20100101 Bot:false Mobile:false",
- },
- {
- title: "CaminoMac",
- ua: "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en; rv:1.8.1.14) Gecko/20080409 Camino/1.6 (like Firefox/2.0.0.14)",
- expected: "Mozilla:5.0 Platform:Macintosh OS:Intel Mac OS X Localization:en Browser:Camino-1.6 Engine:Gecko-20080409 Bot:false Mobile:false",
- expectedOS: &OSInfo{"Intel Mac OS X", "Mac OS X", ""},
- },
- {
- title: "Iceweasel",
- ua: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1) Gecko/20061024 Iceweasel/2.0 (Debian-2.0+dfsg-1)",
- expected: "Mozilla:5.0 Platform:X11 OS:Linux i686 Localization:en-US Browser:Iceweasel-2.0 Engine:Gecko-20061024 Bot:false Mobile:false",
- expectedOS: &OSInfo{"Linux i686", "Linux", ""},
- },
- {
- title: "SeaMonkey",
- ua: "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.1.4) Gecko/20091017 SeaMonkey/2.0",
- expected: "Mozilla:5.0 Platform:Macintosh OS:Intel Mac OS X 10.6 Localization:en-US Browser:SeaMonkey-2.0 Engine:Gecko-20091017 Bot:false Mobile:false",
- },
- {
- title: "AndroidFirefox",
- ua: "Mozilla/5.0 (Android; Mobile; rv:17.0) Gecko/17.0 Firefox/17.0",
- expected: "Mozilla:5.0 Platform:Mobile OS:Android Browser:Firefox-17.0 Engine:Gecko-17.0 Bot:false Mobile:true",
- },
- {
- title: "AndroidFirefoxTablet",
- ua: "Mozilla/5.0 (Android; Tablet; rv:26.0) Gecko/26.0 Firefox/26.0",
- expected: "Mozilla:5.0 Platform:Tablet OS:Android Browser:Firefox-26.0 Engine:Gecko-26.0 Bot:false Mobile:true",
- expectedOS: &OSInfo{"Android", "Android", ""},
- },
- {
- title: "FirefoxOS",
- ua: "Mozilla/5.0 (Mobile; rv:26.0) Gecko/26.0 Firefox/26.0",
- expected: "Mozilla:5.0 Platform:Mobile OS:FirefoxOS Browser:Firefox-26.0 Engine:Gecko-26.0 Bot:false Mobile:true",
- expectedOS: &OSInfo{"FirefoxOS", "FirefoxOS", ""},
- },
- {
- title: "FirefoxOSTablet",
- ua: "Mozilla/5.0 (Tablet; rv:26.0) Gecko/26.0 Firefox/26.0",
- expected: "Mozilla:5.0 Platform:Tablet OS:FirefoxOS Browser:Firefox-26.0 Engine:Gecko-26.0 Bot:false Mobile:true",
- },
- {
- title: "FirefoxWinXP",
- ua: "Mozilla/5.0 (Windows NT 5.2; rv:31.0) Gecko/20100101 Firefox/31.0",
- expected: "Mozilla:5.0 Platform:Windows OS:Windows XP x64 Edition Browser:Firefox-31.0 Engine:Gecko-20100101 Bot:false Mobile:false",
- expectedOS: &OSInfo{"Windows XP x64 Edition", "Windows", "XP"},
- },
- {
- title: "FirefoxMRA",
- ua: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:24.0) Gecko/20130405 MRA 5.5 (build 02842) Firefox/24.0 (.NET CLR 3.5.30729)",
- expected: "Mozilla:5.0 Platform:Windows OS:Windows XP Localization:en-US Browser:Firefox-24.0 Engine:Gecko-20130405 Bot:false Mobile:false",
- },
-
- // Opera
- {
- title: "OperaMac",
- ua: "Opera/9.27 (Macintosh; Intel Mac OS X; U; en)",
- expected: "Platform:Macintosh OS:Intel Mac OS X Localization:en Browser:Opera-9.27 Engine:Presto Bot:false Mobile:false",
- expectedOS: &OSInfo{"Intel Mac OS X", "Mac OS X", ""},
- },
- {
- title: "OperaWin",
- ua: "Opera/9.27 (Windows NT 5.1; U; en)",
- expected: "Platform:Windows OS:Windows XP Localization:en Browser:Opera-9.27 Engine:Presto Bot:false Mobile:false",
- },
- {
- title: "OperaWinNoLocale",
- ua: "Opera/9.80 (Windows NT 5.1) Presto/2.12.388 Version/12.10",
- expected: "Platform:Windows OS:Windows XP Browser:Opera-9.80 Engine:Presto-2.12.388 Bot:false Mobile:false",
- },
- {
- title: "OperaWin2Comment",
- ua: "Opera/9.80 (Windows NT 6.0; WOW64) Presto/2.12.388 Version/12.15",
- expected: "Platform:Windows OS:Windows Vista Browser:Opera-9.80 Engine:Presto-2.12.388 Bot:false Mobile:false",
- expectedOS: &OSInfo{"Windows Vista", "Windows", "Vista"},
- },
- {
- title: "OperaMinimal",
- ua: "Opera/9.80",
- expected: "Browser:Opera-9.80 Engine:Presto Bot:false Mobile:false",
- },
- {
- title: "OperaFull",
- ua: "Opera/9.80 (Windows NT 6.0; U; en) Presto/2.2.15 Version/10.10",
- expected: "Platform:Windows OS:Windows Vista Localization:en Browser:Opera-9.80 Engine:Presto-2.2.15 Bot:false Mobile:false",
- },
- {
- title: "OperaLinux",
- ua: "Opera/9.80 (X11; Linux x86_64) Presto/2.12.388 Version/12.10",
- expected: "Platform:X11 OS:Linux x86_64 Browser:Opera-9.80 Engine:Presto-2.12.388 Bot:false Mobile:false",
- },
- {
- title: "OperaLinux - Ubuntu V41",
- ua: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36 OPR/41.0.2353.69",
- expected: "Mozilla:5.0 Platform:X11 OS:Linux x86_64 Browser:Opera-41.0.2353.69 Engine:AppleWebKit-537.36 Bot:false Mobile:false",
- expectedOS: &OSInfo{"Linux x86_64", "Linux", ""},
- },
- {
- title: "OperaAndroid",
- ua: "Opera/9.80 (Android 4.2.1; Linux; Opera Mobi/ADR-1212030829) Presto/2.11.355 Version/12.10",
- expected: "Platform:Android 4.2.1 OS:Linux Browser:Opera-9.80 Engine:Presto-2.11.355 Bot:false Mobile:true",
- expectedOS: &OSInfo{"Linux", "Linux", ""},
- },
- {
- title: "OperaNested",
- ua: "Opera/9.80 (Windows NT 5.1; MRA 6.0 (build 5831)) Presto/2.12.388 Version/12.10",
- expected: "Platform:Windows OS:Windows XP Browser:Opera-9.80 Engine:Presto-2.12.388 Bot:false Mobile:false",
- },
- {
- title: "OperaMRA",
- ua: "Opera/9.80 (Windows NT 6.1; U; MRA 5.8 (build 4139); en) Presto/2.9.168 Version/11.50",
- expected: "Platform:Windows OS:Windows 7 Localization:en Browser:Opera-9.80 Engine:Presto-2.9.168 Bot:false Mobile:false",
- },
-
- // Other
- {
- title: "Empty",
- ua: "",
- expected: "Bot:false Mobile:false",
- },
- {
- title: "Nil",
- ua: "nil",
- expected: "Browser:nil Bot:false Mobile:false",
- },
- {
- title: "Compatible",
- ua: "Mozilla/4.0 (compatible)",
- expected: "Browser:Mozilla-4.0 Bot:false Mobile:false",
- },
- {
- title: "Mozilla",
- ua: "Mozilla/5.0",
- expected: "Browser:Mozilla-5.0 Bot:false Mobile:false",
- },
- {
- title: "Amaya",
- ua: "amaya/9.51 libwww/5.4.0",
- expected: "Browser:amaya-9.51 Engine:libwww-5.4.0 Bot:false Mobile:false",
- },
- {
- title: "Rails",
- ua: "Rails Testing",
- expected: "Browser:Rails Engine:Testing Bot:false Mobile:false",
- },
- {
- title: "Python",
- ua: "Python-urllib/2.7",
- expected: "Browser:Python-urllib-2.7 Bot:false Mobile:false",
- },
- {
- title: "Curl",
- ua: "curl/7.28.1",
- expected: "Browser:curl-7.28.1 Bot:false Mobile:false",
- },
-
- // WebKit
- {
- title: "ChromeLinux",
- ua: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.97 Safari/537.11",
- expected: "Mozilla:5.0 Platform:X11 OS:Linux x86_64 Browser:Chrome-23.0.1271.97 Engine:AppleWebKit-537.11 Bot:false Mobile:false",
- expectedOS: &OSInfo{"Linux x86_64", "Linux", ""},
- },
- {
- title: "ChromeLinux - Ubuntu V55",
- ua: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36",
- expected: "Mozilla:5.0 Platform:X11 OS:Linux x86_64 Browser:Chrome-55.0.2883.75 Engine:AppleWebKit-537.36 Bot:false Mobile:false",
- },
- {
- title: "ChromeWin7",
- ua: "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.168 Safari/535.19",
- expected: "Mozilla:5.0 Platform:Windows OS:Windows 7 Browser:Chrome-18.0.1025.168 Engine:AppleWebKit-535.19 Bot:false Mobile:false",
- },
- {
- title: "ChromeMinimal",
- ua: "Mozilla/5.0 AppleWebKit/534.10 Chrome/8.0.552.215 Safari/534.10",
- expected: "Mozilla:5.0 Browser:Chrome-8.0.552.215 Engine:AppleWebKit-534.10 Bot:false Mobile:false",
- },
- {
- title: "ChromeMac",
- ua: "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.231 Safari/534.10",
- expected: "Mozilla:5.0 Platform:Macintosh OS:Intel Mac OS X 10_6_5 Localization:en-US Browser:Chrome-8.0.552.231 Engine:AppleWebKit-534.10 Bot:false Mobile:false",
- expectedOS: &OSInfo{"Intel Mac OS X 10_6_5", "Mac OS X", "10.6.5"},
- },
- {
- title: "SafariMac",
- ua: "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16",
- expected: "Mozilla:5.0 Platform:Macintosh OS:Intel Mac OS X 10_6_3 Localization:en-us Browser:Safari-5.0 Engine:AppleWebKit-533.16 Bot:false Mobile:false",
- },
- {
- title: "SafariWin",
- ua: "Mozilla/5.0 (Windows; U; Windows NT 5.1; en) AppleWebKit/526.9 (KHTML, like Gecko) Version/4.0dp1 Safari/526.8",
- expected: "Mozilla:5.0 Platform:Windows OS:Windows XP Localization:en Browser:Safari-4.0dp1 Engine:AppleWebKit-526.9 Bot:false Mobile:false",
- },
- {
- title: "iPhone7",
- ua: "Mozilla/5.0 (iPhone; CPU iPhone OS 7_0_3 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11B511 Safari/9537.53",
- expected: "Mozilla:5.0 Platform:iPhone OS:CPU iPhone OS 7_0_3 like Mac OS X Browser:Safari-7.0 Engine:AppleWebKit-537.51.1 Bot:false Mobile:true",
- expectedOS: &OSInfo{"CPU iPhone OS 7_0_3 like Mac OS X", "iPhone OS", "7.0.3"},
- },
- {
- title: "iPhone",
- ua: "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/4A102 Safari/419",
- expected: "Mozilla:5.0 Platform:iPhone OS:CPU like Mac OS X Localization:en Browser:Safari-3.0 Engine:AppleWebKit-420.1 Bot:false Mobile:true",
- },
- {
- title: "iPod",
- ua: "Mozilla/5.0 (iPod; U; CPU like Mac OS X; en) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/4A102 Safari/419",
- expected: "Mozilla:5.0 Platform:iPod OS:CPU like Mac OS X Localization:en Browser:Safari-3.0 Engine:AppleWebKit-420.1 Bot:false Mobile:true",
- },
- {
- title: "iPad",
- ua: "Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B367 Safari/531.21.10",
- expected: "Mozilla:5.0 Platform:iPad OS:CPU OS 3_2 like Mac OS X Localization:en-us Browser:Safari-4.0.4 Engine:AppleWebKit-531.21.10 Bot:false Mobile:true",
- },
- {
- title: "webOS",
- ua: "Mozilla/5.0 (webOS/1.4.0; U; en-US) AppleWebKit/532.2 (KHTML, like Gecko) Version/1.0 Safari/532.2 Pre/1.1",
- expected: "Mozilla:5.0 Platform:webOS OS:Palm Localization:en-US Browser:webOS-1.0 Engine:AppleWebKit-532.2 Bot:false Mobile:true",
- },
- {
- title: "Android",
- ua: "Mozilla/5.0 (Linux; U; Android 1.5; de-; HTC Magic Build/PLAT-RC33) AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1",
- expected: "Mozilla:5.0 Platform:Linux OS:Android 1.5 Localization:de- Browser:Android-3.1.2 Engine:AppleWebKit-528.5+ Bot:false Mobile:true",
- },
- {
- title: "BlackBerry",
- ua: "Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; en) AppleWebKit/534.1+ (KHTML, Like Gecko) Version/6.0.0.141 Mobile Safari/534.1+",
- expected: "Mozilla:5.0 Platform:BlackBerry OS:BlackBerry 9800 Localization:en Browser:BlackBerry-6.0.0.141 Engine:AppleWebKit-534.1+ Bot:false Mobile:true",
- expectedOS: &OSInfo{"BlackBerry 9800", "BlackBerry", "9800"},
- },
- {
- title: "BB10",
- ua: "Mozilla/5.0 (BB10; Touch) AppleWebKit/537.3+ (KHTML, like Gecko) Version/10.0.9.388 Mobile Safari/537.3+",
- expected: "Mozilla:5.0 Platform:BlackBerry OS:BlackBerry Browser:BlackBerry-10.0.9.388 Engine:AppleWebKit-537.3+ Bot:false Mobile:true",
- },
- {
- title: "Ericsson",
- ua: "Mozilla/5.0 (SymbianOS/9.4; U; Series60/5.0 Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebKit/525 (KHTML, like Gecko) Version/3.0 Safari/525",
- expected: "Mozilla:5.0 Platform:Symbian OS:SymbianOS/9.4 Browser:Symbian-3.0 Engine:AppleWebKit-525 Bot:false Mobile:true",
- expectedOS: &OSInfo{"SymbianOS/9.4", "SymbianOS", "9.4"},
- },
- {
- title: "ChromeAndroid",
- ua: "Mozilla/5.0 (Linux; Android 4.2.1; Galaxy Nexus Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19",
- expected: "Mozilla:5.0 Platform:Linux OS:Android 4.2.1 Browser:Chrome-18.0.1025.166 Engine:AppleWebKit-535.19 Bot:false Mobile:true",
- },
- {
- title: "WebkitNoPlatform",
- ua: "Mozilla/5.0 (en-us) AppleWebKit/525.13 (KHTML, like Gecko; Google Web Preview) Version/3.1 Safari/525.13",
- expected: "Mozilla:5.0 Platform:en-us Localization:en-us Browser:Safari-3.1 Engine:AppleWebKit-525.13 Bot:false Mobile:false",
- },
- {
- title: "OperaWebkitMobile",
- ua: "Mozilla/5.0 (Linux; Android 4.2.2; Galaxy Nexus Build/JDQ39) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.58 Mobile Safari/537.31 OPR/14.0.1074.57453",
- expected: "Mozilla:5.0 Platform:Linux OS:Android 4.2.2 Browser:Opera-14.0.1074.57453 Engine:AppleWebKit-537.31 Bot:false Mobile:true",
- },
- {
- title: "OperaWebkitDesktop",
- ua: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.58 Safari/537.31 OPR/14.0.1074.57453",
- expected: "Mozilla:5.0 Platform:X11 OS:Linux x86_64 Browser:Opera-14.0.1074.57453 Engine:AppleWebKit-537.31 Bot:false Mobile:false",
- },
- {
- title: "ChromeNothingAfterU",
- ua: "Mozilla/5.0 (Linux; U) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.79 Safari/537.4",
- expected: "Mozilla:5.0 Platform:Linux OS:Linux Browser:Chrome-22.0.1229.79 Engine:AppleWebKit-537.4 Bot:false Mobile:false",
- },
- {
- title: "SafariOnSymbian",
- ua: "Mozilla/5.0 (SymbianOS/9.1; U; [en-us]) AppleWebKit/413 (KHTML, like Gecko) Safari/413",
- expected: "Mozilla:5.0 Platform:Symbian OS:SymbianOS/9.1 Browser:Symbian-413 Engine:AppleWebKit-413 Bot:false Mobile:true",
- },
- {
- title: "Chromium - Ubuntu V49",
- ua: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/49.0.2623.108 Chrome/49.0.2623.108 Safari/537.36",
- expected: "Mozilla:5.0 Platform:X11 OS:Linux x86_64 Browser:Chromium-49.0.2623.108 Engine:AppleWebKit-537.36 Bot:false Mobile:false",
- },
- {
- title: "Chromium - Ubuntu V55",
- ua: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/53.0.2785.143 Chrome/53.0.2785.143 Safari/537.36",
- expected: "Mozilla:5.0 Platform:X11 OS:Linux x86_64 Browser:Chromium-53.0.2785.143 Engine:AppleWebKit-537.36 Bot:false Mobile:false",
- },
-
- // Dalvik
- {
- title: "Dalvik - Dell:001DL",
- ua: "Dalvik/1.2.0 (Linux; U; Android 2.2.2; 001DL Build/FRG83G)",
- expected: "Mozilla:5.0 Platform:Linux OS:Android 2.2.2 Bot:false Mobile:true",
- },
- {
- title: "Dalvik - HTC:001HT",
- ua: "Dalvik/1.4.0 (Linux; U; Android 2.3.3; 001HT Build/GRI40)",
- expected: "Mozilla:5.0 Platform:Linux OS:Android 2.3.3 Bot:false Mobile:true",
- },
- {
- title: "Dalvik - ZTE:009Z",
- ua: "Dalvik/1.4.0 (Linux; U; Android 2.3.4; 009Z Build/GINGERBREAD)",
- expected: "Mozilla:5.0 Platform:Linux OS:Android 2.3.4 Bot:false Mobile:true",
- },
- {
- title: "Dalvik - A850",
- ua: "Dalvik/1.6.0 (Linux; U; Android 4.2.2; A850 Build/JDQ39) Configuration/CLDC-1.1; Opera Mini/att/4.2",
- expected: "Mozilla:5.0 Platform:Linux OS:Android 4.2.2 Bot:false Mobile:true",
- },
- {
- title: "Dalvik - Asus:T00Q",
- ua: "Dalvik/1.6.0 (Linux; U; Android 4.4.2; ASUS_T00Q Build/KVT49L)/CLDC-1.1",
- expected: "Mozilla:5.0 Platform:Linux OS:Android 4.4.2 Bot:false Mobile:true",
- expectedOS: &OSInfo{"Android 4.4.2", "Android", "4.4.2"},
- },
- {
- title: "Dalvik - W2430",
- ua: "Dalvik/1.6.0 (Linux; U; Android 4.0.4; W2430 Build/IMM76D)014; Profile/MIDP-2.1 Configuration/CLDC-1",
- expected: "Mozilla:5.0 Platform:Linux OS:Android 4.0.4 Bot:false Mobile:true",
- },
-}
-
-// Internal: beautify the UserAgent reference into a string so it can be
-// tested later on.
-//
-// ua - a UserAgent reference.
-//
-// Returns a string that contains the beautified representation.
-func beautify(ua *UserAgent) (s string) {
- if len(ua.Mozilla()) > 0 {
- s += "Mozilla:" + ua.Mozilla() + " "
- }
- if len(ua.Platform()) > 0 {
- s += "Platform:" + ua.Platform() + " "
- }
- if len(ua.OS()) > 0 {
- s += "OS:" + ua.OS() + " "
- }
- if len(ua.Localization()) > 0 {
- s += "Localization:" + ua.Localization() + " "
- }
- str1, str2 := ua.Browser()
- if len(str1) > 0 {
- s += "Browser:" + str1
- if len(str2) > 0 {
- s += "-" + str2 + " "
- } else {
- s += " "
- }
- }
- str1, str2 = ua.Engine()
- if len(str1) > 0 {
- s += "Engine:" + str1
- if len(str2) > 0 {
- s += "-" + str2 + " "
- } else {
- s += " "
- }
- }
- s += "Bot:" + fmt.Sprintf("%v", ua.Bot()) + " "
- s += "Mobile:" + fmt.Sprintf("%v", ua.Mobile())
- return s
-}
-
-// The test suite.
-func TestUserAgent(t *testing.T) {
- for _, tt := range uastrings {
- ua := New(tt.ua)
- got := beautify(ua)
- if tt.expected != got {
- t.Errorf("\nTest %v\ngot: %q\nexpected %q\n", tt.title, got, tt.expected)
- }
-
- if tt.expectedOS != nil {
- gotOSInfo := ua.OSInfo()
- if !reflect.DeepEqual(tt.expectedOS, &gotOSInfo) {
- t.Errorf("\nTest %v\ngot: %#v\nexpected %#v\n", tt.title, gotOSInfo, tt.expectedOS)
- }
- }
- }
-}
-
-// Benchmark: it parses each User-Agent string on the uastrings slice b.N times.
-func BenchmarkUserAgent(b *testing.B) {
- for i := 0; i < b.N; i++ {
- b.StopTimer()
- for _, tt := range uastrings {
- ua := new(UserAgent)
- b.StartTimer()
- ua.Parse(tt.ua)
- }
- }
-}
diff --git a/vendor/github.com/mssola/user_agent/bot.go b/vendor/github.com/mssola/user_agent/bot.go
deleted file mode 100644
index acccd51d6..000000000
--- a/vendor/github.com/mssola/user_agent/bot.go
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright (C) 2014-2018 Miquel Sabaté Solà <mikisabate@gmail.com>
-// This file is licensed under the MIT license.
-// See the LICENSE file.
-
-package user_agent
-
-import (
- "regexp"
- "strings"
-)
-
-var botFromSiteRegexp = regexp.MustCompile("http://.+\\.\\w+")
-
-// Get the name of the bot from the website that may be in the given comment. If
-// there is no website in the comment, then an empty string is returned.
-func getFromSite(comment []string) string {
- if len(comment) == 0 {
- return ""
- }
-
- // Where we should check the website.
- idx := 2
- if len(comment) < 3 {
- idx = 0
- }
-
- // Pick the site.
- results := botFromSiteRegexp.FindStringSubmatch(comment[idx])
- if len(results) == 1 {
- // If it's a simple comment, just return the name of the site.
- if idx == 0 {
- return results[0]
- }
-
- // This is a large comment, usually the name will be in the previous
- // field of the comment.
- return strings.TrimSpace(comment[1])
- }
- return ""
-}
-
-// Returns true if the info that we currently have corresponds to the Google
-// mobile bot. This function also modifies some attributes in the receiver
-// accordingly.
-func (p *UserAgent) googleBot() bool {
- // This is a hackish way to detect Google's mobile bot.
- if strings.Index(p.ua, "Googlebot") != -1 {
- p.platform = ""
- p.undecided = true
- }
- return p.undecided
-}
-
-// Set the attributes of the receiver as given by the parameters. All the other
-// parameters are set to empty.
-func (p *UserAgent) setSimple(name, version string, bot bool) {
- p.bot = bot
- if !bot {
- p.mozilla = ""
- }
- p.browser.Name = name
- p.browser.Version = version
- p.browser.Engine = ""
- p.browser.EngineVersion = ""
- p.os = ""
- p.localization = ""
-}
-
-// Fix some values for some weird browsers.
-func (p *UserAgent) fixOther(sections []section) {
- if len(sections) > 0 {
- p.browser.Name = sections[0].name
- p.browser.Version = sections[0].version
- p.mozilla = ""
- }
-}
-
-var botRegex = regexp.MustCompile("(?i)(bot|crawler|sp(i|y)der|search|worm|fetch|nutch)")
-
-// Check if we're dealing with a bot or with some weird browser. If that is the
-// case, the receiver will be modified accordingly.
-func (p *UserAgent) checkBot(sections []section) {
- // If there's only one element, and it's doesn't have the Mozilla string,
- // check whether this is a bot or not.
- if len(sections) == 1 && sections[0].name != "Mozilla" {
- p.mozilla = ""
-
- // Check whether the name has some suspicious "bot" or "crawler" in his name.
- if botRegex.Match([]byte(sections[0].name)) {
- p.setSimple(sections[0].name, "", true)
- return
- }
-
- // Tough luck, let's try to see if it has a website in his comment.
- if name := getFromSite(sections[0].comment); name != "" {
- // First of all, this is a bot. Moreover, since it doesn't have the
- // Mozilla string, we can assume that the name and the version are
- // the ones from the first section.
- p.setSimple(sections[0].name, sections[0].version, true)
- return
- }
-
- // At this point we are sure that this is not a bot, but some weirdo.
- p.setSimple(sections[0].name, sections[0].version, false)
- } else {
- // Let's iterate over the available comments and check for a website.
- for _, v := range sections {
- if name := getFromSite(v.comment); name != "" {
- // Ok, we've got a bot name.
- results := strings.SplitN(name, "/", 2)
- version := ""
- if len(results) == 2 {
- version = results[1]
- }
- p.setSimple(results[0], version, true)
- return
- }
- }
-
- // We will assume that this is some other weird browser.
- p.fixOther(sections)
- }
-}
diff --git a/vendor/github.com/mssola/user_agent/browser.go b/vendor/github.com/mssola/user_agent/browser.go
deleted file mode 100644
index c6a1d2469..000000000
--- a/vendor/github.com/mssola/user_agent/browser.go
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright (C) 2012-2018 Miquel Sabaté Solà <mikisabate@gmail.com>
-// This file is licensed under the MIT license.
-// See the LICENSE file.
-
-package user_agent
-
-import (
- "regexp"
- "strings"
-)
-
-var ie11Regexp = regexp.MustCompile("^rv:(.+)$")
-
-// A struct containing all the information that we might be
-// interested from the browser.
-type Browser struct {
- // The name of the browser's engine.
- Engine string
-
- // The version of the browser's engine.
- EngineVersion string
-
- // The name of the browser.
- Name string
-
- // The version of the browser.
- Version string
-}
-
-// Extract all the information that we can get from the User-Agent string
-// about the browser and update the receiver with this information.
-//
-// The function receives just one argument "sections", that contains the
-// sections from the User-Agent string after being parsed.
-func (p *UserAgent) detectBrowser(sections []section) {
- slen := len(sections)
-
- if sections[0].name == "Opera" {
- p.browser.Name = "Opera"
- p.browser.Version = sections[0].version
- p.browser.Engine = "Presto"
- if slen > 1 {
- p.browser.EngineVersion = sections[1].version
- }
- } else if sections[0].name == "Dalvik" {
- // When Dalvik VM is in use, there is no browser info attached to ua.
- // Although browser is still a Mozilla/5.0 compatible.
- p.mozilla = "5.0"
- } else if slen > 1 {
- engine := sections[1]
- p.browser.Engine = engine.name
- p.browser.EngineVersion = engine.version
- if slen > 2 {
- sectionIndex := 2
- // The version after the engine comment is empty on e.g. Ubuntu
- // platforms so if this is the case, let's use the next in line.
- if sections[2].version == "" && slen > 3 {
- sectionIndex = 3
- }
- p.browser.Version = sections[sectionIndex].version
- if engine.name == "AppleWebKit" {
- switch sections[slen-1].name {
- case "Edge":
- p.browser.Name = "Edge"
- p.browser.Version = sections[slen-1].version
- p.browser.Engine = "EdgeHTML"
- p.browser.EngineVersion = ""
- case "OPR":
- p.browser.Name = "Opera"
- p.browser.Version = sections[slen-1].version
- default:
- if sections[sectionIndex].name == "Chrome" {
- p.browser.Name = "Chrome"
- } else if sections[sectionIndex].name == "Chromium" {
- p.browser.Name = "Chromium"
- } else {
- p.browser.Name = "Safari"
- }
- }
- } else if engine.name == "Gecko" {
- name := sections[2].name
- if name == "MRA" && slen > 4 {
- name = sections[4].name
- p.browser.Version = sections[4].version
- }
- p.browser.Name = name
- } else if engine.name == "like" && sections[2].name == "Gecko" {
- // This is the new user agent from Internet Explorer 11.
- p.browser.Engine = "Trident"
- p.browser.Name = "Internet Explorer"
- for _, c := range sections[0].comment {
- version := ie11Regexp.FindStringSubmatch(c)
- if len(version) > 0 {
- p.browser.Version = version[1]
- return
- }
- }
- p.browser.Version = ""
- }
- }
- } else if slen == 1 && len(sections[0].comment) > 1 {
- comment := sections[0].comment
- if comment[0] == "compatible" && strings.HasPrefix(comment[1], "MSIE") {
- p.browser.Engine = "Trident"
- p.browser.Name = "Internet Explorer"
- // The MSIE version may be reported as the compatibility version.
- // For IE 8 through 10, the Trident token is more accurate.
- // http://msdn.microsoft.com/en-us/library/ie/ms537503(v=vs.85).aspx#VerToken
- for _, v := range comment {
- if strings.HasPrefix(v, "Trident/") {
- switch v[8:] {
- case "4.0":
- p.browser.Version = "8.0"
- case "5.0":
- p.browser.Version = "9.0"
- case "6.0":
- p.browser.Version = "10.0"
- }
- break
- }
- }
- // If the Trident token is not provided, fall back to MSIE token.
- if p.browser.Version == "" {
- p.browser.Version = strings.TrimSpace(comment[1][4:])
- }
- }
- }
-}
-
-// Returns two strings. The first string is the name of the engine and the
-// second one is the version of the engine.
-func (p *UserAgent) Engine() (string, string) {
- return p.browser.Engine, p.browser.EngineVersion
-}
-
-// Returns two strings. The first string is the name of the browser and the
-// second one is the version of the browser.
-func (p *UserAgent) Browser() (string, string) {
- return p.browser.Name, p.browser.Version
-}
diff --git a/vendor/github.com/mssola/user_agent/operating_systems.go b/vendor/github.com/mssola/user_agent/operating_systems.go
deleted file mode 100644
index ad4d56680..000000000
--- a/vendor/github.com/mssola/user_agent/operating_systems.go
+++ /dev/null
@@ -1,359 +0,0 @@
-// Copyright (C) 2012-2018 Miquel Sabaté Solà <mikisabate@gmail.com>
-// This file is licensed under the MIT license.
-// See the LICENSE file.
-
-package user_agent
-
-import "strings"
-
-// Represents full information on the operating system extracted from the user agent.
-type OSInfo struct {
- // Full name of the operating system. This is identical to the output of ua.OS()
- FullName string
-
- // Name of the operating system. This is sometimes a shorter version of the
- // operating system name, e.g. "Mac OS X" instead of "Intel Mac OS X"
- Name string
-
- // Operating system version, e.g. 7 for Windows 7 or 10.8 for Max OS X Mountain Lion
- Version string
-}
-
-// Normalize the name of the operating system. By now, this just
-// affects to Windows NT.
-//
-// Returns a string containing the normalized name for the Operating System.
-func normalizeOS(name string) string {
- sp := strings.SplitN(name, " ", 3)
- if len(sp) != 3 || sp[1] != "NT" {
- return name
- }
-
- switch sp[2] {
- case "5.0":
- return "Windows 2000"
- case "5.01":
- return "Windows 2000, Service Pack 1 (SP1)"
- case "5.1":
- return "Windows XP"
- case "5.2":
- return "Windows XP x64 Edition"
- case "6.0":
- return "Windows Vista"
- case "6.1":
- return "Windows 7"
- case "6.2":
- return "Windows 8"
- case "6.3":
- return "Windows 8.1"
- case "10.0":
- return "Windows 10"
- }
- return name
-}
-
-// Guess the OS, the localization and if this is a mobile device for a
-// Webkit-powered browser.
-//
-// The first argument p is a reference to the current UserAgent and the second
-// argument is a slice of strings containing the comment.
-func webkit(p *UserAgent, comment []string) {
- if p.platform == "webOS" {
- p.browser.Name = p.platform
- p.os = "Palm"
- if len(comment) > 2 {
- p.localization = comment[2]
- }
- p.mobile = true
- } else if p.platform == "Symbian" {
- p.mobile = true
- p.browser.Name = p.platform
- p.os = comment[0]
- } else if p.platform == "Linux" {
- p.mobile = true
- if p.browser.Name == "Safari" {
- p.browser.Name = "Android"
- }
- if len(comment) > 1 {
- if comment[1] == "U" {
- if len(comment) > 2 {
- p.os = comment[2]
- } else {
- p.mobile = false
- p.os = comment[0]
- }
- } else {
- p.os = comment[1]
- }
- }
- if len(comment) > 3 {
- p.localization = comment[3]
- } else if len(comment) == 3 {
- _ = p.googleBot()
- }
- } else if len(comment) > 0 {
- if len(comment) > 3 {
- p.localization = comment[3]
- }
- if strings.HasPrefix(comment[0], "Windows NT") {
- p.os = normalizeOS(comment[0])
- } else if len(comment) < 2 {
- p.localization = comment[0]
- } else if len(comment) < 3 {
- if !p.googleBot() {
- p.os = normalizeOS(comment[1])
- }
- } else {
- p.os = normalizeOS(comment[2])
- }
- if p.platform == "BlackBerry" {
- p.browser.Name = p.platform
- if p.os == "Touch" {
- p.os = p.platform
- }
- }
- }
-}
-
-// Guess the OS, the localization and if this is a mobile device
-// for a Gecko-powered browser.
-//
-// The first argument p is a reference to the current UserAgent and the second
-// argument is a slice of strings containing the comment.
-func gecko(p *UserAgent, comment []string) {
- if len(comment) > 1 {
- if comment[1] == "U" {
- if len(comment) > 2 {
- p.os = normalizeOS(comment[2])
- } else {
- p.os = normalizeOS(comment[1])
- }
- } else {
- if p.platform == "Android" {
- p.mobile = true
- p.platform, p.os = normalizeOS(comment[1]), p.platform
- } else if comment[0] == "Mobile" || comment[0] == "Tablet" {
- p.mobile = true
- p.os = "FirefoxOS"
- } else {
- if p.os == "" {
- p.os = normalizeOS(comment[1])
- }
- }
- }
- // Only parse 4th comment as localization if it doesn't start with rv:.
- // For example Firefox on Ubuntu contains "rv:XX.X" in this field.
- if len(comment) > 3 && !strings.HasPrefix(comment[3], "rv:") {
- p.localization = comment[3]
- }
- }
-}
-
-// Guess the OS, the localization and if this is a mobile device
-// for Internet Explorer.
-//
-// The first argument p is a reference to the current UserAgent and the second
-// argument is a slice of strings containing the comment.
-func trident(p *UserAgent, comment []string) {
- // Internet Explorer only runs on Windows.
- p.platform = "Windows"
-
- // The OS can be set before to handle a new case in IE11.
- if p.os == "" {
- if len(comment) > 2 {
- p.os = normalizeOS(comment[2])
- } else {
- p.os = "Windows NT 4.0"
- }
- }
-
- // Last but not least, let's detect if it comes from a mobile device.
- for _, v := range comment {
- if strings.HasPrefix(v, "IEMobile") {
- p.mobile = true
- return
- }
- }
-}
-
-// Guess the OS, the localization and if this is a mobile device
-// for Opera.
-//
-// The first argument p is a reference to the current UserAgent and the second
-// argument is a slice of strings containing the comment.
-func opera(p *UserAgent, comment []string) {
- slen := len(comment)
-
- if strings.HasPrefix(comment[0], "Windows") {
- p.platform = "Windows"
- p.os = normalizeOS(comment[0])
- if slen > 2 {
- if slen > 3 && strings.HasPrefix(comment[2], "MRA") {
- p.localization = comment[3]
- } else {
- p.localization = comment[2]
- }
- }
- } else {
- if strings.HasPrefix(comment[0], "Android") {
- p.mobile = true
- }
- p.platform = comment[0]
- if slen > 1 {
- p.os = comment[1]
- if slen > 3 {
- p.localization = comment[3]
- }
- } else {
- p.os = comment[0]
- }
- }
-}
-
-// Guess the OS. Android browsers send Dalvik as the user agent in the
-// request header.
-//
-// The first argument p is a reference to the current UserAgent and the second
-// argument is a slice of strings containing the comment.
-func dalvik(p *UserAgent, comment []string) {
- slen := len(comment)
-
- if strings.HasPrefix(comment[0], "Linux") {
- p.platform = comment[0]
- if slen > 2 {
- p.os = comment[2]
- }
- p.mobile = true
- }
-}
-
-// Given the comment of the first section of the UserAgent string,
-// get the platform.
-func getPlatform(comment []string) string {
- if len(comment) > 0 {
- if comment[0] != "compatible" {
- if strings.HasPrefix(comment[0], "Windows") {
- return "Windows"
- } else if strings.HasPrefix(comment[0], "Symbian") {
- return "Symbian"
- } else if strings.HasPrefix(comment[0], "webOS") {
- return "webOS"
- } else if comment[0] == "BB10" {
- return "BlackBerry"
- }
- return comment[0]
- }
- }
- return ""
-}
-
-// Detect some properties of the OS from the given section.
-func (p *UserAgent) detectOS(s section) {
- if s.name == "Mozilla" {
- // Get the platform here. Be aware that IE11 provides a new format
- // that is not backwards-compatible with previous versions of IE.
- p.platform = getPlatform(s.comment)
- if p.platform == "Windows" && len(s.comment) > 0 {
- p.os = normalizeOS(s.comment[0])
- }
-
- // And finally get the OS depending on the engine.
- switch p.browser.Engine {
- case "":
- p.undecided = true
- case "Gecko":
- gecko(p, s.comment)
- case "AppleWebKit":
- webkit(p, s.comment)
- case "Trident":
- trident(p, s.comment)
- }
- } else if s.name == "Opera" {
- if len(s.comment) > 0 {
- opera(p, s.comment)
- }
- } else if s.name == "Dalvik" {
- if len(s.comment) > 0 {
- dalvik(p, s.comment)
- }
- } else {
- // Check whether this is a bot or just a weird browser.
- p.undecided = true
- }
-}
-
-// Returns a string containing the platform..
-func (p *UserAgent) Platform() string {
- return p.platform
-}
-
-// Returns a string containing the name of the Operating System.
-func (p *UserAgent) OS() string {
- return p.os
-}
-
-// Returns a string containing the localization.
-func (p *UserAgent) Localization() string {
- return p.localization
-}
-
-// Return OS name and version from a slice of strings created from the full name of the OS.
-func osName(osSplit []string) (name, version string) {
- if len(osSplit) == 1 {
- name = osSplit[0]
- version = ""
- } else {
- // Assume version is stored in the last part of the array.
- nameSplit := osSplit[:len(osSplit)-1]
- version = osSplit[len(osSplit)-1]
-
- // Nicer looking Mac OS X
- if len(nameSplit) >= 2 && nameSplit[0] == "Intel" && nameSplit[1] == "Mac" {
- nameSplit = nameSplit[1:]
- }
- name = strings.Join(nameSplit, " ")
-
- if strings.Contains(version, "x86") || strings.Contains(version, "i686") {
- // x86_64 and i868 are not Linux versions but architectures
- version = ""
- } else if version == "X" && name == "Mac OS" {
- // X is not a version for Mac OS.
- name = name + " " + version
- version = ""
- }
- }
- return name, version
-}
-
-// Returns combined information for the operating system.
-func (p *UserAgent) OSInfo() OSInfo {
- // Special case for iPhone weirdness
- os := strings.Replace(p.os, "like Mac OS X", "", 1)
- os = strings.Replace(os, "CPU", "", 1)
- os = strings.Trim(os, " ")
-
- osSplit := strings.Split(os, " ")
-
- // Special case for x64 edition of Windows
- if os == "Windows XP x64 Edition" {
- osSplit = osSplit[:len(osSplit)-2]
- }
-
- name, version := osName(osSplit)
-
- // Special case for names that contain a forward slash version separator.
- if strings.Contains(name, "/") {
- s := strings.Split(name, "/")
- name = s[0]
- version = s[1]
- }
-
- // Special case for versions that use underscores
- version = strings.Replace(version, "_", ".", -1)
-
- return OSInfo{
- FullName: p.os,
- Name: name,
- Version: version,
- }
-}
diff --git a/vendor/github.com/mssola/user_agent/user_agent.go b/vendor/github.com/mssola/user_agent/user_agent.go
deleted file mode 100644
index 436e94980..000000000
--- a/vendor/github.com/mssola/user_agent/user_agent.go
+++ /dev/null
@@ -1,174 +0,0 @@
-// Copyright (C) 2012-2018 Miquel Sabaté Solà <mikisabate@gmail.com>
-// This file is licensed under the MIT license.
-// See the LICENSE file.
-
-// Package user_agent implements an HTTP User Agent string parser. It defines
-// the type UserAgent that contains all the information from the parsed string.
-// It also implements the Parse function and getters for all the relevant
-// information that has been extracted from a parsed User Agent string.
-package user_agent
-
-import "strings"
-
-// A section contains the name of the product, its version and
-// an optional comment.
-type section struct {
- name string
- version string
- comment []string
-}
-
-// The UserAgent struct contains all the info that can be extracted
-// from the User-Agent string.
-type UserAgent struct {
- ua string
- mozilla string
- platform string
- os string
- localization string
- browser Browser
- bot bool
- mobile bool
- undecided bool
-}
-
-// Read from the given string until the given delimiter or the
-// end of the string have been reached.
-//
-// The first argument is the user agent string being parsed. The second
-// argument is a reference pointing to the current index of the user agent
-// string. The delimiter argument specifies which character is the delimiter
-// and the cat argument determines whether nested '(' should be ignored or not.
-//
-// Returns an array of bytes containing what has been read.
-func readUntil(ua string, index *int, delimiter byte, cat bool) []byte {
- var buffer []byte
-
- i := *index
- catalan := 0
- for ; i < len(ua); i = i + 1 {
- if ua[i] == delimiter {
- if catalan == 0 {
- *index = i + 1
- return buffer
- }
- catalan--
- } else if cat && ua[i] == '(' {
- catalan++
- }
- buffer = append(buffer, ua[i])
- }
- *index = i + 1
- return buffer
-}
-
-// Parse the given product, that is, just a name or a string
-// formatted as Name/Version.
-//
-// It returns two strings. The first string is the name of the product and the
-// second string contains the version of the product.
-func parseProduct(product []byte) (string, string) {
- prod := strings.SplitN(string(product), "/", 2)
- if len(prod) == 2 {
- return prod[0], prod[1]
- }
- return string(product), ""
-}
-
-// Parse a section. A section is typically formatted as follows
-// "Name/Version (comment)". Both, the comment and the version are optional.
-//
-// The first argument is the user agent string being parsed. The second
-// argument is a reference pointing to the current index of the user agent
-// string.
-//
-// Returns a section containing the information that we could extract
-// from the last parsed section.
-func parseSection(ua string, index *int) (s section) {
- buffer := readUntil(ua, index, ' ', false)
-
- s.name, s.version = parseProduct(buffer)
- if *index < len(ua) && ua[*index] == '(' {
- *index++
- buffer = readUntil(ua, index, ')', true)
- s.comment = strings.Split(string(buffer), "; ")
- *index++
- }
- return s
-}
-
-// Initialize the parser.
-func (p *UserAgent) initialize() {
- p.ua = ""
- p.mozilla = ""
- p.platform = ""
- p.os = ""
- p.localization = ""
- p.browser.Engine = ""
- p.browser.EngineVersion = ""
- p.browser.Name = ""
- p.browser.Version = ""
- p.bot = false
- p.mobile = false
- p.undecided = false
-}
-
-// Parse the given User-Agent string and get the resulting UserAgent object.
-//
-// Returns an UserAgent object that has been initialized after parsing
-// the given User-Agent string.
-func New(ua string) *UserAgent {
- o := &UserAgent{}
- o.Parse(ua)
- return o
-}
-
-// Parse the given User-Agent string. After calling this function, the
-// receiver will be setted up with all the information that we've extracted.
-func (p *UserAgent) Parse(ua string) {
- var sections []section
-
- p.initialize()
- p.ua = ua
- for index, limit := 0, len(ua); index < limit; {
- s := parseSection(ua, &index)
- if !p.mobile && s.name == "Mobile" {
- p.mobile = true
- }
- sections = append(sections, s)
- }
-
- if len(sections) > 0 {
- if sections[0].name == "Mozilla" {
- p.mozilla = sections[0].version
- }
-
- p.detectBrowser(sections)
- p.detectOS(sections[0])
-
- if p.undecided {
- p.checkBot(sections)
- }
- }
-}
-
-// Returns the mozilla version (it's how the User Agent string begins:
-// "Mozilla/5.0 ...", unless we're dealing with Opera, of course).
-func (p *UserAgent) Mozilla() string {
- return p.mozilla
-}
-
-// Returns true if it's a bot, false otherwise.
-func (p *UserAgent) Bot() bool {
- return p.bot
-}
-
-// Returns true if it's a mobile device, false otherwise.
-func (p *UserAgent) Mobile() bool {
- return p.mobile
-}
-
-// Returns the original given user agent.
-func (p *UserAgent) UA() string {
- return p.ua
-}