vendor dependencies with dep

This commit is contained in:
dhax 2017-09-25 20:20:52 +02:00
parent 93d8310491
commit 1384296a47
2712 changed files with 965742 additions and 0 deletions

10
vendor/github.com/mssola/user_agent/.travis.yml generated vendored Normal file
View file

@ -0,0 +1,10 @@
language: go
go:
- 1.0
- 1.1
- 1.2
- 1.3
- tip
matrix:
allow_failures:
- go: tip

20
vendor/github.com/mssola/user_agent/LICENSE generated vendored Normal file
View file

@ -0,0 +1,20 @@
Copyright (c) 2012-2014 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.

51
vendor/github.com/mssola/user_agent/README.md generated vendored Normal file
View file

@ -0,0 +1,51 @@
# 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 © 2012-2014 Miquel Sabaté Solà, released under the MIT License.

257
vendor/github.com/mssola/user_agent/all_test.go generated vendored Normal file
View file

@ -0,0 +1,257 @@
// Copyright (C) 2012-2014 Miquel Sabaté Solà <mikisabate@gmail.com>
// This file is licensed under the MIT license.
// See the LICENSE file.
package user_agent
import (
"fmt"
"testing"
)
// Slice that contains all the tests. Each test is contained in a struct
// that groups the name of the test and the User-Agent string to be tested.
var uastrings = []struct {
name string
ua string
}{
// Bots
{"GoogleBot", "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"},
{"GoogleBotSmartphone", "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)"},
{"BingBot", "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"},
{"BaiduBot", "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)"},
{"Twitterbot", "Twitterbot"},
{"YahooBot", "Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)"},
{"FacebookExternalHit", "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)"},
{"FacebookPlatform", "facebookplatform/1.0 (+http://developers.facebook.com)"},
{"FaceBot", "Facebot"},
// Internet Explorer
{"IE10", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)"},
{"Tablet", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; ARM; Trident/6.0; Touch; .NET4.0E; .NET4.0C; Tablet PC 2.0)"},
{"Touch", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; ARM; Trident/6.0; Touch)"},
{"Phone", "Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0; SAMSUNG; SGH-i917)"},
{"IE6", "Mozilla/4.0 (compatible; MSIE6.0; Windows NT 5.0; .NET CLR 1.1.4322)"},
{"IE8Compatibility", "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)"},
{"IE10Compatibility", "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)"},
{"IE11Win81", "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko"},
{"IE11Win7", "Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko"},
{"IE11b32Win7b64", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"},
{"IE11b32Win7b64MDDRJS", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; MDDRJS; rv:11.0) like Gecko"},
{"IE11Compatibility", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; Trident/7.0)"},
// Gecko
{"FirefoxMac", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0b8) Gecko/20100101 Firefox/4.0b8"},
{"FirefoxMacLoc", "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13"},
{"FirefoxLinux", "Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20100101 Firefox/17.0"},
{"FirefoxWin", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14"},
{"Firefox29Win7", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0"},
{"CaminoMac", "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)"},
{"Iceweasel", "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1) Gecko/20061024 Iceweasel/2.0 (Debian-2.0+dfsg-1)"},
{"SeaMonkey", "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.1.4) Gecko/20091017 SeaMonkey/2.0"},
{"AndroidFirefox", "Mozilla/5.0 (Android; Mobile; rv:17.0) Gecko/17.0 Firefox/17.0"},
{"AndroidFirefoxTablet", "Mozilla/5.0 (Android; Tablet; rv:26.0) Gecko/26.0 Firefox/26.0"},
{"FirefoxOS", "Mozilla/5.0 (Mobile; rv:26.0) Gecko/26.0 Firefox/26.0"},
{"FirefoxOSTablet", "Mozilla/5.0 (Tablet; rv:26.0) Gecko/26.0 Firefox/26.0"},
{"FirefoxWinXP", "Mozilla/5.0 (Windows NT 5.2; rv:31.0) Gecko/20100101 Firefox/31.0"},
{"FirefoxMRA", "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)"},
// Opera
{"OperaMac", "Opera/9.27 (Macintosh; Intel Mac OS X; U; en)"},
{"OperaWin", "Opera/9.27 (Windows NT 5.1; U; en)"},
{"OperaWinNoLocale", "Opera/9.80 (Windows NT 5.1) Presto/2.12.388 Version/12.10"},
{"OperaWin2Comment", "Opera/9.80 (Windows NT 6.0; WOW64) Presto/2.12.388 Version/12.15"},
{"OperaMinimal", "Opera/9.80"},
{"OperaFull", "Opera/9.80 (Windows NT 6.0; U; en) Presto/2.2.15 Version/10.10"},
{"OperaLinux", "Opera/9.80 (X11; Linux x86_64) Presto/2.12.388 Version/12.10"},
{"OperaAndroid", "Opera/9.80 (Android 4.2.1; Linux; Opera Mobi/ADR-1212030829) Presto/2.11.355 Version/12.10"},
{"OperaNested", "Opera/9.80 (Windows NT 5.1; MRA 6.0 (build 5831)) Presto/2.12.388 Version/12.10"},
{"OperaMRA", "Opera/9.80 (Windows NT 6.1; U; MRA 5.8 (build 4139); en) Presto/2.9.168 Version/11.50"},
// Other
{"Empty", ""},
{"Nil", "nil"},
{"Compatible", "Mozilla/4.0 (compatible)"},
{"Mozilla", "Mozilla/5.0"},
{"Amaya", "amaya/9.51 libwww/5.4.0"},
{"Rails", "Rails Testing"},
{"Python", "Python-urllib/2.7"},
{"Curl", "curl/7.28.1"},
// WebKit
{"ChromeLinux", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.97 Safari/537.11"},
{"ChromeWin7", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.168 Safari/535.19"},
{"ChromeMinimal", "Mozilla/5.0 AppleWebKit/534.10 Chrome/8.0.552.215 Safari/534.10"},
{"ChromeMac", "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"},
{"SafariMac", "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"},
{"SafariWin", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en) AppleWebKit/526.9 (KHTML, like Gecko) Version/4.0dp1 Safari/526.8"},
{"iPhone7", "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"},
{"iPhone", "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/4A102 Safari/419"},
{"iPod", "Mozilla/5.0 (iPod; U; CPU like Mac OS X; en) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/4A102 Safari/419"},
{"iPad", "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"},
{"webOS", "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"},
{"Android", "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"},
{"BlackBerry", "Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; en) AppleWebKit/534.1+ (KHTML, Like Gecko) Version/6.0.0.141 Mobile Safari/534.1+"},
{"BB10", "Mozilla/5.0 (BB10; Touch) AppleWebKit/537.3+ (KHTML, like Gecko) Version/10.0.9.388 Mobile Safari/537.3+"},
{"Ericsson", "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"},
{"ChromeAndroid", "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"},
{"WebkitNoPlatform", "Mozilla/5.0 (en-us) AppleWebKit/525.13 (KHTML, like Gecko; Google Web Preview) Version/3.1 Safari/525.13"},
{"OperaWebkitMobile", "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"},
{"OperaWebkitDesktop", "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"},
{"ChromeNothingAfterU", "Mozilla/5.0 (Linux; U) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.79 Safari/537.4"},
{"SafariOnSymbian", "Mozilla/5.0 (SymbianOS/9.1; U; [en-us]) AppleWebKit/413 (KHTML, like Gecko) Safari/413"},
}
// Slice of the expected results from the previous slice.
var expected = []string{
// Bots
"Mozilla:5.0 Browser:Googlebot-2.1 Bot:true Mobile:false",
"Mozilla:5.0 Browser:Googlebot-2.1 Bot:true Mobile:true",
"Mozilla:5.0 Browser:bingbot-2.0 Bot:true Mobile:false",
"Mozilla:5.0 Browser:Baiduspider-2.0 Bot:true Mobile:false",
"Browser:Twitterbot Bot:true Mobile:false",
"Mozilla:5.0 Browser:Yahoo! Slurp Bot:true Mobile:false",
"Browser:facebookexternalhit-1.1 Bot:true Mobile:false",
"Browser:facebookplatform-1.0 Bot:true Mobile:false",
"Browser:Facebot Bot:true Mobile:false",
// Internet Explorer
"Mozilla:5.0 Platform:Windows OS:Windows 8 Browser:Internet Explorer-10.0 Engine:Trident Bot:false Mobile:false",
"Mozilla:4.0 Platform:Windows OS:Windows 8 Browser:Internet Explorer-10.0 Engine:Trident Bot:false Mobile:false",
"Mozilla:5.0 Platform:Windows OS:Windows 8 Browser:Internet Explorer-10.0 Engine:Trident Bot:false Mobile:false",
"Mozilla:4.0 Platform:Windows OS:Windows Phone OS 7.0 Browser:Internet Explorer-7.0 Engine:Trident Bot:false Mobile:true",
"Mozilla:4.0 Platform:Windows OS:Windows 2000 Browser:Internet Explorer-6.0 Engine:Trident Bot:false Mobile:false",
"Mozilla:4.0 Platform:Windows OS:Windows 7 Browser:Internet Explorer-8.0 Engine:Trident Bot:false Mobile:false",
"Mozilla:4.0 Platform:Windows OS:Windows 7 Browser:Internet Explorer-10.0 Engine:Trident Bot:false Mobile:false",
"Mozilla:5.0 Platform:Windows OS:Windows 8.1 Browser:Internet Explorer-11.0 Engine:Trident Bot:false Mobile:false",
"Mozilla:5.0 Platform:Windows OS:Windows 7 Browser:Internet Explorer-11.0 Engine:Trident Bot:false Mobile:false",
"Mozilla:5.0 Platform:Windows OS:Windows 7 Browser:Internet Explorer-11.0 Engine:Trident Bot:false Mobile:false",
"Mozilla:5.0 Platform:Windows OS:Windows 7 Browser:Internet Explorer-11.0 Engine:Trident Bot:false Mobile:false",
"Mozilla:4.0 Platform:Windows OS:Windows 8.1 Browser:Internet Explorer-7.0 Engine:Trident Bot:false Mobile:false",
// Gecko
"Mozilla:5.0 Platform:Macintosh OS:Intel Mac OS X 10.6 Browser:Firefox-4.0b8 Engine:Gecko-20100101 Bot:false Mobile:false",
"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",
"Mozilla:5.0 Platform:X11 OS:Linux x86_64 Browser:Firefox-17.0 Engine:Gecko-20100101 Bot:false Mobile:false",
"Mozilla:5.0 Platform:Windows OS:Windows XP Localization:en-US Browser:Firefox-2.0.0.14 Engine:Gecko-20080404 Bot:false Mobile:false",
"Mozilla:5.0 Platform:Windows OS:Windows 7 Browser:Firefox-29.0 Engine:Gecko-20100101 Bot:false Mobile:false",
"Mozilla:5.0 Platform:Macintosh OS:Intel Mac OS X Localization:en Browser:Camino-1.6 Engine:Gecko-20080409 Bot:false Mobile:false",
"Mozilla:5.0 Platform:X11 OS:Linux i686 Localization:en-US Browser:Iceweasel-2.0 Engine:Gecko-20061024 Bot:false Mobile:false",
"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",
"Mozilla:5.0 Platform:Mobile OS:Android Browser:Firefox-17.0 Engine:Gecko-17.0 Bot:false Mobile:true",
"Mozilla:5.0 Platform:Tablet OS:Android Browser:Firefox-26.0 Engine:Gecko-26.0 Bot:false Mobile:true",
"Mozilla:5.0 Platform:Mobile OS:FirefoxOS Browser:Firefox-26.0 Engine:Gecko-26.0 Bot:false Mobile:true",
"Mozilla:5.0 Platform:Tablet OS:FirefoxOS Browser:Firefox-26.0 Engine:Gecko-26.0 Bot:false Mobile:true",
"Mozilla:5.0 Platform:Windows OS:Windows XP x64 Edition Browser:Firefox-31.0 Engine:Gecko-20100101 Bot:false Mobile:false",
"Mozilla:5.0 Platform:Windows OS:Windows XP Localization:en-US Browser:Firefox-24.0 Engine:Gecko-20130405 Bot:false Mobile:false",
// Opera
"Platform:Macintosh OS:Intel Mac OS X Localization:en Browser:Opera-9.27 Engine:Presto Bot:false Mobile:false",
"Platform:Windows OS:Windows XP Localization:en Browser:Opera-9.27 Engine:Presto Bot:false Mobile:false",
"Platform:Windows OS:Windows XP Browser:Opera-9.80 Engine:Presto-2.12.388 Bot:false Mobile:false",
"Platform:Windows OS:Windows Vista Browser:Opera-9.80 Engine:Presto-2.12.388 Bot:false Mobile:false",
"Browser:Opera-9.80 Engine:Presto Bot:false Mobile:false",
"Platform:Windows OS:Windows Vista Localization:en Browser:Opera-9.80 Engine:Presto-2.2.15 Bot:false Mobile:false",
"Platform:X11 OS:Linux x86_64 Browser:Opera-9.80 Engine:Presto-2.12.388 Bot:false Mobile:false",
"Platform:Android 4.2.1 OS:Linux Browser:Opera-9.80 Engine:Presto-2.11.355 Bot:false Mobile:true",
"Platform:Windows OS:Windows XP Browser:Opera-9.80 Engine:Presto-2.12.388 Bot:false Mobile:false",
"Platform:Windows OS:Windows 7 Localization:en Browser:Opera-9.80 Engine:Presto-2.9.168 Bot:false Mobile:false",
// Other
"Bot:false Mobile:false",
"Browser:nil Bot:false Mobile:false",
"Browser:Mozilla-4.0 Bot:false Mobile:false",
"Browser:Mozilla-5.0 Bot:false Mobile:false",
"Browser:amaya-9.51 Engine:libwww-5.4.0 Bot:false Mobile:false",
"Browser:Rails Engine:Testing Bot:false Mobile:false",
"Browser:Python-urllib-2.7 Bot:false Mobile:false",
"Browser:curl-7.28.1 Bot:false Mobile:false",
// WebKit
"Mozilla:5.0 Platform:X11 OS:Linux x86_64 Browser:Chrome-23.0.1271.97 Engine:AppleWebKit-537.11 Bot:false Mobile:false",
"Mozilla:5.0 Platform:Windows OS:Windows 7 Browser:Chrome-18.0.1025.168 Engine:AppleWebKit-535.19 Bot:false Mobile:false",
"Mozilla:5.0 Browser:Chrome-8.0.552.215 Engine:AppleWebKit-534.10 Bot:false Mobile:false",
"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",
"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",
"Mozilla:5.0 Platform:Windows OS:Windows XP Localization:en Browser:Safari-4.0dp1 Engine:AppleWebKit-526.9 Bot:false Mobile:false",
"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",
"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",
"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",
"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",
"Mozilla:5.0 Platform:webOS OS:Palm Localization:en-US Browser:webOS-1.0 Engine:AppleWebKit-532.2 Bot:false Mobile:true",
"Mozilla:5.0 Platform:Linux OS:Android 1.5 Localization:de- Browser:Android-3.1.2 Engine:AppleWebKit-528.5+ Bot:false Mobile:true",
"Mozilla:5.0 Platform:BlackBerry OS:BlackBerry 9800 Localization:en Browser:BlackBerry-6.0.0.141 Engine:AppleWebKit-534.1+ Bot:false Mobile:true",
"Mozilla:5.0 Platform:BlackBerry OS:BlackBerry Browser:BlackBerry-10.0.9.388 Engine:AppleWebKit-537.3+ Bot:false Mobile:true",
"Mozilla:5.0 Platform:Symbian OS:SymbianOS/9.4 Browser:Symbian-3.0 Engine:AppleWebKit-525 Bot:false Mobile:true",
"Mozilla:5.0 Platform:Linux OS:Android 4.2.1 Browser:Chrome-18.0.1025.166 Engine:AppleWebKit-535.19 Bot:false Mobile:true",
"Mozilla:5.0 Platform:en-us Localization:en-us Browser:Safari-3.1 Engine:AppleWebKit-525.13 Bot:false Mobile:false",
"Mozilla:5.0 Platform:Linux OS:Android 4.2.2 Browser:Opera-14.0.1074.57453 Engine:AppleWebKit-537.31 Bot:false Mobile:true",
"Mozilla:5.0 Platform:X11 OS:Linux x86_64 Browser:Opera-14.0.1074.57453 Engine:AppleWebKit-537.31 Bot:false Mobile:false",
"Mozilla:5.0 Platform:Linux OS:Linux Browser:Chrome-22.0.1229.79 Engine:AppleWebKit-537.4 Bot:false Mobile:false",
"Mozilla:5.0 Platform:Symbian OS:SymbianOS/9.1 Browser:Symbian-413 Engine:AppleWebKit-413 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 i, tt := range uastrings {
ua := New(tt.ua)
got := beautify(ua)
if expected[i] != got {
t.Errorf("Test %v => %q, expected %q", tt.name, got, expected[i])
}
}
}
// 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)
}
}
}

121
vendor/github.com/mssola/user_agent/bot.go generated vendored Normal file
View file

@ -0,0 +1,121 @@
// Copyright (C) 2014 Miquel Sabaté Solà <mikisabate@gmail.com>
// This file is licensed under the MIT license.
// See the LICENSE file.
package user_agent
import (
"regexp"
"strings"
)
// 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.
re := regexp.MustCompile("http://.+\\.\\w+")
results := re.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 = ""
}
}
// 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" in his name.
reg, _ := regexp.Compile("(?i)bot")
if reg.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)
}
}

