├── .gitignore ├── .travis.yml ├── Dockerfile ├── LICENSE ├── README.md ├── api.go ├── cache.go ├── certs ├── goproxy.crt └── goproxy.key ├── cmd ├── main.go └── question_utils.go ├── db.go ├── docs ├── 1.jpg ├── 2.jpg ├── 3.jpeg ├── 4.jpeg ├── FAQ.md └── donate.jpg ├── handler.go ├── merge.data ├── questions.data ├── spider.go └── vendor ├── github.com ├── PuerkitoBio │ └── goquery │ │ ├── LICENSE │ │ ├── README.md │ │ ├── array.go │ │ ├── doc.go │ │ ├── expand.go │ │ ├── filter.go │ │ ├── iteration.go │ │ ├── manipulation.go │ │ ├── property.go │ │ ├── query.go │ │ ├── traversal.go │ │ ├── type.go │ │ └── utilities.go ├── andybalholm │ └── cascadia │ │ ├── LICENSE │ │ ├── README.md │ │ ├── parser.go │ │ └── selector.go ├── boltdb │ └── bolt │ │ ├── LICENSE │ │ ├── Makefile │ │ ├── README.md │ │ ├── appveyor.yml │ │ ├── bolt_386.go │ │ ├── bolt_amd64.go │ │ ├── bolt_arm.go │ │ ├── bolt_arm64.go │ │ ├── bolt_linux.go │ │ ├── bolt_openbsd.go │ │ ├── bolt_ppc.go │ │ ├── bolt_ppc64.go │ │ ├── bolt_ppc64le.go │ │ ├── bolt_s390x.go │ │ ├── bolt_unix.go │ │ ├── bolt_unix_solaris.go │ │ ├── bolt_windows.go │ │ ├── boltsync_unix.go │ │ ├── bucket.go │ │ ├── cursor.go │ │ ├── db.go │ │ ├── doc.go │ │ ├── errors.go │ │ ├── freelist.go │ │ ├── node.go │ │ ├── page.go │ │ └── tx.go ├── coreos │ └── goproxy │ │ ├── LICENSE │ │ ├── README.md │ │ ├── actions.go │ │ ├── all.bash │ │ ├── ca.pem │ │ ├── certs.go │ │ ├── chunked.go │ │ ├── counterecryptor.go │ │ ├── ctx.go │ │ ├── dispatcher.go │ │ ├── doc.go │ │ ├── https.go │ │ ├── key.pem │ │ ├── proxy.go │ │ ├── responses.go │ │ ├── signer.go │ │ └── websocket.go ├── elazarl │ └── goproxy │ │ ├── LICENSE │ │ ├── README.md │ │ ├── actions.go │ │ ├── all.bash │ │ ├── ca.pem │ │ ├── certs.go │ │ ├── chunked.go │ │ ├── counterecryptor.go │ │ ├── ctx.go │ │ ├── dispatcher.go │ │ ├── doc.go │ │ ├── https.go │ │ ├── key.pem │ │ ├── proxy.go │ │ ├── responses.go │ │ └── signer.go └── patrickmn │ └── go-cache │ ├── CONTRIBUTORS │ ├── LICENSE │ ├── README.md │ ├── cache.go │ └── sharded.go ├── golang.org └── x │ ├── net │ ├── LICENSE │ ├── PATENTS │ └── html │ │ ├── atom │ │ ├── atom.go │ │ ├── gen.go │ │ └── table.go │ │ ├── charset │ │ └── charset.go │ │ ├── const.go │ │ ├── doc.go │ │ ├── doctype.go │ │ ├── entity.go │ │ ├── escape.go │ │ ├── foreign.go │ │ ├── node.go │ │ ├── parse.go │ │ ├── render.go │ │ └── token.go │ └── text │ ├── LICENSE │ ├── PATENTS │ ├── encoding │ ├── charmap │ │ ├── charmap.go │ │ ├── maketables.go │ │ └── tables.go │ ├── encoding.go │ ├── htmlindex │ │ ├── gen.go │ │ ├── htmlindex.go │ │ ├── map.go │ │ └── tables.go │ ├── internal │ │ ├── identifier │ │ │ ├── gen.go │ │ │ ├── identifier.go │ │ │ └── mib.go │ │ └── internal.go │ ├── japanese │ │ ├── all.go │ │ ├── eucjp.go │ │ ├── iso2022jp.go │ │ ├── maketables.go │ │ ├── shiftjis.go │ │ └── tables.go │ ├── korean │ │ ├── euckr.go │ │ ├── maketables.go │ │ └── tables.go │ ├── simplifiedchinese │ │ ├── all.go │ │ ├── gbk.go │ │ ├── hzgb2312.go │ │ ├── maketables.go │ │ └── tables.go │ ├── traditionalchinese │ │ ├── big5.go │ │ ├── maketables.go │ │ └── tables.go │ └── unicode │ │ ├── override.go │ │ └── unicode.go │ ├── internal │ ├── tag │ │ └── tag.go │ └── utf8internal │ │ └── utf8internal.go │ ├── language │ ├── Makefile │ ├── common.go │ ├── coverage.go │ ├── gen_common.go │ ├── gen_index.go │ ├── go1_1.go │ ├── go1_2.go │ ├── index.go │ ├── language.go │ ├── lookup.go │ ├── maketables.go │ ├── match.go │ ├── parse.go │ ├── tables.go │ └── tags.go │ ├── runes │ ├── cond.go │ └── runes.go │ └── transform │ └── transform.go ├── mantic ├── cache │ └── dns │ │ └── cache.go ├── conf │ └── config.go └── downloader │ └── surfer │ ├── agent │ ├── agent.go │ ├── agent_bsd.go │ ├── agent_linux.go │ └── agent_windows.go │ ├── param.go │ ├── phantom.go │ ├── puppeteer.go │ ├── request.go │ ├── surf.go │ ├── surfer.go │ └── util.go └── vendor.json /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | tmp 3 | .DS_Store 4 | dist 5 | .goreleaser.yml 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.9 4 | 5 | install: true 6 | 7 | before_script: 8 | - echo "start merging zip file from issues" 9 | 10 | script: 11 | - go run cmd/question_utils.go -s="issue" 12 | 13 | after_script: 14 | - git add *.data 15 | - git commit -m "[skip ci]auto update data" 16 | - git push "https://${GH_TOKEN}@${GH_REF}" HEAD:master 17 | 18 | branches: 19 | only: 20 | - master 21 | env: 22 | global: 23 | - GH_REF: github.com/sundy-li/wechat_brain.git 24 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:latest 2 | 3 | MAINTAINER Allen.Cai "caizz520@gmail.com" 4 | 5 | WORKDIR $GOPATH/src/github.com/sundy-li/wechat_brain 6 | ADD . $GOPATH/src/github.com/sundy-li/wechat_brain 7 | RUN go build ./cmd/main.go 8 | 9 | EXPOSE 8998 10 | 11 | ENTRYPOINT ["./main"] 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 sundyli 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wechat_brain 2 | 知乎答题王(小程序头脑王者)辅助工具,上万题库。 3 | 4 | 5 | ## 注意 6 | 本工具仅供辅助娱乐。 7 | 8 | ## 使用原理 9 | 本工具运行在PC端,本质是一个http/https代理服务,对头脑王者的接口请求进行截获,主要作用有 10 | 11 | - 将题目和返回的标准答案存储于本地数据库中(questions.data文件) 12 | - 未匹配到标准答案情况下,自动请求搜索引擎,注解形式返回最佳概率结果 13 | 14 | ## 使用步骤: 15 | 本工具必须结合PC和手机共同使用,PC和手机须在同一个网络下 16 | 17 | #### 以下为PC电脑操作步骤 18 | 19 | - 运行主程序。运行方法(三选一) 20 | 1. 方法一: 在[release](https://github.com/sundy-li/wechat_brain/releases)页面下载对应的操作系统执行文件, 解压后, 将最新版本的[questions.data](https://github.com/sundy-li/wechat_brain/blob/master/questions.data) 文件下载到同一个目录, 然后运行brain文件即可,命令行输入`./brain` 21 | 2. 方法二: 安装go(>=1.8)环境后, clone本repo源码到对应`$GOPATH/src/github.com/sundy-li/`下, 进入源码目录后,执行 `go run cmd/main.go`。 22 | 3. 方法三: 使用docker命令运行: 23 | 24 | 25 | git clone https://github.com/sundy-li/wechat_brain.git 26 | cd wechat_brain 27 | docker build . -t wechat_brain 28 | docker run -p 8998:8998 --name my_wechat_brain -d wechat_brain 29 | 30 | 31 | 32 | - 新版本(version >= v0.18)加入了三种模式, 大家根据自己的需求选择模式运行 33 | 1. 模式一: 默认模式, 修改了服务端返回的数据, 更加友好地提示正确答案, 运行方式如上所述: `./brain` 或者源码下执行 `go run cmd/main.go` 34 | 2. 模式二: 隐身模式, 严格返回原始数据, 该模式可以防止作弊检测(客户端提交返回题目和服务端对比,模式一很容易被侦测出使用了作弊, 模式二避免了这类检测), 但该模式的缺点是降低了用户的体验,题目答案的提示只能在PC电脑上显示, 运行方式如上所述 `./brain -m 1` 或者源码下执行 `go run cmd/main.go -m 1` 35 | 3. 模式三:自动模式 ** 注意此模式不同手机点击可能不稳定, 谨慎使用 ** 安卓机的自动刷题模式,需要将手机连接到电脑,并安装adb,且需要在开发者模式中打开usb调试,使用前请根据自身手机分辨率,调整spider文件clickProcess中的相应参数:手机屏幕中心x坐标,第一个选项中心y坐标,排位列表中最后一项中心y坐标。运行方式如上所述 `./brain -a 1 -m 1` 或者源码下执行 `go run cmd/main.go -a 1 -m 1` 36 | 37 | #### 以下为手机安装步骤 38 | 39 | - 设置手机代理。手机连接wifi后进行代理设置,代理IP为个人pc的内网ip地址,以及端口为8998,移动网络下可通过设置新建APN并在其中设置代理的方式实现。如: 40 |
41 | 配置代理 42 |
43 | 44 | - 安装证书。代理运行成功后,手机浏览器访问 `abc.com`安装证书,ios记得要信任证书 (或者将 `certs/goproxy.crt`传到手机, 点击安装证书), 很多朋友会卡在安装证书这一步骤, 不同手机会有不同的安装方式,建议大家多搜索下自己机型如何安装证书 45 | 46 | - 打开微信并启动头脑王者小程序。 47 | - 正确的答案将在小程序的选项中以【标准答案】或【数字】字样。如: 48 |
49 | 自动提示标准答案 50 | 自动估算最可能的答案 51 |
52 | 53 | ## 问题 54 | - [FAQ](https://github.com/sundy-li/wechat_brain/blob/master/docs/FAQ.md) 55 | - 感谢@HsiangHo, @milkmeowo 的贡献,修复了ios代理问题,更新新版本后,最好重新安装证书,重启微信进程 56 | ~~~ios端由于goproxy无法代理websocket问题,暂时无法使用,希望大家可以来完善这个问题,见[这个issue](https://github.com/sundy-li/wechat_brain/issues/18)~~~ 57 | 58 | ## 合并题库 59 | - 请将questions.data文件压缩为zip文件后提交到[这里](https://github.com/sundy-li/wechat_brain/issues/17), 题库将会定期合并更新。 60 | 61 | ## 支持 62 | 维护开源软件需要花费很大时间精力,如果各位觉得本工具对你有帮助,可以请我喝杯咖啡支持一下 63 |
64 | 65 |
66 | 67 | 68 | ## 轻松上王者效果图 69 | 70 |
71 | 自动提示标准答案 72 |
73 | 74 | -------------------------------------------------------------------------------- /api.go: -------------------------------------------------------------------------------- 1 | package wechat_brain 2 | 3 | import ( 4 | "net/http" 5 | "net/url" 6 | "strings" 7 | 8 | "github.com/PuerkitoBio/goquery" 9 | ) 10 | 11 | var ( 12 | baidu_url = "http://www.baidu.com/s?" 13 | ) 14 | 15 | func GetFromBaidu(quiz string, options []string) map[string]int { 16 | values := url.Values{} 17 | values.Add("wd", quiz) 18 | req, _ := http.NewRequest("GET", baidu_url+values.Encode(), nil) 19 | return GetFromApi(req, quiz, options) 20 | } 21 | 22 | func GetFromApi(req *http.Request, quiz string, options []string) (res map[string]int) { 23 | res = make(map[string]int, len(options)) 24 | for _, option := range options { 25 | res[option] = 0 26 | } 27 | resp, _ := http.DefaultClient.Do(req) 28 | if resp == nil { 29 | return 30 | } 31 | doc, _ := goquery.NewDocumentFromReader(resp.Body) 32 | defer resp.Body.Close() 33 | str := doc.Find("#content_left .result").Text() 34 | for _, option := range options { 35 | res[option] = strings.Count(str, option) 36 | } 37 | return 38 | } 39 | -------------------------------------------------------------------------------- /cache.go: -------------------------------------------------------------------------------- 1 | package wechat_brain 2 | 3 | import ( 4 | "time" 5 | 6 | cache "github.com/patrickmn/go-cache" 7 | ) 8 | 9 | var ( 10 | questions *cache.Cache 11 | ) 12 | 13 | func init() { 14 | // Create a cache with a default expiration time of 5 minutes, and which 15 | // purges expired items every 10 minutes 16 | questions = cache.New(5*time.Minute, 10*time.Minute) 17 | } 18 | 19 | func GetQuestion(roomID, quizNum string) *Question { 20 | key := roomID + "_" + quizNum 21 | if entity, ok := questions.Get(key); ok { 22 | return entity.(*Question) 23 | } 24 | return nil 25 | } 26 | 27 | func SetQuestion(question *Question) { 28 | key := question.CalData.RoomID + "_" + question.CalData.quizNum 29 | questions.Set(key, question, cache.DefaultExpiration) 30 | } 31 | -------------------------------------------------------------------------------- /certs/goproxy.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIF8jCCA9qgAwIBAgIUAp68XvvuMwaTCeQQjGxHEZhJcPgwDQYJKoZIhvcNAQEN 3 | BQAwgZAxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZy 4 | YW5jaXNjbzEUMBIGA1UEChMLQ29yZU9TLCBJbmMxIjAgBgNVBAsTGWdpdGh1Yi5j 5 | b20vY29yZW9zL2dvcHJveHkxIjAgBgNVBAMTGWdpdGh1Yi5jb20vY29yZW9zL2dv 6 | cHJveHkwHhcNMTcwMjIyMjI0NjAwWhcNMjIwMjIxMjI0NjAwWjCBkDELMAkGA1UE 7 | BhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRQwEgYD 8 | VQQKEwtDb3JlT1MsIEluYzEiMCAGA1UECxMZZ2l0aHViLmNvbS9jb3Jlb3MvZ29w 9 | cm94eTEiMCAGA1UEAxMZZ2l0aHViLmNvbS9jb3Jlb3MvZ29wcm94eTCCAiIwDQYJ 10 | KoZIhvcNAQEBBQADggIPADCCAgoCggIBANghh+Y4gUYyIY1YzAgHBuLjTt13z5ED 11 | tbjksaK8kUMofaYCnQRrepTORB3xpxn9cIXpmmPND/c3pUZz+sSbidZF+Rfkz+G4 12 | oo5I04X7R2iFrw9jECcavr7qGqOt+vhep9iqVaioSWTKZoXY9FOxTpEUfdKyLE8K 13 | 7rd6PfdjkbZ2ZqoKdRHARBE6QlTJv+elIRM6kzshx0oSdZfaUvLdmXFqHdfKz8gb 14 | FABaa8Aca6r76wHRnhK3+RQ2p+Wfz45/ZMxqQVIMr2mbiCCL4lSUPkUrid6L5DoA 15 | 4A4pLqY+Y0cX2qIF+lmgUwUPvunqM7dA9toHjwBgeB1yF+jVOhFOizB/dXSCsBA2 16 | D47raP3REIxE6N05pEpGZqUPatcdyakP1Dan9aVO2W3o7P/LGPBdB5AiwVxRiVPx 17 | dNrz+UcE3dCPBrc9bxJLjyD7PtgPTrZ+hzR/kBfBW/+jvBRKIB5NCNSuQEUN99it 18 | P1fIencEz1ghaWhCAU5tQutnVBu8d0YlgjfnaD4vCJYEprifAiIpgZH3HaiHfG14 19 | UXFbdU0MmuIrie2PMAGmtnjhWHG0vc8f2THRklq/CtbfNWtPzUfYv+rpaOFw7bj+ 20 | km0n3kVuGzWZhXPixe63TATR5lK9p21CZPXS+2mW/8uswBiJ4aT5lUZmCf/i1xyn 21 | Gzgv9so56vjFAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD 22 | AQH/MB0GA1UdDgQWBBSYLcfHmyPv3jmdTyBs/lu5PZLxPTANBgkqhkiG9w0BAQ0F 23 | AAOCAgEAppb+3MhGcL/IjqyRIWCc587eVMMtuHwGlczpMfXnf8TU0MPrvOdTPrqg 24 | a+AEc1W8O6IGrowmgbZVgfr7Pw0BL4VcSdAEbP7QcbPmRAudF+/xdm5vylJmB339 25 | 4Yq5v1G2Ya5AN5PAHx3WVOA7s/caz30DGrsAoNhezlrk8WJRRxrQUauNveXyxNya 26 | urBrqjqNVUWAlv2fRHuNXsxMvG32MWQ1BoPa9Ix+dUWYeeWkxS5E9oNo99TRRTHB 27 | WX4SpsIynmhE+pFEzu2HVP2k5GE5+i78F9/N0cgI5QMSzgYxSebyPEflL1ziqWoq 28 | 4xio69OM0Cq+GCxvOZmvKaNlOjwJa6NWa8IyumNFclTLNzMlBaDkVE9Tb5VEBphO 29 | ODzSxFMuAfXba4UlRjG9+BLg8ayzu2t9amB+B5/3/1+gkx1TE26jZNwleU6MnpFv 30 | umPqPa9AW2ZPobCTGjV3MwOIKFyO/cPt4fI6BpKF7jYhUYzsht/BZqQZU/rWY6h8 31 | GSEH8LcJk+Paaw03HzZWSbMp2oXNTz/BpQjuAdWAkeS3yhx5gvHIysWHvPRT017b 32 | Tx+Va9+T4DElT0HtmR/w27bXNL9Urj38ETSlbYoilL7ZKltj8djXmqkI1ZF8T1zk 33 | tj1zk0XYkestBgfrk9XYwvvL7DLyRPPZTAiVq/o5xn5zWp/y40M= 34 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /certs/goproxy.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIJKQIBAAKCAgEA2CGH5jiBRjIhjVjMCAcG4uNO3XfPkQO1uOSxoryRQyh9pgKd 3 | BGt6lM5EHfGnGf1whemaY80P9zelRnP6xJuJ1kX5F+TP4biijkjThftHaIWvD2MQ 4 | Jxq+vuoao636+F6n2KpVqKhJZMpmhdj0U7FOkRR90rIsTwrut3o992ORtnZmqgp1 5 | EcBEETpCVMm/56UhEzqTOyHHShJ1l9pS8t2ZcWod18rPyBsUAFprwBxrqvvrAdGe 6 | Erf5FDan5Z/Pjn9kzGpBUgyvaZuIIIviVJQ+RSuJ3ovkOgDgDikupj5jRxfaogX6 7 | WaBTBQ++6eozt0D22gePAGB4HXIX6NU6EU6LMH91dIKwEDYPjuto/dEQjETo3Tmk 8 | SkZmpQ9q1x3JqQ/UNqf1pU7Zbejs/8sY8F0HkCLBXFGJU/F02vP5RwTd0I8Gtz1v 9 | EkuPIPs+2A9Otn6HNH+QF8Fb/6O8FEogHk0I1K5ARQ332K0/V8h6dwTPWCFpaEIB 10 | Tm1C62dUG7x3RiWCN+doPi8IlgSmuJ8CIimBkfcdqId8bXhRcVt1TQya4iuJ7Y8w 11 | Aaa2eOFYcbS9zx/ZMdGSWr8K1t81a0/NR9i/6ulo4XDtuP6SbSfeRW4bNZmFc+LF 12 | 7rdMBNHmUr2nbUJk9dL7aZb/y6zAGInhpPmVRmYJ/+LXHKcbOC/2yjnq+MUCAwEA 13 | AQKCAgBDt83SzmWCzvZASVA0O69mq33sWjvI3fa0JcOaj6ab+jXULAFyfxJ7SV2C 14 | XFLVC9mTu6vKFVgpR2AbgP9TVsCLSIVRfTm9KZKVLjBITIEFOM2u7oUDG5gkTUln 15 | e32lEFNayZPpMkE8uUYCLgXvqyBIyLjbqUPEyFIfXsfHmYTwPIzSPlCL7UfmdfCO 16 | jF/6fnysf6/d2SmOBdaea6ONwOzw4iTTlhIgSouryKj2GnGJs0Dg4wK6LrZ2JOHa 17 | SoZHyZaVjb1Frf/QARFX0Txq77/LAGdEOWSa3+dTyId7QxTsE4dHOMRGDLu2XEaf 18 | F+h4RHyTt8aQgalg4HypURXOkmN9jSodE8wBlj+oA5AOTFknqu2RMH+UX82uC4gs 19 | ccVDvd553SJyUtpSkvLvYv2Lu+o4w+uDsYZhdt12MDucnTwAzUqOWt2OSuX5LwZO 20 | Qi0xTmj5YnOju9MayfSuh14YRvxsVDK0XTZGm1FVlLtm6iitdSWCXZjGgKHEmNCk 21 | spd8sxdROxUID79tp4SVuAHzLZ3OTUrMVRvUksFRIiOX4vwcupvS8OVnRFC0yTpB 22 | d+V126XI5qISP0nAEvYOuI3GF3RiEiJ6P9PL15on3YY4AzmaAC8OimlFc7Gv2Vkt 23 | L7EvT83u/vT00H4xt85YMUksLupQXKSRnm7aTpHdW59zNO7AQQKCAQEA7QtGuzTt 24 | hG17hOBJ/VK9PE1Jy7aQ+SBZiY+92KgE9xAYoyPsFb/o0gLd11achsPUpTlku08n 25 | sgaW33wxFvTPL3Qf0TAwXxvavA/2JNboDy7iQbP7SBsNg0DaBU77bBpZo3/DBqK8 26 | vQPHN+CjiXLYqKFKk4FCX9umN6h1TClFmAQF9VS6pPjZJum3ECgHpvQJQlf4IX/l 27 | B9rV0wgfy1rnRgSC7eFSYaRiGv8uu1N9EHWQNa3R/a/2lADDTnwWcDsyE1Lu9WoT 28 | fv4LcOoYAvvNCSzkDwffvQcpJKluMcpZWOO6RqODdS4rv6nIS/Tyucj9jT0+6DGh 29 | raH80VDS0i+5aQKCAQEA6WogPbSqodvx5gwCCnQ6P/inbQV5rWU9hQfBmhYHGLan 30 | 9cFMcZFWDDLvvEsuvdReFbnwsSfCT8BJWE/xsHbn39ep7mdPunqN3tfyF5sYRS18 31 | nLJrOQM50xePMbwFd7mnSuUauiDGPpOr0TF7C6kzUyTT3Mnzcxta5Yzpi9rQkm4C 32 | PcxctPrM6Xq3JZVrehZ/t1Ok+srEpfLbOMcDu22DejjfvMF0enSKZVEGTq3Ls1Yc 33 | LjhAoOP/YL9LcQqYmIkw8Cj9/5DEGaX97of+UxdDvRb5x4bn1/6/qaJxfSXSy+Rv 34 | n/E4+HccWRoA9KA0YUdLVBAsO9f2h+u7HUK3vkdc/QKCAQEA21in5uufLf+xYM+7 35 | J7K8cWSDeQJDPIR21hgw8J7pmUVHxw6ik6213z/P0EfRJ9Nmnk1xrPIeJVp7ment 36 | 8vQuFBc8qfIRkLDRw1xxxL0ol4Qm0e2eBKcj5eTI2kiv1uS7NdQvv6AvTiiE3Gv+ 37 | aF3hpok53SyrItC6Cp7Ti9pVD8oJSW9SFv4+0wdJ4qVoD1Gaj82fSkByysXxPwox 38 | gZdokx3xmfX6qWfXcGvZ7nXfMK/Y9hMWUc3WOjZKhAHHMatVNxRzEp1J1SV3qNC1 39 | z2z52he0IUSEAQLzS32M/n3kF6EC6gK8zl4fFYgiVEchpFEcbunRoELs/SL8MyS7 40 | MMwAoQKCAQAH+0II+iGPkVbPN//l3Z2UTGtlNfe4LysQXniHTVOGy9AofiigBYk8 41 | t40tEiESCq4A7i/Fzwc89OVNKMap8xbwt44vAcdfKAur4BR+LCaDTw/gx9UUyQB0 42 | MG0MFVLWijmnPPhR/wboYuJQL/H2Lx37LNo1xY4WlIviJ5Rg3OWe7DYVaOSOp7jU 43 | DwcuONLJBPXvDeQpUz+wMQLACUYeZZtGVaWI7dCO02dcGY4uqJC7nCkwh2nmVoWI 44 | CGKLBgK7zI0o2S3+TDP4cI2jV3Eh5DzDvYJjCUDqSOLC6TQaRG3V3QTYIkaBcIk+ 45 | nr4Dn2rLHMX9pOPuU+8xLKVkVcC0t/n9AoIBAQDUPPjFkg80Cl63TZLpToB7K9Ki 46 | hmoVDqgG2E+91E3cDK2+/8knaPB57A3a34qqp06YjUaKr5v6dwuKgTK4ubUxtw4d 47 | iTIly2KJQX9U7kFira68irP+q+h6sbi0JfK9+lv5ITmJCBsy1MY4U7rLWnn3P+VS 48 | UtLGOP4gEn4ZtNFBrFJmP+AySvtTNhM+CF8Hi9p4i7tAkIzZ9kpMiQKU70LizCV9 49 | 2FrsKJw2g4JaU97IFIquM/c6NG4cH+D9eP4YL3G+uodmdERvXJ5muFGUMaXMn/TC 50 | +dyEZ2Dlz6DiGF63r7qGCi4nxyI3HfY3+hNA6X3NuucN8nVnD/S7kuzLWKhZ 51 | -----END RSA PRIVATE KEY----- -------------------------------------------------------------------------------- /cmd/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "os" 6 | "os/signal" 7 | 8 | brain "github.com/sundy-li/wechat_brain" 9 | ) 10 | 11 | var ( 12 | mode int 13 | automatic int 14 | ) 15 | 16 | func init() { 17 | flag.IntVar(&mode, "m", 0, "run mode 0 : default mode, easy to be detected of cheating; 1 : invisible mode") 18 | flag.IntVar(&automatic, "a", 0, "run automatic 0 : manual 1 : automatic") 19 | flag.Parse() 20 | } 21 | 22 | func main() { 23 | c := make(chan os.Signal) 24 | signal.Notify(c, os.Interrupt, os.Kill) 25 | go func() { 26 | brain.Run("8998", mode, automatic) 27 | }() 28 | <-c 29 | brain.Close() 30 | } 31 | -------------------------------------------------------------------------------- /cmd/question_utils.go: -------------------------------------------------------------------------------- 1 | //跑这个脚本的时候记得关掉其他服务,因为这个脚本需要读取questions.data 2 | package main 3 | 4 | import ( 5 | "archive/zip" 6 | "flag" 7 | "fmt" 8 | "io" 9 | "log" 10 | "net/http" 11 | "os" 12 | "path/filepath" 13 | "strings" 14 | 15 | "github.com/boltdb/bolt" 16 | brain "github.com/sundy-li/wechat_brain" 17 | 18 | "github.com/PuerkitoBio/goquery" 19 | ) 20 | 21 | var ( 22 | source string 23 | fs string 24 | issueUrl = "https://github.com/sundy-li/wechat_brain/issues/17" 25 | tmpDir = "/tmp/" 26 | ) 27 | 28 | func init() { 29 | flag.StringVar(&source, "s", "show", "source value -> show | file | issue") 30 | flag.StringVar(&fs, "fs", "", "merge data files") 31 | flag.Parse() 32 | 33 | initDb() 34 | } 35 | 36 | func main() { 37 | if source == "file" { 38 | files := strings.Split(fs, " ") 39 | if len(files) < 1 { 40 | log.Println("empty files") 41 | return 42 | } 43 | brain.MergeQuestions(files...) 44 | } else if source == "issue" { 45 | doc, _ := goquery.NewDocument(issueUrl) 46 | doc.Find("div.timeline-comment-wrapper").Each(func(index int, comment *goquery.Selection) { 47 | author := comment.Find("a.author").Text() 48 | comment.Find("td.d-block p a").Each(func(i int, s *goquery.Selection) { 49 | if strings.Contains(s.Text(), ".zip") { 50 | href, _ := s.Attr("href") 51 | if href != "" { 52 | err := handleZipUrl(author, href) 53 | if err != nil { 54 | log.Println("Error", err.Error()) 55 | } 56 | } 57 | } 58 | }) 59 | }) 60 | } else { 61 | brain.ShowAllQuestions() 62 | } 63 | total := brain.CountQuestions() 64 | log.Println("total questions =>", total) 65 | } 66 | 67 | func handleZipUrl(author, url string) error { 68 | println("handling", author, url) 69 | var exist bool 70 | memoryDb.View(func(tx *bolt.Tx) error { 71 | b := tx.Bucket([]byte(QuestionUrlBucket)) 72 | v := b.Get([]byte(url)) 73 | if len(v) != 0 { 74 | exist = true 75 | } 76 | return nil 77 | }) 78 | if exist { 79 | log.Println("skip already merged file url", url) 80 | return nil 81 | } 82 | resp, err := http.Get(url) 83 | if err != nil { 84 | return err 85 | } 86 | defer resp.Body.Close() 87 | out, err := os.Create(tmpDir + "questions.zip") 88 | if err != nil { 89 | return err 90 | } 91 | defer out.Close() 92 | io.Copy(out, resp.Body) 93 | _, err = Unzip(tmpDir+"questions.zip", tmpDir) 94 | if err != nil { 95 | return err 96 | } 97 | //merge data 98 | brain.MergeQuestions(tmpDir + "questions.data") 99 | log.Println("merged", url) 100 | 101 | memoryDb.Update(func(tx *bolt.Tx) error { 102 | b := tx.Bucket([]byte(QuestionUrlBucket)) 103 | b.Put([]byte(url), []byte("ok")) 104 | return nil 105 | }) 106 | return nil 107 | } 108 | 109 | // Unzip will un-compress a zip archive, 110 | // moving all files and folders to an output directory 111 | func Unzip(src, dest string) ([]string, error) { 112 | var filenames []string 113 | r, err := zip.OpenReader(src) 114 | if err != nil { 115 | return filenames, err 116 | } 117 | defer r.Close() 118 | 119 | for _, f := range r.File { 120 | 121 | rc, err := f.Open() 122 | if err != nil { 123 | return filenames, err 124 | } 125 | defer rc.Close() 126 | 127 | // Store filename/path for returning and using later on 128 | fpath := filepath.Join(dest, f.Name) 129 | filenames = append(filenames, fpath) 130 | 131 | if f.FileInfo().IsDir() { 132 | // Make Folder 133 | os.MkdirAll(fpath, os.ModePerm) 134 | 135 | } else { 136 | 137 | // Make File 138 | var fdir string 139 | if lastIndex := strings.LastIndex(fpath, string(os.PathSeparator)); lastIndex > -1 { 140 | fdir = fpath[:lastIndex] 141 | } 142 | 143 | err = os.MkdirAll(fdir, os.ModePerm) 144 | if err != nil { 145 | log.Fatal(err) 146 | return filenames, err 147 | } 148 | f, err := os.OpenFile( 149 | fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) 150 | if err != nil { 151 | return filenames, err 152 | } 153 | defer f.Close() 154 | 155 | _, err = io.Copy(f, rc) 156 | if err != nil { 157 | return filenames, err 158 | } 159 | } 160 | } 161 | return filenames, nil 162 | } 163 | 164 | //questions.data中存入url的cache, 防止重复merge,提高性能 165 | 166 | var ( 167 | memoryDb *bolt.DB 168 | QuestionUrlBucket = "QuestionUrl" 169 | ) 170 | 171 | func initDb() { 172 | var err error 173 | memoryDb, err = bolt.Open("merge.data", 0600, nil) 174 | if err != nil { 175 | log.Fatal(err) 176 | } 177 | memoryDb.Update(func(tx *bolt.Tx) error { 178 | _, err := tx.CreateBucketIfNotExists([]byte(QuestionUrlBucket)) 179 | if err != nil { 180 | return fmt.Errorf("create bucket: %s", err) 181 | } 182 | return nil 183 | }) 184 | } 185 | -------------------------------------------------------------------------------- /db.go: -------------------------------------------------------------------------------- 1 | package wechat_brain 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "log" 7 | "time" 8 | 9 | "github.com/boltdb/bolt" 10 | ) 11 | 12 | var ( 13 | memoryDb *bolt.DB 14 | QuestionBucket = "Question" 15 | ) 16 | 17 | func init() { 18 | var err error 19 | memoryDb, err = bolt.Open("questions.data", 0600, nil) 20 | if err != nil { 21 | log.Fatal(err) 22 | } 23 | memoryDb.Update(func(tx *bolt.Tx) error { 24 | _, err := tx.CreateBucketIfNotExists([]byte(QuestionBucket)) 25 | if err != nil { 26 | return fmt.Errorf("create bucket: %s", err) 27 | } 28 | return nil 29 | }) 30 | } 31 | 32 | func StoreQuestion(question *Question) error { 33 | if question.CalData.TrueAnswer != "" { 34 | return memoryDb.Update(func(tx *bolt.Tx) error { 35 | b := tx.Bucket([]byte(QuestionBucket)) 36 | v := NewQuestionCols(question.CalData.TrueAnswer) 37 | err := b.Put([]byte(question.Data.Quiz), v.GetData()) 38 | return err 39 | }) 40 | } 41 | return nil 42 | } 43 | 44 | func FetchQuestion(question *Question) (str string) { 45 | memoryDb.View(func(tx *bolt.Tx) error { 46 | b := tx.Bucket([]byte(QuestionBucket)) 47 | v := b.Get([]byte(question.Data.Quiz)) 48 | if len(v) == 0 { 49 | return nil 50 | } 51 | q := DecodeQuestionCols(v, time.Now().Unix()) 52 | str = q.Answer 53 | return nil 54 | }) 55 | return 56 | } 57 | 58 | func FetchQuestionTime(quiz string) (res int64) { 59 | memoryDb.View(func(tx *bolt.Tx) error { 60 | b := tx.Bucket([]byte(QuestionBucket)) 61 | v := b.Get([]byte(quiz)) 62 | if len(v) == 0 { 63 | res = -1 64 | return nil 65 | } 66 | q := DecodeQuestionCols(v, time.Now().Unix()) 67 | res = q.Update 68 | return nil 69 | }) 70 | return 71 | } 72 | 73 | func ShowAllQuestions() { 74 | var kv = map[string]string{} 75 | memoryDb.View(func(tx *bolt.Tx) error { 76 | // Assume bucket exists and has keys 77 | b := tx.Bucket([]byte(QuestionBucket)) 78 | c := b.Cursor() 79 | for k, v := c.First(); k != nil; k, v = c.Next() { 80 | fmt.Printf("key=%s, value=%s\n", k, v) 81 | kv[string(k)] = string(v) 82 | } 83 | return nil 84 | }) 85 | 86 | } 87 | 88 | func CountQuestions() int { 89 | var i int 90 | memoryDb.View(func(tx *bolt.Tx) error { 91 | // Assume bucket exists and has keys 92 | b := tx.Bucket([]byte(QuestionBucket)) 93 | c := b.Cursor() 94 | 95 | for k, _ := c.First(); k != nil; k, _ = c.Next() { 96 | i++ 97 | } 98 | return nil 99 | }) 100 | return i 101 | } 102 | 103 | func MergeQuestions(fs ...string) { 104 | var i int 105 | for _, f := range fs { 106 | thirdDb, err := bolt.Open(f, 0600, nil) 107 | defer thirdDb.Close() 108 | if err != nil { 109 | log.Println("error in merge file db "+f, err.Error()) 110 | continue 111 | } 112 | thirdDb.View(func(thirdTx *bolt.Tx) error { 113 | // Assume bucket exists and has keys 114 | b := thirdTx.Bucket([]byte(QuestionBucket)) 115 | c := b.Cursor() 116 | for k, v := c.First(); k != nil; k, v = c.Next() { 117 | memoryDb.Update(func(tx *bolt.Tx) error { 118 | b := tx.Bucket([]byte(QuestionBucket)) 119 | //三方包的时间 120 | q := DecodeQuestionCols(v, 0) 121 | //数据库中的时间 122 | if q.Update > FetchQuestionTime(string(k)) { 123 | i++ 124 | b.Put(k, q.GetData()) 125 | } 126 | return nil 127 | }) 128 | } 129 | log.Println("merged file", f) 130 | return nil 131 | }) 132 | } 133 | log.Println("merged", i, "questions") 134 | } 135 | 136 | type QuestionCols struct { 137 | Answer string `json:"a"` 138 | Update int64 `json:"ts"` 139 | } 140 | 141 | func NewQuestionCols(answer string) *QuestionCols { 142 | return &QuestionCols{ 143 | Answer: answer, 144 | Update: time.Now().Unix(), 145 | } 146 | } 147 | 148 | func DecodeQuestionCols(bs []byte, update int64) *QuestionCols { 149 | var q = &QuestionCols{} 150 | err := json.Unmarshal(bs, q) 151 | if err == nil { 152 | return q 153 | } else { 154 | q = NewQuestionCols(string(bs)) 155 | q.Update = update 156 | } 157 | return q 158 | } 159 | 160 | func (q *QuestionCols) GetData() []byte { 161 | bs, _ := json.Marshal(q) 162 | return bs 163 | } 164 | 165 | func max(a, b int64) int64 { 166 | if a > b { 167 | return a 168 | } 169 | return b 170 | } 171 | -------------------------------------------------------------------------------- /docs/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sundy-li/wechat_brain/b49fc95d3e06b2841dc394c86831ca07c04d8803/docs/1.jpg -------------------------------------------------------------------------------- /docs/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sundy-li/wechat_brain/b49fc95d3e06b2841dc394c86831ca07c04d8803/docs/2.jpg -------------------------------------------------------------------------------- /docs/3.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sundy-li/wechat_brain/b49fc95d3e06b2841dc394c86831ca07c04d8803/docs/3.jpeg -------------------------------------------------------------------------------- /docs/4.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sundy-li/wechat_brain/b49fc95d3e06b2841dc394c86831ca07c04d8803/docs/4.jpeg -------------------------------------------------------------------------------- /docs/FAQ.md: -------------------------------------------------------------------------------- 1 | FAQ 2 | 3 | ------------------------------------------------------------------------ 4 | 5 | 6 | ## 之前一直正常,偶尔抽风登录不上 7 | 8 | 建议方法, 关掉代理服务, 然后重启微信进程, 打开头脑登录后, 再开代理服务 9 | 10 | 11 | ## 代理设置了,连不上网 12 | 13 | 90%以上可能性是你配置错了代理的ip或者port, 也可能是局域网防火墙问题, 查看ip windows下使用 `ipconfig/all`, linux/unix使用 `ifconfig`, 14 | 附三类内网ip范围 15 | A类:10.0.0.0-10.255.255.255 16 | B类:172.16.0.0-172.31.255.255 17 | C类:192.168.0.0-192.168.255.255 18 | 19 | 20 | ## IOS证书失效 21 | 22 | 很多朋友ios已经试验成功了, 主要是ios要信任证书, 并且配置好正确的代理, 参考 #90 22 23 | 24 | 25 | ## 代理配置成功后,无法访问`abc.com` 26 | 27 | 确保代理的正确配置 28 | 29 | 30 | 31 | ## 我的XXX手机怎么安装证书? 32 | 33 | 这个问题实在很难回答, 作者也没有各种手机来测试兼容, 建议大家百度google一下, 也有的手机厂商不允许安装三方证书, 这种情况只能换个手机了~ 34 | 35 | 36 | ## 自动点击模式不精准 37 | 38 | 自动点击模式不同手机不同兼容,需要修改坐标,修改spider.go代码文件,重新运行 39 | -------------------------------------------------------------------------------- /docs/donate.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sundy-li/wechat_brain/b49fc95d3e06b2841dc394c86831ca07c04d8803/docs/donate.jpg -------------------------------------------------------------------------------- /handler.go: -------------------------------------------------------------------------------- 1 | package wechat_brain 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "log" 7 | "math/rand" 8 | "net/url" 9 | "strconv" 10 | "time" 11 | ) 12 | 13 | var ( 14 | roomID string 15 | ) 16 | 17 | func handleQuestionReq(bs []byte) { 18 | values, _ := url.ParseQuery(string(bs)) 19 | roomID = values.Get("roomID") 20 | } 21 | 22 | //根据题目返回,进行答案搜索 23 | func handleQuestionResp(bs []byte) (bsNew []byte, ansPos int) { 24 | bsNew = bs 25 | question := &Question{} 26 | json.Unmarshal(bs, question) 27 | question.CalData.RoomID = roomID 28 | question.CalData.quizNum = strconv.Itoa(question.Data.Num) 29 | 30 | //Get the answer from the db 31 | answer := FetchQuestion(question) 32 | var ret map[string]int 33 | if answer == "" { 34 | tx := time.Now() 35 | ret = GetFromBaidu(question.Data.Quiz, question.Data.Options) 36 | tx2 := time.Now() 37 | log.Printf("Cost time %d ms\n", tx2.Sub(tx).Nanoseconds()/1e6) 38 | } 39 | question.CalData.TrueAnswer = answer 40 | question.CalData.Answer = answer 41 | SetQuestion(question) 42 | 43 | ansPos = 0 44 | respQuestion := &Question{} 45 | json.Unmarshal(bs, respQuestion) 46 | if question.CalData.TrueAnswer != "" { 47 | for i, option := range respQuestion.Data.Options { 48 | if option == question.CalData.TrueAnswer { 49 | respQuestion.Data.Options[i] = option + "[标准答案]" 50 | ansPos = i + 1 51 | break 52 | } 53 | } 54 | } else { 55 | var max int = 0 56 | for i, option := range respQuestion.Data.Options { 57 | if ret[option] > 0 { 58 | respQuestion.Data.Options[i] = option + "[" + strconv.Itoa(ret[option]) + "]" 59 | if ret[option] > max { 60 | max = ret[option] 61 | ansPos = i + 1 62 | } 63 | } 64 | } 65 | } 66 | bsNew, _ = json.Marshal(respQuestion) 67 | 68 | var out bytes.Buffer 69 | json.Indent(&out, bsNew, "", " ") 70 | //log.Printf("Question answer predict => %v\n", out.String()) 71 | var answerItem string = "不知道" 72 | if ansPos != 0 { 73 | answerItem = respQuestion.Data.Options[ansPos-1] 74 | } else { 75 | //随机点击 76 | ansPos = rand.Intn(4) + 1 77 | } 78 | log.Printf("Question answer predict =>\n 【题目】 %v\n 【正确答案】%v\n", respQuestion.Data.Quiz, answerItem) 79 | 80 | //直接将答案返回在客户端,可能导致封号,所以只在服务端显示 81 | if Mode == 0 { 82 | //返回修改后的答案 83 | return out.Bytes(), ansPos 84 | } else { 85 | //返回答案 86 | return bs, ansPos 87 | } 88 | } 89 | 90 | //hijack 提交请求 91 | func handleChooseReq(bs []byte) (newBs []byte) { 92 | newBs = bs 93 | values, _ := url.ParseQuery(string(bs)) 94 | quizNum := values.Get("quizNum") 95 | question := GetQuestion(roomID, quizNum) 96 | if question == nil { 97 | return 98 | } 99 | // var idx = -1 100 | // for i, option := range question.Data.Options { 101 | // if question.CalData.Answer == option { 102 | // idx = i + 1 //TODO ? 103 | // break 104 | // } 105 | // } 106 | // if idx != -1 { 107 | // values.Set("option", strconv.Itoa(idx)) 108 | // newBs = []byte(values.Encode()) 109 | // } 110 | return 111 | } 112 | 113 | func handleChooseResponse(bs []byte) { 114 | chooseResp := &ChooseResp{} 115 | json.Unmarshal(bs, chooseResp) 116 | 117 | //log.Println("response choose", roomID, chooseResp.Data.Num, string(bs)) 118 | question := GetQuestion(roomID, strconv.Itoa(chooseResp.Data.Num)) 119 | if question == nil { 120 | log.Println("error in get question", chooseResp.Data.RoomID, chooseResp.Data.Num) 121 | return 122 | } 123 | question.CalData.TrueAnswer = question.Data.Options[chooseResp.Data.Answer-1] 124 | if chooseResp.Data.Yes { 125 | question.CalData.TrueAnswer = question.Data.Options[chooseResp.Data.Option-1] 126 | } 127 | log.Printf("【保存数据】 %s, %s", question.Data.Quiz, question.CalData.TrueAnswer) 128 | StoreQuestion(question) 129 | } 130 | 131 | type Question struct { 132 | Data struct { 133 | Quiz string `json:"quiz"` 134 | Options []string `json:"options"` 135 | Num int `json:"num"` 136 | School string `json:"school"` 137 | Type string `json:"type"` 138 | Contributor string `json:"contributor"` 139 | EndTime int `json:"endTime"` 140 | CurTime int `json:"curTime"` 141 | } `json:"data"` 142 | Errcode int `json:"errcode"` 143 | 144 | CalData struct { 145 | RoomID string 146 | quizNum string 147 | Answer string 148 | TrueAnswer string 149 | } `json:"-"` 150 | } 151 | 152 | type ChooseResp struct { 153 | Data struct { 154 | UID int `json:"uid"` 155 | Num int `json:"num"` 156 | Answer int `json:"answer"` 157 | Option int `json:"option"` 158 | Yes bool `json:"yes"` 159 | Score int `json:"score"` 160 | TotalScore int `json:"totalScore"` 161 | RowNum int `json:"rowNum"` 162 | RowMult int `json:"rowMult"` 163 | CostTime int `json:"costTime"` 164 | RoomID int `json:"roomId"` 165 | EnemyScore int `json:"enemyScore"` 166 | EnemyAnswer int `json:"enemyAnswer"` 167 | } `json:"data"` 168 | Errcode int `json:"errcode"` 169 | } 170 | 171 | //roomID=476376430&quizNum=4&option=4&uid=26394007&t=1515326786076&sign=3592b9d28d045f3465206b4147ea872b 172 | -------------------------------------------------------------------------------- /merge.data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sundy-li/wechat_brain/b49fc95d3e06b2841dc394c86831ca07c04d8803/merge.data -------------------------------------------------------------------------------- /questions.data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sundy-li/wechat_brain/b49fc95d3e06b2841dc394c86831ca07c04d8803/questions.data -------------------------------------------------------------------------------- /spider.go: -------------------------------------------------------------------------------- 1 | package wechat_brain 2 | 3 | import ( 4 | "bytes" 5 | "io/ioutil" 6 | "log" 7 | "net/http" 8 | "os/exec" 9 | "strconv" 10 | "time" 11 | 12 | "github.com/coreos/goproxy" 13 | ) 14 | 15 | var ( 16 | _spider = newSpider() 17 | Mode int 18 | AutoMatic int 19 | ) 20 | 21 | type spider struct { 22 | proxy *goproxy.ProxyHttpServer 23 | } 24 | 25 | func Run(port string, mode, automatic int) { 26 | Mode = mode 27 | AutoMatic = automatic 28 | _spider.Init() 29 | _spider.Run(port) 30 | } 31 | 32 | func Close() { 33 | memoryDb.Close() 34 | } 35 | 36 | func newSpider() *spider { 37 | sp := &spider{} 38 | sp.proxy = goproxy.NewProxyHttpServer() 39 | sp.proxy.OnRequest().HandleConnect(goproxy.AlwaysMitm) 40 | return sp 41 | } 42 | 43 | func (s *spider) Run(port string) { 44 | log.Println("server will at port:" + port) 45 | log.Fatal(http.ListenAndServe(":"+port, s.proxy)) 46 | } 47 | 48 | func (s *spider) Init() { 49 | requestHandleFunc := func(request *http.Request, ctx *goproxy.ProxyCtx) (req *http.Request, resp *http.Response) { 50 | req = request 51 | if ctx.Req.URL.Path == `/question/bat/findQuiz` || ctx.Req.URL.Path == `/question/fight/findQuiz` { 52 | bs, _ := ioutil.ReadAll(req.Body) 53 | req.Body = ioutil.NopCloser(bytes.NewReader(bs)) 54 | handleQuestionReq(bs) 55 | } else if ctx.Req.URL.Path == `/question/bat/choose` || ctx.Req.URL.Path == `/question/fight/choose` { 56 | bs, _ := ioutil.ReadAll(req.Body) 57 | req.Body = ioutil.NopCloser(bytes.NewReader(bs)) 58 | handleChooseReq(bs) 59 | } else if ctx.Req.URL.Host == `abc.com` { 60 | resp = new(http.Response) 61 | resp.StatusCode = 200 62 | resp.Header = make(http.Header) 63 | resp.Header.Add("Content-Disposition", "attachment; filename=ca.crt") 64 | resp.Header.Add("Content-Type", "application/octet-stream") 65 | resp.Body = ioutil.NopCloser(bytes.NewReader(goproxy.CA_CERT)) 66 | } 67 | return 68 | } 69 | responseHandleFunc := func(resp *http.Response, ctx *goproxy.ProxyCtx) *http.Response { 70 | if resp == nil { 71 | return resp 72 | } 73 | if ctx.Req.URL.Path == "/question/bat/findQuiz" || ctx.Req.URL.Path == "/question/fight/findQuiz" { 74 | bs, _ := ioutil.ReadAll(resp.Body) 75 | bsNew, ansPos := handleQuestionResp(bs) 76 | resp.Body = ioutil.NopCloser(bytes.NewReader(bsNew)) 77 | if AutoMatic == 1 { 78 | go clickProcess(ansPos) 79 | } // click answer 80 | } else if ctx.Req.URL.Path == "/question/bat/choose" || ctx.Req.URL.Path == "/question/fight/choose" { 81 | bs, _ := ioutil.ReadAll(resp.Body) 82 | resp.Body = ioutil.NopCloser(bytes.NewReader(bs)) 83 | go handleChooseResponse(bs) 84 | } else if ctx.Req.URL.Path == "/question/bat/fightResult" || ctx.Req.URL.Path == "/question/fight/fightResult" { 85 | if AutoMatic == 1 { 86 | go clickProcess(-1) 87 | } // go to next match 88 | } 89 | return resp 90 | } 91 | s.proxy.OnResponse().DoFunc(responseHandleFunc) 92 | s.proxy.OnRequest().DoFunc(requestHandleFunc) 93 | } 94 | 95 | func clickProcess(ansPos int) { 96 | var screanCenterX = 550 // center of screen 97 | var firstItemY = 1280 // center of first item (y) 98 | var qualifyingItemY = 2000 // 排位列表最后一项 y 坐标 99 | if ansPos >= 0 { 100 | log.Printf("【点击】正在点击选项:%d", ansPos) 101 | time.Sleep(time.Millisecond * 3800) //延迟 102 | go clickAction(screanCenterX, firstItemY+200*(ansPos-1)) // process click 103 | } else { 104 | // go to next match 105 | log.Printf("【点击】将点击继续挑战按钮...") 106 | time.Sleep(time.Millisecond * 7500) 107 | go clickAction(screanCenterX, firstItemY+400) // 继续挑战 按钮在第三个item处 108 | log.Printf("【点击】将点击排位列表底部一项,进行比赛匹配...") 109 | time.Sleep(time.Millisecond * 2000) 110 | go clickAction(screanCenterX, qualifyingItemY) 111 | } 112 | } 113 | 114 | func clickAction(posX int, posY int) { 115 | var err error 116 | touchX, touchY := strconv.Itoa(posX), strconv.Itoa(posY) 117 | _, err = exec.Command("adb", "shell", "input", "swipe", touchX, touchY, touchX, touchY).Output() 118 | if err != nil { 119 | log.Fatal("error: check adb connection.") 120 | } 121 | } 122 | 123 | func orPanic(err error) { 124 | if err != nil { 125 | panic(err) 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /vendor/github.com/PuerkitoBio/goquery/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2016, Martin Angers & Contributors 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | * Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 13 | -------------------------------------------------------------------------------- /vendor/github.com/PuerkitoBio/goquery/array.go: -------------------------------------------------------------------------------- 1 | package goquery 2 | 3 | import ( 4 | "golang.org/x/net/html" 5 | ) 6 | 7 | // First reduces the set of matched elements to the first in the set. 8 | // It returns a new Selection object, and an empty Selection object if the 9 | // the selection is empty. 10 | func (s *Selection) First() *Selection { 11 | return s.Eq(0) 12 | } 13 | 14 | // Last reduces the set of matched elements to the last in the set. 15 | // It returns a new Selection object, and an empty Selection object if 16 | // the selection is empty. 17 | func (s *Selection) Last() *Selection { 18 | return s.Eq(-1) 19 | } 20 | 21 | // Eq reduces the set of matched elements to the one at the specified index. 22 | // If a negative index is given, it counts backwards starting at the end of the 23 | // set. It returns a new Selection object, and an empty Selection object if the 24 | // index is invalid. 25 | func (s *Selection) Eq(index int) *Selection { 26 | if index < 0 { 27 | index += len(s.Nodes) 28 | } 29 | 30 | if index >= len(s.Nodes) || index < 0 { 31 | return newEmptySelection(s.document) 32 | } 33 | 34 | return s.Slice(index, index+1) 35 | } 36 | 37 | // Slice reduces the set of matched elements to a subset specified by a range 38 | // of indices. 39 | func (s *Selection) Slice(start, end int) *Selection { 40 | if start < 0 { 41 | start += len(s.Nodes) 42 | } 43 | if end < 0 { 44 | end += len(s.Nodes) 45 | } 46 | return pushStack(s, s.Nodes[start:end]) 47 | } 48 | 49 | // Get retrieves the underlying node at the specified index. 50 | // Get without parameter is not implemented, since the node array is available 51 | // on the Selection object. 52 | func (s *Selection) Get(index int) *html.Node { 53 | if index < 0 { 54 | index += len(s.Nodes) // Negative index gets from the end 55 | } 56 | return s.Nodes[index] 57 | } 58 | 59 | // Index returns the position of the first element within the Selection object 60 | // relative to its sibling elements. 61 | func (s *Selection) Index() int { 62 | if len(s.Nodes) > 0 { 63 | return newSingleSelection(s.Nodes[0], s.document).PrevAll().Length() 64 | } 65 | return -1 66 | } 67 | 68 | // IndexSelector returns the position of the first element within the 69 | // Selection object relative to the elements matched by the selector, or -1 if 70 | // not found. 71 | func (s *Selection) IndexSelector(selector string) int { 72 | if len(s.Nodes) > 0 { 73 | sel := s.document.Find(selector) 74 | return indexInSlice(sel.Nodes, s.Nodes[0]) 75 | } 76 | return -1 77 | } 78 | 79 | // IndexMatcher returns the position of the first element within the 80 | // Selection object relative to the elements matched by the matcher, or -1 if 81 | // not found. 82 | func (s *Selection) IndexMatcher(m Matcher) int { 83 | if len(s.Nodes) > 0 { 84 | sel := s.document.FindMatcher(m) 85 | return indexInSlice(sel.Nodes, s.Nodes[0]) 86 | } 87 | return -1 88 | } 89 | 90 | // IndexOfNode returns the position of the specified node within the Selection 91 | // object, or -1 if not found. 92 | func (s *Selection) IndexOfNode(node *html.Node) int { 93 | return indexInSlice(s.Nodes, node) 94 | } 95 | 96 | // IndexOfSelection returns the position of the first node in the specified 97 | // Selection object within this Selection object, or -1 if not found. 98 | func (s *Selection) IndexOfSelection(sel *Selection) int { 99 | if sel != nil && len(sel.Nodes) > 0 { 100 | return indexInSlice(s.Nodes, sel.Nodes[0]) 101 | } 102 | return -1 103 | } 104 | -------------------------------------------------------------------------------- /vendor/github.com/PuerkitoBio/goquery/expand.go: -------------------------------------------------------------------------------- 1 | package goquery 2 | 3 | import "golang.org/x/net/html" 4 | 5 | // Add adds the selector string's matching nodes to those in the current 6 | // selection and returns a new Selection object. 7 | // The selector string is run in the context of the document of the current 8 | // Selection object. 9 | func (s *Selection) Add(selector string) *Selection { 10 | return s.AddNodes(findWithMatcher([]*html.Node{s.document.rootNode}, compileMatcher(selector))...) 11 | } 12 | 13 | // AddMatcher adds the matcher's matching nodes to those in the current 14 | // selection and returns a new Selection object. 15 | // The matcher is run in the context of the document of the current 16 | // Selection object. 17 | func (s *Selection) AddMatcher(m Matcher) *Selection { 18 | return s.AddNodes(findWithMatcher([]*html.Node{s.document.rootNode}, m)...) 19 | } 20 | 21 | // AddSelection adds the specified Selection object's nodes to those in the 22 | // current selection and returns a new Selection object. 23 | func (s *Selection) AddSelection(sel *Selection) *Selection { 24 | if sel == nil { 25 | return s.AddNodes() 26 | } 27 | return s.AddNodes(sel.Nodes...) 28 | } 29 | 30 | // Union is an alias for AddSelection. 31 | func (s *Selection) Union(sel *Selection) *Selection { 32 | return s.AddSelection(sel) 33 | } 34 | 35 | // AddNodes adds the specified nodes to those in the 36 | // current selection and returns a new Selection object. 37 | func (s *Selection) AddNodes(nodes ...*html.Node) *Selection { 38 | return pushStack(s, appendWithoutDuplicates(s.Nodes, nodes, nil)) 39 | } 40 | 41 | // AndSelf adds the previous set of elements on the stack to the current set. 42 | // It returns a new Selection object containing the current Selection combined 43 | // with the previous one. 44 | func (s *Selection) AndSelf() *Selection { 45 | return s.AddSelection(s.prevSel) 46 | } 47 | -------------------------------------------------------------------------------- /vendor/github.com/PuerkitoBio/goquery/iteration.go: -------------------------------------------------------------------------------- 1 | package goquery 2 | 3 | // Each iterates over a Selection object, executing a function for each 4 | // matched element. It returns the current Selection object. The function 5 | // f is called for each element in the selection with the index of the 6 | // element in that selection starting at 0, and a *Selection that contains 7 | // only that element. 8 | func (s *Selection) Each(f func(int, *Selection)) *Selection { 9 | for i, n := range s.Nodes { 10 | f(i, newSingleSelection(n, s.document)) 11 | } 12 | return s 13 | } 14 | 15 | // EachWithBreak iterates over a Selection object, executing a function for each 16 | // matched element. It is identical to Each except that it is possible to break 17 | // out of the loop by returning false in the callback function. It returns the 18 | // current Selection object. 19 | func (s *Selection) EachWithBreak(f func(int, *Selection) bool) *Selection { 20 | for i, n := range s.Nodes { 21 | if !f(i, newSingleSelection(n, s.document)) { 22 | return s 23 | } 24 | } 25 | return s 26 | } 27 | 28 | // Map passes each element in the current matched set through a function, 29 | // producing a slice of string holding the returned values. The function 30 | // f is called for each element in the selection with the index of the 31 | // element in that selection starting at 0, and a *Selection that contains 32 | // only that element. 33 | func (s *Selection) Map(f func(int, *Selection) string) (result []string) { 34 | for i, n := range s.Nodes { 35 | result = append(result, f(i, newSingleSelection(n, s.document))) 36 | } 37 | 38 | return result 39 | } 40 | -------------------------------------------------------------------------------- /vendor/github.com/PuerkitoBio/goquery/query.go: -------------------------------------------------------------------------------- 1 | package goquery 2 | 3 | import "golang.org/x/net/html" 4 | 5 | // Is checks the current matched set of elements against a selector and 6 | // returns true if at least one of these elements matches. 7 | func (s *Selection) Is(selector string) bool { 8 | if len(s.Nodes) > 0 { 9 | return s.IsMatcher(compileMatcher(selector)) 10 | } 11 | 12 | return false 13 | } 14 | 15 | // IsMatcher checks the current matched set of elements against a matcher and 16 | // returns true if at least one of these elements matches. 17 | func (s *Selection) IsMatcher(m Matcher) bool { 18 | if len(s.Nodes) > 0 { 19 | if len(s.Nodes) == 1 { 20 | return m.Match(s.Nodes[0]) 21 | } 22 | return len(m.Filter(s.Nodes)) > 0 23 | } 24 | 25 | return false 26 | } 27 | 28 | // IsFunction checks the current matched set of elements against a predicate and 29 | // returns true if at least one of these elements matches. 30 | func (s *Selection) IsFunction(f func(int, *Selection) bool) bool { 31 | return s.FilterFunction(f).Length() > 0 32 | } 33 | 34 | // IsSelection checks the current matched set of elements against a Selection object 35 | // and returns true if at least one of these elements matches. 36 | func (s *Selection) IsSelection(sel *Selection) bool { 37 | return s.FilterSelection(sel).Length() > 0 38 | } 39 | 40 | // IsNodes checks the current matched set of elements against the specified nodes 41 | // and returns true if at least one of these elements matches. 42 | func (s *Selection) IsNodes(nodes ...*html.Node) bool { 43 | return s.FilterNodes(nodes...).Length() > 0 44 | } 45 | 46 | // Contains returns true if the specified Node is within, 47 | // at any depth, one of the nodes in the Selection object. 48 | // It is NOT inclusive, to behave like jQuery's implementation, and 49 | // unlike Javascript's .contains, so if the contained 50 | // node is itself in the selection, it returns false. 51 | func (s *Selection) Contains(n *html.Node) bool { 52 | return sliceContains(s.Nodes, n) 53 | } 54 | -------------------------------------------------------------------------------- /vendor/github.com/PuerkitoBio/goquery/type.go: -------------------------------------------------------------------------------- 1 | package goquery 2 | 3 | import ( 4 | "errors" 5 | "io" 6 | "net/http" 7 | "net/url" 8 | 9 | "github.com/andybalholm/cascadia" 10 | 11 | "golang.org/x/net/html" 12 | ) 13 | 14 | // Document represents an HTML document to be manipulated. Unlike jQuery, which 15 | // is loaded as part of a DOM document, and thus acts upon its containing 16 | // document, GoQuery doesn't know which HTML document to act upon. So it needs 17 | // to be told, and that's what the Document class is for. It holds the root 18 | // document node to manipulate, and can make selections on this document. 19 | type Document struct { 20 | *Selection 21 | Url *url.URL 22 | rootNode *html.Node 23 | } 24 | 25 | // NewDocumentFromNode is a Document constructor that takes a root html Node 26 | // as argument. 27 | func NewDocumentFromNode(root *html.Node) *Document { 28 | return newDocument(root, nil) 29 | } 30 | 31 | // NewDocument is a Document constructor that takes a string URL as argument. 32 | // It loads the specified document, parses it, and stores the root Document 33 | // node, ready to be manipulated. 34 | func NewDocument(url string) (*Document, error) { 35 | // Load the URL 36 | res, e := http.Get(url) 37 | if e != nil { 38 | return nil, e 39 | } 40 | return NewDocumentFromResponse(res) 41 | } 42 | 43 | // NewDocumentFromReader returns a Document from a generic reader. 44 | // It returns an error as second value if the reader's data cannot be parsed 45 | // as html. It does *not* check if the reader is also an io.Closer, so the 46 | // provided reader is never closed by this call, it is the responsibility 47 | // of the caller to close it if required. 48 | func NewDocumentFromReader(r io.Reader) (*Document, error) { 49 | root, e := html.Parse(r) 50 | if e != nil { 51 | return nil, e 52 | } 53 | return newDocument(root, nil), nil 54 | } 55 | 56 | // NewDocumentFromResponse is another Document constructor that takes an http response as argument. 57 | // It loads the specified response's document, parses it, and stores the root Document 58 | // node, ready to be manipulated. The response's body is closed on return. 59 | func NewDocumentFromResponse(res *http.Response) (*Document, error) { 60 | if res == nil { 61 | return nil, errors.New("Response is nil") 62 | } 63 | defer res.Body.Close() 64 | if res.Request == nil { 65 | return nil, errors.New("Response.Request is nil") 66 | } 67 | 68 | // Parse the HTML into nodes 69 | root, e := html.Parse(res.Body) 70 | if e != nil { 71 | return nil, e 72 | } 73 | 74 | // Create and fill the document 75 | return newDocument(root, res.Request.URL), nil 76 | } 77 | 78 | // CloneDocument creates a deep-clone of a document. 79 | func CloneDocument(doc *Document) *Document { 80 | return newDocument(cloneNode(doc.rootNode), doc.Url) 81 | } 82 | 83 | // Private constructor, make sure all fields are correctly filled. 84 | func newDocument(root *html.Node, url *url.URL) *Document { 85 | // Create and fill the document 86 | d := &Document{nil, url, root} 87 | d.Selection = newSingleSelection(root, d) 88 | return d 89 | } 90 | 91 | // Selection represents a collection of nodes matching some criteria. The 92 | // initial Selection can be created by using Document.Find, and then 93 | // manipulated using the jQuery-like chainable syntax and methods. 94 | type Selection struct { 95 | Nodes []*html.Node 96 | document *Document 97 | prevSel *Selection 98 | } 99 | 100 | // Helper constructor to create an empty selection 101 | func newEmptySelection(doc *Document) *Selection { 102 | return &Selection{nil, doc, nil} 103 | } 104 | 105 | // Helper constructor to create a selection of only one node 106 | func newSingleSelection(node *html.Node, doc *Document) *Selection { 107 | return &Selection{[]*html.Node{node}, doc, nil} 108 | } 109 | 110 | // Matcher is an interface that defines the methods to match 111 | // HTML nodes against a compiled selector string. Cascadia's 112 | // Selector implements this interface. 113 | type Matcher interface { 114 | Match(*html.Node) bool 115 | MatchAll(*html.Node) []*html.Node 116 | Filter([]*html.Node) []*html.Node 117 | } 118 | 119 | // compileMatcher compiles the selector string s and returns 120 | // the corresponding Matcher. If s is an invalid selector string, 121 | // it returns a Matcher that fails all matches. 122 | func compileMatcher(s string) Matcher { 123 | cs, err := cascadia.Compile(s) 124 | if err != nil { 125 | return invalidMatcher{} 126 | } 127 | return cs 128 | } 129 | 130 | // invalidMatcher is a Matcher that always fails to match. 131 | type invalidMatcher struct{} 132 | 133 | func (invalidMatcher) Match(n *html.Node) bool { return false } 134 | func (invalidMatcher) MatchAll(n *html.Node) []*html.Node { return nil } 135 | func (invalidMatcher) Filter(ns []*html.Node) []*html.Node { return nil } 136 | -------------------------------------------------------------------------------- /vendor/github.com/andybalholm/cascadia/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011 Andy Balholm. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 15 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 18 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /vendor/github.com/andybalholm/cascadia/README.md: -------------------------------------------------------------------------------- 1 | # cascadia 2 | 3 | [![](https://travis-ci.org/andybalholm/cascadia.svg)](https://travis-ci.org/andybalholm/cascadia) 4 | 5 | The Cascadia package implements CSS selectors for use with the parse trees produced by the html package. 6 | 7 | To test CSS selectors without writing Go code, check out [cascadia](https://github.com/suntong/cascadia) the command line tool, a thin wrapper around this package. 8 | -------------------------------------------------------------------------------- /vendor/github.com/boltdb/bolt/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Ben Johnson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /vendor/github.com/boltdb/bolt/Makefile: -------------------------------------------------------------------------------- 1 | BRANCH=`git rev-parse --abbrev-ref HEAD` 2 | COMMIT=`git rev-parse --short HEAD` 3 | GOLDFLAGS="-X main.branch $(BRANCH) -X main.commit $(COMMIT)" 4 | 5 | default: build 6 | 7 | race: 8 | @go test -v -race -test.run="TestSimulate_(100op|1000op)" 9 | 10 | # go get github.com/kisielk/errcheck 11 | errcheck: 12 | @errcheck -ignorepkg=bytes -ignore=os:Remove github.com/boltdb/bolt 13 | 14 | test: 15 | @go test -v -cover . 16 | @go test -v ./cmd/bolt 17 | 18 | .PHONY: fmt test 19 | -------------------------------------------------------------------------------- /vendor/github.com/boltdb/bolt/appveyor.yml: -------------------------------------------------------------------------------- 1 | version: "{build}" 2 | 3 | os: Windows Server 2012 R2 4 | 5 | clone_folder: c:\gopath\src\github.com\boltdb\bolt 6 | 7 | environment: 8 | GOPATH: c:\gopath 9 | 10 | install: 11 | - echo %PATH% 12 | - echo %GOPATH% 13 | - go version 14 | - go env 15 | - go get -v -t ./... 16 | 17 | build_script: 18 | - go test -v ./... 19 | -------------------------------------------------------------------------------- /vendor/github.com/boltdb/bolt/bolt_386.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | // maxMapSize represents the largest mmap size supported by Bolt. 4 | const maxMapSize = 0x7FFFFFFF // 2GB 5 | 6 | // maxAllocSize is the size used when creating array pointers. 7 | const maxAllocSize = 0xFFFFFFF 8 | 9 | // Are unaligned load/stores broken on this arch? 10 | var brokenUnaligned = false 11 | -------------------------------------------------------------------------------- /vendor/github.com/boltdb/bolt/bolt_amd64.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | // maxMapSize represents the largest mmap size supported by Bolt. 4 | const maxMapSize = 0xFFFFFFFFFFFF // 256TB 5 | 6 | // maxAllocSize is the size used when creating array pointers. 7 | const maxAllocSize = 0x7FFFFFFF 8 | 9 | // Are unaligned load/stores broken on this arch? 10 | var brokenUnaligned = false 11 | -------------------------------------------------------------------------------- /vendor/github.com/boltdb/bolt/bolt_arm.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | import "unsafe" 4 | 5 | // maxMapSize represents the largest mmap size supported by Bolt. 6 | const maxMapSize = 0x7FFFFFFF // 2GB 7 | 8 | // maxAllocSize is the size used when creating array pointers. 9 | const maxAllocSize = 0xFFFFFFF 10 | 11 | // Are unaligned load/stores broken on this arch? 12 | var brokenUnaligned bool 13 | 14 | func init() { 15 | // Simple check to see whether this arch handles unaligned load/stores 16 | // correctly. 17 | 18 | // ARM9 and older devices require load/stores to be from/to aligned 19 | // addresses. If not, the lower 2 bits are cleared and that address is 20 | // read in a jumbled up order. 21 | 22 | // See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka15414.html 23 | 24 | raw := [6]byte{0xfe, 0xef, 0x11, 0x22, 0x22, 0x11} 25 | val := *(*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(&raw)) + 2)) 26 | 27 | brokenUnaligned = val != 0x11222211 28 | } 29 | -------------------------------------------------------------------------------- /vendor/github.com/boltdb/bolt/bolt_arm64.go: -------------------------------------------------------------------------------- 1 | // +build arm64 2 | 3 | package bolt 4 | 5 | // maxMapSize represents the largest mmap size supported by Bolt. 6 | const maxMapSize = 0xFFFFFFFFFFFF // 256TB 7 | 8 | // maxAllocSize is the size used when creating array pointers. 9 | const maxAllocSize = 0x7FFFFFFF 10 | 11 | // Are unaligned load/stores broken on this arch? 12 | var brokenUnaligned = false 13 | -------------------------------------------------------------------------------- /vendor/github.com/boltdb/bolt/bolt_linux.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | import ( 4 | "syscall" 5 | ) 6 | 7 | // fdatasync flushes written data to a file descriptor. 8 | func fdatasync(db *DB) error { 9 | return syscall.Fdatasync(int(db.file.Fd())) 10 | } 11 | -------------------------------------------------------------------------------- /vendor/github.com/boltdb/bolt/bolt_openbsd.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | import ( 4 | "syscall" 5 | "unsafe" 6 | ) 7 | 8 | const ( 9 | msAsync = 1 << iota // perform asynchronous writes 10 | msSync // perform synchronous writes 11 | msInvalidate // invalidate cached data 12 | ) 13 | 14 | func msync(db *DB) error { 15 | _, _, errno := syscall.Syscall(syscall.SYS_MSYNC, uintptr(unsafe.Pointer(db.data)), uintptr(db.datasz), msInvalidate) 16 | if errno != 0 { 17 | return errno 18 | } 19 | return nil 20 | } 21 | 22 | func fdatasync(db *DB) error { 23 | if db.data != nil { 24 | return msync(db) 25 | } 26 | return db.file.Sync() 27 | } 28 | -------------------------------------------------------------------------------- /vendor/github.com/boltdb/bolt/bolt_ppc.go: -------------------------------------------------------------------------------- 1 | // +build ppc 2 | 3 | package bolt 4 | 5 | // maxMapSize represents the largest mmap size supported by Bolt. 6 | const maxMapSize = 0x7FFFFFFF // 2GB 7 | 8 | // maxAllocSize is the size used when creating array pointers. 9 | const maxAllocSize = 0xFFFFFFF 10 | -------------------------------------------------------------------------------- /vendor/github.com/boltdb/bolt/bolt_ppc64.go: -------------------------------------------------------------------------------- 1 | // +build ppc64 2 | 3 | package bolt 4 | 5 | // maxMapSize represents the largest mmap size supported by Bolt. 6 | const maxMapSize = 0xFFFFFFFFFFFF // 256TB 7 | 8 | // maxAllocSize is the size used when creating array pointers. 9 | const maxAllocSize = 0x7FFFFFFF 10 | 11 | // Are unaligned load/stores broken on this arch? 12 | var brokenUnaligned = false 13 | -------------------------------------------------------------------------------- /vendor/github.com/boltdb/bolt/bolt_ppc64le.go: -------------------------------------------------------------------------------- 1 | // +build ppc64le 2 | 3 | package bolt 4 | 5 | // maxMapSize represents the largest mmap size supported by Bolt. 6 | const maxMapSize = 0xFFFFFFFFFFFF // 256TB 7 | 8 | // maxAllocSize is the size used when creating array pointers. 9 | const maxAllocSize = 0x7FFFFFFF 10 | 11 | // Are unaligned load/stores broken on this arch? 12 | var brokenUnaligned = false 13 | -------------------------------------------------------------------------------- /vendor/github.com/boltdb/bolt/bolt_s390x.go: -------------------------------------------------------------------------------- 1 | // +build s390x 2 | 3 | package bolt 4 | 5 | // maxMapSize represents the largest mmap size supported by Bolt. 6 | const maxMapSize = 0xFFFFFFFFFFFF // 256TB 7 | 8 | // maxAllocSize is the size used when creating array pointers. 9 | const maxAllocSize = 0x7FFFFFFF 10 | 11 | // Are unaligned load/stores broken on this arch? 12 | var brokenUnaligned = false 13 | -------------------------------------------------------------------------------- /vendor/github.com/boltdb/bolt/bolt_unix.go: -------------------------------------------------------------------------------- 1 | // +build !windows,!plan9,!solaris 2 | 3 | package bolt 4 | 5 | import ( 6 | "fmt" 7 | "os" 8 | "syscall" 9 | "time" 10 | "unsafe" 11 | ) 12 | 13 | // flock acquires an advisory lock on a file descriptor. 14 | func flock(db *DB, mode os.FileMode, exclusive bool, timeout time.Duration) error { 15 | var t time.Time 16 | for { 17 | // If we're beyond our timeout then return an error. 18 | // This can only occur after we've attempted a flock once. 19 | if t.IsZero() { 20 | t = time.Now() 21 | } else if timeout > 0 && time.Since(t) > timeout { 22 | return ErrTimeout 23 | } 24 | flag := syscall.LOCK_SH 25 | if exclusive { 26 | flag = syscall.LOCK_EX 27 | } 28 | 29 | // Otherwise attempt to obtain an exclusive lock. 30 | err := syscall.Flock(int(db.file.Fd()), flag|syscall.LOCK_NB) 31 | if err == nil { 32 | return nil 33 | } else if err != syscall.EWOULDBLOCK { 34 | return err 35 | } 36 | 37 | // Wait for a bit and try again. 38 | time.Sleep(50 * time.Millisecond) 39 | } 40 | } 41 | 42 | // funlock releases an advisory lock on a file descriptor. 43 | func funlock(db *DB) error { 44 | return syscall.Flock(int(db.file.Fd()), syscall.LOCK_UN) 45 | } 46 | 47 | // mmap memory maps a DB's data file. 48 | func mmap(db *DB, sz int) error { 49 | // Map the data file to memory. 50 | b, err := syscall.Mmap(int(db.file.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED|db.MmapFlags) 51 | if err != nil { 52 | return err 53 | } 54 | 55 | // Advise the kernel that the mmap is accessed randomly. 56 | if err := madvise(b, syscall.MADV_RANDOM); err != nil { 57 | return fmt.Errorf("madvise: %s", err) 58 | } 59 | 60 | // Save the original byte slice and convert to a byte array pointer. 61 | db.dataref = b 62 | db.data = (*[maxMapSize]byte)(unsafe.Pointer(&b[0])) 63 | db.datasz = sz 64 | return nil 65 | } 66 | 67 | // munmap unmaps a DB's data file from memory. 68 | func munmap(db *DB) error { 69 | // Ignore the unmap if we have no mapped data. 70 | if db.dataref == nil { 71 | return nil 72 | } 73 | 74 | // Unmap using the original byte slice. 75 | err := syscall.Munmap(db.dataref) 76 | db.dataref = nil 77 | db.data = nil 78 | db.datasz = 0 79 | return err 80 | } 81 | 82 | // NOTE: This function is copied from stdlib because it is not available on darwin. 83 | func madvise(b []byte, advice int) (err error) { 84 | _, _, e1 := syscall.Syscall(syscall.SYS_MADVISE, uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), uintptr(advice)) 85 | if e1 != 0 { 86 | err = e1 87 | } 88 | return 89 | } 90 | -------------------------------------------------------------------------------- /vendor/github.com/boltdb/bolt/bolt_unix_solaris.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "syscall" 7 | "time" 8 | "unsafe" 9 | 10 | "golang.org/x/sys/unix" 11 | ) 12 | 13 | // flock acquires an advisory lock on a file descriptor. 14 | func flock(db *DB, mode os.FileMode, exclusive bool, timeout time.Duration) error { 15 | var t time.Time 16 | for { 17 | // If we're beyond our timeout then return an error. 18 | // This can only occur after we've attempted a flock once. 19 | if t.IsZero() { 20 | t = time.Now() 21 | } else if timeout > 0 && time.Since(t) > timeout { 22 | return ErrTimeout 23 | } 24 | var lock syscall.Flock_t 25 | lock.Start = 0 26 | lock.Len = 0 27 | lock.Pid = 0 28 | lock.Whence = 0 29 | lock.Pid = 0 30 | if exclusive { 31 | lock.Type = syscall.F_WRLCK 32 | } else { 33 | lock.Type = syscall.F_RDLCK 34 | } 35 | err := syscall.FcntlFlock(db.file.Fd(), syscall.F_SETLK, &lock) 36 | if err == nil { 37 | return nil 38 | } else if err != syscall.EAGAIN { 39 | return err 40 | } 41 | 42 | // Wait for a bit and try again. 43 | time.Sleep(50 * time.Millisecond) 44 | } 45 | } 46 | 47 | // funlock releases an advisory lock on a file descriptor. 48 | func funlock(db *DB) error { 49 | var lock syscall.Flock_t 50 | lock.Start = 0 51 | lock.Len = 0 52 | lock.Type = syscall.F_UNLCK 53 | lock.Whence = 0 54 | return syscall.FcntlFlock(uintptr(db.file.Fd()), syscall.F_SETLK, &lock) 55 | } 56 | 57 | // mmap memory maps a DB's data file. 58 | func mmap(db *DB, sz int) error { 59 | // Map the data file to memory. 60 | b, err := unix.Mmap(int(db.file.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED|db.MmapFlags) 61 | if err != nil { 62 | return err 63 | } 64 | 65 | // Advise the kernel that the mmap is accessed randomly. 66 | if err := unix.Madvise(b, syscall.MADV_RANDOM); err != nil { 67 | return fmt.Errorf("madvise: %s", err) 68 | } 69 | 70 | // Save the original byte slice and convert to a byte array pointer. 71 | db.dataref = b 72 | db.data = (*[maxMapSize]byte)(unsafe.Pointer(&b[0])) 73 | db.datasz = sz 74 | return nil 75 | } 76 | 77 | // munmap unmaps a DB's data file from memory. 78 | func munmap(db *DB) error { 79 | // Ignore the unmap if we have no mapped data. 80 | if db.dataref == nil { 81 | return nil 82 | } 83 | 84 | // Unmap using the original byte slice. 85 | err := unix.Munmap(db.dataref) 86 | db.dataref = nil 87 | db.data = nil 88 | db.datasz = 0 89 | return err 90 | } 91 | -------------------------------------------------------------------------------- /vendor/github.com/boltdb/bolt/bolt_windows.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "syscall" 7 | "time" 8 | "unsafe" 9 | ) 10 | 11 | // LockFileEx code derived from golang build filemutex_windows.go @ v1.5.1 12 | var ( 13 | modkernel32 = syscall.NewLazyDLL("kernel32.dll") 14 | procLockFileEx = modkernel32.NewProc("LockFileEx") 15 | procUnlockFileEx = modkernel32.NewProc("UnlockFileEx") 16 | ) 17 | 18 | const ( 19 | lockExt = ".lock" 20 | 21 | // see https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx 22 | flagLockExclusive = 2 23 | flagLockFailImmediately = 1 24 | 25 | // see https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx 26 | errLockViolation syscall.Errno = 0x21 27 | ) 28 | 29 | func lockFileEx(h syscall.Handle, flags, reserved, locklow, lockhigh uint32, ol *syscall.Overlapped) (err error) { 30 | r, _, err := procLockFileEx.Call(uintptr(h), uintptr(flags), uintptr(reserved), uintptr(locklow), uintptr(lockhigh), uintptr(unsafe.Pointer(ol))) 31 | if r == 0 { 32 | return err 33 | } 34 | return nil 35 | } 36 | 37 | func unlockFileEx(h syscall.Handle, reserved, locklow, lockhigh uint32, ol *syscall.Overlapped) (err error) { 38 | r, _, err := procUnlockFileEx.Call(uintptr(h), uintptr(reserved), uintptr(locklow), uintptr(lockhigh), uintptr(unsafe.Pointer(ol)), 0) 39 | if r == 0 { 40 | return err 41 | } 42 | return nil 43 | } 44 | 45 | // fdatasync flushes written data to a file descriptor. 46 | func fdatasync(db *DB) error { 47 | return db.file.Sync() 48 | } 49 | 50 | // flock acquires an advisory lock on a file descriptor. 51 | func flock(db *DB, mode os.FileMode, exclusive bool, timeout time.Duration) error { 52 | // Create a separate lock file on windows because a process 53 | // cannot share an exclusive lock on the same file. This is 54 | // needed during Tx.WriteTo(). 55 | f, err := os.OpenFile(db.path+lockExt, os.O_CREATE, mode) 56 | if err != nil { 57 | return err 58 | } 59 | db.lockfile = f 60 | 61 | var t time.Time 62 | for { 63 | // If we're beyond our timeout then return an error. 64 | // This can only occur after we've attempted a flock once. 65 | if t.IsZero() { 66 | t = time.Now() 67 | } else if timeout > 0 && time.Since(t) > timeout { 68 | return ErrTimeout 69 | } 70 | 71 | var flag uint32 = flagLockFailImmediately 72 | if exclusive { 73 | flag |= flagLockExclusive 74 | } 75 | 76 | err := lockFileEx(syscall.Handle(db.lockfile.Fd()), flag, 0, 1, 0, &syscall.Overlapped{}) 77 | if err == nil { 78 | return nil 79 | } else if err != errLockViolation { 80 | return err 81 | } 82 | 83 | // Wait for a bit and try again. 84 | time.Sleep(50 * time.Millisecond) 85 | } 86 | } 87 | 88 | // funlock releases an advisory lock on a file descriptor. 89 | func funlock(db *DB) error { 90 | err := unlockFileEx(syscall.Handle(db.lockfile.Fd()), 0, 1, 0, &syscall.Overlapped{}) 91 | db.lockfile.Close() 92 | os.Remove(db.path + lockExt) 93 | return err 94 | } 95 | 96 | // mmap memory maps a DB's data file. 97 | // Based on: https://github.com/edsrzf/mmap-go 98 | func mmap(db *DB, sz int) error { 99 | if !db.readOnly { 100 | // Truncate the database to the size of the mmap. 101 | if err := db.file.Truncate(int64(sz)); err != nil { 102 | return fmt.Errorf("truncate: %s", err) 103 | } 104 | } 105 | 106 | // Open a file mapping handle. 107 | sizelo := uint32(sz >> 32) 108 | sizehi := uint32(sz) & 0xffffffff 109 | h, errno := syscall.CreateFileMapping(syscall.Handle(db.file.Fd()), nil, syscall.PAGE_READONLY, sizelo, sizehi, nil) 110 | if h == 0 { 111 | return os.NewSyscallError("CreateFileMapping", errno) 112 | } 113 | 114 | // Create the memory map. 115 | addr, errno := syscall.MapViewOfFile(h, syscall.FILE_MAP_READ, 0, 0, uintptr(sz)) 116 | if addr == 0 { 117 | return os.NewSyscallError("MapViewOfFile", errno) 118 | } 119 | 120 | // Close mapping handle. 121 | if err := syscall.CloseHandle(syscall.Handle(h)); err != nil { 122 | return os.NewSyscallError("CloseHandle", err) 123 | } 124 | 125 | // Convert to a byte array. 126 | db.data = ((*[maxMapSize]byte)(unsafe.Pointer(addr))) 127 | db.datasz = sz 128 | 129 | return nil 130 | } 131 | 132 | // munmap unmaps a pointer from a file. 133 | // Based on: https://github.com/edsrzf/mmap-go 134 | func munmap(db *DB) error { 135 | if db.data == nil { 136 | return nil 137 | } 138 | 139 | addr := (uintptr)(unsafe.Pointer(&db.data[0])) 140 | if err := syscall.UnmapViewOfFile(addr); err != nil { 141 | return os.NewSyscallError("UnmapViewOfFile", err) 142 | } 143 | return nil 144 | } 145 | -------------------------------------------------------------------------------- /vendor/github.com/boltdb/bolt/boltsync_unix.go: -------------------------------------------------------------------------------- 1 | // +build !windows,!plan9,!linux,!openbsd 2 | 3 | package bolt 4 | 5 | // fdatasync flushes written data to a file descriptor. 6 | func fdatasync(db *DB) error { 7 | return db.file.Sync() 8 | } 9 | -------------------------------------------------------------------------------- /vendor/github.com/boltdb/bolt/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package bolt implements a low-level key/value store in pure Go. It supports 3 | fully serializable transactions, ACID semantics, and lock-free MVCC with 4 | multiple readers and a single writer. Bolt can be used for projects that 5 | want a simple data store without the need to add large dependencies such as 6 | Postgres or MySQL. 7 | 8 | Bolt is a single-level, zero-copy, B+tree data store. This means that Bolt is 9 | optimized for fast read access and does not require recovery in the event of a 10 | system crash. Transactions which have not finished committing will simply be 11 | rolled back in the event of a crash. 12 | 13 | The design of Bolt is based on Howard Chu's LMDB database project. 14 | 15 | Bolt currently works on Windows, Mac OS X, and Linux. 16 | 17 | 18 | Basics 19 | 20 | There are only a few types in Bolt: DB, Bucket, Tx, and Cursor. The DB is 21 | a collection of buckets and is represented by a single file on disk. A bucket is 22 | a collection of unique keys that are associated with values. 23 | 24 | Transactions provide either read-only or read-write access to the database. 25 | Read-only transactions can retrieve key/value pairs and can use Cursors to 26 | iterate over the dataset sequentially. Read-write transactions can create and 27 | delete buckets and can insert and remove keys. Only one read-write transaction 28 | is allowed at a time. 29 | 30 | 31 | Caveats 32 | 33 | The database uses a read-only, memory-mapped data file to ensure that 34 | applications cannot corrupt the database, however, this means that keys and 35 | values returned from Bolt cannot be changed. Writing to a read-only byte slice 36 | will cause Go to panic. 37 | 38 | Keys and values retrieved from the database are only valid for the life of 39 | the transaction. When used outside the transaction, these byte slices can 40 | point to different data or can point to invalid memory which will cause a panic. 41 | 42 | 43 | */ 44 | package bolt 45 | -------------------------------------------------------------------------------- /vendor/github.com/boltdb/bolt/errors.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | import "errors" 4 | 5 | // These errors can be returned when opening or calling methods on a DB. 6 | var ( 7 | // ErrDatabaseNotOpen is returned when a DB instance is accessed before it 8 | // is opened or after it is closed. 9 | ErrDatabaseNotOpen = errors.New("database not open") 10 | 11 | // ErrDatabaseOpen is returned when opening a database that is 12 | // already open. 13 | ErrDatabaseOpen = errors.New("database already open") 14 | 15 | // ErrInvalid is returned when both meta pages on a database are invalid. 16 | // This typically occurs when a file is not a bolt database. 17 | ErrInvalid = errors.New("invalid database") 18 | 19 | // ErrVersionMismatch is returned when the data file was created with a 20 | // different version of Bolt. 21 | ErrVersionMismatch = errors.New("version mismatch") 22 | 23 | // ErrChecksum is returned when either meta page checksum does not match. 24 | ErrChecksum = errors.New("checksum error") 25 | 26 | // ErrTimeout is returned when a database cannot obtain an exclusive lock 27 | // on the data file after the timeout passed to Open(). 28 | ErrTimeout = errors.New("timeout") 29 | ) 30 | 31 | // These errors can occur when beginning or committing a Tx. 32 | var ( 33 | // ErrTxNotWritable is returned when performing a write operation on a 34 | // read-only transaction. 35 | ErrTxNotWritable = errors.New("tx not writable") 36 | 37 | // ErrTxClosed is returned when committing or rolling back a transaction 38 | // that has already been committed or rolled back. 39 | ErrTxClosed = errors.New("tx closed") 40 | 41 | // ErrDatabaseReadOnly is returned when a mutating transaction is started on a 42 | // read-only database. 43 | ErrDatabaseReadOnly = errors.New("database is in read-only mode") 44 | ) 45 | 46 | // These errors can occur when putting or deleting a value or a bucket. 47 | var ( 48 | // ErrBucketNotFound is returned when trying to access a bucket that has 49 | // not been created yet. 50 | ErrBucketNotFound = errors.New("bucket not found") 51 | 52 | // ErrBucketExists is returned when creating a bucket that already exists. 53 | ErrBucketExists = errors.New("bucket already exists") 54 | 55 | // ErrBucketNameRequired is returned when creating a bucket with a blank name. 56 | ErrBucketNameRequired = errors.New("bucket name required") 57 | 58 | // ErrKeyRequired is returned when inserting a zero-length key. 59 | ErrKeyRequired = errors.New("key required") 60 | 61 | // ErrKeyTooLarge is returned when inserting a key that is larger than MaxKeySize. 62 | ErrKeyTooLarge = errors.New("key too large") 63 | 64 | // ErrValueTooLarge is returned when inserting a value that is larger than MaxValueSize. 65 | ErrValueTooLarge = errors.New("value too large") 66 | 67 | // ErrIncompatibleValue is returned when trying create or delete a bucket 68 | // on an existing non-bucket key or when trying to create or delete a 69 | // non-bucket key on an existing bucket key. 70 | ErrIncompatibleValue = errors.New("incompatible value") 71 | ) 72 | -------------------------------------------------------------------------------- /vendor/github.com/coreos/goproxy/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Elazar Leibovich. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Elazar Leibovich. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/github.com/coreos/goproxy/actions.go: -------------------------------------------------------------------------------- 1 | package goproxy 2 | 3 | import "net/http" 4 | 5 | // ReqHandler will "tamper" with the request coming to the proxy server 6 | // If Handle returns req,nil the proxy will send the returned request 7 | // to the destination server. If it returns nil,resp the proxy will 8 | // skip sending any requests, and will simply return the response `resp` 9 | // to the client. 10 | type ReqHandler interface { 11 | Handle(req *http.Request, ctx *ProxyCtx) (*http.Request, *http.Response) 12 | } 13 | 14 | // A wrapper that would convert a function to a ReqHandler interface type 15 | type FuncReqHandler func(req *http.Request, ctx *ProxyCtx) (*http.Request, *http.Response) 16 | 17 | // FuncReqHandler.Handle(req,ctx) <=> FuncReqHandler(req,ctx) 18 | func (f FuncReqHandler) Handle(req *http.Request, ctx *ProxyCtx) (*http.Request, *http.Response) { 19 | return f(req, ctx) 20 | } 21 | 22 | // after the proxy have sent the request to the destination server, it will 23 | // "filter" the response through the RespHandlers it has. 24 | // The proxy server will send to the client the response returned by the RespHandler. 25 | // In case of error, resp will be nil, and ctx.RoundTrip.Error will contain the error 26 | type RespHandler interface { 27 | Handle(resp *http.Response, ctx *ProxyCtx) *http.Response 28 | } 29 | 30 | // A wrapper that would convert a function to a RespHandler interface type 31 | type FuncRespHandler func(resp *http.Response, ctx *ProxyCtx) *http.Response 32 | 33 | // FuncRespHandler.Handle(req,ctx) <=> FuncRespHandler(req,ctx) 34 | func (f FuncRespHandler) Handle(resp *http.Response, ctx *ProxyCtx) *http.Response { 35 | return f(resp, ctx) 36 | } 37 | 38 | // When a client send a CONNECT request to a host, the request is filtered through 39 | // all the HttpsHandlers the proxy has, and if one returns true, the connection is 40 | // sniffed using Man in the Middle attack. 41 | // That is, the proxy will create a TLS connection with the client, another TLS 42 | // connection with the destination the client wished to connect to, and would 43 | // send back and forth all messages from the server to the client and vice versa. 44 | // The request and responses sent in this Man In the Middle channel are filtered 45 | // through the usual flow (request and response filtered through the ReqHandlers 46 | // and RespHandlers) 47 | type HttpsHandler interface { 48 | HandleConnect(req string, ctx *ProxyCtx) (*ConnectAction, string) 49 | } 50 | 51 | // A wrapper that would convert a function to a HttpsHandler interface type 52 | type FuncHttpsHandler func(host string, ctx *ProxyCtx) (*ConnectAction, string) 53 | 54 | // FuncHttpsHandler should implement the RespHandler interface 55 | func (f FuncHttpsHandler) HandleConnect(host string, ctx *ProxyCtx) (*ConnectAction, string) { 56 | return f(host, ctx) 57 | } 58 | -------------------------------------------------------------------------------- /vendor/github.com/coreos/goproxy/all.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | go test || exit 4 | for action in $@; do go $action; done 5 | 6 | mkdir -p bin 7 | find regretable examples/* ext/* -maxdepth 0 -type d | while read d; do 8 | (cd $d 9 | go build -o ../../bin/$(basename $d) 10 | find *_test.go -maxdepth 0 2>/dev/null|while read f;do 11 | for action in $@; do go $action; done 12 | go test 13 | break 14 | done) 15 | done 16 | -------------------------------------------------------------------------------- /vendor/github.com/coreos/goproxy/ca.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICSjCCAbWgAwIBAgIBADALBgkqhkiG9w0BAQUwSjEjMCEGA1UEChMaZ2l0aHVi 3 | LmNvbS9lbGF6YXJsL2dvcHJveHkxIzAhBgNVBAMTGmdpdGh1Yi5jb20vZWxhemFy 4 | bC9nb3Byb3h5MB4XDTAwMDEwMTAwMDAwMFoXDTQ5MTIzMTIzNTk1OVowSjEjMCEG 5 | A1UEChMaZ2l0aHViLmNvbS9lbGF6YXJsL2dvcHJveHkxIzAhBgNVBAMTGmdpdGh1 6 | Yi5jb20vZWxhemFybC9nb3Byb3h5MIGdMAsGCSqGSIb3DQEBAQOBjQAwgYkCgYEA 7 | vz9BbCaJjxs73Tvcq3leP32hAGerQ1RgvlZ68Z4nZmoVHfl+2Nr/m0dmW+GdOfpT 8 | cs/KzfJjYGr/84x524fiuR8GdZ0HOtXJzyF5seoWnbBIuyr1PbEpgRhGQMqqOUuj 9 | YExeLbfNHPIoJ8XZ1Vzyv3YxjbmjWA+S/uOe9HWtDbMCAwEAAaNGMEQwDgYDVR0P 10 | AQH/BAQDAgCkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8w 11 | DAYDVR0RBAUwA4IBKjALBgkqhkiG9w0BAQUDgYEAIcL8huSmGMompNujsvePTUnM 12 | oEUKtX4Eh/+s+DSfV/TyI0I+3GiPpLplEgFWuoBIJGios0r1dKh5N0TGjxX/RmGm 13 | qo7E4jjJuo8Gs5U8/fgThZmshax2lwLtbRNwhvUVr65GdahLsZz8I+hySLuatVvR 14 | qHHq/FQORIiNyNpq/Hg= 15 | -----END CERTIFICATE----- 16 | -------------------------------------------------------------------------------- /vendor/github.com/coreos/goproxy/chunked.go: -------------------------------------------------------------------------------- 1 | // Taken from $GOROOT/src/pkg/net/http/chunked 2 | // needed to write https responses to client. 3 | package goproxy 4 | 5 | import ( 6 | "io" 7 | "strconv" 8 | ) 9 | 10 | // newChunkedWriter returns a new chunkedWriter that translates writes into HTTP 11 | // "chunked" format before writing them to w. Closing the returned chunkedWriter 12 | // sends the final 0-length chunk that marks the end of the stream. 13 | // 14 | // newChunkedWriter is not needed by normal applications. The http 15 | // package adds chunking automatically if handlers don't set a 16 | // Content-Length header. Using newChunkedWriter inside a handler 17 | // would result in double chunking or chunking with a Content-Length 18 | // length, both of which are wrong. 19 | func newChunkedWriter(w io.Writer) io.WriteCloser { 20 | return &chunkedWriter{w} 21 | } 22 | 23 | // Writing to chunkedWriter translates to writing in HTTP chunked Transfer 24 | // Encoding wire format to the underlying Wire chunkedWriter. 25 | type chunkedWriter struct { 26 | Wire io.Writer 27 | } 28 | 29 | // Write the contents of data as one chunk to Wire. 30 | // NOTE: Note that the corresponding chunk-writing procedure in Conn.Write has 31 | // a bug since it does not check for success of io.WriteString 32 | func (cw *chunkedWriter) Write(data []byte) (n int, err error) { 33 | 34 | // Don't send 0-length data. It looks like EOF for chunked encoding. 35 | if len(data) == 0 { 36 | return 0, nil 37 | } 38 | 39 | head := strconv.FormatInt(int64(len(data)), 16) + "\r\n" 40 | 41 | if _, err = io.WriteString(cw.Wire, head); err != nil { 42 | return 0, err 43 | } 44 | if n, err = cw.Wire.Write(data); err != nil { 45 | return 46 | } 47 | if n != len(data) { 48 | err = io.ErrShortWrite 49 | return 50 | } 51 | _, err = io.WriteString(cw.Wire, "\r\n") 52 | 53 | return 54 | } 55 | 56 | func (cw *chunkedWriter) Close() error { 57 | _, err := io.WriteString(cw.Wire, "0\r\n") 58 | return err 59 | } 60 | -------------------------------------------------------------------------------- /vendor/github.com/coreos/goproxy/counterecryptor.go: -------------------------------------------------------------------------------- 1 | package goproxy 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "crypto/rsa" 7 | "crypto/sha256" 8 | "crypto/x509" 9 | "errors" 10 | ) 11 | 12 | type CounterEncryptorRand struct { 13 | cipher cipher.Block 14 | counter []byte 15 | rand []byte 16 | ix int 17 | } 18 | 19 | func NewCounterEncryptorRandFromKey(key interface{}, seed []byte) (r CounterEncryptorRand, err error) { 20 | var keyBytes []byte 21 | switch key := key.(type) { 22 | case *rsa.PrivateKey: 23 | keyBytes = x509.MarshalPKCS1PrivateKey(key) 24 | default: 25 | err = errors.New("only RSA keys supported") 26 | return 27 | } 28 | h := sha256.New() 29 | if r.cipher, err = aes.NewCipher(h.Sum(keyBytes)[:aes.BlockSize]); err != nil { 30 | return 31 | } 32 | r.counter = make([]byte, r.cipher.BlockSize()) 33 | if seed != nil { 34 | copy(r.counter, h.Sum(seed)[:r.cipher.BlockSize()]) 35 | } 36 | r.rand = make([]byte, r.cipher.BlockSize()) 37 | r.ix = len(r.rand) 38 | return 39 | } 40 | 41 | func (c *CounterEncryptorRand) Seed(b []byte) { 42 | if len(b) != len(c.counter) { 43 | panic("SetCounter: wrong counter size") 44 | } 45 | copy(c.counter, b) 46 | } 47 | 48 | func (c *CounterEncryptorRand) refill() { 49 | c.cipher.Encrypt(c.rand, c.counter) 50 | for i := 0; i < len(c.counter); i++ { 51 | if c.counter[i]++; c.counter[i] != 0 { 52 | break 53 | } 54 | } 55 | c.ix = 0 56 | } 57 | 58 | func (c *CounterEncryptorRand) Read(b []byte) (n int, err error) { 59 | if c.ix == len(c.rand) { 60 | c.refill() 61 | } 62 | if n = len(c.rand) - c.ix; n > len(b) { 63 | n = len(b) 64 | } 65 | copy(b, c.rand[c.ix:c.ix+n]) 66 | c.ix += n 67 | return 68 | } 69 | -------------------------------------------------------------------------------- /vendor/github.com/coreos/goproxy/ctx.go: -------------------------------------------------------------------------------- 1 | package goproxy 2 | 3 | import ( 4 | "net/http" 5 | "regexp" 6 | ) 7 | 8 | // ProxyCtx is the Proxy context, contains useful information about every request. It is passed to 9 | // every user function. Also used as a logger. 10 | type ProxyCtx struct { 11 | // Will contain the client request from the proxy 12 | Req *http.Request 13 | // Will contain the remote server's response (if available. nil if the request wasn't send yet) 14 | Resp *http.Response 15 | RoundTripper RoundTripper 16 | // will contain the recent error that occured while trying to send receive or parse traffic 17 | Error error 18 | // A handle for the user to keep data in the context, from the call of ReqHandler to the 19 | // call of RespHandler 20 | UserData interface{} 21 | // Will connect a request to a response 22 | Session int64 23 | proxy *ProxyHttpServer 24 | } 25 | 26 | type RoundTripper interface { 27 | RoundTrip(req *http.Request, ctx *ProxyCtx) (*http.Response, error) 28 | } 29 | 30 | type RoundTripperFunc func(req *http.Request, ctx *ProxyCtx) (*http.Response, error) 31 | 32 | func (f RoundTripperFunc) RoundTrip(req *http.Request, ctx *ProxyCtx) (*http.Response, error) { 33 | return f(req, ctx) 34 | } 35 | 36 | func (ctx *ProxyCtx) RoundTrip(req *http.Request) (*http.Response, error) { 37 | if ctx.RoundTripper != nil { 38 | return ctx.RoundTripper.RoundTrip(req, ctx) 39 | } 40 | return ctx.proxy.Tr.RoundTrip(req) 41 | } 42 | 43 | func (ctx *ProxyCtx) printf(msg string, argv ...interface{}) { 44 | ctx.proxy.Logger.Printf("[%03d] "+msg+"\n", append([]interface{}{ctx.Session & 0xFF}, argv...)...) 45 | } 46 | 47 | // Logf prints a message to the proxy's log. Should be used in a ProxyHttpServer's filter 48 | // This message will be printed only if the Verbose field of the ProxyHttpServer is set to true 49 | // 50 | // proxy.OnRequest().DoFunc(func(r *http.Request,ctx *goproxy.ProxyCtx) (*http.Request, *http.Response){ 51 | // nr := atomic.AddInt32(&counter,1) 52 | // ctx.Printf("So far %d requests",nr) 53 | // return r, nil 54 | // }) 55 | func (ctx *ProxyCtx) Logf(msg string, argv ...interface{}) { 56 | if ctx.proxy.Verbose { 57 | ctx.printf("INFO: "+msg, argv...) 58 | } 59 | } 60 | 61 | // Warnf prints a message to the proxy's log. Should be used in a ProxyHttpServer's filter 62 | // This message will always be printed. 63 | // 64 | // proxy.OnRequest().DoFunc(func(r *http.Request,ctx *goproxy.ProxyCtx) (*http.Request, *http.Response){ 65 | // f,err := os.OpenFile(cachedContent) 66 | // if err != nil { 67 | // ctx.Warnf("error open file %v: %v",cachedContent,err) 68 | // return r, nil 69 | // } 70 | // return r, nil 71 | // }) 72 | func (ctx *ProxyCtx) Warnf(msg string, argv ...interface{}) { 73 | ctx.printf("WARN: "+msg, argv...) 74 | } 75 | 76 | var charsetFinder = regexp.MustCompile("charset=([^ ;]*)") 77 | 78 | // Will try to infer the character set of the request from the headers. 79 | // Returns the empty string if we don't know which character set it used. 80 | // Currently it will look for charset= in the Content-Type header of the request. 81 | func (ctx *ProxyCtx) Charset() string { 82 | charsets := charsetFinder.FindStringSubmatch(ctx.Resp.Header.Get("Content-Type")) 83 | if charsets == nil { 84 | return "" 85 | } 86 | return charsets[1] 87 | } 88 | -------------------------------------------------------------------------------- /vendor/github.com/coreos/goproxy/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package goproxy provides a customizable HTTP proxy, 3 | supporting hijacking HTTPS connection. 4 | 5 | The intent of the proxy, is to be usable with reasonable amount of traffic 6 | yet, customizable and programable. 7 | 8 | The proxy itself is simply an `net/http` handler. 9 | 10 | Typical usage is 11 | 12 | proxy := goproxy.NewProxyHttpServer() 13 | proxy.OnRequest(..conditions..).Do(..requesthandler..) 14 | proxy.OnRequest(..conditions..).DoFunc(..requesthandlerFunction..) 15 | proxy.OnResponse(..conditions..).Do(..responesHandler..) 16 | proxy.OnResponse(..conditions..).DoFunc(..responesHandlerFunction..) 17 | http.ListenAndServe(":8080", proxy) 18 | 19 | Adding a header to each request 20 | 21 | proxy.OnRequest().DoFunc(func(r *http.Request,ctx *goproxy.ProxyCtx) (*http.Request, *http.Response){ 22 | r.Header.Set("X-GoProxy","1") 23 | return r, nil 24 | }) 25 | 26 | Note that the function is called before the proxy sends the request to the server 27 | 28 | For printing the content type of all incoming responses 29 | 30 | proxy.OnResponse().DoFunc(func(r *http.Response, ctx *goproxy.ProxyCtx)*http.Response{ 31 | println(ctx.Req.Host,"->",r.Header.Get("Content-Type")) 32 | return r 33 | }) 34 | 35 | note that we used the ProxyCtx context variable here. It contains the request 36 | and the response (Req and Resp, Resp is nil if unavailable) of this specific client 37 | interaction with the proxy. 38 | 39 | To print the content type of all responses from a certain url, we'll add a 40 | ReqCondition to the OnResponse function: 41 | 42 | proxy.OnResponse(goproxy.UrlIs("golang.org/pkg")).DoFunc(func(r *http.Response, ctx *goproxy.ProxyCtx)*http.Response{ 43 | println(ctx.Req.Host,"->",r.Header.Get("Content-Type")) 44 | return r 45 | }) 46 | 47 | We can write the condition ourselves, conditions can be set on request and on response 48 | 49 | var random = ReqConditionFunc(func(r *http.Request) bool { 50 | return rand.Intn(1) == 0 51 | }) 52 | var hasGoProxyHeader = RespConditionFunc(func(resp *http.Response,req *http.Request)bool { 53 | return resp.Header.Get("X-GoProxy") != "" 54 | }) 55 | 56 | Caution! If you give a RespCondition to the OnRequest function, you'll get a run time panic! It doesn't 57 | make sense to read the response, if you still haven't got it! 58 | 59 | Finally, we have convenience function to throw a quick response 60 | 61 | proxy.OnResponse(hasGoProxyHeader).DoFunc(func(r*http.Response,ctx *goproxy.ProxyCtx)*http.Response { 62 | r.Body.Close() 63 | return goproxy.ForbiddenTextResponse(ctx.Req,"Can't see response with X-GoProxy header!") 64 | }) 65 | 66 | we close the body of the original repsonse, and return a new 403 response with a short message. 67 | 68 | Example use cases: 69 | 70 | 1. https://github.com/elazarl/goproxy/tree/master/examples/goproxy-avgsize 71 | 72 | To measure the average size of an Html served in your site. One can ask 73 | all the QA team to access the website by a proxy, and the proxy will 74 | measure the average size of all text/html responses from your host. 75 | 76 | 2. [not yet implemented] 77 | 78 | All requests to your web servers should be directed through the proxy, 79 | when the proxy will detect html pieces sent as a response to AJAX 80 | request, it'll send a warning email. 81 | 82 | 3. https://github.com/elazarl/goproxy/blob/master/examples/goproxy-httpdump/ 83 | 84 | Generate a real traffic to your website by real users using through 85 | proxy. Record the traffic, and try it again for more real load testing. 86 | 87 | 4. https://github.com/elazarl/goproxy/tree/master/examples/goproxy-no-reddit-at-worktime 88 | 89 | Will allow browsing to reddit.com between 8:00am and 17:00pm 90 | 91 | 5. https://github.com/elazarl/goproxy/tree/master/examples/goproxy-jquery-version 92 | 93 | Will warn if multiple versions of jquery are used in the same domain. 94 | 95 | 6. https://github.com/elazarl/goproxy/blob/master/examples/goproxy-upside-down-ternet/ 96 | 97 | Modifies image files in an HTTP response via goproxy's image extension found in ext/. 98 | 99 | */ 100 | package goproxy 101 | -------------------------------------------------------------------------------- /vendor/github.com/coreos/goproxy/key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICXQIBAAKBgQC/P0FsJomPGzvdO9yreV4/faEAZ6tDVGC+VnrxnidmahUd+X7Y 3 | 2v+bR2Zb4Z05+lNyz8rN8mNgav/zjHnbh+K5HwZ1nQc61cnPIXmx6hadsEi7KvU9 4 | sSmBGEZAyqo5S6NgTF4tt80c8ignxdnVXPK/djGNuaNYD5L+4570da0NswIDAQAB 5 | AoGBALzIv1b4D7ARTR3NOr6V9wArjiOtMjUrdLhO+9vIp9IEA8ZsA9gjDlCEwbkP 6 | VDnoLjnWfraff5Os6+3JjHy1fYpUiCdnk2XA6iJSL1XWKQZPt3wOunxP4lalDgED 7 | QTRReFbA/y/Z4kSfTXpVj68ytcvSRW/N7q5/qRtbN9804jpBAkEA0s6lvH2btSLA 8 | mcEdwhs7zAslLbdld7rvfUeP82gPPk0S6yUqTNyikqshM9AwAktHY7WvYdKl+ghZ 9 | HTxKVC4DoQJBAOg/IAW5RbXknP+Lf7AVtBgw3E+Yfa3mcdLySe8hjxxyZq825Zmu 10 | Rt5Qj4Lw6ifSFNy4kiiSpE/ZCukYvUXGENMCQFkPxSWlS6tzSzuqQxBGwTSrYMG3 11 | wb6b06JyIXcMd6Qym9OMmBpw/J5KfnSNeDr/4uFVWQtTG5xO+pdHaX+3EQECQQDl 12 | qcbY4iX1gWVfr2tNjajSYz751yoxVbkpiT9joiQLVXYFvpu+JYEfRzsjmWl0h2Lq 13 | AftG8/xYmaEYcMZ6wSrRAkBUwiom98/8wZVlB6qbwhU1EKDFANvICGSWMIhPx3v7 14 | MJqTIj4uJhte2/uyVvZ6DC6noWYgy+kLgqG0S97tUEG8 15 | -----END RSA PRIVATE KEY----- 16 | -------------------------------------------------------------------------------- /vendor/github.com/coreos/goproxy/responses.go: -------------------------------------------------------------------------------- 1 | package goproxy 2 | 3 | import ( 4 | "bytes" 5 | "io/ioutil" 6 | "net/http" 7 | ) 8 | 9 | // Will generate a valid http response to the given request the response will have 10 | // the given contentType, and http status. 11 | // Typical usage, refuse to process requests to local addresses: 12 | // 13 | // proxy.OnRequest(IsLocalHost()).DoFunc(func(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request,*http.Response) { 14 | // return nil,NewResponse(r,goproxy.ContentTypeHtml,http.StatusUnauthorized, 15 | // `Can't use proxy for local addresses`) 16 | // }) 17 | func NewResponse(r *http.Request, contentType string, status int, body string) *http.Response { 18 | resp := &http.Response{} 19 | resp.Request = r 20 | resp.TransferEncoding = r.TransferEncoding 21 | resp.Header = make(http.Header) 22 | resp.Header.Add("Content-Type", contentType) 23 | resp.StatusCode = status 24 | buf := bytes.NewBufferString(body) 25 | resp.ContentLength = int64(buf.Len()) 26 | resp.Body = ioutil.NopCloser(buf) 27 | return resp 28 | } 29 | 30 | const ( 31 | ContentTypeText = "text/plain" 32 | ContentTypeHtml = "text/html" 33 | ) 34 | 35 | // Alias for NewResponse(r,ContentTypeText,http.StatusAccepted,text) 36 | func TextResponse(r *http.Request, text string) *http.Response { 37 | return NewResponse(r, ContentTypeText, http.StatusAccepted, text) 38 | } 39 | -------------------------------------------------------------------------------- /vendor/github.com/coreos/goproxy/signer.go: -------------------------------------------------------------------------------- 1 | package goproxy 2 | 3 | import ( 4 | "crypto/rsa" 5 | "crypto/sha1" 6 | "crypto/tls" 7 | "crypto/x509" 8 | "crypto/x509/pkix" 9 | "math/big" 10 | "net" 11 | "runtime" 12 | "sort" 13 | "time" 14 | ) 15 | 16 | func hashSorted(lst []string) []byte { 17 | c := make([]string, len(lst)) 18 | copy(c, lst) 19 | sort.Strings(c) 20 | h := sha1.New() 21 | for _, s := range c { 22 | h.Write([]byte(s + ",")) 23 | } 24 | return h.Sum(nil) 25 | } 26 | 27 | func hashSortedBigInt(lst []string) *big.Int { 28 | rv := new(big.Int) 29 | rv.SetBytes(hashSorted(lst)) 30 | return rv 31 | } 32 | 33 | var goproxySignerVersion = ":goroxy1" 34 | 35 | func signHost(ca tls.Certificate, hosts []string) (cert tls.Certificate, err error) { 36 | var x509ca *x509.Certificate 37 | 38 | // Use the provided ca and not the global GoproxyCa for certificate generation. 39 | if x509ca, err = x509.ParseCertificate(ca.Certificate[0]); err != nil { 40 | return 41 | } 42 | start := time.Unix(0, 0) 43 | end, err := time.Parse("2006-01-02", "2049-12-31") 44 | if err != nil { 45 | panic(err) 46 | } 47 | hash := hashSorted(append(hosts, goproxySignerVersion, ":"+runtime.Version())) 48 | serial := new(big.Int) 49 | serial.SetBytes(hash) 50 | template := x509.Certificate{ 51 | // TODO(elazar): instead of this ugly hack, just encode the certificate and hash the binary form. 52 | SerialNumber: serial, 53 | Issuer: x509ca.Subject, 54 | Subject: pkix.Name{ 55 | Organization: []string{"GoProxy untrusted MITM proxy Inc"}, 56 | }, 57 | NotBefore: start, 58 | NotAfter: end, 59 | 60 | KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, 61 | ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, 62 | BasicConstraintsValid: true, 63 | } 64 | for _, h := range hosts { 65 | if ip := net.ParseIP(h); ip != nil { 66 | template.IPAddresses = append(template.IPAddresses, ip) 67 | } else { 68 | template.DNSNames = append(template.DNSNames, h) 69 | } 70 | } 71 | var csprng CounterEncryptorRand 72 | if csprng, err = NewCounterEncryptorRandFromKey(ca.PrivateKey, hash); err != nil { 73 | return 74 | } 75 | var certpriv *rsa.PrivateKey 76 | if certpriv, err = rsa.GenerateKey(&csprng, 1024); err != nil { 77 | return 78 | } 79 | var derBytes []byte 80 | if derBytes, err = x509.CreateCertificate(&csprng, &template, x509ca, &certpriv.PublicKey, ca.PrivateKey); err != nil { 81 | return 82 | } 83 | return tls.Certificate{ 84 | Certificate: [][]byte{derBytes, ca.Certificate[0]}, 85 | PrivateKey: certpriv, 86 | }, nil 87 | } 88 | -------------------------------------------------------------------------------- /vendor/github.com/coreos/goproxy/websocket.go: -------------------------------------------------------------------------------- 1 | package goproxy 2 | 3 | import ( 4 | "bufio" 5 | "crypto/tls" 6 | "io" 7 | "net/http" 8 | "net/url" 9 | "strings" 10 | ) 11 | 12 | func headerContains(header http.Header, name string, value string) bool { 13 | for _, v := range header[name] { 14 | for _, s := range strings.Split(v, ",") { 15 | if strings.EqualFold(value, strings.TrimSpace(s)) { 16 | return true 17 | } 18 | } 19 | } 20 | return false 21 | } 22 | 23 | func isWebSocketRequest(r *http.Request) bool { 24 | return headerContains(r.Header, "Connection", "upgrade") && 25 | headerContains(r.Header, "Upgrade", "websocket") 26 | } 27 | 28 | func (proxy *ProxyHttpServer) serveWebsocketTLS(ctx *ProxyCtx, w http.ResponseWriter, req *http.Request, tlsConfig *tls.Config, clientConn *tls.Conn) { 29 | targetURL := url.URL{Scheme: "wss", Host: req.URL.Host, Path: req.URL.Path} 30 | 31 | // Connect to upstream 32 | targetConn, err := tls.Dial("tcp", targetURL.Host, tlsConfig) 33 | if err != nil { 34 | ctx.Warnf("Error dialing target site: %v", err) 35 | return 36 | } 37 | defer targetConn.Close() 38 | 39 | // Perform handshake 40 | if err := proxy.websocketHandshake(ctx, req, targetConn, clientConn); err != nil { 41 | ctx.Warnf("Websocket handshake error: %v", err) 42 | return 43 | } 44 | 45 | // Proxy wss connection 46 | proxy.proxyWebsocket(ctx, targetConn, clientConn) 47 | } 48 | 49 | func (proxy *ProxyHttpServer) serveWebsocket(ctx *ProxyCtx, w http.ResponseWriter, req *http.Request) { 50 | targetURL := url.URL{Scheme: "ws", Host: req.URL.Host, Path: req.URL.Path} 51 | 52 | targetConn, err := proxy.connectDial("tcp", targetURL.Host) 53 | if err != nil { 54 | ctx.Warnf("Error dialing target site: %v", err) 55 | return 56 | } 57 | defer targetConn.Close() 58 | 59 | // Connect to Client 60 | hj, ok := w.(http.Hijacker) 61 | if !ok { 62 | panic("httpserver does not support hijacking") 63 | } 64 | clientConn, _, err := hj.Hijack() 65 | if err != nil { 66 | ctx.Warnf("Hijack error: %v", err) 67 | return 68 | } 69 | 70 | // Perform handshake 71 | if err := proxy.websocketHandshake(ctx, req, targetConn, clientConn); err != nil { 72 | ctx.Warnf("Websocket handshake error: %v", err) 73 | return 74 | } 75 | 76 | // Proxy ws connection 77 | proxy.proxyWebsocket(ctx, targetConn, clientConn) 78 | } 79 | 80 | func (proxy *ProxyHttpServer) websocketHandshake(ctx *ProxyCtx, req *http.Request, targetSiteConn io.ReadWriter, clientConn io.ReadWriter) error { 81 | // write handshake request to target 82 | err := req.Write(targetSiteConn) 83 | if err != nil { 84 | ctx.Warnf("Error writing upgrade request: %v", err) 85 | return err 86 | } 87 | 88 | targetTLSReader := bufio.NewReader(targetSiteConn) 89 | 90 | // Read handshake response from target 91 | resp, err := http.ReadResponse(targetTLSReader, req) 92 | if err != nil { 93 | ctx.Warnf("Error reading handhsake response %v", err) 94 | return err 95 | } 96 | 97 | // Run response through handlers 98 | resp = proxy.filterResponse(resp, ctx) 99 | 100 | // Proxy handshake back to client 101 | err = resp.Write(clientConn) 102 | if err != nil { 103 | ctx.Warnf("Error writing handshake response: %v", err) 104 | return err 105 | } 106 | return nil 107 | } 108 | 109 | func (proxy *ProxyHttpServer) proxyWebsocket(ctx *ProxyCtx, dest io.ReadWriter, source io.ReadWriter) { 110 | errChan := make(chan error, 2) 111 | cp := func(dst io.Writer, src io.Reader) { 112 | _, err := io.Copy(dst, src) 113 | ctx.Warnf("Websocket error: %v", err) 114 | errChan <- err 115 | } 116 | 117 | // Start proxying websocket data 118 | go cp(dest, source) 119 | go cp(source, dest) 120 | <-errChan 121 | } 122 | -------------------------------------------------------------------------------- /vendor/github.com/elazarl/goproxy/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Elazar Leibovich. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Elazar Leibovich. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/github.com/elazarl/goproxy/actions.go: -------------------------------------------------------------------------------- 1 | package goproxy 2 | 3 | import "net/http" 4 | 5 | // ReqHandler will "tamper" with the request coming to the proxy server 6 | // If Handle returns req,nil the proxy will send the returned request 7 | // to the destination server. If it returns nil,resp the proxy will 8 | // skip sending any requests, and will simply return the response `resp` 9 | // to the client. 10 | type ReqHandler interface { 11 | Handle(req *http.Request, ctx *ProxyCtx) (*http.Request, *http.Response) 12 | } 13 | 14 | // A wrapper that would convert a function to a ReqHandler interface type 15 | type FuncReqHandler func(req *http.Request, ctx *ProxyCtx) (*http.Request, *http.Response) 16 | 17 | // FuncReqHandler.Handle(req,ctx) <=> FuncReqHandler(req,ctx) 18 | func (f FuncReqHandler) Handle(req *http.Request, ctx *ProxyCtx) (*http.Request, *http.Response) { 19 | return f(req, ctx) 20 | } 21 | 22 | // after the proxy have sent the request to the destination server, it will 23 | // "filter" the response through the RespHandlers it has. 24 | // The proxy server will send to the client the response returned by the RespHandler. 25 | // In case of error, resp will be nil, and ctx.RoundTrip.Error will contain the error 26 | type RespHandler interface { 27 | Handle(resp *http.Response, ctx *ProxyCtx) *http.Response 28 | } 29 | 30 | // A wrapper that would convert a function to a RespHandler interface type 31 | type FuncRespHandler func(resp *http.Response, ctx *ProxyCtx) *http.Response 32 | 33 | // FuncRespHandler.Handle(req,ctx) <=> FuncRespHandler(req,ctx) 34 | func (f FuncRespHandler) Handle(resp *http.Response, ctx *ProxyCtx) *http.Response { 35 | return f(resp, ctx) 36 | } 37 | 38 | // When a client send a CONNECT request to a host, the request is filtered through 39 | // all the HttpsHandlers the proxy has, and if one returns true, the connection is 40 | // sniffed using Man in the Middle attack. 41 | // That is, the proxy will create a TLS connection with the client, another TLS 42 | // connection with the destination the client wished to connect to, and would 43 | // send back and forth all messages from the server to the client and vice versa. 44 | // The request and responses sent in this Man In the Middle channel are filtered 45 | // through the usual flow (request and response filtered through the ReqHandlers 46 | // and RespHandlers) 47 | type HttpsHandler interface { 48 | HandleConnect(req string, ctx *ProxyCtx) (*ConnectAction, string) 49 | } 50 | 51 | // A wrapper that would convert a function to a HttpsHandler interface type 52 | type FuncHttpsHandler func(host string, ctx *ProxyCtx) (*ConnectAction, string) 53 | 54 | // FuncHttpsHandler should implement the RespHandler interface 55 | func (f FuncHttpsHandler) HandleConnect(host string, ctx *ProxyCtx) (*ConnectAction, string) { 56 | return f(host, ctx) 57 | } 58 | -------------------------------------------------------------------------------- /vendor/github.com/elazarl/goproxy/all.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | go test || exit 4 | for action in $@; do go $action; done 5 | 6 | mkdir -p bin 7 | find regretable examples/* ext/* -maxdepth 0 -type d | while read d; do 8 | (cd $d 9 | go build -o ../../bin/$(basename $d) 10 | find *_test.go -maxdepth 0 2>/dev/null|while read f;do 11 | for action in $@; do go $action; done 12 | go test 13 | break 14 | done) 15 | done 16 | -------------------------------------------------------------------------------- /vendor/github.com/elazarl/goproxy/ca.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIF9DCCA9ygAwIBAgIJAODqYUwoVjJkMA0GCSqGSIb3DQEBCwUAMIGOMQswCQYD 3 | VQQGEwJJTDEPMA0GA1UECAwGQ2VudGVyMQwwCgYDVQQHDANMb2QxEDAOBgNVBAoM 4 | B0dvUHJveHkxEDAOBgNVBAsMB0dvUHJveHkxGjAYBgNVBAMMEWdvcHJveHkuZ2l0 5 | aHViLmlvMSAwHgYJKoZIhvcNAQkBFhFlbGF6YXJsQGdtYWlsLmNvbTAeFw0xNzA0 6 | MDUyMDAwMTBaFw0zNzAzMzEyMDAwMTBaMIGOMQswCQYDVQQGEwJJTDEPMA0GA1UE 7 | CAwGQ2VudGVyMQwwCgYDVQQHDANMb2QxEDAOBgNVBAoMB0dvUHJveHkxEDAOBgNV 8 | BAsMB0dvUHJveHkxGjAYBgNVBAMMEWdvcHJveHkuZ2l0aHViLmlvMSAwHgYJKoZI 9 | hvcNAQkBFhFlbGF6YXJsQGdtYWlsLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP 10 | ADCCAgoCggIBAJ4Qy+H6hhoY1s0QRcvIhxrjSHaO/RbaFj3rwqcnpOgFq07gRdI9 11 | 3c0TFKQJHpgv6feLRhEvX/YllFYu4J35lM9ZcYY4qlKFuStcX8Jm8fqpgtmAMBzP 12 | sqtqDi8M9RQGKENzU9IFOnCV7SAeh45scMuI3wz8wrjBcH7zquHkvqUSYZz035t9 13 | V6WTrHyTEvT4w+lFOVN2bA/6DAIxrjBiF6DhoJqnha0SZtDfv77XpwGG3EhA/qoh 14 | hiYrDruYK7zJdESQL44LwzMPupVigqalfv+YHfQjbhT951IVurW2NJgRyBE62dLr 15 | lHYdtT9tCTCrd+KJNMJ+jp9hAjdIu1Br/kifU4F4+4ZLMR9Ueji0GkkPKsYdyMnq 16 | j0p0PogyvP1l4qmboPImMYtaoFuYmMYlebgC9LN10bL91K4+jLt0I1YntEzrqgJo 17 | WsJztYDw543NzSy5W+/cq4XRYgtq1b0RWwuUiswezmMoeyHZ8BQJe2xMjAOllASD 18 | fqa8OK3WABHJpy4zUrnUBiMuPITzD/FuDx4C5IwwlC68gHAZblNqpBZCX0nFCtKj 19 | YOcI2So5HbQ2OC8QF+zGVuduHUSok4hSy2BBfZ1pfvziqBeetWJwFvapGB44nIHh 20 | WKNKvqOxLNIy7e+TGRiWOomrAWM18VSR9LZbBxpJK7PLSzWqYJYTRCZHAgMBAAGj 21 | UzBRMB0GA1UdDgQWBBR4uDD9Y6x7iUoHO+32ioOcw1ICZTAfBgNVHSMEGDAWgBR4 22 | uDD9Y6x7iUoHO+32ioOcw1ICZTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB 23 | CwUAA4ICAQAaCEupzGGqcdh+L7BzhX7zyd7yzAKUoLxFrxaZY34Xyj3lcx1XoK6F 24 | AqsH2JM25GixgadzhNt92JP7vzoWeHZtLfstrPS638Y1zZi6toy4E49viYjFk5J0 25 | C6ZcFC04VYWWx6z0HwJuAS08tZ37JuFXpJGfXJOjZCQyxse0Lg0tuKLMeXDCk2Y3 26 | Ba0noeuNyHRoWXXPyiUoeApkVCU5gIsyiJSWOjhJ5hpJG06rQNfNYexgKrrraEin 27 | o0jmEMtJMx5TtD83hSnLCnFGBBq5lkE7jgXME1KsbIE3lJZzRX1mQwUK8CJDYxye 28 | i6M/dzSvy0SsPvz8fTAlprXRtWWtJQmxgWENp3Dv+0Pmux/l+ilk7KA4sMXGhsfr 29 | bvTOeWl1/uoFTPYiWR/ww7QEPLq23yDFY04Q7Un0qjIk8ExvaY8lCkXMgc8i7sGY 30 | VfvOYb0zm67EfAQl3TW8Ky5fl5CcxpVCD360Bzi6hwjYixa3qEeBggOixFQBFWft 31 | 8wrkKTHpOQXjn4sDPtet8imm9UYEtzWrFX6T9MFYkBR0/yye0FIh9+YPiTA6WB86 32 | NCNwK5Yl6HuvF97CIH5CdgO+5C7KifUtqTOL8pQKbNwy0S3sNYvB+njGvRpR7pKV 33 | BUnFpB/Atptqr4CUlTXrc5IPLAqAfmwk5IKcwy3EXUbruf9Dwz69YA== 34 | -----END CERTIFICATE----- 35 | -------------------------------------------------------------------------------- /vendor/github.com/elazarl/goproxy/chunked.go: -------------------------------------------------------------------------------- 1 | // Taken from $GOROOT/src/pkg/net/http/chunked 2 | // needed to write https responses to client. 3 | package goproxy 4 | 5 | import ( 6 | "io" 7 | "strconv" 8 | ) 9 | 10 | // newChunkedWriter returns a new chunkedWriter that translates writes into HTTP 11 | // "chunked" format before writing them to w. Closing the returned chunkedWriter 12 | // sends the final 0-length chunk that marks the end of the stream. 13 | // 14 | // newChunkedWriter is not needed by normal applications. The http 15 | // package adds chunking automatically if handlers don't set a 16 | // Content-Length header. Using newChunkedWriter inside a handler 17 | // would result in double chunking or chunking with a Content-Length 18 | // length, both of which are wrong. 19 | func newChunkedWriter(w io.Writer) io.WriteCloser { 20 | return &chunkedWriter{w} 21 | } 22 | 23 | // Writing to chunkedWriter translates to writing in HTTP chunked Transfer 24 | // Encoding wire format to the underlying Wire chunkedWriter. 25 | type chunkedWriter struct { 26 | Wire io.Writer 27 | } 28 | 29 | // Write the contents of data as one chunk to Wire. 30 | // NOTE: Note that the corresponding chunk-writing procedure in Conn.Write has 31 | // a bug since it does not check for success of io.WriteString 32 | func (cw *chunkedWriter) Write(data []byte) (n int, err error) { 33 | 34 | // Don't send 0-length data. It looks like EOF for chunked encoding. 35 | if len(data) == 0 { 36 | return 0, nil 37 | } 38 | 39 | head := strconv.FormatInt(int64(len(data)), 16) + "\r\n" 40 | 41 | if _, err = io.WriteString(cw.Wire, head); err != nil { 42 | return 0, err 43 | } 44 | if n, err = cw.Wire.Write(data); err != nil { 45 | return 46 | } 47 | if n != len(data) { 48 | err = io.ErrShortWrite 49 | return 50 | } 51 | _, err = io.WriteString(cw.Wire, "\r\n") 52 | 53 | return 54 | } 55 | 56 | func (cw *chunkedWriter) Close() error { 57 | _, err := io.WriteString(cw.Wire, "0\r\n") 58 | return err 59 | } 60 | -------------------------------------------------------------------------------- /vendor/github.com/elazarl/goproxy/counterecryptor.go: -------------------------------------------------------------------------------- 1 | package goproxy 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "crypto/rsa" 7 | "crypto/sha256" 8 | "crypto/x509" 9 | "errors" 10 | ) 11 | 12 | type CounterEncryptorRand struct { 13 | cipher cipher.Block 14 | counter []byte 15 | rand []byte 16 | ix int 17 | } 18 | 19 | func NewCounterEncryptorRandFromKey(key interface{}, seed []byte) (r CounterEncryptorRand, err error) { 20 | var keyBytes []byte 21 | switch key := key.(type) { 22 | case *rsa.PrivateKey: 23 | keyBytes = x509.MarshalPKCS1PrivateKey(key) 24 | default: 25 | err = errors.New("only RSA keys supported") 26 | return 27 | } 28 | h := sha256.New() 29 | if r.cipher, err = aes.NewCipher(h.Sum(keyBytes)[:aes.BlockSize]); err != nil { 30 | return 31 | } 32 | r.counter = make([]byte, r.cipher.BlockSize()) 33 | if seed != nil { 34 | copy(r.counter, h.Sum(seed)[:r.cipher.BlockSize()]) 35 | } 36 | r.rand = make([]byte, r.cipher.BlockSize()) 37 | r.ix = len(r.rand) 38 | return 39 | } 40 | 41 | func (c *CounterEncryptorRand) Seed(b []byte) { 42 | if len(b) != len(c.counter) { 43 | panic("SetCounter: wrong counter size") 44 | } 45 | copy(c.counter, b) 46 | } 47 | 48 | func (c *CounterEncryptorRand) refill() { 49 | c.cipher.Encrypt(c.rand, c.counter) 50 | for i := 0; i < len(c.counter); i++ { 51 | if c.counter[i]++; c.counter[i] != 0 { 52 | break 53 | } 54 | } 55 | c.ix = 0 56 | } 57 | 58 | func (c *CounterEncryptorRand) Read(b []byte) (n int, err error) { 59 | if c.ix == len(c.rand) { 60 | c.refill() 61 | } 62 | if n = len(c.rand) - c.ix; n > len(b) { 63 | n = len(b) 64 | } 65 | copy(b, c.rand[c.ix:c.ix+n]) 66 | c.ix += n 67 | return 68 | } 69 | -------------------------------------------------------------------------------- /vendor/github.com/elazarl/goproxy/ctx.go: -------------------------------------------------------------------------------- 1 | package goproxy 2 | 3 | import ( 4 | "net/http" 5 | "regexp" 6 | ) 7 | 8 | // ProxyCtx is the Proxy context, contains useful information about every request. It is passed to 9 | // every user function. Also used as a logger. 10 | type ProxyCtx struct { 11 | // Will contain the client request from the proxy 12 | Req *http.Request 13 | // Will contain the remote server's response (if available. nil if the request wasn't send yet) 14 | Resp *http.Response 15 | RoundTripper RoundTripper 16 | // will contain the recent error that occurred while trying to send receive or parse traffic 17 | Error error 18 | // A handle for the user to keep data in the context, from the call of ReqHandler to the 19 | // call of RespHandler 20 | UserData interface{} 21 | // Will connect a request to a response 22 | Session int64 23 | proxy *ProxyHttpServer 24 | } 25 | 26 | type RoundTripper interface { 27 | RoundTrip(req *http.Request, ctx *ProxyCtx) (*http.Response, error) 28 | } 29 | 30 | type RoundTripperFunc func(req *http.Request, ctx *ProxyCtx) (*http.Response, error) 31 | 32 | func (f RoundTripperFunc) RoundTrip(req *http.Request, ctx *ProxyCtx) (*http.Response, error) { 33 | return f(req, ctx) 34 | } 35 | 36 | func (ctx *ProxyCtx) RoundTrip(req *http.Request) (*http.Response, error) { 37 | if ctx.RoundTripper != nil { 38 | return ctx.RoundTripper.RoundTrip(req, ctx) 39 | } 40 | return ctx.proxy.Tr.RoundTrip(req) 41 | } 42 | 43 | func (ctx *ProxyCtx) printf(msg string, argv ...interface{}) { 44 | ctx.proxy.Logger.Printf("[%03d] "+msg+"\n", append([]interface{}{ctx.Session & 0xFF}, argv...)...) 45 | } 46 | 47 | // Logf prints a message to the proxy's log. Should be used in a ProxyHttpServer's filter 48 | // This message will be printed only if the Verbose field of the ProxyHttpServer is set to true 49 | // 50 | // proxy.OnRequest().DoFunc(func(r *http.Request,ctx *goproxy.ProxyCtx) (*http.Request, *http.Response){ 51 | // nr := atomic.AddInt32(&counter,1) 52 | // ctx.Printf("So far %d requests",nr) 53 | // return r, nil 54 | // }) 55 | func (ctx *ProxyCtx) Logf(msg string, argv ...interface{}) { 56 | if ctx.proxy.Verbose { 57 | ctx.printf("INFO: "+msg, argv...) 58 | } 59 | } 60 | 61 | // Warnf prints a message to the proxy's log. Should be used in a ProxyHttpServer's filter 62 | // This message will always be printed. 63 | // 64 | // proxy.OnRequest().DoFunc(func(r *http.Request,ctx *goproxy.ProxyCtx) (*http.Request, *http.Response){ 65 | // f,err := os.OpenFile(cachedContent) 66 | // if err != nil { 67 | // ctx.Warnf("error open file %v: %v",cachedContent,err) 68 | // return r, nil 69 | // } 70 | // return r, nil 71 | // }) 72 | func (ctx *ProxyCtx) Warnf(msg string, argv ...interface{}) { 73 | ctx.printf("WARN: "+msg, argv...) 74 | } 75 | 76 | var charsetFinder = regexp.MustCompile("charset=([^ ;]*)") 77 | 78 | // Will try to infer the character set of the request from the headers. 79 | // Returns the empty string if we don't know which character set it used. 80 | // Currently it will look for charset= in the Content-Type header of the request. 81 | func (ctx *ProxyCtx) Charset() string { 82 | charsets := charsetFinder.FindStringSubmatch(ctx.Resp.Header.Get("Content-Type")) 83 | if charsets == nil { 84 | return "" 85 | } 86 | return charsets[1] 87 | } 88 | -------------------------------------------------------------------------------- /vendor/github.com/elazarl/goproxy/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package goproxy provides a customizable HTTP proxy, 3 | supporting hijacking HTTPS connection. 4 | 5 | The intent of the proxy, is to be usable with reasonable amount of traffic 6 | yet, customizable and programable. 7 | 8 | The proxy itself is simply an `net/http` handler. 9 | 10 | Typical usage is 11 | 12 | proxy := goproxy.NewProxyHttpServer() 13 | proxy.OnRequest(..conditions..).Do(..requesthandler..) 14 | proxy.OnRequest(..conditions..).DoFunc(..requesthandlerFunction..) 15 | proxy.OnResponse(..conditions..).Do(..responesHandler..) 16 | proxy.OnResponse(..conditions..).DoFunc(..responesHandlerFunction..) 17 | http.ListenAndServe(":8080", proxy) 18 | 19 | Adding a header to each request 20 | 21 | proxy.OnRequest().DoFunc(func(r *http.Request,ctx *goproxy.ProxyCtx) (*http.Request, *http.Response){ 22 | r.Header.Set("X-GoProxy","1") 23 | return r, nil 24 | }) 25 | 26 | Note that the function is called before the proxy sends the request to the server 27 | 28 | For printing the content type of all incoming responses 29 | 30 | proxy.OnResponse().DoFunc(func(r *http.Response, ctx *goproxy.ProxyCtx)*http.Response{ 31 | println(ctx.Req.Host,"->",r.Header.Get("Content-Type")) 32 | return r 33 | }) 34 | 35 | note that we used the ProxyCtx context variable here. It contains the request 36 | and the response (Req and Resp, Resp is nil if unavailable) of this specific client 37 | interaction with the proxy. 38 | 39 | To print the content type of all responses from a certain url, we'll add a 40 | ReqCondition to the OnResponse function: 41 | 42 | proxy.OnResponse(goproxy.UrlIs("golang.org/pkg")).DoFunc(func(r *http.Response, ctx *goproxy.ProxyCtx)*http.Response{ 43 | println(ctx.Req.Host,"->",r.Header.Get("Content-Type")) 44 | return r 45 | }) 46 | 47 | We can write the condition ourselves, conditions can be set on request and on response 48 | 49 | var random = ReqConditionFunc(func(r *http.Request) bool { 50 | return rand.Intn(1) == 0 51 | }) 52 | var hasGoProxyHeader = RespConditionFunc(func(resp *http.Response,req *http.Request)bool { 53 | return resp.Header.Get("X-GoProxy") != "" 54 | }) 55 | 56 | Caution! If you give a RespCondition to the OnRequest function, you'll get a run time panic! It doesn't 57 | make sense to read the response, if you still haven't got it! 58 | 59 | Finally, we have convenience function to throw a quick response 60 | 61 | proxy.OnResponse(hasGoProxyHeader).DoFunc(func(r*http.Response,ctx *goproxy.ProxyCtx)*http.Response { 62 | r.Body.Close() 63 | return goproxy.ForbiddenTextResponse(ctx.Req,"Can't see response with X-GoProxy header!") 64 | }) 65 | 66 | we close the body of the original repsonse, and return a new 403 response with a short message. 67 | 68 | Example use cases: 69 | 70 | 1. https://github.com/elazarl/goproxy/tree/master/examples/goproxy-avgsize 71 | 72 | To measure the average size of an Html served in your site. One can ask 73 | all the QA team to access the website by a proxy, and the proxy will 74 | measure the average size of all text/html responses from your host. 75 | 76 | 2. [not yet implemented] 77 | 78 | All requests to your web servers should be directed through the proxy, 79 | when the proxy will detect html pieces sent as a response to AJAX 80 | request, it'll send a warning email. 81 | 82 | 3. https://github.com/elazarl/goproxy/blob/master/examples/goproxy-httpdump/ 83 | 84 | Generate a real traffic to your website by real users using through 85 | proxy. Record the traffic, and try it again for more real load testing. 86 | 87 | 4. https://github.com/elazarl/goproxy/tree/master/examples/goproxy-no-reddit-at-worktime 88 | 89 | Will allow browsing to reddit.com between 8:00am and 17:00pm 90 | 91 | 5. https://github.com/elazarl/goproxy/tree/master/examples/goproxy-jquery-version 92 | 93 | Will warn if multiple versions of jquery are used in the same domain. 94 | 95 | 6. https://github.com/elazarl/goproxy/blob/master/examples/goproxy-upside-down-ternet/ 96 | 97 | Modifies image files in an HTTP response via goproxy's image extension found in ext/. 98 | 99 | */ 100 | package goproxy 101 | -------------------------------------------------------------------------------- /vendor/github.com/elazarl/goproxy/key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIJKAIBAAKCAgEAnhDL4fqGGhjWzRBFy8iHGuNIdo79FtoWPevCpyek6AWrTuBF 3 | 0j3dzRMUpAkemC/p94tGES9f9iWUVi7gnfmUz1lxhjiqUoW5K1xfwmbx+qmC2YAw 4 | HM+yq2oOLwz1FAYoQ3NT0gU6cJXtIB6Hjmxwy4jfDPzCuMFwfvOq4eS+pRJhnPTf 5 | m31XpZOsfJMS9PjD6UU5U3ZsD/oMAjGuMGIXoOGgmqeFrRJm0N+/vtenAYbcSED+ 6 | qiGGJisOu5grvMl0RJAvjgvDMw+6lWKCpqV+/5gd9CNuFP3nUhW6tbY0mBHIETrZ 7 | 0uuUdh21P20JMKt34ok0wn6On2ECN0i7UGv+SJ9TgXj7hksxH1R6OLQaSQ8qxh3I 8 | yeqPSnQ+iDK8/WXiqZug8iYxi1qgW5iYxiV5uAL0s3XRsv3Urj6Mu3QjVie0TOuq 9 | AmhawnO1gPDnjc3NLLlb79yrhdFiC2rVvRFbC5SKzB7OYyh7IdnwFAl7bEyMA6WU 10 | BIN+prw4rdYAEcmnLjNSudQGIy48hPMP8W4PHgLkjDCULryAcBluU2qkFkJfScUK 11 | 0qNg5wjZKjkdtDY4LxAX7MZW524dRKiTiFLLYEF9nWl+/OKoF561YnAW9qkYHjic 12 | geFYo0q+o7Es0jLt75MZGJY6iasBYzXxVJH0tlsHGkkrs8tLNapglhNEJkcCAwEA 13 | AQKCAgAwSuNvxHHqUUJ3XoxkiXy1u1EtX9x1eeYnvvs2xMb+WJURQTYz2NEGUdkR 14 | kPO2/ZSXHAcpQvcnpi2e8y2PNmy/uQ0VPATVt6NuWweqxncR5W5j82U/uDlXY8y3 15 | lVbfak4s5XRri0tikHvlP06dNgZ0OPok5qi7d+Zd8yZ3Y8LXfjkykiIrSG1Z2jdt 16 | zCWTkNmSUKMGG/1CGFxI41Lb12xuq+C8v4f469Fb6bCUpyCQN9rffHQSGLH6wVb7 17 | +68JO+d49zCATpmx5RFViMZwEcouXxRvvc9pPHXLP3ZPBD8nYu9kTD220mEGgWcZ 18 | 3L9dDlZPcSocbjw295WMvHz2QjhrDrb8gXwdpoRyuyofqgCyNxSnEC5M13SjOxtf 19 | pjGzjTqh0kDlKXg2/eTkd9xIHjVhFYiHIEeITM/lHCfWwBCYxViuuF7pSRPzTe8U 20 | C440b62qZSPMjVoquaMg+qx0n9fKSo6n1FIKHypv3Kue2G0WhDeK6u0U288vQ1t4 21 | Ood3Qa13gZ+9hwDLbM/AoBfVBDlP/tpAwa7AIIU1ZRDNbZr7emFdctx9B6kLINv3 22 | 4PDOGM2xrjOuACSGMq8Zcu7LBz35PpIZtviJOeKNwUd8/xHjWC6W0itgfJb5I1Nm 23 | V6Vj368pGlJx6Se26lvXwyyrc9pSw6jSAwARBeU4YkNWpi4i6QKCAQEA0T7u3P/9 24 | jZJSnDN1o2PXymDrJulE61yguhc/QSmLccEPZe7or06/DmEhhKuCbv+1MswKDeag 25 | /1JdFPGhL2+4G/f/9BK3BJPdcOZSz7K6Ty8AMMBf8AehKTcSBqwkJWcbEvpHpKJ6 26 | eDqn1B6brXTNKMT6fEEXCuZJGPBpNidyLv/xXDcN7kCOo3nGYKfB5OhFpNiL63tw 27 | +LntU56WESZwEqr8Pf80uFvsyXQK3a5q5HhIQtxl6tqQuPlNjsDBvCqj0x72mmaJ 28 | ZVsVWlv7khUrCwAXz7Y8K7mKKBd2ekF5hSbryfJsxFyvEaWUPhnJpTKV85lAS+tt 29 | FQuIp9TvKYlRQwKCAQEAwWJN8jysapdhi67jO0HtYOEl9wwnF4w6XtiOYtllkMmC 30 | 06/e9h7RsRyWPMdu3qRDPUYFaVDy6+dpUDSQ0+E2Ot6AHtVyvjeUTIL651mFIo/7 31 | OSUCEc+HRo3SfPXdPhSQ2thNTxl6y9XcFacuvbthgr70KXbvC4k6IEmdpf/0Kgs9 32 | 7QTZCG26HDrEZ2q9yMRlRaL2SRD+7Y2xra7gB+cQGFj6yn0Wd/07er49RqMXidQf 33 | KR2oYfev2BDtHXoSZFfhFGHlOdLvWRh90D4qZf4vQ+g/EIMgcNSoxjvph1EShmKt 34 | sjhTHtoHuu+XmEQvIewk2oCI+JvofBkcnpFrVvUUrQKCAQAaTIufETmgCo0BfuJB 35 | N/JOSGIl0NnNryWwXe2gVgVltbsmt6FdL0uKFiEtWJUbOF5g1Q5Kcvs3O/XhBQGa 36 | QbNlKIVt+tAv7hm97+Tmn/MUsraWagdk1sCluns0hXxBizT27KgGhDlaVRz05yfv 37 | 5CdJAYDuDwxDXXBAhy7iFJEgYSDH00+X61tCJrMNQOh4ycy/DEyBu1EWod+3S85W 38 | t3sMjZsIe8P3i+4137Th6eMbdha2+JaCrxfTd9oMoCN5b+6JQXIDM/H+4DTN15PF 39 | 540yY7+aZrAnWrmHknNcqFAKsTqfdi2/fFqwoBwCtiEG91WreU6AfEWIiJuTZIru 40 | sIibAoIBAAqIwlo5t+KukF+9jR9DPh0S5rCIdvCvcNaN0WPNF91FPN0vLWQW1bFi 41 | L0TsUDvMkuUZlV3hTPpQxsnZszH3iK64RB5p3jBCcs+gKu7DT59MXJEGVRCHT4Um 42 | YJryAbVKBYIGWl++sZO8+JotWzx2op8uq7o+glMMjKAJoo7SXIiVyC/LHc95urOi 43 | 9+PySphPKn0anXPpexmRqGYfqpCDo7rPzgmNutWac80B4/CfHb8iUPg6Z1u+1FNe 44 | yKvcZHgW2Wn00znNJcCitufLGyAnMofudND/c5rx2qfBx7zZS7sKUQ/uRYjes6EZ 45 | QBbJUA/2/yLv8YYpaAaqj4aLwV8hRpkCggEBAIh3e25tr3avCdGgtCxS7Y1blQ2c 46 | ue4erZKmFP1u8wTNHQ03T6sECZbnIfEywRD/esHpclfF3kYAKDRqIP4K905Rb0iH 47 | 759ZWt2iCbqZznf50XTvptdmjm5KxvouJzScnQ52gIV6L+QrCKIPelLBEIqCJREh 48 | pmcjjocD/UCCSuHgbAYNNnO/JdhnSylz1tIg26I+2iLNyeTKIepSNlsBxnkLmqM1 49 | cj/azKBaT04IOMLaN8xfSqitJYSraWMVNgGJM5vfcVaivZnNh0lZBv+qu6YkdM88 50 | 4/avCJ8IutT+FcMM+GbGazOm5ALWqUyhrnbLGc4CQMPfe7Il6NxwcrOxT8w= 51 | -----END RSA PRIVATE KEY----- 52 | -------------------------------------------------------------------------------- /vendor/github.com/elazarl/goproxy/responses.go: -------------------------------------------------------------------------------- 1 | package goproxy 2 | 3 | import ( 4 | "bytes" 5 | "io/ioutil" 6 | "net/http" 7 | ) 8 | 9 | // Will generate a valid http response to the given request the response will have 10 | // the given contentType, and http status. 11 | // Typical usage, refuse to process requests to local addresses: 12 | // 13 | // proxy.OnRequest(IsLocalHost()).DoFunc(func(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request,*http.Response) { 14 | // return nil,NewResponse(r,goproxy.ContentTypeHtml,http.StatusUnauthorized, 15 | // `Can't use proxy for local addresses`) 16 | // }) 17 | func NewResponse(r *http.Request, contentType string, status int, body string) *http.Response { 18 | resp := &http.Response{} 19 | resp.Request = r 20 | resp.TransferEncoding = r.TransferEncoding 21 | resp.Header = make(http.Header) 22 | resp.Header.Add("Content-Type", contentType) 23 | resp.StatusCode = status 24 | buf := bytes.NewBufferString(body) 25 | resp.ContentLength = int64(buf.Len()) 26 | resp.Body = ioutil.NopCloser(buf) 27 | return resp 28 | } 29 | 30 | const ( 31 | ContentTypeText = "text/plain" 32 | ContentTypeHtml = "text/html" 33 | ) 34 | 35 | // Alias for NewResponse(r,ContentTypeText,http.StatusAccepted,text) 36 | func TextResponse(r *http.Request, text string) *http.Response { 37 | return NewResponse(r, ContentTypeText, http.StatusAccepted, text) 38 | } 39 | -------------------------------------------------------------------------------- /vendor/github.com/elazarl/goproxy/signer.go: -------------------------------------------------------------------------------- 1 | package goproxy 2 | 3 | import ( 4 | "crypto/rsa" 5 | "crypto/sha1" 6 | "crypto/tls" 7 | "crypto/x509" 8 | "crypto/x509/pkix" 9 | "math/big" 10 | "net" 11 | "runtime" 12 | "sort" 13 | "time" 14 | ) 15 | 16 | func hashSorted(lst []string) []byte { 17 | c := make([]string, len(lst)) 18 | copy(c, lst) 19 | sort.Strings(c) 20 | h := sha1.New() 21 | for _, s := range c { 22 | h.Write([]byte(s + ",")) 23 | } 24 | return h.Sum(nil) 25 | } 26 | 27 | func hashSortedBigInt(lst []string) *big.Int { 28 | rv := new(big.Int) 29 | rv.SetBytes(hashSorted(lst)) 30 | return rv 31 | } 32 | 33 | var goproxySignerVersion = ":goroxy1" 34 | 35 | func signHost(ca tls.Certificate, hosts []string) (cert tls.Certificate, err error) { 36 | var x509ca *x509.Certificate 37 | 38 | // Use the provided ca and not the global GoproxyCa for certificate generation. 39 | if x509ca, err = x509.ParseCertificate(ca.Certificate[0]); err != nil { 40 | return 41 | } 42 | start := time.Unix(0, 0) 43 | end, err := time.Parse("2006-01-02", "2049-12-31") 44 | if err != nil { 45 | panic(err) 46 | } 47 | hash := hashSorted(append(hosts, goproxySignerVersion, ":"+runtime.Version())) 48 | serial := new(big.Int) 49 | serial.SetBytes(hash) 50 | template := x509.Certificate{ 51 | // TODO(elazar): instead of this ugly hack, just encode the certificate and hash the binary form. 52 | SerialNumber: serial, 53 | Issuer: x509ca.Subject, 54 | Subject: pkix.Name{ 55 | Organization: []string{"GoProxy untrusted MITM proxy Inc"}, 56 | }, 57 | NotBefore: start, 58 | NotAfter: end, 59 | 60 | KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, 61 | ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, 62 | BasicConstraintsValid: true, 63 | } 64 | for _, h := range hosts { 65 | if ip := net.ParseIP(h); ip != nil { 66 | template.IPAddresses = append(template.IPAddresses, ip) 67 | } else { 68 | template.DNSNames = append(template.DNSNames, h) 69 | } 70 | } 71 | var csprng CounterEncryptorRand 72 | if csprng, err = NewCounterEncryptorRandFromKey(ca.PrivateKey, hash); err != nil { 73 | return 74 | } 75 | var certpriv *rsa.PrivateKey 76 | if certpriv, err = rsa.GenerateKey(&csprng, 1024); err != nil { 77 | return 78 | } 79 | var derBytes []byte 80 | if derBytes, err = x509.CreateCertificate(&csprng, &template, x509ca, &certpriv.PublicKey, ca.PrivateKey); err != nil { 81 | return 82 | } 83 | return tls.Certificate{ 84 | Certificate: [][]byte{derBytes, ca.Certificate[0]}, 85 | PrivateKey: certpriv, 86 | }, nil 87 | } 88 | -------------------------------------------------------------------------------- /vendor/github.com/patrickmn/go-cache/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | This is a list of people who have contributed code to go-cache. They, or their 2 | employers, are the copyright holders of the contributed code. Contributed code 3 | is subject to the license restrictions listed in LICENSE (as they were when the 4 | code was contributed.) 5 | 6 | Dustin Sallings 7 | Jason Mooberry 8 | Sergey Shepelev 9 | Alex Edwards 10 | -------------------------------------------------------------------------------- /vendor/github.com/patrickmn/go-cache/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2017 Patrick Mylund Nielsen and the go-cache contributors 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /vendor/github.com/patrickmn/go-cache/README.md: -------------------------------------------------------------------------------- 1 | # go-cache 2 | 3 | go-cache is an in-memory key:value store/cache similar to memcached that is 4 | suitable for applications running on a single machine. Its major advantage is 5 | that, being essentially a thread-safe `map[string]interface{}` with expiration 6 | times, it doesn't need to serialize or transmit its contents over the network. 7 | 8 | Any object can be stored, for a given duration or forever, and the cache can be 9 | safely used by multiple goroutines. 10 | 11 | Although go-cache isn't meant to be used as a persistent datastore, the entire 12 | cache can be saved to and loaded from a file (using `c.Items()` to retrieve the 13 | items map to serialize, and `NewFrom()` to create a cache from a deserialized 14 | one) to recover from downtime quickly. (See the docs for `NewFrom()` for caveats.) 15 | 16 | ### Installation 17 | 18 | `go get github.com/patrickmn/go-cache` 19 | 20 | ### Usage 21 | 22 | ```go 23 | import ( 24 | "fmt" 25 | "github.com/patrickmn/go-cache" 26 | "time" 27 | ) 28 | 29 | func main() { 30 | // Create a cache with a default expiration time of 5 minutes, and which 31 | // purges expired items every 10 minutes 32 | c := cache.New(5*time.Minute, 10*time.Minute) 33 | 34 | // Set the value of the key "foo" to "bar", with the default expiration time 35 | c.Set("foo", "bar", cache.DefaultExpiration) 36 | 37 | // Set the value of the key "baz" to 42, with no expiration time 38 | // (the item won't be removed until it is re-set, or removed using 39 | // c.Delete("baz") 40 | c.Set("baz", 42, cache.NoExpiration) 41 | 42 | // Get the string associated with the key "foo" from the cache 43 | foo, found := c.Get("foo") 44 | if found { 45 | fmt.Println(foo) 46 | } 47 | 48 | // Since Go is statically typed, and cache values can be anything, type 49 | // assertion is needed when values are being passed to functions that don't 50 | // take arbitrary types, (i.e. interface{}). The simplest way to do this for 51 | // values which will only be used once--e.g. for passing to another 52 | // function--is: 53 | foo, found := c.Get("foo") 54 | if found { 55 | MyFunction(foo.(string)) 56 | } 57 | 58 | // This gets tedious if the value is used several times in the same function. 59 | // You might do either of the following instead: 60 | if x, found := c.Get("foo"); found { 61 | foo := x.(string) 62 | // ... 63 | } 64 | // or 65 | var foo string 66 | if x, found := c.Get("foo"); found { 67 | foo = x.(string) 68 | } 69 | // ... 70 | // foo can then be passed around freely as a string 71 | 72 | // Want performance? Store pointers! 73 | c.Set("foo", &MyStruct, cache.DefaultExpiration) 74 | if x, found := c.Get("foo"); found { 75 | foo := x.(*MyStruct) 76 | // ... 77 | } 78 | } 79 | ``` 80 | 81 | ### Reference 82 | 83 | `godoc` or [http://godoc.org/github.com/patrickmn/go-cache](http://godoc.org/github.com/patrickmn/go-cache) 84 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/html/atom/atom.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package atom provides integer codes (also known as atoms) for a fixed set of 6 | // frequently occurring HTML strings: tag names and attribute keys such as "p" 7 | // and "id". 8 | // 9 | // Sharing an atom's name between all elements with the same tag can result in 10 | // fewer string allocations when tokenizing and parsing HTML. Integer 11 | // comparisons are also generally faster than string comparisons. 12 | // 13 | // The value of an atom's particular code is not guaranteed to stay the same 14 | // between versions of this package. Neither is any ordering guaranteed: 15 | // whether atom.H1 < atom.H2 may also change. The codes are not guaranteed to 16 | // be dense. The only guarantees are that e.g. looking up "div" will yield 17 | // atom.Div, calling atom.Div.String will return "div", and atom.Div != 0. 18 | package atom // import "golang.org/x/net/html/atom" 19 | 20 | // Atom is an integer code for a string. The zero value maps to "". 21 | type Atom uint32 22 | 23 | // String returns the atom's name. 24 | func (a Atom) String() string { 25 | start := uint32(a >> 8) 26 | n := uint32(a & 0xff) 27 | if start+n > uint32(len(atomText)) { 28 | return "" 29 | } 30 | return atomText[start : start+n] 31 | } 32 | 33 | func (a Atom) string() string { 34 | return atomText[a>>8 : a>>8+a&0xff] 35 | } 36 | 37 | // fnv computes the FNV hash with an arbitrary starting value h. 38 | func fnv(h uint32, s []byte) uint32 { 39 | for i := range s { 40 | h ^= uint32(s[i]) 41 | h *= 16777619 42 | } 43 | return h 44 | } 45 | 46 | func match(s string, t []byte) bool { 47 | for i, c := range t { 48 | if s[i] != c { 49 | return false 50 | } 51 | } 52 | return true 53 | } 54 | 55 | // Lookup returns the atom whose name is s. It returns zero if there is no 56 | // such atom. The lookup is case sensitive. 57 | func Lookup(s []byte) Atom { 58 | if len(s) == 0 || len(s) > maxAtomLen { 59 | return 0 60 | } 61 | h := fnv(hash0, s) 62 | if a := table[h&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) { 63 | return a 64 | } 65 | if a := table[(h>>16)&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) { 66 | return a 67 | } 68 | return 0 69 | } 70 | 71 | // String returns a string whose contents are equal to s. In that sense, it is 72 | // equivalent to string(s) but may be more efficient. 73 | func String(s []byte) string { 74 | if a := Lookup(s); a != 0 { 75 | return a.String() 76 | } 77 | return string(s) 78 | } 79 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/html/const.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package html 6 | 7 | // Section 12.2.3.2 of the HTML5 specification says "The following elements 8 | // have varying levels of special parsing rules". 9 | // https://html.spec.whatwg.org/multipage/syntax.html#the-stack-of-open-elements 10 | var isSpecialElementMap = map[string]bool{ 11 | "address": true, 12 | "applet": true, 13 | "area": true, 14 | "article": true, 15 | "aside": true, 16 | "base": true, 17 | "basefont": true, 18 | "bgsound": true, 19 | "blockquote": true, 20 | "body": true, 21 | "br": true, 22 | "button": true, 23 | "caption": true, 24 | "center": true, 25 | "col": true, 26 | "colgroup": true, 27 | "dd": true, 28 | "details": true, 29 | "dir": true, 30 | "div": true, 31 | "dl": true, 32 | "dt": true, 33 | "embed": true, 34 | "fieldset": true, 35 | "figcaption": true, 36 | "figure": true, 37 | "footer": true, 38 | "form": true, 39 | "frame": true, 40 | "frameset": true, 41 | "h1": true, 42 | "h2": true, 43 | "h3": true, 44 | "h4": true, 45 | "h5": true, 46 | "h6": true, 47 | "head": true, 48 | "header": true, 49 | "hgroup": true, 50 | "hr": true, 51 | "html": true, 52 | "iframe": true, 53 | "img": true, 54 | "input": true, 55 | "isindex": true, 56 | "li": true, 57 | "link": true, 58 | "listing": true, 59 | "marquee": true, 60 | "menu": true, 61 | "meta": true, 62 | "nav": true, 63 | "noembed": true, 64 | "noframes": true, 65 | "noscript": true, 66 | "object": true, 67 | "ol": true, 68 | "p": true, 69 | "param": true, 70 | "plaintext": true, 71 | "pre": true, 72 | "script": true, 73 | "section": true, 74 | "select": true, 75 | "source": true, 76 | "style": true, 77 | "summary": true, 78 | "table": true, 79 | "tbody": true, 80 | "td": true, 81 | "template": true, 82 | "textarea": true, 83 | "tfoot": true, 84 | "th": true, 85 | "thead": true, 86 | "title": true, 87 | "tr": true, 88 | "track": true, 89 | "ul": true, 90 | "wbr": true, 91 | "xmp": true, 92 | } 93 | 94 | func isSpecialElement(element *Node) bool { 95 | switch element.Namespace { 96 | case "", "html": 97 | return isSpecialElementMap[element.Data] 98 | case "svg": 99 | return element.Data == "foreignObject" 100 | } 101 | return false 102 | } 103 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/html/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | /* 6 | Package html implements an HTML5-compliant tokenizer and parser. 7 | 8 | Tokenization is done by creating a Tokenizer for an io.Reader r. It is the 9 | caller's responsibility to ensure that r provides UTF-8 encoded HTML. 10 | 11 | z := html.NewTokenizer(r) 12 | 13 | Given a Tokenizer z, the HTML is tokenized by repeatedly calling z.Next(), 14 | which parses the next token and returns its type, or an error: 15 | 16 | for { 17 | tt := z.Next() 18 | if tt == html.ErrorToken { 19 | // ... 20 | return ... 21 | } 22 | // Process the current token. 23 | } 24 | 25 | There are two APIs for retrieving the current token. The high-level API is to 26 | call Token; the low-level API is to call Text or TagName / TagAttr. Both APIs 27 | allow optionally calling Raw after Next but before Token, Text, TagName, or 28 | TagAttr. In EBNF notation, the valid call sequence per token is: 29 | 30 | Next {Raw} [ Token | Text | TagName {TagAttr} ] 31 | 32 | Token returns an independent data structure that completely describes a token. 33 | Entities (such as "<") are unescaped, tag names and attribute keys are 34 | lower-cased, and attributes are collected into a []Attribute. For example: 35 | 36 | for { 37 | if z.Next() == html.ErrorToken { 38 | // Returning io.EOF indicates success. 39 | return z.Err() 40 | } 41 | emitToken(z.Token()) 42 | } 43 | 44 | The low-level API performs fewer allocations and copies, but the contents of 45 | the []byte values returned by Text, TagName and TagAttr may change on the next 46 | call to Next. For example, to extract an HTML page's anchor text: 47 | 48 | depth := 0 49 | for { 50 | tt := z.Next() 51 | switch tt { 52 | case ErrorToken: 53 | return z.Err() 54 | case TextToken: 55 | if depth > 0 { 56 | // emitBytes should copy the []byte it receives, 57 | // if it doesn't process it immediately. 58 | emitBytes(z.Text()) 59 | } 60 | case StartTagToken, EndTagToken: 61 | tn, _ := z.TagName() 62 | if len(tn) == 1 && tn[0] == 'a' { 63 | if tt == StartTagToken { 64 | depth++ 65 | } else { 66 | depth-- 67 | } 68 | } 69 | } 70 | } 71 | 72 | Parsing is done by calling Parse with an io.Reader, which returns the root of 73 | the parse tree (the document element) as a *Node. It is the caller's 74 | responsibility to ensure that the Reader provides UTF-8 encoded HTML. For 75 | example, to process each anchor node in depth-first order: 76 | 77 | doc, err := html.Parse(r) 78 | if err != nil { 79 | // ... 80 | } 81 | var f func(*html.Node) 82 | f = func(n *html.Node) { 83 | if n.Type == html.ElementNode && n.Data == "a" { 84 | // Do something with n... 85 | } 86 | for c := n.FirstChild; c != nil; c = c.NextSibling { 87 | f(c) 88 | } 89 | } 90 | f(doc) 91 | 92 | The relevant specifications include: 93 | https://html.spec.whatwg.org/multipage/syntax.html and 94 | https://html.spec.whatwg.org/multipage/syntax.html#tokenization 95 | */ 96 | package html // import "golang.org/x/net/html" 97 | 98 | // The tokenization algorithm implemented by this package is not a line-by-line 99 | // transliteration of the relatively verbose state-machine in the WHATWG 100 | // specification. A more direct approach is used instead, where the program 101 | // counter implies the state, such as whether it is tokenizing a tag or a text 102 | // node. Specification compliance is verified by checking expected and actual 103 | // outputs over a test suite rather than aiming for algorithmic fidelity. 104 | 105 | // TODO(nigeltao): Does a DOM API belong in this package or a separate one? 106 | // TODO(nigeltao): How does parsing interact with a JavaScript engine? 107 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/encoding/htmlindex/gen.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build ignore 6 | 7 | package main 8 | 9 | import ( 10 | "bytes" 11 | "encoding/json" 12 | "fmt" 13 | "log" 14 | "strings" 15 | 16 | "golang.org/x/text/internal/gen" 17 | ) 18 | 19 | type group struct { 20 | Encodings []struct { 21 | Labels []string 22 | Name string 23 | } 24 | } 25 | 26 | func main() { 27 | gen.Init() 28 | 29 | r := gen.Open("https://encoding.spec.whatwg.org", "whatwg", "encodings.json") 30 | var groups []group 31 | if err := json.NewDecoder(r).Decode(&groups); err != nil { 32 | log.Fatalf("Error reading encodings.json: %v", err) 33 | } 34 | 35 | w := &bytes.Buffer{} 36 | fmt.Fprintln(w, "type htmlEncoding byte") 37 | fmt.Fprintln(w, "const (") 38 | for i, g := range groups { 39 | for _, e := range g.Encodings { 40 | key := strings.ToLower(e.Name) 41 | name := consts[key] 42 | if name == "" { 43 | log.Fatalf("No const defined for %s.", key) 44 | } 45 | if i == 0 { 46 | fmt.Fprintf(w, "%s htmlEncoding = iota\n", name) 47 | } else { 48 | fmt.Fprintf(w, "%s\n", name) 49 | } 50 | } 51 | } 52 | fmt.Fprintln(w, "numEncodings") 53 | fmt.Fprint(w, ")\n\n") 54 | 55 | fmt.Fprintln(w, "var canonical = [numEncodings]string{") 56 | for _, g := range groups { 57 | for _, e := range g.Encodings { 58 | fmt.Fprintf(w, "%q,\n", strings.ToLower(e.Name)) 59 | } 60 | } 61 | fmt.Fprint(w, "}\n\n") 62 | 63 | fmt.Fprintln(w, "var nameMap = map[string]htmlEncoding{") 64 | for _, g := range groups { 65 | for _, e := range g.Encodings { 66 | for _, l := range e.Labels { 67 | key := strings.ToLower(e.Name) 68 | name := consts[key] 69 | fmt.Fprintf(w, "%q: %s,\n", l, name) 70 | } 71 | } 72 | } 73 | fmt.Fprint(w, "}\n\n") 74 | 75 | var tags []string 76 | fmt.Fprintln(w, "var localeMap = []htmlEncoding{") 77 | for _, loc := range locales { 78 | tags = append(tags, loc.tag) 79 | fmt.Fprintf(w, "%s, // %s \n", consts[loc.name], loc.tag) 80 | } 81 | fmt.Fprint(w, "}\n\n") 82 | 83 | fmt.Fprintf(w, "const locales = %q\n", strings.Join(tags, " ")) 84 | 85 | gen.WriteGoFile("tables.go", "htmlindex", w.Bytes()) 86 | } 87 | 88 | // consts maps canonical encoding name to internal constant. 89 | var consts = map[string]string{ 90 | "utf-8": "utf8", 91 | "ibm866": "ibm866", 92 | "iso-8859-2": "iso8859_2", 93 | "iso-8859-3": "iso8859_3", 94 | "iso-8859-4": "iso8859_4", 95 | "iso-8859-5": "iso8859_5", 96 | "iso-8859-6": "iso8859_6", 97 | "iso-8859-7": "iso8859_7", 98 | "iso-8859-8": "iso8859_8", 99 | "iso-8859-8-i": "iso8859_8I", 100 | "iso-8859-10": "iso8859_10", 101 | "iso-8859-13": "iso8859_13", 102 | "iso-8859-14": "iso8859_14", 103 | "iso-8859-15": "iso8859_15", 104 | "iso-8859-16": "iso8859_16", 105 | "koi8-r": "koi8r", 106 | "koi8-u": "koi8u", 107 | "macintosh": "macintosh", 108 | "windows-874": "windows874", 109 | "windows-1250": "windows1250", 110 | "windows-1251": "windows1251", 111 | "windows-1252": "windows1252", 112 | "windows-1253": "windows1253", 113 | "windows-1254": "windows1254", 114 | "windows-1255": "windows1255", 115 | "windows-1256": "windows1256", 116 | "windows-1257": "windows1257", 117 | "windows-1258": "windows1258", 118 | "x-mac-cyrillic": "macintoshCyrillic", 119 | "gbk": "gbk", 120 | "gb18030": "gb18030", 121 | // "hz-gb-2312": "hzgb2312", // Was removed from WhatWG 122 | "big5": "big5", 123 | "euc-jp": "eucjp", 124 | "iso-2022-jp": "iso2022jp", 125 | "shift_jis": "shiftJIS", 126 | "euc-kr": "euckr", 127 | "replacement": "replacement", 128 | "utf-16be": "utf16be", 129 | "utf-16le": "utf16le", 130 | "x-user-defined": "xUserDefined", 131 | } 132 | 133 | // locales is taken from 134 | // https://html.spec.whatwg.org/multipage/syntax.html#encoding-sniffing-algorithm. 135 | var locales = []struct{ tag, name string }{ 136 | {"und", "windows-1252"}, // The default value. 137 | {"ar", "windows-1256"}, 138 | {"ba", "windows-1251"}, 139 | {"be", "windows-1251"}, 140 | {"bg", "windows-1251"}, 141 | {"cs", "windows-1250"}, 142 | {"el", "iso-8859-7"}, 143 | {"et", "windows-1257"}, 144 | {"fa", "windows-1256"}, 145 | {"he", "windows-1255"}, 146 | {"hr", "windows-1250"}, 147 | {"hu", "iso-8859-2"}, 148 | {"ja", "shift_jis"}, 149 | {"kk", "windows-1251"}, 150 | {"ko", "euc-kr"}, 151 | {"ku", "windows-1254"}, 152 | {"ky", "windows-1251"}, 153 | {"lt", "windows-1257"}, 154 | {"lv", "windows-1257"}, 155 | {"mk", "windows-1251"}, 156 | {"pl", "iso-8859-2"}, 157 | {"ru", "windows-1251"}, 158 | {"sah", "windows-1251"}, 159 | {"sk", "windows-1250"}, 160 | {"sl", "iso-8859-2"}, 161 | {"sr", "windows-1251"}, 162 | {"tg", "windows-1251"}, 163 | {"th", "windows-874"}, 164 | {"tr", "windows-1254"}, 165 | {"tt", "windows-1251"}, 166 | {"uk", "windows-1251"}, 167 | {"vi", "windows-1258"}, 168 | {"zh-hans", "gb18030"}, 169 | {"zh-hant", "big5"}, 170 | } 171 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/encoding/htmlindex/htmlindex.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:generate go run gen.go 6 | 7 | // Package htmlindex maps character set encoding names to Encodings as 8 | // recommended by the W3C for use in HTML 5. See http://www.w3.org/TR/encoding. 9 | package htmlindex 10 | 11 | // TODO: perhaps have a "bare" version of the index (used by this package) that 12 | // is not pre-loaded with all encodings. Global variables in encodings prevent 13 | // the linker from being able to purge unneeded tables. This means that 14 | // referencing all encodings, as this package does for the default index, links 15 | // in all encodings unconditionally. 16 | // 17 | // This issue can be solved by either solving the linking issue (see 18 | // https://github.com/golang/go/issues/6330) or refactoring the encoding tables 19 | // (e.g. moving the tables to internal packages that do not use global 20 | // variables). 21 | 22 | // TODO: allow canonicalizing names 23 | 24 | import ( 25 | "errors" 26 | "strings" 27 | "sync" 28 | 29 | "golang.org/x/text/encoding" 30 | "golang.org/x/text/encoding/internal/identifier" 31 | "golang.org/x/text/language" 32 | ) 33 | 34 | var ( 35 | errInvalidName = errors.New("htmlindex: invalid encoding name") 36 | errUnknown = errors.New("htmlindex: unknown Encoding") 37 | errUnsupported = errors.New("htmlindex: this encoding is not supported") 38 | ) 39 | 40 | var ( 41 | matcherOnce sync.Once 42 | matcher language.Matcher 43 | ) 44 | 45 | // LanguageDefault returns the canonical name of the default encoding for a 46 | // given language. 47 | func LanguageDefault(tag language.Tag) string { 48 | matcherOnce.Do(func() { 49 | tags := []language.Tag{} 50 | for _, t := range strings.Split(locales, " ") { 51 | tags = append(tags, language.MustParse(t)) 52 | } 53 | matcher = language.NewMatcher(tags) 54 | }) 55 | _, i, _ := matcher.Match(tag) 56 | return canonical[localeMap[i]] // Default is Windows-1252. 57 | } 58 | 59 | // Get returns an Encoding for one of the names listed in 60 | // http://www.w3.org/TR/encoding using the Default Index. Matching is case- 61 | // insensitive. 62 | func Get(name string) (encoding.Encoding, error) { 63 | x, ok := nameMap[strings.ToLower(strings.TrimSpace(name))] 64 | if !ok { 65 | return nil, errInvalidName 66 | } 67 | return encodings[x], nil 68 | } 69 | 70 | // Name reports the canonical name of the given Encoding. It will return 71 | // an error if e is not associated with a supported encoding scheme. 72 | func Name(e encoding.Encoding) (string, error) { 73 | id, ok := e.(identifier.Interface) 74 | if !ok { 75 | return "", errUnknown 76 | } 77 | mib, _ := id.ID() 78 | if mib == 0 { 79 | return "", errUnknown 80 | } 81 | v, ok := mibMap[mib] 82 | if !ok { 83 | return "", errUnsupported 84 | } 85 | return canonical[v], nil 86 | } 87 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/encoding/htmlindex/map.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package htmlindex 6 | 7 | import ( 8 | "golang.org/x/text/encoding" 9 | "golang.org/x/text/encoding/charmap" 10 | "golang.org/x/text/encoding/internal/identifier" 11 | "golang.org/x/text/encoding/japanese" 12 | "golang.org/x/text/encoding/korean" 13 | "golang.org/x/text/encoding/simplifiedchinese" 14 | "golang.org/x/text/encoding/traditionalchinese" 15 | "golang.org/x/text/encoding/unicode" 16 | ) 17 | 18 | // mibMap maps a MIB identifier to an htmlEncoding index. 19 | var mibMap = map[identifier.MIB]htmlEncoding{ 20 | identifier.UTF8: utf8, 21 | identifier.UTF16BE: utf16be, 22 | identifier.UTF16LE: utf16le, 23 | identifier.IBM866: ibm866, 24 | identifier.ISOLatin2: iso8859_2, 25 | identifier.ISOLatin3: iso8859_3, 26 | identifier.ISOLatin4: iso8859_4, 27 | identifier.ISOLatinCyrillic: iso8859_5, 28 | identifier.ISOLatinArabic: iso8859_6, 29 | identifier.ISOLatinGreek: iso8859_7, 30 | identifier.ISOLatinHebrew: iso8859_8, 31 | identifier.ISO88598I: iso8859_8I, 32 | identifier.ISOLatin6: iso8859_10, 33 | identifier.ISO885913: iso8859_13, 34 | identifier.ISO885914: iso8859_14, 35 | identifier.ISO885915: iso8859_15, 36 | identifier.ISO885916: iso8859_16, 37 | identifier.KOI8R: koi8r, 38 | identifier.KOI8U: koi8u, 39 | identifier.Macintosh: macintosh, 40 | identifier.MacintoshCyrillic: macintoshCyrillic, 41 | identifier.Windows874: windows874, 42 | identifier.Windows1250: windows1250, 43 | identifier.Windows1251: windows1251, 44 | identifier.Windows1252: windows1252, 45 | identifier.Windows1253: windows1253, 46 | identifier.Windows1254: windows1254, 47 | identifier.Windows1255: windows1255, 48 | identifier.Windows1256: windows1256, 49 | identifier.Windows1257: windows1257, 50 | identifier.Windows1258: windows1258, 51 | identifier.XUserDefined: xUserDefined, 52 | identifier.GBK: gbk, 53 | identifier.GB18030: gb18030, 54 | identifier.Big5: big5, 55 | identifier.EUCPkdFmtJapanese: eucjp, 56 | identifier.ISO2022JP: iso2022jp, 57 | identifier.ShiftJIS: shiftJIS, 58 | identifier.EUCKR: euckr, 59 | identifier.Replacement: replacement, 60 | } 61 | 62 | // encodings maps the internal htmlEncoding to an Encoding. 63 | // TODO: consider using a reusable index in encoding/internal. 64 | var encodings = [numEncodings]encoding.Encoding{ 65 | utf8: unicode.UTF8, 66 | ibm866: charmap.CodePage866, 67 | iso8859_2: charmap.ISO8859_2, 68 | iso8859_3: charmap.ISO8859_3, 69 | iso8859_4: charmap.ISO8859_4, 70 | iso8859_5: charmap.ISO8859_5, 71 | iso8859_6: charmap.ISO8859_6, 72 | iso8859_7: charmap.ISO8859_7, 73 | iso8859_8: charmap.ISO8859_8, 74 | iso8859_8I: charmap.ISO8859_8I, 75 | iso8859_10: charmap.ISO8859_10, 76 | iso8859_13: charmap.ISO8859_13, 77 | iso8859_14: charmap.ISO8859_14, 78 | iso8859_15: charmap.ISO8859_15, 79 | iso8859_16: charmap.ISO8859_16, 80 | koi8r: charmap.KOI8R, 81 | koi8u: charmap.KOI8U, 82 | macintosh: charmap.Macintosh, 83 | windows874: charmap.Windows874, 84 | windows1250: charmap.Windows1250, 85 | windows1251: charmap.Windows1251, 86 | windows1252: charmap.Windows1252, 87 | windows1253: charmap.Windows1253, 88 | windows1254: charmap.Windows1254, 89 | windows1255: charmap.Windows1255, 90 | windows1256: charmap.Windows1256, 91 | windows1257: charmap.Windows1257, 92 | windows1258: charmap.Windows1258, 93 | macintoshCyrillic: charmap.MacintoshCyrillic, 94 | gbk: simplifiedchinese.GBK, 95 | gb18030: simplifiedchinese.GB18030, 96 | big5: traditionalchinese.Big5, 97 | eucjp: japanese.EUCJP, 98 | iso2022jp: japanese.ISO2022JP, 99 | shiftJIS: japanese.ShiftJIS, 100 | euckr: korean.EUCKR, 101 | replacement: encoding.Replacement, 102 | utf16be: unicode.UTF16(unicode.BigEndian, unicode.IgnoreBOM), 103 | utf16le: unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM), 104 | xUserDefined: charmap.XUserDefined, 105 | } 106 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/encoding/internal/identifier/gen.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build ignore 6 | 7 | package main 8 | 9 | import ( 10 | "bytes" 11 | "encoding/xml" 12 | "fmt" 13 | "io" 14 | "log" 15 | "strings" 16 | 17 | "golang.org/x/text/internal/gen" 18 | ) 19 | 20 | type registry struct { 21 | XMLName xml.Name `xml:"registry"` 22 | Updated string `xml:"updated"` 23 | Registry []struct { 24 | ID string `xml:"id,attr"` 25 | Record []struct { 26 | Name string `xml:"name"` 27 | Xref []struct { 28 | Type string `xml:"type,attr"` 29 | Data string `xml:"data,attr"` 30 | } `xml:"xref"` 31 | Desc struct { 32 | Data string `xml:",innerxml"` 33 | // Any []struct { 34 | // Data string `xml:",chardata"` 35 | // } `xml:",any"` 36 | // Data string `xml:",chardata"` 37 | } `xml:"description,"` 38 | MIB string `xml:"value"` 39 | Alias []string `xml:"alias"` 40 | MIME string `xml:"preferred_alias"` 41 | } `xml:"record"` 42 | } `xml:"registry"` 43 | } 44 | 45 | func main() { 46 | r := gen.OpenIANAFile("assignments/character-sets/character-sets.xml") 47 | reg := ®istry{} 48 | if err := xml.NewDecoder(r).Decode(®); err != nil && err != io.EOF { 49 | log.Fatalf("Error decoding charset registry: %v", err) 50 | } 51 | if len(reg.Registry) == 0 || reg.Registry[0].ID != "character-sets-1" { 52 | log.Fatalf("Unexpected ID %s", reg.Registry[0].ID) 53 | } 54 | 55 | w := &bytes.Buffer{} 56 | fmt.Fprintf(w, "const (\n") 57 | for _, rec := range reg.Registry[0].Record { 58 | constName := "" 59 | for _, a := range rec.Alias { 60 | if strings.HasPrefix(a, "cs") && strings.IndexByte(a, '-') == -1 { 61 | // Some of the constant definitions have comments in them. Strip those. 62 | constName = strings.Title(strings.SplitN(a[2:], "\n", 2)[0]) 63 | } 64 | } 65 | if constName == "" { 66 | switch rec.MIB { 67 | case "2085": 68 | constName = "HZGB2312" // Not listed as alias for some reason. 69 | default: 70 | log.Fatalf("No cs alias defined for %s.", rec.MIB) 71 | } 72 | } 73 | if rec.MIME != "" { 74 | rec.MIME = fmt.Sprintf(" (MIME: %s)", rec.MIME) 75 | } 76 | fmt.Fprintf(w, "// %s is the MIB identifier with IANA name %s%s.\n//\n", constName, rec.Name, rec.MIME) 77 | if len(rec.Desc.Data) > 0 { 78 | fmt.Fprint(w, "// ") 79 | d := xml.NewDecoder(strings.NewReader(rec.Desc.Data)) 80 | inElem := true 81 | attr := "" 82 | for { 83 | t, err := d.Token() 84 | if err != nil { 85 | if err != io.EOF { 86 | log.Fatal(err) 87 | } 88 | break 89 | } 90 | switch x := t.(type) { 91 | case xml.CharData: 92 | attr = "" // Don't need attribute info. 93 | a := bytes.Split([]byte(x), []byte("\n")) 94 | for i, b := range a { 95 | if b = bytes.TrimSpace(b); len(b) != 0 { 96 | if !inElem && i > 0 { 97 | fmt.Fprint(w, "\n// ") 98 | } 99 | inElem = false 100 | fmt.Fprintf(w, "%s ", string(b)) 101 | } 102 | } 103 | case xml.StartElement: 104 | if x.Name.Local == "xref" { 105 | inElem = true 106 | use := false 107 | for _, a := range x.Attr { 108 | if a.Name.Local == "type" { 109 | use = use || a.Value != "person" 110 | } 111 | if a.Name.Local == "data" && use { 112 | attr = a.Value + " " 113 | } 114 | } 115 | } 116 | case xml.EndElement: 117 | inElem = false 118 | fmt.Fprint(w, attr) 119 | } 120 | } 121 | fmt.Fprint(w, "\n") 122 | } 123 | for _, x := range rec.Xref { 124 | switch x.Type { 125 | case "rfc": 126 | fmt.Fprintf(w, "// Reference: %s\n", strings.ToUpper(x.Data)) 127 | case "uri": 128 | fmt.Fprintf(w, "// Reference: %s\n", x.Data) 129 | } 130 | } 131 | fmt.Fprintf(w, "%s MIB = %s\n", constName, rec.MIB) 132 | fmt.Fprintln(w) 133 | } 134 | fmt.Fprintln(w, ")") 135 | 136 | gen.WriteGoFile("mib.go", "identifier", w.Bytes()) 137 | } 138 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/encoding/internal/identifier/identifier.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:generate go run gen.go 6 | 7 | // Package identifier defines the contract between implementations of Encoding 8 | // and Index by defining identifiers that uniquely identify standardized coded 9 | // character sets (CCS) and character encoding schemes (CES), which we will 10 | // together refer to as encodings, for which Encoding implementations provide 11 | // converters to and from UTF-8. This package is typically only of concern to 12 | // implementers of Indexes and Encodings. 13 | // 14 | // One part of the identifier is the MIB code, which is defined by IANA and 15 | // uniquely identifies a CCS or CES. Each code is associated with data that 16 | // references authorities, official documentation as well as aliases and MIME 17 | // names. 18 | // 19 | // Not all CESs are covered by the IANA registry. The "other" string that is 20 | // returned by ID can be used to identify other character sets or versions of 21 | // existing ones. 22 | // 23 | // It is recommended that each package that provides a set of Encodings provide 24 | // the All and Common variables to reference all supported encodings and 25 | // commonly used subset. This allows Index implementations to include all 26 | // available encodings without explicitly referencing or knowing about them. 27 | package identifier 28 | 29 | // Note: this package is internal, but could be made public if there is a need 30 | // for writing third-party Indexes and Encodings. 31 | 32 | // References: 33 | // - http://source.icu-project.org/repos/icu/icu/trunk/source/data/mappings/convrtrs.txt 34 | // - http://www.iana.org/assignments/character-sets/character-sets.xhtml 35 | // - http://www.iana.org/assignments/ianacharset-mib/ianacharset-mib 36 | // - http://www.ietf.org/rfc/rfc2978.txt 37 | // - http://www.unicode.org/reports/tr22/ 38 | // - http://www.w3.org/TR/encoding/ 39 | // - https://encoding.spec.whatwg.org/ 40 | // - https://encoding.spec.whatwg.org/encodings.json 41 | // - https://tools.ietf.org/html/rfc6657#section-5 42 | 43 | // Interface can be implemented by Encodings to define the CCS or CES for which 44 | // it implements conversions. 45 | type Interface interface { 46 | // ID returns an encoding identifier. Exactly one of the mib and other 47 | // values should be non-zero. 48 | // 49 | // In the usual case it is only necessary to indicate the MIB code. The 50 | // other string can be used to specify encodings for which there is no MIB, 51 | // such as "x-mac-dingbat". 52 | // 53 | // The other string may only contain the characters a-z, A-Z, 0-9, - and _. 54 | ID() (mib MIB, other string) 55 | 56 | // NOTE: the restrictions on the encoding are to allow extending the syntax 57 | // with additional information such as versions, vendors and other variants. 58 | } 59 | 60 | // A MIB identifies an encoding. It is derived from the IANA MIB codes and adds 61 | // some identifiers for some encodings that are not covered by the IANA 62 | // standard. 63 | // 64 | // See http://www.iana.org/assignments/ianacharset-mib. 65 | type MIB uint16 66 | 67 | // These additional MIB types are not defined in IANA. They are added because 68 | // they are common and defined within the text repo. 69 | const ( 70 | // Unofficial marks the start of encodings not registered by IANA. 71 | Unofficial MIB = 10000 + iota 72 | 73 | // Replacement is the WhatWG replacement encoding. 74 | Replacement 75 | 76 | // XUserDefined is the code for x-user-defined. 77 | XUserDefined 78 | 79 | // MacintoshCyrillic is the code for x-mac-cyrillic. 80 | MacintoshCyrillic 81 | ) 82 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/encoding/internal/internal.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package internal contains code that is shared among encoding implementations. 6 | package internal 7 | 8 | import ( 9 | "golang.org/x/text/encoding" 10 | "golang.org/x/text/encoding/internal/identifier" 11 | "golang.org/x/text/transform" 12 | ) 13 | 14 | // Encoding is an implementation of the Encoding interface that adds the String 15 | // and ID methods to an existing encoding. 16 | type Encoding struct { 17 | encoding.Encoding 18 | Name string 19 | MIB identifier.MIB 20 | } 21 | 22 | // _ verifies that Encoding implements identifier.Interface. 23 | var _ identifier.Interface = (*Encoding)(nil) 24 | 25 | func (e *Encoding) String() string { 26 | return e.Name 27 | } 28 | 29 | func (e *Encoding) ID() (mib identifier.MIB, other string) { 30 | return e.MIB, "" 31 | } 32 | 33 | // SimpleEncoding is an Encoding that combines two Transformers. 34 | type SimpleEncoding struct { 35 | Decoder transform.Transformer 36 | Encoder transform.Transformer 37 | } 38 | 39 | func (e *SimpleEncoding) NewDecoder() *encoding.Decoder { 40 | return &encoding.Decoder{Transformer: e.Decoder} 41 | } 42 | 43 | func (e *SimpleEncoding) NewEncoder() *encoding.Encoder { 44 | return &encoding.Encoder{Transformer: e.Encoder} 45 | } 46 | 47 | // FuncEncoding is an Encoding that combines two functions returning a new 48 | // Transformer. 49 | type FuncEncoding struct { 50 | Decoder func() transform.Transformer 51 | Encoder func() transform.Transformer 52 | } 53 | 54 | func (e FuncEncoding) NewDecoder() *encoding.Decoder { 55 | return &encoding.Decoder{Transformer: e.Decoder()} 56 | } 57 | 58 | func (e FuncEncoding) NewEncoder() *encoding.Encoder { 59 | return &encoding.Encoder{Transformer: e.Encoder()} 60 | } 61 | 62 | // A RepertoireError indicates a rune is not in the repertoire of a destination 63 | // encoding. It is associated with an encoding-specific suggested replacement 64 | // byte. 65 | type RepertoireError byte 66 | 67 | // Error implements the error interrface. 68 | func (r RepertoireError) Error() string { 69 | return "encoding: rune not supported by encoding." 70 | } 71 | 72 | // Replacement returns the replacement string associated with this error. 73 | func (r RepertoireError) Replacement() byte { return byte(r) } 74 | 75 | var ErrASCIIReplacement = RepertoireError(encoding.ASCIISub) 76 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/encoding/japanese/all.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package japanese 6 | 7 | import ( 8 | "golang.org/x/text/encoding" 9 | ) 10 | 11 | // All is a list of all defined encodings in this package. 12 | var All = []encoding.Encoding{EUCJP, ISO2022JP, ShiftJIS} 13 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/encoding/korean/euckr.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package korean 6 | 7 | import ( 8 | "unicode/utf8" 9 | 10 | "golang.org/x/text/encoding" 11 | "golang.org/x/text/encoding/internal" 12 | "golang.org/x/text/encoding/internal/identifier" 13 | "golang.org/x/text/transform" 14 | ) 15 | 16 | // All is a list of all defined encodings in this package. 17 | var All = []encoding.Encoding{EUCKR} 18 | 19 | // EUCKR is the EUC-KR encoding, also known as Code Page 949. 20 | var EUCKR encoding.Encoding = &eucKR 21 | 22 | var eucKR = internal.Encoding{ 23 | &internal.SimpleEncoding{eucKRDecoder{}, eucKREncoder{}}, 24 | "EUC-KR", 25 | identifier.EUCKR, 26 | } 27 | 28 | type eucKRDecoder struct{ transform.NopResetter } 29 | 30 | func (eucKRDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { 31 | r, size := rune(0), 0 32 | loop: 33 | for ; nSrc < len(src); nSrc += size { 34 | switch c0 := src[nSrc]; { 35 | case c0 < utf8.RuneSelf: 36 | r, size = rune(c0), 1 37 | 38 | case 0x81 <= c0 && c0 < 0xff: 39 | if nSrc+1 >= len(src) { 40 | if !atEOF { 41 | err = transform.ErrShortSrc 42 | break loop 43 | } 44 | r, size = utf8.RuneError, 1 45 | break 46 | } 47 | c1 := src[nSrc+1] 48 | size = 2 49 | if c0 < 0xc7 { 50 | r = 178 * rune(c0-0x81) 51 | switch { 52 | case 0x41 <= c1 && c1 < 0x5b: 53 | r += rune(c1) - (0x41 - 0*26) 54 | case 0x61 <= c1 && c1 < 0x7b: 55 | r += rune(c1) - (0x61 - 1*26) 56 | case 0x81 <= c1 && c1 < 0xff: 57 | r += rune(c1) - (0x81 - 2*26) 58 | default: 59 | goto decError 60 | } 61 | } else if 0xa1 <= c1 && c1 < 0xff { 62 | r = 178*(0xc7-0x81) + rune(c0-0xc7)*94 + rune(c1-0xa1) 63 | } else { 64 | goto decError 65 | } 66 | if int(r) < len(decode) { 67 | r = rune(decode[r]) 68 | if r != 0 { 69 | break 70 | } 71 | } 72 | decError: 73 | r = utf8.RuneError 74 | if c1 < utf8.RuneSelf { 75 | size = 1 76 | } 77 | 78 | default: 79 | r, size = utf8.RuneError, 1 80 | break 81 | } 82 | 83 | if nDst+utf8.RuneLen(r) > len(dst) { 84 | err = transform.ErrShortDst 85 | break 86 | } 87 | nDst += utf8.EncodeRune(dst[nDst:], r) 88 | } 89 | return nDst, nSrc, err 90 | } 91 | 92 | type eucKREncoder struct{ transform.NopResetter } 93 | 94 | func (eucKREncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { 95 | r, size := rune(0), 0 96 | for ; nSrc < len(src); nSrc += size { 97 | r = rune(src[nSrc]) 98 | 99 | // Decode a 1-byte rune. 100 | if r < utf8.RuneSelf { 101 | size = 1 102 | 103 | if nDst >= len(dst) { 104 | err = transform.ErrShortDst 105 | break 106 | } 107 | dst[nDst] = uint8(r) 108 | nDst++ 109 | continue 110 | 111 | } else { 112 | // Decode a multi-byte rune. 113 | r, size = utf8.DecodeRune(src[nSrc:]) 114 | if size == 1 { 115 | // All valid runes of size 1 (those below utf8.RuneSelf) were 116 | // handled above. We have invalid UTF-8 or we haven't seen the 117 | // full character yet. 118 | if !atEOF && !utf8.FullRune(src[nSrc:]) { 119 | err = transform.ErrShortSrc 120 | break 121 | } 122 | } 123 | 124 | // func init checks that the switch covers all tables. 125 | switch { 126 | case encode0Low <= r && r < encode0High: 127 | if r = rune(encode0[r-encode0Low]); r != 0 { 128 | goto write2 129 | } 130 | case encode1Low <= r && r < encode1High: 131 | if r = rune(encode1[r-encode1Low]); r != 0 { 132 | goto write2 133 | } 134 | case encode2Low <= r && r < encode2High: 135 | if r = rune(encode2[r-encode2Low]); r != 0 { 136 | goto write2 137 | } 138 | case encode3Low <= r && r < encode3High: 139 | if r = rune(encode3[r-encode3Low]); r != 0 { 140 | goto write2 141 | } 142 | case encode4Low <= r && r < encode4High: 143 | if r = rune(encode4[r-encode4Low]); r != 0 { 144 | goto write2 145 | } 146 | case encode5Low <= r && r < encode5High: 147 | if r = rune(encode5[r-encode5Low]); r != 0 { 148 | goto write2 149 | } 150 | case encode6Low <= r && r < encode6High: 151 | if r = rune(encode6[r-encode6Low]); r != 0 { 152 | goto write2 153 | } 154 | } 155 | err = internal.ErrASCIIReplacement 156 | break 157 | } 158 | 159 | write2: 160 | if nDst+2 > len(dst) { 161 | err = transform.ErrShortDst 162 | break 163 | } 164 | dst[nDst+0] = uint8(r >> 8) 165 | dst[nDst+1] = uint8(r) 166 | nDst += 2 167 | continue 168 | } 169 | return nDst, nSrc, err 170 | } 171 | 172 | func init() { 173 | // Check that the hard-coded encode switch covers all tables. 174 | if numEncodeTables != 7 { 175 | panic("bad numEncodeTables") 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/encoding/korean/maketables.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build ignore 6 | 7 | package main 8 | 9 | // This program generates tables.go: 10 | // go run maketables.go | gofmt > tables.go 11 | 12 | import ( 13 | "bufio" 14 | "fmt" 15 | "log" 16 | "net/http" 17 | "sort" 18 | "strings" 19 | ) 20 | 21 | func main() { 22 | fmt.Printf("// generated by go run maketables.go; DO NOT EDIT\n\n") 23 | fmt.Printf("// Package korean provides Korean encodings such as EUC-KR.\n") 24 | fmt.Printf(`package korean // import "golang.org/x/text/encoding/korean"` + "\n\n") 25 | 26 | res, err := http.Get("http://encoding.spec.whatwg.org/index-euc-kr.txt") 27 | if err != nil { 28 | log.Fatalf("Get: %v", err) 29 | } 30 | defer res.Body.Close() 31 | 32 | mapping := [65536]uint16{} 33 | reverse := [65536]uint16{} 34 | 35 | scanner := bufio.NewScanner(res.Body) 36 | for scanner.Scan() { 37 | s := strings.TrimSpace(scanner.Text()) 38 | if s == "" || s[0] == '#' { 39 | continue 40 | } 41 | x, y := uint16(0), uint16(0) 42 | if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { 43 | log.Fatalf("could not parse %q", s) 44 | } 45 | if x < 0 || 178*(0xc7-0x81)+(0xfe-0xc7)*94+(0xff-0xa1) <= x { 46 | log.Fatalf("EUC-KR code %d is out of range", x) 47 | } 48 | mapping[x] = y 49 | if reverse[y] == 0 { 50 | c0, c1 := uint16(0), uint16(0) 51 | if x < 178*(0xc7-0x81) { 52 | c0 = uint16(x/178) + 0x81 53 | c1 = uint16(x % 178) 54 | switch { 55 | case c1 < 1*26: 56 | c1 += 0x41 57 | case c1 < 2*26: 58 | c1 += 0x47 59 | default: 60 | c1 += 0x4d 61 | } 62 | } else { 63 | x -= 178 * (0xc7 - 0x81) 64 | c0 = uint16(x/94) + 0xc7 65 | c1 = uint16(x%94) + 0xa1 66 | } 67 | reverse[y] = c0<<8 | c1 68 | } 69 | } 70 | if err := scanner.Err(); err != nil { 71 | log.Fatalf("scanner error: %v", err) 72 | } 73 | 74 | fmt.Printf("// decode is the decoding table from EUC-KR code to Unicode.\n") 75 | fmt.Printf("// It is defined at http://encoding.spec.whatwg.org/index-euc-kr.txt\n") 76 | fmt.Printf("var decode = [...]uint16{\n") 77 | for i, v := range mapping { 78 | if v != 0 { 79 | fmt.Printf("\t%d: 0x%04X,\n", i, v) 80 | } 81 | } 82 | fmt.Printf("}\n\n") 83 | 84 | // Any run of at least separation continuous zero entries in the reverse map will 85 | // be a separate encode table. 86 | const separation = 1024 87 | 88 | intervals := []interval(nil) 89 | low, high := -1, -1 90 | for i, v := range reverse { 91 | if v == 0 { 92 | continue 93 | } 94 | if low < 0 { 95 | low = i 96 | } else if i-high >= separation { 97 | if high >= 0 { 98 | intervals = append(intervals, interval{low, high}) 99 | } 100 | low = i 101 | } 102 | high = i + 1 103 | } 104 | if high >= 0 { 105 | intervals = append(intervals, interval{low, high}) 106 | } 107 | sort.Sort(byDecreasingLength(intervals)) 108 | 109 | fmt.Printf("const numEncodeTables = %d\n\n", len(intervals)) 110 | fmt.Printf("// encodeX are the encoding tables from Unicode to EUC-KR code,\n") 111 | fmt.Printf("// sorted by decreasing length.\n") 112 | for i, v := range intervals { 113 | fmt.Printf("// encode%d: %5d entries for runes in [%5d, %5d).\n", i, v.len(), v.low, v.high) 114 | } 115 | fmt.Printf("\n") 116 | 117 | for i, v := range intervals { 118 | fmt.Printf("const encode%dLow, encode%dHigh = %d, %d\n\n", i, i, v.low, v.high) 119 | fmt.Printf("var encode%d = [...]uint16{\n", i) 120 | for j := v.low; j < v.high; j++ { 121 | x := reverse[j] 122 | if x == 0 { 123 | continue 124 | } 125 | fmt.Printf("\t%d-%d: 0x%04X,\n", j, v.low, x) 126 | } 127 | fmt.Printf("}\n\n") 128 | } 129 | } 130 | 131 | // interval is a half-open interval [low, high). 132 | type interval struct { 133 | low, high int 134 | } 135 | 136 | func (i interval) len() int { return i.high - i.low } 137 | 138 | // byDecreasingLength sorts intervals by decreasing length. 139 | type byDecreasingLength []interval 140 | 141 | func (b byDecreasingLength) Len() int { return len(b) } 142 | func (b byDecreasingLength) Less(i, j int) bool { return b[i].len() > b[j].len() } 143 | func (b byDecreasingLength) Swap(i, j int) { b[i], b[j] = b[j], b[i] } 144 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/encoding/simplifiedchinese/all.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package simplifiedchinese 6 | 7 | import ( 8 | "golang.org/x/text/encoding" 9 | ) 10 | 11 | // All is a list of all defined encodings in this package. 12 | var All = []encoding.Encoding{GB18030, GBK, HZGB2312} 13 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/encoding/simplifiedchinese/maketables.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build ignore 6 | 7 | package main 8 | 9 | // This program generates tables.go: 10 | // go run maketables.go | gofmt > tables.go 11 | 12 | import ( 13 | "bufio" 14 | "fmt" 15 | "log" 16 | "net/http" 17 | "sort" 18 | "strings" 19 | ) 20 | 21 | func main() { 22 | fmt.Printf("// generated by go run maketables.go; DO NOT EDIT\n\n") 23 | fmt.Printf("// Package simplifiedchinese provides Simplified Chinese encodings such as GBK.\n") 24 | fmt.Printf(`package simplifiedchinese // import "golang.org/x/text/encoding/simplifiedchinese"` + "\n\n") 25 | 26 | printGB18030() 27 | printGBK() 28 | } 29 | 30 | func printGB18030() { 31 | res, err := http.Get("http://encoding.spec.whatwg.org/index-gb18030.txt") 32 | if err != nil { 33 | log.Fatalf("Get: %v", err) 34 | } 35 | defer res.Body.Close() 36 | 37 | fmt.Printf("// gb18030 is the table from http://encoding.spec.whatwg.org/index-gb18030.txt\n") 38 | fmt.Printf("var gb18030 = [...][2]uint16{\n") 39 | scanner := bufio.NewScanner(res.Body) 40 | for scanner.Scan() { 41 | s := strings.TrimSpace(scanner.Text()) 42 | if s == "" || s[0] == '#' { 43 | continue 44 | } 45 | x, y := uint32(0), uint32(0) 46 | if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { 47 | log.Fatalf("could not parse %q", s) 48 | } 49 | if x < 0x10000 && y < 0x10000 { 50 | fmt.Printf("\t{0x%04x, 0x%04x},\n", x, y) 51 | } 52 | } 53 | fmt.Printf("}\n\n") 54 | } 55 | 56 | func printGBK() { 57 | res, err := http.Get("http://encoding.spec.whatwg.org/index-gbk.txt") 58 | if err != nil { 59 | log.Fatalf("Get: %v", err) 60 | } 61 | defer res.Body.Close() 62 | 63 | mapping := [65536]uint16{} 64 | reverse := [65536]uint16{} 65 | 66 | scanner := bufio.NewScanner(res.Body) 67 | for scanner.Scan() { 68 | s := strings.TrimSpace(scanner.Text()) 69 | if s == "" || s[0] == '#' { 70 | continue 71 | } 72 | x, y := uint16(0), uint16(0) 73 | if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { 74 | log.Fatalf("could not parse %q", s) 75 | } 76 | if x < 0 || 126*190 <= x { 77 | log.Fatalf("GBK code %d is out of range", x) 78 | } 79 | mapping[x] = y 80 | if reverse[y] == 0 { 81 | c0, c1 := x/190, x%190 82 | if c1 >= 0x3f { 83 | c1++ 84 | } 85 | reverse[y] = (0x81+c0)<<8 | (0x40 + c1) 86 | } 87 | } 88 | if err := scanner.Err(); err != nil { 89 | log.Fatalf("scanner error: %v", err) 90 | } 91 | 92 | fmt.Printf("// decode is the decoding table from GBK code to Unicode.\n") 93 | fmt.Printf("// It is defined at http://encoding.spec.whatwg.org/index-gbk.txt\n") 94 | fmt.Printf("var decode = [...]uint16{\n") 95 | for i, v := range mapping { 96 | if v != 0 { 97 | fmt.Printf("\t%d: 0x%04X,\n", i, v) 98 | } 99 | } 100 | fmt.Printf("}\n\n") 101 | 102 | // Any run of at least separation continuous zero entries in the reverse map will 103 | // be a separate encode table. 104 | const separation = 1024 105 | 106 | intervals := []interval(nil) 107 | low, high := -1, -1 108 | for i, v := range reverse { 109 | if v == 0 { 110 | continue 111 | } 112 | if low < 0 { 113 | low = i 114 | } else if i-high >= separation { 115 | if high >= 0 { 116 | intervals = append(intervals, interval{low, high}) 117 | } 118 | low = i 119 | } 120 | high = i + 1 121 | } 122 | if high >= 0 { 123 | intervals = append(intervals, interval{low, high}) 124 | } 125 | sort.Sort(byDecreasingLength(intervals)) 126 | 127 | fmt.Printf("const numEncodeTables = %d\n\n", len(intervals)) 128 | fmt.Printf("// encodeX are the encoding tables from Unicode to GBK code,\n") 129 | fmt.Printf("// sorted by decreasing length.\n") 130 | for i, v := range intervals { 131 | fmt.Printf("// encode%d: %5d entries for runes in [%5d, %5d).\n", i, v.len(), v.low, v.high) 132 | } 133 | fmt.Printf("\n") 134 | 135 | for i, v := range intervals { 136 | fmt.Printf("const encode%dLow, encode%dHigh = %d, %d\n\n", i, i, v.low, v.high) 137 | fmt.Printf("var encode%d = [...]uint16{\n", i) 138 | for j := v.low; j < v.high; j++ { 139 | x := reverse[j] 140 | if x == 0 { 141 | continue 142 | } 143 | fmt.Printf("\t%d-%d: 0x%04X,\n", j, v.low, x) 144 | } 145 | fmt.Printf("}\n\n") 146 | } 147 | } 148 | 149 | // interval is a half-open interval [low, high). 150 | type interval struct { 151 | low, high int 152 | } 153 | 154 | func (i interval) len() int { return i.high - i.low } 155 | 156 | // byDecreasingLength sorts intervals by decreasing length. 157 | type byDecreasingLength []interval 158 | 159 | func (b byDecreasingLength) Len() int { return len(b) } 160 | func (b byDecreasingLength) Less(i, j int) bool { return b[i].len() > b[j].len() } 161 | func (b byDecreasingLength) Swap(i, j int) { b[i], b[j] = b[j], b[i] } 162 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/encoding/traditionalchinese/maketables.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build ignore 6 | 7 | package main 8 | 9 | // This program generates tables.go: 10 | // go run maketables.go | gofmt > tables.go 11 | 12 | import ( 13 | "bufio" 14 | "fmt" 15 | "log" 16 | "net/http" 17 | "sort" 18 | "strings" 19 | ) 20 | 21 | func main() { 22 | fmt.Printf("// generated by go run maketables.go; DO NOT EDIT\n\n") 23 | fmt.Printf("// Package traditionalchinese provides Traditional Chinese encodings such as Big5.\n") 24 | fmt.Printf(`package traditionalchinese // import "golang.org/x/text/encoding/traditionalchinese"` + "\n\n") 25 | 26 | res, err := http.Get("http://encoding.spec.whatwg.org/index-big5.txt") 27 | if err != nil { 28 | log.Fatalf("Get: %v", err) 29 | } 30 | defer res.Body.Close() 31 | 32 | mapping := [65536]uint32{} 33 | reverse := [65536 * 4]uint16{} 34 | 35 | scanner := bufio.NewScanner(res.Body) 36 | for scanner.Scan() { 37 | s := strings.TrimSpace(scanner.Text()) 38 | if s == "" || s[0] == '#' { 39 | continue 40 | } 41 | x, y := uint16(0), uint32(0) 42 | if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil { 43 | log.Fatalf("could not parse %q", s) 44 | } 45 | if x < 0 || 126*157 <= x { 46 | log.Fatalf("Big5 code %d is out of range", x) 47 | } 48 | mapping[x] = y 49 | 50 | // The WHATWG spec http://encoding.spec.whatwg.org/#indexes says that 51 | // "The index pointer for code point in index is the first pointer 52 | // corresponding to code point in index", which would normally mean 53 | // that the code below should be guarded by "if reverse[y] == 0", but 54 | // last instead of first seems to match the behavior of 55 | // "iconv -f UTF-8 -t BIG5". For example, U+8005 者 occurs twice in 56 | // http://encoding.spec.whatwg.org/index-big5.txt, as index 2148 57 | // (encoded as "\x8e\xcd") and index 6543 (encoded as "\xaa\xcc") 58 | // and "echo 者 | iconv -f UTF-8 -t BIG5 | xxd" gives "\xaa\xcc". 59 | c0, c1 := x/157, x%157 60 | if c1 < 0x3f { 61 | c1 += 0x40 62 | } else { 63 | c1 += 0x62 64 | } 65 | reverse[y] = (0x81+c0)<<8 | c1 66 | } 67 | if err := scanner.Err(); err != nil { 68 | log.Fatalf("scanner error: %v", err) 69 | } 70 | 71 | fmt.Printf("// decode is the decoding table from Big5 code to Unicode.\n") 72 | fmt.Printf("// It is defined at http://encoding.spec.whatwg.org/index-big5.txt\n") 73 | fmt.Printf("var decode = [...]uint32{\n") 74 | for i, v := range mapping { 75 | if v != 0 { 76 | fmt.Printf("\t%d: 0x%08X,\n", i, v) 77 | } 78 | } 79 | fmt.Printf("}\n\n") 80 | 81 | // Any run of at least separation continuous zero entries in the reverse map will 82 | // be a separate encode table. 83 | const separation = 1024 84 | 85 | intervals := []interval(nil) 86 | low, high := -1, -1 87 | for i, v := range reverse { 88 | if v == 0 { 89 | continue 90 | } 91 | if low < 0 { 92 | low = i 93 | } else if i-high >= separation { 94 | if high >= 0 { 95 | intervals = append(intervals, interval{low, high}) 96 | } 97 | low = i 98 | } 99 | high = i + 1 100 | } 101 | if high >= 0 { 102 | intervals = append(intervals, interval{low, high}) 103 | } 104 | sort.Sort(byDecreasingLength(intervals)) 105 | 106 | fmt.Printf("const numEncodeTables = %d\n\n", len(intervals)) 107 | fmt.Printf("// encodeX are the encoding tables from Unicode to Big5 code,\n") 108 | fmt.Printf("// sorted by decreasing length.\n") 109 | for i, v := range intervals { 110 | fmt.Printf("// encode%d: %5d entries for runes in [%6d, %6d).\n", i, v.len(), v.low, v.high) 111 | } 112 | fmt.Printf("\n") 113 | 114 | for i, v := range intervals { 115 | fmt.Printf("const encode%dLow, encode%dHigh = %d, %d\n\n", i, i, v.low, v.high) 116 | fmt.Printf("var encode%d = [...]uint16{\n", i) 117 | for j := v.low; j < v.high; j++ { 118 | x := reverse[j] 119 | if x == 0 { 120 | continue 121 | } 122 | fmt.Printf("\t%d-%d: 0x%04X,\n", j, v.low, x) 123 | } 124 | fmt.Printf("}\n\n") 125 | } 126 | } 127 | 128 | // interval is a half-open interval [low, high). 129 | type interval struct { 130 | low, high int 131 | } 132 | 133 | func (i interval) len() int { return i.high - i.low } 134 | 135 | // byDecreasingLength sorts intervals by decreasing length. 136 | type byDecreasingLength []interval 137 | 138 | func (b byDecreasingLength) Len() int { return len(b) } 139 | func (b byDecreasingLength) Less(i, j int) bool { return b[i].len() > b[j].len() } 140 | func (b byDecreasingLength) Swap(i, j int) { b[i], b[j] = b[j], b[i] } 141 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/encoding/unicode/override.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package unicode 6 | 7 | import ( 8 | "golang.org/x/text/transform" 9 | ) 10 | 11 | // BOMOverride returns a new decoder transformer that is identical to fallback, 12 | // except that the presence of a Byte Order Mark at the start of the input 13 | // causes it to switch to the corresponding Unicode decoding. It will only 14 | // consider BOMs for UTF-8, UTF-16BE, and UTF-16LE. 15 | // 16 | // This differs from using ExpectBOM by allowing a BOM to switch to UTF-8, not 17 | // just UTF-16 variants, and allowing falling back to any encoding scheme. 18 | // 19 | // This technique is recommended by the W3C for use in HTML 5: "For 20 | // compatibility with deployed content, the byte order mark (also known as BOM) 21 | // is considered more authoritative than anything else." 22 | // http://www.w3.org/TR/encoding/#specification-hooks 23 | // 24 | // Using BOMOverride is mostly intended for use cases where the first characters 25 | // of a fallback encoding are known to not be a BOM, for example, for valid HTML 26 | // and most encodings. 27 | func BOMOverride(fallback transform.Transformer) transform.Transformer { 28 | // TODO: possibly allow a variadic argument of unicode encodings to allow 29 | // specifying details of which fallbacks are supported as well as 30 | // specifying the details of the implementations. This would also allow for 31 | // support for UTF-32, which should not be supported by default. 32 | return &bomOverride{fallback: fallback} 33 | } 34 | 35 | type bomOverride struct { 36 | fallback transform.Transformer 37 | current transform.Transformer 38 | } 39 | 40 | func (d *bomOverride) Reset() { 41 | d.current = nil 42 | d.fallback.Reset() 43 | } 44 | 45 | var ( 46 | // TODO: we could use decode functions here, instead of allocating a new 47 | // decoder on every NewDecoder as IgnoreBOM decoders can be stateless. 48 | utf16le = UTF16(LittleEndian, IgnoreBOM) 49 | utf16be = UTF16(BigEndian, IgnoreBOM) 50 | ) 51 | 52 | const utf8BOM = "\ufeff" 53 | 54 | func (d *bomOverride) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { 55 | if d.current != nil { 56 | return d.current.Transform(dst, src, atEOF) 57 | } 58 | if len(src) < 3 && !atEOF { 59 | return 0, 0, transform.ErrShortSrc 60 | } 61 | d.current = d.fallback 62 | bomSize := 0 63 | if len(src) >= 2 { 64 | if src[0] == 0xFF && src[1] == 0xFE { 65 | d.current = utf16le.NewDecoder() 66 | bomSize = 2 67 | } else if src[0] == 0xFE && src[1] == 0xFF { 68 | d.current = utf16be.NewDecoder() 69 | bomSize = 2 70 | } else if len(src) >= 3 && 71 | src[0] == utf8BOM[0] && 72 | src[1] == utf8BOM[1] && 73 | src[2] == utf8BOM[2] { 74 | d.current = transform.Nop 75 | bomSize = 3 76 | } 77 | } 78 | if bomSize < len(src) { 79 | nDst, nSrc, err = d.current.Transform(dst, src[bomSize:], atEOF) 80 | } 81 | return nDst, nSrc + bomSize, err 82 | } 83 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/internal/tag/tag.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package tag contains functionality handling tags and related data. 6 | package tag // import "golang.org/x/text/internal/tag" 7 | 8 | import "sort" 9 | 10 | // An Index converts tags to a compact numeric value. 11 | // 12 | // All elements are of size 4. Tags may be up to 4 bytes long. Excess bytes can 13 | // be used to store additional information about the tag. 14 | type Index string 15 | 16 | // Elem returns the element data at the given index. 17 | func (s Index) Elem(x int) string { 18 | return string(s[x*4 : x*4+4]) 19 | } 20 | 21 | // Index reports the index of the given key or -1 if it could not be found. 22 | // Only the first len(key) bytes from the start of the 4-byte entries will be 23 | // considered for the search and the first match in Index will be returned. 24 | func (s Index) Index(key []byte) int { 25 | n := len(key) 26 | // search the index of the first entry with an equal or higher value than 27 | // key in s. 28 | index := sort.Search(len(s)/4, func(i int) bool { 29 | return cmp(s[i*4:i*4+n], key) != -1 30 | }) 31 | i := index * 4 32 | if cmp(s[i:i+len(key)], key) != 0 { 33 | return -1 34 | } 35 | return index 36 | } 37 | 38 | // Next finds the next occurrence of key after index x, which must have been 39 | // obtained from a call to Index using the same key. It returns x+1 or -1. 40 | func (s Index) Next(key []byte, x int) int { 41 | if x++; x*4 < len(s) && cmp(s[x*4:x*4+len(key)], key) == 0 { 42 | return x 43 | } 44 | return -1 45 | } 46 | 47 | // cmp returns an integer comparing a and b lexicographically. 48 | func cmp(a Index, b []byte) int { 49 | n := len(a) 50 | if len(b) < n { 51 | n = len(b) 52 | } 53 | for i, c := range b[:n] { 54 | switch { 55 | case a[i] > c: 56 | return 1 57 | case a[i] < c: 58 | return -1 59 | } 60 | } 61 | switch { 62 | case len(a) < len(b): 63 | return -1 64 | case len(a) > len(b): 65 | return 1 66 | } 67 | return 0 68 | } 69 | 70 | // Compare returns an integer comparing a and b lexicographically. 71 | func Compare(a string, b []byte) int { 72 | return cmp(Index(a), b) 73 | } 74 | 75 | // FixCase reformats b to the same pattern of cases as form. 76 | // If returns false if string b is malformed. 77 | func FixCase(form string, b []byte) bool { 78 | if len(form) != len(b) { 79 | return false 80 | } 81 | for i, c := range b { 82 | if form[i] <= 'Z' { 83 | if c >= 'a' { 84 | c -= 'z' - 'Z' 85 | } 86 | if c < 'A' || 'Z' < c { 87 | return false 88 | } 89 | } else { 90 | if c <= 'Z' { 91 | c += 'z' - 'Z' 92 | } 93 | if c < 'a' || 'z' < c { 94 | return false 95 | } 96 | } 97 | b[i] = c 98 | } 99 | return true 100 | } 101 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/internal/utf8internal/utf8internal.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package utf8internal contains low-level utf8-related constants, tables, etc. 6 | // that are used internally by the text package. 7 | package utf8internal 8 | 9 | // The default lowest and highest continuation byte. 10 | const ( 11 | LoCB = 0x80 // 1000 0000 12 | HiCB = 0xBF // 1011 1111 13 | ) 14 | 15 | // Constants related to getting information of first bytes of UTF-8 sequences. 16 | const ( 17 | // ASCII identifies a UTF-8 byte as ASCII. 18 | ASCII = as 19 | 20 | // FirstInvalid indicates a byte is invalid as a first byte of a UTF-8 21 | // sequence. 22 | FirstInvalid = xx 23 | 24 | // SizeMask is a mask for the size bits. Use use x&SizeMask to get the size. 25 | SizeMask = 7 26 | 27 | // AcceptShift is the right-shift count for the first byte info byte to get 28 | // the index into the AcceptRanges table. See AcceptRanges. 29 | AcceptShift = 4 30 | 31 | // The names of these constants are chosen to give nice alignment in the 32 | // table below. The first nibble is an index into acceptRanges or F for 33 | // special one-byte cases. The second nibble is the Rune length or the 34 | // Status for the special one-byte case. 35 | xx = 0xF1 // invalid: size 1 36 | as = 0xF0 // ASCII: size 1 37 | s1 = 0x02 // accept 0, size 2 38 | s2 = 0x13 // accept 1, size 3 39 | s3 = 0x03 // accept 0, size 3 40 | s4 = 0x23 // accept 2, size 3 41 | s5 = 0x34 // accept 3, size 4 42 | s6 = 0x04 // accept 0, size 4 43 | s7 = 0x44 // accept 4, size 4 44 | ) 45 | 46 | // First is information about the first byte in a UTF-8 sequence. 47 | var First = [256]uint8{ 48 | // 1 2 3 4 5 6 7 8 9 A B C D E F 49 | as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x00-0x0F 50 | as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x10-0x1F 51 | as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x20-0x2F 52 | as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x30-0x3F 53 | as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x40-0x4F 54 | as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x50-0x5F 55 | as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x60-0x6F 56 | as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x70-0x7F 57 | // 1 2 3 4 5 6 7 8 9 A B C D E F 58 | xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0x80-0x8F 59 | xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0x90-0x9F 60 | xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xA0-0xAF 61 | xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xB0-0xBF 62 | xx, xx, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, // 0xC0-0xCF 63 | s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, // 0xD0-0xDF 64 | s2, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s4, s3, s3, // 0xE0-0xEF 65 | s5, s6, s6, s6, s7, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xF0-0xFF 66 | } 67 | 68 | // AcceptRange gives the range of valid values for the second byte in a UTF-8 69 | // sequence for any value for First that is not ASCII or FirstInvalid. 70 | type AcceptRange struct { 71 | Lo uint8 // lowest value for second byte. 72 | Hi uint8 // highest value for second byte. 73 | } 74 | 75 | // AcceptRanges is a slice of AcceptRange values. For a given byte sequence b 76 | // 77 | // AcceptRanges[First[b[0]]>>AcceptShift] 78 | // 79 | // will give the value of AcceptRange for the multi-byte UTF-8 sequence starting 80 | // at b[0]. 81 | var AcceptRanges = [...]AcceptRange{ 82 | 0: {LoCB, HiCB}, 83 | 1: {0xA0, HiCB}, 84 | 2: {LoCB, 0x9F}, 85 | 3: {0x90, HiCB}, 86 | 4: {LoCB, 0x8F}, 87 | } 88 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/language/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2013 The Go Authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | CLEANFILES+=maketables 6 | 7 | maketables: maketables.go 8 | go build $^ 9 | 10 | tables: maketables 11 | ./maketables > tables.go 12 | gofmt -w -s tables.go 13 | 14 | # Build (but do not run) maketables during testing, 15 | # just to make sure it still compiles. 16 | testshort: maketables 17 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/language/common.go: -------------------------------------------------------------------------------- 1 | // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. 2 | 3 | package language 4 | 5 | // This file contains code common to the maketables.go and the package code. 6 | 7 | // langAliasType is the type of an alias in langAliasMap. 8 | type langAliasType int8 9 | 10 | const ( 11 | langDeprecated langAliasType = iota 12 | langMacro 13 | langLegacy 14 | 15 | langAliasTypeUnknown langAliasType = -1 16 | ) 17 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/language/gen_common.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build ignore 6 | 7 | package main 8 | 9 | // This file contains code common to the maketables.go and the package code. 10 | 11 | // langAliasType is the type of an alias in langAliasMap. 12 | type langAliasType int8 13 | 14 | const ( 15 | langDeprecated langAliasType = iota 16 | langMacro 17 | langLegacy 18 | 19 | langAliasTypeUnknown langAliasType = -1 20 | ) 21 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/language/go1_1.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !go1.2 6 | 7 | package language 8 | 9 | import "sort" 10 | 11 | func sortStable(s sort.Interface) { 12 | ss := stableSort{ 13 | s: s, 14 | pos: make([]int, s.Len()), 15 | } 16 | for i := range ss.pos { 17 | ss.pos[i] = i 18 | } 19 | sort.Sort(&ss) 20 | } 21 | 22 | type stableSort struct { 23 | s sort.Interface 24 | pos []int 25 | } 26 | 27 | func (s *stableSort) Len() int { 28 | return len(s.pos) 29 | } 30 | 31 | func (s *stableSort) Less(i, j int) bool { 32 | return s.s.Less(i, j) || !s.s.Less(j, i) && s.pos[i] < s.pos[j] 33 | } 34 | 35 | func (s *stableSort) Swap(i, j int) { 36 | s.s.Swap(i, j) 37 | s.pos[i], s.pos[j] = s.pos[j], s.pos[i] 38 | } 39 | -------------------------------------------------------------------------------- /vendor/golang.org/x/text/language/go1_2.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build go1.2 6 | 7 | package language 8 | 9 | import "sort" 10 | 11 | var sortStable = sort.Stable 12 | -------------------------------------------------------------------------------- /vendor/mantic/cache/dns/cache.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | import ( 4 | "net" 5 | "sync" 6 | "time" 7 | ) 8 | 9 | type Resolver struct { 10 | lock sync.RWMutex 11 | cache map[string][]net.IP 12 | } 13 | 14 | func New(refreshRate time.Duration) *Resolver { 15 | resolver := &Resolver{ 16 | cache: make(map[string][]net.IP, 64), 17 | } 18 | if refreshRate > 0 { 19 | go resolver.autoRefresh(refreshRate) 20 | } 21 | return resolver 22 | } 23 | 24 | func (r *Resolver) Fetch(address string) ([]net.IP, error) { 25 | r.lock.RLock() 26 | ips, exists := r.cache[address] 27 | r.lock.RUnlock() 28 | if exists { 29 | return ips, nil 30 | } 31 | 32 | return r.Lookup(address) 33 | } 34 | 35 | func (r *Resolver) FetchOne(address string) (net.IP, error) { 36 | ips, err := r.Fetch(address) 37 | if err != nil || len(ips) == 0 { 38 | return nil, err 39 | } 40 | return ips[0], nil 41 | } 42 | 43 | func (r *Resolver) FetchOneString(address string) (string, error) { 44 | ip, err := r.FetchOne(address) 45 | if err != nil || ip == nil { 46 | return "", err 47 | } 48 | return ip.String(), nil 49 | } 50 | 51 | func (r *Resolver) Refresh() { 52 | i := 0 53 | r.lock.RLock() 54 | addresses := make([]string, len(r.cache)) 55 | for key, _ := range r.cache { 56 | addresses[i] = key 57 | i++ 58 | } 59 | r.lock.RUnlock() 60 | 61 | for _, address := range addresses { 62 | r.Lookup(address) 63 | time.Sleep(time.Second * 2) 64 | } 65 | } 66 | 67 | func (r *Resolver) Lookup(address string) ([]net.IP, error) { 68 | ips, err := net.LookupIP(address) 69 | if err != nil { 70 | return nil, err 71 | } 72 | 73 | r.lock.Lock() 74 | r.cache[address] = ips 75 | r.lock.Unlock() 76 | return ips, nil 77 | } 78 | 79 | func (r *Resolver) autoRefresh(rate time.Duration) { 80 | for { 81 | time.Sleep(rate) 82 | r.Refresh() 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /vendor/mantic/conf/config.go: -------------------------------------------------------------------------------- 1 | package conf 2 | 3 | type Config struct { 4 | // 下载线程数 5 | DownloadThread int 6 | 7 | // phantomjs 执行文件路径 8 | Phantomjs string 9 | // js临时目录 10 | PhantomjsTemp string 11 | PuppeteerUrl string 12 | } 13 | 14 | var ( 15 | baseConfig = &Config{ 16 | DownloadThread: DOWNLOAD_THREAD, 17 | Phantomjs: "/usr/local/phantomjs/bin/phantomjs", 18 | PhantomjsTemp: "/tmp/", 19 | PuppeteerUrl: "http://localhost:8000", 20 | } 21 | ) 22 | 23 | func Conf() Config { 24 | return *baseConfig 25 | } 26 | 27 | func InitConfig(config Config) { 28 | if config.DownloadThread != 0 { 29 | baseConfig.DownloadThread = config.DownloadThread 30 | } 31 | if config.Phantomjs != "" { 32 | baseConfig.Phantomjs = config.Phantomjs 33 | } 34 | if config.PhantomjsTemp != "" { 35 | baseConfig.PhantomjsTemp = config.PhantomjsTemp 36 | } 37 | } 38 | 39 | // Some default values 40 | var ( 41 | DOWNLOAD_THREAD = 50 42 | ) 43 | -------------------------------------------------------------------------------- /vendor/mantic/downloader/surfer/agent/agent_bsd.go: -------------------------------------------------------------------------------- 1 | // +build darwin dragonfly freebsd netbsd openbsd 2 | 3 | package agent 4 | 5 | import ( 6 | "runtime" 7 | "syscall" 8 | ) 9 | 10 | // osName returns the name of the OS. 11 | func osName() string { 12 | name, err := syscall.Sysctl("kern.ostype") 13 | if err != nil { 14 | return runtime.GOOS 15 | } 16 | return name 17 | } 18 | 19 | // osVersion returns the OS version. 20 | func osVersion() string { 21 | release, err := syscall.Sysctl("kern.osrelease") 22 | if err != nil { 23 | return "0.0" 24 | } 25 | return release 26 | } 27 | -------------------------------------------------------------------------------- /vendor/mantic/downloader/surfer/agent/agent_linux.go: -------------------------------------------------------------------------------- 1 | // +build linux 2 | 3 | package agent 4 | 5 | import ( 6 | "runtime" 7 | "syscall" 8 | ) 9 | 10 | // osName returns the name of the OS. 11 | func osName() string { 12 | buf := &syscall.Utsname{} 13 | err := syscall.Uname(buf) 14 | if err != nil { 15 | return runtime.GOOS 16 | } 17 | return charsToString(buf.Sysname) 18 | } 19 | 20 | // osVersion returns the OS version. 21 | func osVersion() string { 22 | buf := &syscall.Utsname{} 23 | err := syscall.Uname(buf) 24 | if err != nil { 25 | return "0.0" 26 | } 27 | return charsToString(buf.Release) 28 | } 29 | 30 | // charsToString converts a [65]int8 byte array into a string. 31 | func charsToString(ca [65]int8) string { 32 | s := make([]byte, len(ca)) 33 | var lens int 34 | for ; lens < len(ca); lens++ { 35 | if ca[lens] == 0 { 36 | break 37 | } 38 | s[lens] = uint8(ca[lens]) 39 | } 40 | return string(s[0:lens]) 41 | } 42 | -------------------------------------------------------------------------------- /vendor/mantic/downloader/surfer/agent/agent_windows.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package agent 4 | 5 | import ( 6 | "fmt" 7 | "runtime" 8 | "syscall" 9 | ) 10 | 11 | // osName returns the name of the OS. 12 | func osName() string { 13 | return runtime.GOOS 14 | } 15 | 16 | // osVersion returns the OS version. 17 | func osVersion() string { 18 | v, err := syscall.GetVersion() 19 | if err != nil { 20 | return "0.0" 21 | } 22 | major := uint8(v) 23 | minor := uint8(v >> 8) 24 | return fmt.Sprintf("%d.%d", major, minor) 25 | } 26 | -------------------------------------------------------------------------------- /vendor/mantic/downloader/surfer/param.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 henrylee2cn Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package surfer 16 | 17 | import ( 18 | "bytes" 19 | "fmt" 20 | "io" 21 | "math/rand" 22 | "mime/multipart" 23 | "net/http" 24 | "net/url" 25 | "strings" 26 | "time" 27 | 28 | "mantic/downloader/surfer/agent" 29 | ) 30 | 31 | type Param struct { 32 | method string 33 | url *url.URL 34 | proxy *url.URL 35 | body io.Reader 36 | header http.Header 37 | enableCookie bool 38 | dialTimeout time.Duration 39 | connTimeout time.Duration 40 | tryTimes int 41 | retryPause time.Duration 42 | redirectTimes int 43 | client *http.Client 44 | } 45 | 46 | func NewParam(req Request) (param *Param, err error) { 47 | param = new(Param) 48 | param.url, err = UrlEncode(req.GetUrl()) 49 | if err != nil { 50 | return nil, err 51 | } 52 | 53 | if req.GetProxy() != "" { 54 | if param.proxy, err = url.Parse(req.GetProxy()); err != nil { 55 | return nil, err 56 | } 57 | } 58 | 59 | param.header = req.GetHeader() 60 | if param.header == nil { 61 | param.header = make(http.Header) 62 | } 63 | 64 | switch method := strings.ToUpper(req.GetMethod()); method { 65 | case "GET", "HEAD": 66 | param.method = method 67 | case "POST": 68 | param.method = method 69 | param.header.Add("Content-Type", "application/x-www-form-urlencoded") 70 | param.body = strings.NewReader(req.GetPostData()) 71 | case "POST-M": 72 | param.method = "POST" 73 | body := &bytes.Buffer{} 74 | writer := multipart.NewWriter(body) 75 | values, _ := url.ParseQuery(req.GetPostData()) 76 | for k, vs := range values { 77 | for _, v := range vs { 78 | writer.WriteField(k, v) 79 | } 80 | } 81 | err := writer.Close() 82 | if err != nil { 83 | return nil, err 84 | } 85 | param.header.Add("Content-Type", writer.FormDataContentType()) 86 | param.body = body 87 | 88 | default: 89 | param.method = "GET" 90 | } 91 | 92 | param.enableCookie = req.GetEnableCookie() 93 | 94 | if len(param.header.Get("User-Agent")) == 0 { 95 | if param.enableCookie { 96 | param.header.Add("User-Agent", agent.UserAgents["common"][0]) 97 | } else { 98 | l := len(agent.UserAgents["common"]) 99 | r := rand.New(rand.NewSource(time.Now().UnixNano())) 100 | param.header.Add("User-Agent", agent.UserAgents["common"][r.Intn(l)]) 101 | } 102 | } 103 | 104 | param.dialTimeout = req.GetDialTimeout() 105 | if param.dialTimeout < 0 { 106 | param.dialTimeout = 0 107 | } 108 | 109 | param.connTimeout = req.GetConnTimeout() 110 | param.tryTimes = req.GetTryTimes() 111 | param.retryPause = req.GetRetryPause() 112 | param.redirectTimes = req.GetRedirectTimes() 113 | return 114 | } 115 | 116 | // 回写Request内容 117 | func (self *Param) writeback(resp *http.Response) *http.Response { 118 | if resp == nil { 119 | resp = new(http.Response) 120 | resp.Request = new(http.Request) 121 | } else if resp.Request == nil { 122 | resp.Request = new(http.Request) 123 | } 124 | 125 | resp.Request.Method = self.method 126 | resp.Request.Header = self.header 127 | resp.Request.Host = self.url.Host 128 | 129 | return resp 130 | } 131 | 132 | // checkRedirect is used as the value to http.Client.CheckRedirect 133 | // when redirectTimes equal 0, redirect times is ∞ 134 | // when redirectTimes less than 0, not allow redirects 135 | func (self *Param) checkRedirect(req *http.Request, via []*http.Request) error { 136 | if self.redirectTimes == 0 { 137 | return nil 138 | } 139 | if len(via) >= self.redirectTimes { 140 | if self.redirectTimes < 0 { 141 | return fmt.Errorf("not allow redirects.") 142 | } 143 | return fmt.Errorf("stopped after %v redirects.", self.redirectTimes) 144 | } 145 | return nil 146 | } 147 | -------------------------------------------------------------------------------- /vendor/mantic/downloader/surfer/puppeteer.go: -------------------------------------------------------------------------------- 1 | package surfer 2 | 3 | import ( 4 | "net/http" 5 | "net/http/cookiejar" 6 | ) 7 | 8 | type Puppeteer struct { 9 | nodeUrl string 10 | } 11 | 12 | //nodeUrl是puppeteer写的一个http服务的地址 13 | func NewPuppeteer(nodeUrl string) Surfer { 14 | return &Puppeteer{ 15 | nodeUrl: nodeUrl, 16 | } 17 | } 18 | 19 | func (p *Puppeteer) Download(req Request) (resp *http.Response, err error) { 20 | clinet := http.Client{} 21 | getUrl := p.nodeUrl + "?url=" + req.GetUrl() 22 | r, _ := http.NewRequest("GET", getUrl, nil) 23 | return clinet.Do(r) 24 | } 25 | 26 | func (p *Puppeteer) SetCookieJar(jar *cookiejar.Jar) { 27 | return 28 | } 29 | 30 | func (p *Puppeteer) Jar() *cookiejar.Jar { 31 | return nil 32 | } 33 | -------------------------------------------------------------------------------- /vendor/mantic/downloader/surfer/surfer.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 henrylee2cn Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // surfer是一款Go语言编写的高并发web下载器,支持 GET/POST/HEAD 方法及 http/https 协议,同时支持固定UserAgent自动保存cookie与随机大量UserAgent禁用cookie两种模式,高度模拟浏览器行为,可实现模拟登录等功能。 16 | package surfer 17 | 18 | import ( 19 | "net/http" 20 | "net/http/cookiejar" 21 | "sync" 22 | 23 | "mantic/conf" 24 | ) 25 | 26 | var ( 27 | surf Surfer 28 | phantom Surfer 29 | once_surf sync.Once 30 | once_phantom sync.Once 31 | phantomjsFile = conf.Conf().Phantomjs 32 | tempJsDir = conf.Conf().PhantomjsTemp 33 | ) 34 | 35 | func Download(req Request) (resp *http.Response, err error) { 36 | err = req.Prepare() 37 | if err != nil { 38 | return 39 | } 40 | switch req.GetDownloaderID() { 41 | case SurfID: 42 | once_surf.Do(func() { surf = New() }) 43 | resp, err = surf.Download(req) 44 | case PhomtomJsID: 45 | once_phantom.Do(func() { phantom = NewPhantom(phantomjsFile, tempJsDir) }) 46 | resp, err = phantom.Download(req) 47 | } 48 | return 49 | } 50 | 51 | //销毁Phantomjs的js临时文件 52 | func DestroyJsFiles() { 53 | if pt, ok := phantom.(*Phantom); ok { 54 | pt.DestroyJsFiles() 55 | } 56 | } 57 | 58 | // Downloader represents an core of HTTP web browser for crawler. 59 | type Surfer interface { 60 | // GET @param url string, header http.Header, cookies []*http.Cookie 61 | // HEAD @param url string, header http.Header, cookies []*http.Cookie 62 | // POST PostForm @param url, referer string, values url.Values, header http.Header, cookies []*http.Cookie 63 | // POST-M PostMultipart @param url, referer string, values url.Values, header http.Header, cookies []*http.Cookie 64 | Download(Request) (resp *http.Response, err error) 65 | 66 | SetCookieJar(jar *cookiejar.Jar) 67 | Jar() *cookiejar.Jar 68 | } 69 | -------------------------------------------------------------------------------- /vendor/mantic/downloader/surfer/util.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 henrylee2cn Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package surfer 16 | 17 | import ( 18 | "io" 19 | "io/ioutil" 20 | "log" 21 | "net/http" 22 | "net/url" 23 | "os" 24 | "path/filepath" 25 | "strings" 26 | 27 | "golang.org/x/net/html/charset" 28 | ) 29 | 30 | // 采用surf内核下载时,可以尝试自动转码为utf8 31 | // 采用phantomjs内核时,无需转码(已是utf8) 32 | func AutoToUTF8(resp *http.Response) error { 33 | destReader, err := charset.NewReader(resp.Body, resp.Header.Get("Content-Type")) 34 | if err == nil { 35 | resp.Body = &Body{ 36 | ReadCloser: resp.Body, 37 | Reader: destReader, 38 | } 39 | } 40 | return err 41 | } 42 | 43 | // 读取完整响应流正文 44 | func BodyBytes(resp *http.Response) ([]byte, error) { 45 | body, err := ioutil.ReadAll(resp.Body) 46 | resp.Body.Close() 47 | return body, err 48 | } 49 | 50 | // 返回编码后的url.URL指针、及解析错误 51 | func UrlEncode(urlStr string) (*url.URL, error) { 52 | urlObj, err := url.Parse(urlStr) 53 | urlObj.RawQuery = urlObj.Query().Encode() 54 | return urlObj, err 55 | } 56 | 57 | // The GetWDPath gets the work directory path. 58 | func GetWDPath() string { 59 | wd := os.Getenv("GOPATH") 60 | if wd == "" { 61 | panic("GOPATH is not setted in env.") 62 | } 63 | return wd 64 | } 65 | 66 | // The IsDirExists judges path is directory or not. 67 | func IsDirExists(path string) bool { 68 | fi, err := os.Stat(path) 69 | 70 | if err != nil { 71 | return os.IsExist(err) 72 | } else { 73 | return fi.IsDir() 74 | } 75 | 76 | panic("util isDirExists not reached") 77 | } 78 | 79 | // The IsFileExists judges path is file or not. 80 | func IsFileExists(path string) bool { 81 | fi, err := os.Stat(path) 82 | 83 | if err != nil { 84 | return os.IsExist(err) 85 | } else { 86 | return !fi.IsDir() 87 | } 88 | 89 | panic("util isFileExists not reached") 90 | } 91 | 92 | // 遍历目录,可指定后缀 93 | func WalkDir(targpath string, suffixes ...string) (dirlist []string) { 94 | if !filepath.IsAbs(targpath) { 95 | targpath, _ = filepath.Abs(targpath) 96 | } 97 | err := filepath.Walk(targpath, func(retpath string, f os.FileInfo, err error) error { 98 | if err != nil { 99 | return err 100 | } 101 | if !f.IsDir() { 102 | return nil 103 | } 104 | if len(suffixes) == 0 { 105 | dirlist = append(dirlist, retpath) 106 | return nil 107 | } 108 | for _, suffix := range suffixes { 109 | if strings.HasSuffix(retpath, suffix) { 110 | dirlist = append(dirlist, retpath) 111 | } 112 | } 113 | return nil 114 | }) 115 | 116 | if err != nil { 117 | log.Printf("utils.WalkDir: %v\n", err) 118 | return 119 | } 120 | 121 | return 122 | } 123 | 124 | // 封装Response.Body 125 | type Body struct { 126 | io.ReadCloser 127 | io.Reader 128 | } 129 | 130 | func (b *Body) Read(p []byte) (int, error) { 131 | return b.Reader.Read(p) 132 | } 133 | -------------------------------------------------------------------------------- /vendor/vendor.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "", 3 | "ignore": "test", 4 | "package": [ 5 | { 6 | "checksumSHA1": "iTyK6+LglXn9zjYGbjMTLxtLXio=", 7 | "path": "github.com/PuerkitoBio/goquery", 8 | "revision": "8806ada2a4ab225c06e9106f9631be80932db7ce", 9 | "revisionTime": "2017-06-23T16:21:02Z" 10 | }, 11 | { 12 | "checksumSHA1": "2rWSos1D+xqNSGkvEMOG3pntod8=", 13 | "path": "github.com/andybalholm/cascadia", 14 | "revision": "349dd0209470eabd9514242c688c403c0926d266", 15 | "revisionTime": "2016-12-24T14:14:13Z" 16 | }, 17 | { 18 | "checksumSHA1": "lbE4q2dpUgue10EEx8eutP36vzo=", 19 | "path": "github.com/boltdb/bolt", 20 | "revision": "9da31745363232bc1e27dbab3569e77383a51585", 21 | "revisionTime": "2017-11-20T01:03:07Z" 22 | }, 23 | { 24 | "checksumSHA1": "RbvI/I41Th10HSa2dC3IS2JzW/w=", 25 | "path": "github.com/elazarl/goproxy", 26 | "revision": "a96fa3a318260eab29abaf32f7128c9eb07fb073", 27 | "revisionTime": "2017-11-01T14:35:03Z" 28 | }, 29 | { 30 | "checksumSHA1": "JVGDxPn66bpe6xEiexs1r+y6jF0=", 31 | "path": "github.com/patrickmn/go-cache", 32 | "revision": "a3647f8e31d79543b2d0f0ae2fe5c379d72cedc0", 33 | "revisionTime": "2017-07-22T04:01:10Z" 34 | }, 35 | { 36 | "checksumSHA1": "vqc3a+oTUGX8PmD0TS+qQ7gmN8I=", 37 | "path": "golang.org/x/net/html", 38 | "revision": "1f9224279e98554b6a6432d4dd998a739f8b2b7c", 39 | "revisionTime": "2017-06-29T16:46:45Z" 40 | }, 41 | { 42 | "checksumSHA1": "00eQaGynDYrv3tL+C7l9xH0IDZg=", 43 | "path": "golang.org/x/net/html/atom", 44 | "revision": "1f9224279e98554b6a6432d4dd998a739f8b2b7c", 45 | "revisionTime": "2017-06-29T16:46:45Z" 46 | }, 47 | { 48 | "checksumSHA1": "barUU39reQ7LdgYLA323hQ/UGy4=", 49 | "path": "golang.org/x/net/html/charset", 50 | "revision": "1f9224279e98554b6a6432d4dd998a739f8b2b7c", 51 | "revisionTime": "2017-06-29T16:46:45Z" 52 | }, 53 | { 54 | "checksumSHA1": "Mr4ur60bgQJnQFfJY0dGtwWwMPE=", 55 | "path": "golang.org/x/text/encoding", 56 | "revision": "" 57 | }, 58 | { 59 | "checksumSHA1": "HgcUFTOQF5jOYtTIj5obR3GVN9A=", 60 | "path": "golang.org/x/text/encoding/charmap", 61 | "revision": "" 62 | }, 63 | { 64 | "checksumSHA1": "qY7yktJmh0KmASIBlpLQ3IsR/Yc=", 65 | "path": "golang.org/x/text/encoding/htmlindex", 66 | "revision": "" 67 | }, 68 | { 69 | "checksumSHA1": "zeHyHebIZl1tGuwGllIhjfci+wI=", 70 | "path": "golang.org/x/text/encoding/internal", 71 | "revision": "" 72 | }, 73 | { 74 | "checksumSHA1": "9cg4nSGfKTIWKb6bWV7U4lnuFKA=", 75 | "path": "golang.org/x/text/encoding/internal/identifier", 76 | "revision": "" 77 | }, 78 | { 79 | "checksumSHA1": "f/PWjU17cU5uo0zkdi+Iz80Megk=", 80 | "path": "golang.org/x/text/encoding/japanese", 81 | "revision": "" 82 | }, 83 | { 84 | "checksumSHA1": "qHQ79q9peY8ZkCMC8kJAb52BAWg=", 85 | "path": "golang.org/x/text/encoding/korean", 86 | "revision": "" 87 | }, 88 | { 89 | "checksumSHA1": "55UdScb+EMOCPr7OW0hCwDsVxpg=", 90 | "path": "golang.org/x/text/encoding/simplifiedchinese", 91 | "revision": "" 92 | }, 93 | { 94 | "checksumSHA1": "9EZF1SHTpjVmaT9sARitvGKUXOY=", 95 | "path": "golang.org/x/text/encoding/traditionalchinese", 96 | "revision": "" 97 | }, 98 | { 99 | "checksumSHA1": "G9LfJI9gySazd+MyyC6QbTHx4to=", 100 | "path": "golang.org/x/text/encoding/unicode", 101 | "revision": "" 102 | }, 103 | { 104 | "checksumSHA1": "hyNCcTwMQnV6/MK8uUW9E5H0J0M=", 105 | "path": "golang.org/x/text/internal/tag", 106 | "revision": "" 107 | }, 108 | { 109 | "checksumSHA1": "Qk7dljcrEK1BJkAEZguxAbG9dSo=", 110 | "path": "golang.org/x/text/internal/utf8internal", 111 | "revision": "" 112 | }, 113 | { 114 | "checksumSHA1": "Dhc7bHUc+d1uuYO/byxQf7AfW+o=", 115 | "path": "golang.org/x/text/language", 116 | "revision": "" 117 | }, 118 | { 119 | "checksumSHA1": "IV4MN7KGBSocu/5NR3le3sxup4Y=", 120 | "path": "golang.org/x/text/runes", 121 | "revision": "" 122 | }, 123 | { 124 | "checksumSHA1": "ziMb9+ANGRJSSIuxYdRbA+cDRBQ=", 125 | "path": "golang.org/x/text/transform", 126 | "revision": "" 127 | }, 128 | { 129 | "checksumSHA1": "4d+dZvtwjb+F87nPk4a6q2hMDjE=", 130 | "path": "mantic/cache/dns", 131 | "revision": "800efb83cfe6003e7a8ce7b650bc52a43d8f3315", 132 | "revisionTime": "2017-10-09T03:03:38Z" 133 | }, 134 | { 135 | "checksumSHA1": "/MTHcMLYGTvvZ6ajNHzW/EwdCZY=", 136 | "path": "mantic/conf", 137 | "revision": "800efb83cfe6003e7a8ce7b650bc52a43d8f3315", 138 | "revisionTime": "2017-10-09T03:03:38Z" 139 | }, 140 | { 141 | "checksumSHA1": "yCyExQm3rTjlD3AJdPOh40Qt5/A=", 142 | "path": "mantic/downloader/surfer", 143 | "revision": "800efb83cfe6003e7a8ce7b650bc52a43d8f3315", 144 | "revisionTime": "2017-10-09T03:03:38Z" 145 | }, 146 | { 147 | "checksumSHA1": "lZ+93LhE2PAh0QOUObhgheUowC4=", 148 | "path": "mantic/downloader/surfer/agent", 149 | "revision": "800efb83cfe6003e7a8ce7b650bc52a43d8f3315", 150 | "revisionTime": "2017-10-09T03:03:38Z" 151 | } 152 | ], 153 | "rootPath": "github.com/sundy-li/wechat_brain" 154 | } 155 | --------------------------------------------------------------------------------