├── .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)
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 |
--------------------------------------------------------------------------------