120
vendor/github.com/mssola/user_agent/browser.go generated vendored Normal file
View file

@ -0,0 +1,120 @@
// Copyright (C) 2012-2014 Miquel Sabaté Solà <mikisabate@gmail.com>
// This file is licensed under the MIT license.
// See the LICENSE file.
package user_agent
import (
"regexp"
"strings"
)
// 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.mozilla = ""
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 slen > 1 {
engine := sections[1]
p.browser.Engine = engine.name
p.browser.EngineVersion = engine.version
if slen > 2 {
p.browser.Version = sections[2].version
if engine.name == "AppleWebKit" {
if sections[slen-1].name == "OPR" {
p.browser.Name = "Opera"
p.browser.Version = sections[slen-1].version
} else if sections[2].name == "Chrome" {
p.browser.Name = "Chrome"
} 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"
reg, _ := regexp.Compile("^rv:(.+)$")
for _, c := range sections[0].comment {
version := reg.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
}

View file

@ -0,0 +1,260 @@
// Copyright (C) 2012-2014 Miquel Sabaté Solà <mikisabate@gmail.com>
// This file is licensed under the MIT license.
// See the LICENSE file.
package user_agent
import "strings"
// Normalize the name of the operating system. By now, this just
// affects to Windows.
//
// 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 {
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 "6.4":
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) > 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])
}
}
}
if len(comment) > 3 {
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]
}
}
}
// 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 {
// 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
}

169
vendor/github.com/mssola/user_agent/user_agent.go generated vendored Normal file
View file

@ -0,0 +1,169 @@
// Copyright (C) 2012-2014 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 {
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
}