├── .gitignore ├── Godeps ├── Godeps.json └── Readme ├── LICENSE ├── README.md ├── api ├── event.go ├── item.go ├── rpc.go ├── strategy.go └── user.go ├── backend └── rpc.go ├── cfg.example.json ├── control ├── cron ├── clear.go ├── fetcher.go └── init.go ├── g ├── config.go ├── const.go └── var.go ├── handler ├── domain_handler.go ├── home_handler.go ├── item_handler.go ├── required.go ├── status_handler.go ├── stra_handler.go ├── team_handler.go └── user_handler.go ├── http ├── cookie │ └── cookie.go ├── errors │ └── errors.go ├── helper │ └── helper.go ├── http.go ├── middleware │ ├── logger.go │ └── recovery.go ├── param │ └── param.go ├── render │ └── render.go └── routes.go ├── main.go ├── model ├── event.go ├── item_status.go ├── rel_sid_ip.go ├── rel_team_user.go ├── strategy.go ├── team.go └── user.go ├── schema.sql ├── sender ├── alarm.go ├── init.go └── ring.go ├── static ├── .DS_Store ├── css │ ├── error.css │ ├── g.css │ ├── home.css │ ├── login.css │ └── strategy.css ├── img │ └── logo.png ├── js │ ├── g.js │ └── team.js └── lib │ ├── .DS_Store │ ├── bootstrap │ ├── bootstrap-tokenfield.min.css │ ├── bootstrap-tokenfield.min.js │ ├── bootstrap.css.map │ ├── bootstrap.min.css │ ├── bootstrap.min.js │ └── tokenfield-typeahead.min.css │ ├── echarts │ └── echarts.min.js │ ├── fa │ ├── .DS_Store │ ├── css │ │ └── font-awesome.min.css │ └── fonts │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.svg │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ └── fontawesome-webfont.woff2 │ ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.woff2 │ ├── jquery │ ├── flot │ │ ├── jquery.flot.js │ │ ├── jquery.flot.selection.js │ │ ├── jquery.flot.spline.js │ │ ├── jquery.flot.stack.js │ │ └── jquery.flot.time.js │ └── jquery.min.js │ ├── layer │ ├── extend │ │ └── layer.ext.js │ ├── layer.js │ └── skin │ │ ├── default │ │ ├── icon-ext.png │ │ ├── icon.png │ │ ├── loading-0.gif │ │ ├── loading-1.gif │ │ └── loading-2.gif │ │ ├── layer.css │ │ └── layer.ext.css │ └── select2 │ ├── select2-bootstrap.css │ ├── select2-spinner.gif │ ├── select2.css │ ├── select2.min.js │ ├── select2.png │ └── select2x2.png ├── store └── mysql.go ├── utils ├── dns.go ├── falcon.go ├── ldap.go └── utils.go ├── vendor ├── github.com │ ├── astaxie │ │ └── beego │ │ │ ├── LICENSE │ │ │ └── httplib │ │ │ ├── README.md │ │ │ └── httplib.go │ ├── codegangsta │ │ └── negroni │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── doc.go │ │ │ ├── logger.go │ │ │ ├── negroni.go │ │ │ ├── recovery.go │ │ │ ├── response_writer.go │ │ │ └── static.go │ ├── go-sql-driver │ │ └── mysql │ │ │ ├── .gitignore │ │ │ ├── .travis.yml │ │ │ ├── AUTHORS │ │ │ ├── CHANGELOG.md │ │ │ ├── CONTRIBUTING.md │ │ │ ├── ISSUE_TEMPLATE.md │ │ │ ├── LICENSE │ │ │ ├── PULL_REQUEST_TEMPLATE.md │ │ │ ├── README.md │ │ │ ├── appengine.go │ │ │ ├── buffer.go │ │ │ ├── collations.go │ │ │ ├── connection.go │ │ │ ├── const.go │ │ │ ├── driver.go │ │ │ ├── dsn.go │ │ │ ├── errors.go │ │ │ ├── infile.go │ │ │ ├── packets.go │ │ │ ├── result.go │ │ │ ├── rows.go │ │ │ ├── statement.go │ │ │ ├── transaction.go │ │ │ └── utils.go │ ├── go-xorm │ │ ├── core │ │ │ ├── .gitignore │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── benchmark.sh │ │ │ ├── cache.go │ │ │ ├── column.go │ │ │ ├── converstion.go │ │ │ ├── db.go │ │ │ ├── dialect.go │ │ │ ├── driver.go │ │ │ ├── error.go │ │ │ ├── filter.go │ │ │ ├── ilogger.go │ │ │ ├── index.go │ │ │ ├── mapper.go │ │ │ ├── pk.go │ │ │ ├── scan.go │ │ │ ├── table.go │ │ │ └── type.go │ │ └── xorm │ │ │ ├── .gitignore │ │ │ ├── .gitmodules │ │ │ ├── .gopmfile │ │ │ ├── CONTRIBUTING.md │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── README_CN.md │ │ │ ├── VERSION │ │ │ ├── doc.go │ │ │ ├── engine.go │ │ │ ├── error.go │ │ │ ├── gen_reserved.sh │ │ │ ├── goracle_driver.go │ │ │ ├── helpers.go │ │ │ ├── logger.go │ │ │ ├── lru_cacher.go │ │ │ ├── memory_store.go │ │ │ ├── mssql_dialect.go │ │ │ ├── mymysql_driver.go │ │ │ ├── mysql_dialect.go │ │ │ ├── mysql_driver.go │ │ │ ├── oci8_driver.go │ │ │ ├── odbc_driver.go │ │ │ ├── oracle_dialect.go │ │ │ ├── pg_reserved.txt │ │ │ ├── postgres_dialect.go │ │ │ ├── pq_driver.go │ │ │ ├── processors.go │ │ │ ├── rows.go │ │ │ ├── session.go │ │ │ ├── sqlite3_dialect.go │ │ │ ├── sqlite3_driver.go │ │ │ ├── statement.go │ │ │ ├── syslogger.go │ │ │ ├── types.go │ │ │ └── xorm.go │ ├── gorilla │ │ ├── context │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── context.go │ │ │ └── doc.go │ │ ├── mux │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── doc.go │ │ │ ├── mux.go │ │ │ ├── regexp.go │ │ │ └── route.go │ │ └── securecookie │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── doc.go │ │ │ ├── fuzz.go │ │ │ └── securecookie.go │ ├── miekg │ │ └── dns │ │ │ ├── .gitignore │ │ │ ├── .travis.yml │ │ │ ├── AUTHORS │ │ │ ├── CONTRIBUTORS │ │ │ ├── COPYRIGHT │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── client.go │ │ │ ├── clientconfig.go │ │ │ ├── defaults.go │ │ │ ├── dns.go │ │ │ ├── dnssec.go │ │ │ ├── dnssec_keygen.go │ │ │ ├── dnssec_keyscan.go │ │ │ ├── dnssec_privkey.go │ │ │ ├── doc.go │ │ │ ├── edns.go │ │ │ ├── format.go │ │ │ ├── labels.go │ │ │ ├── msg.go │ │ │ ├── nsecx.go │ │ │ ├── privaterr.go │ │ │ ├── rawmsg.go │ │ │ ├── sanitize.go │ │ │ ├── scanner.go │ │ │ ├── server.go │ │ │ ├── sig0.go │ │ │ ├── singleinflight.go │ │ │ ├── tlsa.go │ │ │ ├── tsig.go │ │ │ ├── types.go │ │ │ ├── types_generate.go │ │ │ ├── udp.go │ │ │ ├── udp_linux.go │ │ │ ├── udp_other.go │ │ │ ├── udp_plan9.go │ │ │ ├── udp_windows.go │ │ │ ├── update.go │ │ │ ├── xfr.go │ │ │ ├── zgenerate.go │ │ │ ├── zscan.go │ │ │ ├── zscan_rr.go │ │ │ └── ztypes.go │ ├── mmitton │ │ └── ldap │ │ │ ├── .gitignore │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── Makefile │ │ │ ├── README │ │ │ ├── README.md │ │ │ ├── add.go │ │ │ ├── atomic_value.go │ │ │ ├── atomic_value_go13.go │ │ │ ├── bind.go │ │ │ ├── client.go │ │ │ ├── compare.go │ │ │ ├── conn.go │ │ │ ├── control.go │ │ │ ├── debug.go │ │ │ ├── del.go │ │ │ ├── dn.go │ │ │ ├── doc.go │ │ │ ├── error.go │ │ │ ├── filter.go │ │ │ ├── ldap.go │ │ │ ├── modify.go │ │ │ ├── passwdmodify.go │ │ │ └── search.go │ ├── toolkits │ │ ├── container │ │ │ └── list │ │ │ │ ├── safelinkedlist.go │ │ │ │ └── safelist.go │ │ ├── core │ │ │ ├── convert.go │ │ │ └── format.go │ │ ├── file │ │ │ ├── downloader.go │ │ │ ├── file.go │ │ │ ├── reader.go │ │ │ └── writer.go │ │ ├── str │ │ │ ├── .gitignore │ │ │ ├── base64.go │ │ │ ├── ids.go │ │ │ ├── md5.go │ │ │ ├── rand.go │ │ │ └── regexp.go │ │ └── web │ │ │ └── paginator.go │ └── unrolled │ │ └── render │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── README.md │ │ ├── buffer.go │ │ ├── doc.go │ │ ├── engine.go │ │ ├── helpers.go │ │ ├── helpers_pre16.go │ │ └── render.go ├── gopkg.in │ └── asn1-ber.v1 │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── README.md │ │ ├── ber.go │ │ ├── content_int.go │ │ ├── header.go │ │ ├── identifier.go │ │ ├── length.go │ │ └── util.go └── stathat.com │ └── c │ └── consistent │ ├── LICENSE │ ├── README.md │ └── consistent.go └── views ├── auth ├── login.html └── register.html ├── chart └── index.html ├── home └── index.html ├── inc ├── chpwd.html ├── error.html ├── footer.html ├── head.html ├── nav.html ├── nav_chart.html ├── pager.html ├── profile.html └── select2.html ├── status └── log.html ├── strategy ├── create.html └── edit.html └── team ├── create.html ├── edit.html └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | var/ 2 | cfg.json 3 | urlooker-* 4 | cfg.local.json 5 | *DS_Store 6 | -------------------------------------------------------------------------------- /Godeps/Godeps.json: -------------------------------------------------------------------------------- 1 | { 2 | "ImportPath": "github.com/urlooker/web", 3 | "GoVersion": "go1.7", 4 | "GodepVersion": "v75", 5 | "Deps": [ 6 | { 7 | "ImportPath": "github.com/astaxie/beego/httplib", 8 | "Comment": "v1.6.1-5-g88c5dfa", 9 | "Rev": "88c5dfa6ead42e624c2e7d9e04eab6cb2d07412a" 10 | }, 11 | { 12 | "ImportPath": "github.com/codegangsta/negroni", 13 | "Comment": "v0.1-70-gc7477ad", 14 | "Rev": "c7477ad8e330bef55bf1ebe300cf8aa67c492d1b" 15 | }, 16 | { 17 | "ImportPath": "github.com/go-sql-driver/mysql", 18 | "Comment": "v1.2-194-g7ebe0a5", 19 | "Rev": "7ebe0a500653eeb1859664bed5e48dec1e164e73" 20 | }, 21 | { 22 | "ImportPath": "github.com/go-xorm/core", 23 | "Comment": "v0.5.2-1-gb9277f8", 24 | "Rev": "b9277f807c011387baed9748a45f26da65b42077" 25 | }, 26 | { 27 | "ImportPath": "github.com/go-xorm/xorm", 28 | "Comment": "v0.5.2-6-g21d219c", 29 | "Rev": "21d219c8725c658cee4c9026efb448ecac8e3ed1" 30 | }, 31 | { 32 | "ImportPath": "github.com/gorilla/context", 33 | "Rev": "1ea25387ff6f684839d82767c1733ff4d4d15d0a" 34 | }, 35 | { 36 | "ImportPath": "github.com/gorilla/mux", 37 | "Comment": "v1.1", 38 | "Rev": "0eeaf8392f5b04950925b8a69fe70f110fa7cbfc" 39 | }, 40 | { 41 | "ImportPath": "github.com/gorilla/securecookie", 42 | "Comment": "v1.1", 43 | "Rev": "667fe4e3466a040b780561fe9b51a83a3753eefc" 44 | }, 45 | { 46 | "ImportPath": "github.com/miekg/dns", 47 | "Rev": "c9d1302d540edfb97d9ecbfe90b4fb515088630b" 48 | }, 49 | { 50 | "ImportPath": "github.com/mmitton/ldap", 51 | "Rev": "2890b18948f26e61b62dc6878d0c14a708f0d57e" 52 | }, 53 | { 54 | "ImportPath": "github.com/toolkits/container/list", 55 | "Rev": "ba7d73adeaca8dc16c676dedbbb48cc46d3eccb0" 56 | }, 57 | { 58 | "ImportPath": "github.com/toolkits/core", 59 | "Rev": "0ebf14900fe2ef12a8a19a0c04711538531d51e3" 60 | }, 61 | { 62 | "ImportPath": "github.com/toolkits/file", 63 | "Rev": "a5b3c5147e07f934d9f9d00b901a20b2529f1a57" 64 | }, 65 | { 66 | "ImportPath": "github.com/toolkits/str", 67 | "Rev": "29a153db8892174849cb83986a2c942375977d61" 68 | }, 69 | { 70 | "ImportPath": "github.com/toolkits/web", 71 | "Rev": "dc0f03327e1d58851ef88fca6e8008ffb6de806a" 72 | }, 73 | { 74 | "ImportPath": "github.com/unrolled/render", 75 | "Rev": "198ad4d8b8a4612176b804ca10555b222a086b40" 76 | }, 77 | { 78 | "ImportPath": "gopkg.in/asn1-ber.v1", 79 | "Comment": "v1.2", 80 | "Rev": "379148ca0225df7a432012b8df0355c2a2063ac0" 81 | }, 82 | { 83 | "ImportPath": "stathat.com/c/consistent", 84 | "Rev": "748f01b59d1b2218efe39513039e9ee31266d7c7" 85 | } 86 | ] 87 | } 88 | -------------------------------------------------------------------------------- /Godeps/Readme: -------------------------------------------------------------------------------- 1 | This directory tree is generated automatically by godep. 2 | 3 | Please do not edit. 4 | 5 | See https://github.com/tools/godep for more information. 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## [urlooker][1] 2 | 监控web服务可用性及访问质量,采用go语言编写,易于安装和二次开发 3 | 4 | ## Feature 5 | - 返回状态码检测 6 | - 页面响应时间检测 7 | - 页面关键词匹配检测 8 | - 自定义Header 9 | - GET、POST、PUT访问 10 | - 自定义POST BODY 11 | - 检测结果支持向open-falcon推送 12 | 13 | ## Architecture 14 | ![此处输入图片的描述][2] 15 | 16 | ## ScreenShot 17 | 18 | ![看图][3] 19 | 20 | ![此处输入图片的描述][4] 21 | 22 | ![添加监控项][5] 23 | 24 | ## 常见问题 25 | - [wiki手册][6] 26 | - [常见问题][7] 27 | - 初始用户名密码:admin/password 28 | 29 | ## Install 30 | 31 | #### 源码安装 32 | ###### 安装依赖 33 | ``` 34 | yum install -y redis 35 | yum install -y mysql-server 36 | ``` 37 | ###### 导入数据库 38 | ``` 39 | wget https://raw.githubusercontent.com/URLooker/web/master/schema.sql 40 | mysql -h 127.0.0.1 -u root -p < schema.sql 41 | ``` 42 | 43 | ###### 安装组件 44 | ```bash 45 | # set $GOPATH and $GOROOT 46 | mkdir -p $GOPATH/src/github.com/710leo 47 | cd $GOPATH/src/github.com/710leo 48 | git clone https://github.com/710leo/urlooker.git 49 | go get ./... 50 | ./control build 51 | ./control start all 52 | ``` 53 | 54 | 打开浏览器访问 http://127.0.0.1:1984 即可 55 | 56 | 57 | ## 答疑 58 | QQ交流群:556988374 59 | 60 | ## Thanks 61 | 一些功能参考了open-falcon,感谢 [UlricQin][9] & [laiwei][10] 62 | 63 | 64 | [1]: https://github.com/urlooker 65 | [2]: https://github.com/urlooker/wiki/raw/master/img/urlooker4.png 66 | [3]: https://github.com/urlooker/wiki/raw/master/img/urlooker1.png 67 | [4]: https://github.com/urlooker/wiki/raw/master/img/urlooker3.png 68 | [5]: https://github.com/urlooker/wiki/raw/master/img/urlooker2.png 69 | [6]: https://github.com/URLooker/web 70 | [7]: https://github.com/URLooker/agent 71 | [8]: https://github.com/URLooker/alarm 72 | [9]: http://ulricqin.com/ 73 | [10]: https://github.com/laiwei -------------------------------------------------------------------------------- /api/event.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/urlooker/web/model" 5 | ) 6 | 7 | func (this *Web) SaveEvent(event *model.Event, reply *string) error { 8 | err := event.Insert() 9 | if err != nil { 10 | *reply = err.Error() 11 | } 12 | 13 | return nil 14 | } 15 | -------------------------------------------------------------------------------- /api/item.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "log" 5 | "time" 6 | 7 | "github.com/urlooker/web/g" 8 | "github.com/urlooker/web/model" 9 | "github.com/urlooker/web/sender" 10 | "github.com/urlooker/web/utils" 11 | ) 12 | 13 | type SendResultReq struct { 14 | Hostname string 15 | CheckResults []*g.CheckResult 16 | } 17 | 18 | func (this *Web) SendResult(req SendResultReq, reply *string) error { 19 | for _, arg := range req.CheckResults { 20 | itemStatus := model.ItemStatus{ 21 | Ip: arg.Ip, 22 | Sid: arg.Sid, 23 | RespTime: arg.RespTime, 24 | RespCode: arg.RespCode, 25 | PushTime: arg.PushTime, 26 | Result: arg.Status, 27 | } 28 | 29 | relSidIp := model.RelSidIp{ 30 | Sid: arg.Sid, 31 | Ip: arg.Ip, 32 | Ts: time.Now().Unix(), 33 | } 34 | 35 | err := relSidIp.Save() 36 | if err != nil { 37 | log.Println("save sid_ip error:", err) 38 | *reply = "save sid_ip error:" + err.Error() 39 | return nil 40 | } 41 | 42 | err = itemStatus.Save() 43 | if err != nil { 44 | log.Println("save item error:", err) 45 | *reply = "save item error:" + err.Error() 46 | return nil 47 | } 48 | 49 | if g.Config.Alarm.Enable { 50 | node, err := sender.NodeRing.GetNode(itemStatus.PK()) 51 | if err != nil { 52 | log.Println("error:", err) 53 | *reply = "get node error:" + err.Error() 54 | return nil 55 | } 56 | 57 | Q := sender.SendQueues[node] 58 | isSuccess := Q.PushFront(itemStatus) 59 | if !isSuccess { 60 | log.Println("push itemStatus error:", itemStatus) 61 | *reply = "push itemStatus error" 62 | return nil 63 | } 64 | } 65 | 66 | } 67 | 68 | if g.Config.Falcon.Enable { 69 | if len(req.CheckResults) > 0 { 70 | utils.PushFalcon(req.CheckResults, req.Hostname) 71 | } 72 | } 73 | 74 | *reply = "" 75 | return nil 76 | } 77 | 78 | type GetItemResponse struct { 79 | Message string 80 | Data []*g.DetectedItem 81 | } 82 | 83 | func (this *Web) GetItem(hostname string, resp *GetItemResponse) error { 84 | items, exists := g.DetectedItemMap.Get(hostname) 85 | if !exists { 86 | resp.Message = "no found item assigned to " + hostname 87 | } 88 | resp.Data = items 89 | return nil 90 | } 91 | -------------------------------------------------------------------------------- /api/rpc.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "log" 5 | "net" 6 | "net/rpc" 7 | "net/rpc/jsonrpc" 8 | 9 | "github.com/urlooker/web/g" 10 | ) 11 | 12 | type Web int 13 | 14 | func Start() { 15 | addr := g.Config.Rpc.Listen 16 | 17 | server := rpc.NewServer() 18 | server.Register(new(Web)) 19 | 20 | l, e := net.Listen("tcp", addr) 21 | if e != nil { 22 | log.Fatalln("listen occur error", e) 23 | } else { 24 | log.Println("listening on", addr) 25 | } 26 | 27 | for { 28 | conn, err := l.Accept() 29 | if err != nil { 30 | log.Println("listener accept occur error", err) 31 | continue 32 | } 33 | go server.ServeCodec(jsonrpc.NewServerCodec(conn)) 34 | } 35 | } 36 | 37 | func (this *Web) Ping(req interface{}, reply *string) error { 38 | *reply = "ok" 39 | return nil 40 | } 41 | -------------------------------------------------------------------------------- /api/strategy.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/urlooker/web/model" 5 | ) 6 | 7 | type StrategyResponse struct { 8 | Message string 9 | Data []*model.Strategy 10 | } 11 | 12 | func (this *Web) GetStrategies(req interface{}, resp *StrategyResponse) error { 13 | strategies, err := model.GetAllStrategyByCron() 14 | if err != nil { 15 | resp.Message = err.Error() 16 | } 17 | resp.Data = strategies 18 | 19 | return nil 20 | } 21 | -------------------------------------------------------------------------------- /api/user.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "log" 5 | "strconv" 6 | "strings" 7 | 8 | "github.com/urlooker/web/model" 9 | ) 10 | 11 | type UsersResponse struct { 12 | Message string 13 | Data []*model.User 14 | } 15 | 16 | func (this *Web) GetUsersByTeam(req string, reply *UsersResponse) error { 17 | tids := strings.Split(req, ",") 18 | if len(tids) < 1 || tids[0] == "" { 19 | reply.Message = "user no exists!" 20 | return nil 21 | } 22 | allUsers := make([]*model.User, 0) 23 | for _, tid := range tids { 24 | id, err := strconv.ParseInt(tid, 10, 64) 25 | if err != nil { 26 | log.Println("tid error:", err) 27 | continue 28 | } 29 | users, err := model.UsersInfoOfTeam(id) 30 | if err != nil { 31 | reply.Message = err.Error() 32 | } 33 | 34 | for _, user := range users { 35 | allUsers = append(allUsers, user) 36 | } 37 | } 38 | 39 | reply.Data = allUsers 40 | return nil 41 | } 42 | -------------------------------------------------------------------------------- /backend/rpc.go: -------------------------------------------------------------------------------- 1 | package backend 2 | 3 | import ( 4 | "log" 5 | "math" 6 | "net" 7 | "net/rpc" 8 | "net/rpc/jsonrpc" 9 | "sync" 10 | "time" 11 | 12 | "github.com/urlooker/web/g" 13 | ) 14 | 15 | type SingleConnRpcClient struct { 16 | sync.Mutex 17 | rpcClient *rpc.Client 18 | RpcServer string 19 | Timeout time.Duration 20 | } 21 | 22 | func (this *SingleConnRpcClient) close() { 23 | if this.rpcClient != nil { 24 | this.rpcClient.Close() 25 | this.rpcClient = nil 26 | } 27 | } 28 | 29 | func (this *SingleConnRpcClient) insureConn() { 30 | if this.rpcClient != nil { 31 | return 32 | } 33 | 34 | var err error 35 | var retry int = 1 36 | 37 | for { 38 | if this.rpcClient != nil { 39 | return 40 | } 41 | 42 | this.rpcClient, err = NewClient("tcp", this.RpcServer, this.Timeout) 43 | if err == nil { 44 | return 45 | } 46 | 47 | log.Printf("dial %s fail: %v", this.RpcServer, err) 48 | 49 | if retry > 8 { 50 | retry = 1 51 | } 52 | 53 | time.Sleep(time.Duration(math.Pow(2.0, float64(retry))) * time.Second) 54 | 55 | retry++ 56 | } 57 | } 58 | 59 | func (this *SingleConnRpcClient) Call(method string, args interface{}, reply interface{}) error { 60 | 61 | this.Lock() 62 | defer this.Unlock() 63 | 64 | this.insureConn() 65 | 66 | timeout := time.Duration(15 * time.Second) 67 | done := make(chan error, 1) 68 | 69 | go func() { 70 | err := this.rpcClient.Call(method, args, reply) 71 | done <- err 72 | }() 73 | 74 | select { 75 | case <-time.After(timeout): 76 | log.Printf("[WARN] rpc call timeout %v => %v", this.rpcClient, this.RpcServer) 77 | this.close() 78 | case err := <-done: 79 | if err != nil { 80 | this.close() 81 | return err 82 | } 83 | this.close() 84 | } 85 | 86 | return nil 87 | } 88 | 89 | func NewClient(network, address string, timeout time.Duration) (*rpc.Client, error) { 90 | conn, err := net.DialTimeout(network, address, timeout) 91 | if err != nil { 92 | return nil, err 93 | } 94 | return jsonrpc.NewClient(conn), err 95 | } 96 | 97 | func NewRpcClient(addr string) *SingleConnRpcClient { 98 | return &SingleConnRpcClient{ 99 | RpcServer: addr, 100 | Timeout: time.Duration(g.Config.Alarm.CallTimeout) * time.Millisecond, 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /cfg.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "debug": false, 3 | "admins":["ning","admin"], 4 | "salt": "have fun!", 5 | "past": 30, 6 | "http": { 7 | "listen": "0.0.0.0:1984", 8 | "secret": "secret" 9 | }, 10 | "rpc": { 11 | "listen": "0.0.0.0:1985" 12 | }, 13 | "mysql": { 14 | "addr": "root:123456@tcp(127.0.0.1:3306)/urlooker?charset=utf8&&loc=Asia%2FShanghai", 15 | "idle": 10, 16 | "max": 20 17 | }, 18 | "ldap": { 19 | "enabled": false, 20 | "addr": "ldap.example.com:389", 21 | "baseDN": "dc=example,dc=com", 22 | "bindDN": "cn=mananger,dc=example,dc=com", 23 | "bindPasswd": "12345678", 24 | "userField": "uid", 25 | "attributes": ["sn","mail","telephoneNumber"] 26 | }, 27 | "alarm":{ 28 | "enable": true, 29 | "batch": 200, 30 | "replicas": 500, 31 | "connTimeout": 1000, 32 | "callTimeout": 5000, 33 | "maxConns": 32, 34 | "maxIdle": 32, 35 | "sleepTime":30, 36 | "cluster":{ 37 | "node-1":"127.0.0.1:1986" 38 | } 39 | }, 40 | "monitorMap": { 41 | "default":["hostname.1"], 42 | "idc1":["hostname.2"] 43 | }, 44 | "falcon":{ 45 | "enable": false, 46 | "addr":"http://falcon.transfer.addr/api/push", 47 | "interval": 60 48 | }, 49 | "internalDns":{ 50 | "enable": false, 51 | "addr":"" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /cron/clear.go: -------------------------------------------------------------------------------- 1 | package cron 2 | 3 | import ( 4 | "log" 5 | "time" 6 | 7 | "github.com/urlooker/web/model" 8 | ) 9 | 10 | func DeleteOld() { 11 | d := 12 12 | t1 := time.NewTicker(time.Duration(d) * time.Second) 13 | for { 14 | <-t1.C 15 | err := model.RelSidIpRepo.DeleteOld(int64(d)) 16 | if err != nil { 17 | log.Println("delete error:", err) 18 | } 19 | 20 | err = model.ItemStatusRepo.DeleteOld(int64(d)) 21 | if err != nil { 22 | log.Println("delete error:", err) 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /cron/init.go: -------------------------------------------------------------------------------- 1 | package cron 2 | 3 | func Init() { 4 | go GetDetectedItem() 5 | go DeleteOld() 6 | } 7 | -------------------------------------------------------------------------------- /g/const.go: -------------------------------------------------------------------------------- 1 | package g 2 | 3 | const ( 4 | VERSION = "0.2.0" 5 | ) 6 | 7 | //0.0.2 fix event_id报错,加强user信息保护,增加管理员编辑功能 8 | //0.0.3 fix err处理异常 9 | //0.0.4 fix 登陆问题 10 | //0.1.0 增加ldap登陆;域名可以指定ip 11 | //0.2.0 增加策略禁用功能 12 | -------------------------------------------------------------------------------- /g/var.go: -------------------------------------------------------------------------------- 1 | package g 2 | 3 | import ( 4 | "sync" 5 | ) 6 | 7 | type IpIdc struct { 8 | Ip string 9 | Idc string 10 | } 11 | 12 | //下发给agent的数据结构 13 | type DetectedItem struct { 14 | Sid int64 `json:"sid"` 15 | Domain string `json:"domain"` 16 | Target string `json:"target"` 17 | Ip string `json:"ip"` 18 | Keywords string `json:"keywords"` 19 | Timeout int `json:"timeout"` 20 | Creator string `json:"creator"` 21 | Data string `json:"data"` 22 | Tag string `json:"tag"` 23 | ExpectCode string `json:"expect_code"` 24 | Idc string `json:"idc"` 25 | } 26 | 27 | //agent上报的数据结构 28 | type CheckResult struct { 29 | Sid int64 `json:"sid"` 30 | Domain string `json:"domain"` 31 | Target string `json:"target"` 32 | Creator string `json:"creator"` 33 | Tag string `json:"tag"` 34 | RespCode string `json:"resp_code"` 35 | RespTime int `json:"resp_time"` 36 | Status int64 `json:"status"` 37 | PushTime int64 `json:"push_time"` 38 | Ip string `json:"ip"` 39 | } 40 | 41 | type DetectedItemSafeMap struct { 42 | sync.RWMutex 43 | M map[string][]*DetectedItem 44 | } 45 | 46 | var ( 47 | DetectedItemMap = &DetectedItemSafeMap{M: make(map[string][]*DetectedItem)} 48 | ) 49 | 50 | func (this *DetectedItemSafeMap) Get(key string) ([]*DetectedItem, bool) { 51 | this.RLock() 52 | defer this.RUnlock() 53 | ipItem, exists := this.M[key] 54 | return ipItem, exists 55 | } 56 | 57 | func (this *DetectedItemSafeMap) Set(detectedItemMap map[string][]*DetectedItem) { 58 | this.Lock() 59 | defer this.Unlock() 60 | this.M = detectedItemMap 61 | } 62 | -------------------------------------------------------------------------------- /handler/domain_handler.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/urlooker/web/g" 7 | "github.com/urlooker/web/http/errors" 8 | "github.com/urlooker/web/http/param" 9 | "github.com/urlooker/web/http/render" 10 | "github.com/urlooker/web/model" 11 | "github.com/urlooker/web/utils" 12 | ) 13 | 14 | type Url struct { 15 | Ip string `json:"ip"` 16 | Status []*model.ItemStatus `json:"status"` 17 | } 18 | 19 | func UrlStatus(w http.ResponseWriter, r *http.Request) { 20 | sid := param.MustInt64(r, "id") 21 | 22 | sidIpIndex, err := model.RelSidIpRepo.GetBySid(sid) 23 | errors.MaybePanic(err) 24 | 25 | urlArr := make([]Url, 0) 26 | idx := 0 27 | var ts int64 = 0 28 | for i, index := range sidIpIndex { 29 | url := Url{ 30 | Ip: index.Ip, 31 | } 32 | url.Status, err = model.ItemStatusRepo.GetByIpAndSid(index.Ip, index.Sid) 33 | errors.MaybePanic(err) 34 | 35 | if len(url.Status) > 0 && ts < url.Status[len(url.Status)-1].PushTime { 36 | ts = url.Status[len(url.Status)-1].PushTime 37 | idx = i 38 | } 39 | 40 | urlArr = append(urlArr, url) 41 | } 42 | 43 | //绘图使用,时间轴 44 | var timeData []string 45 | if len(urlArr) > 0 { 46 | for _, item := range urlArr[idx].Status { 47 | t := utils.TimeFormat(item.PushTime) 48 | timeData = append(timeData, t) 49 | } 50 | } 51 | 52 | events, err := model.EventRepo.GetByStrategyId(sid, g.Config.Past*60) 53 | errors.MaybePanic(err) 54 | 55 | strategy, err := model.GetStrategyById(sid) 56 | errors.MaybePanic(err) 57 | 58 | render.Put(r, "AlarmOn", g.Config.Alarm.Enable) 59 | render.Put(r, "TimeData", timeData) 60 | render.Put(r, "Id", sid) 61 | render.Put(r, "Url", strategy.Url) 62 | render.Put(r, "Events", events) 63 | render.Put(r, "Data", urlArr) 64 | render.HTML(r, w, "chart/index") 65 | } 66 | -------------------------------------------------------------------------------- /handler/home_handler.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/toolkits/str" 7 | "github.com/toolkits/web" 8 | 9 | "github.com/urlooker/web/http/errors" 10 | "github.com/urlooker/web/http/param" 11 | "github.com/urlooker/web/http/render" 12 | "github.com/urlooker/web/model" 13 | ) 14 | 15 | func HomeIndex(w http.ResponseWriter, r *http.Request) { 16 | me := MeRequired(LoginRequired(w, r)) 17 | username := me.Name 18 | mine := param.Int(r, "mine", 1) 19 | query := param.String(r, "q", "") 20 | if str.HasDangerousCharacters(query) { 21 | errors.Panic("查询字符不合法") 22 | } 23 | 24 | limit := param.Int(r, "limit", 10) 25 | total, err := model.GetAllStrategyCount(mine, query, username) 26 | errors.MaybePanic(err) 27 | pager := web.NewPaginator(r, limit, total) 28 | 29 | strategies, err := model.GetAllStrategy(mine, limit, pager.Offset(), query, username) 30 | 31 | errors.MaybePanic(err) 32 | render.Put(r, "Strategies", strategies) 33 | render.Put(r, "Pager", pager) 34 | render.Put(r, "Mine", mine) 35 | render.Put(r, "Query", query) 36 | render.HTML(r, w, "home/index") 37 | } 38 | -------------------------------------------------------------------------------- /handler/item_handler.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/urlooker/web/g" 7 | "github.com/urlooker/web/http/render" 8 | ) 9 | 10 | func GetHostIpItem(w http.ResponseWriter, r *http.Request) { 11 | hostname := HostnameRequired(r) 12 | ipItem, exists := g.DetectedItemMap.Get(hostname) 13 | if !exists { 14 | render.Data(w, "") 15 | return 16 | } 17 | render.Data(w, ipItem) 18 | } 19 | -------------------------------------------------------------------------------- /handler/required.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "net/http" 5 | "strconv" 6 | 7 | "github.com/gorilla/mux" 8 | "github.com/toolkits/str" 9 | 10 | "github.com/urlooker/web/g" 11 | "github.com/urlooker/web/http/cookie" 12 | "github.com/urlooker/web/http/errors" 13 | "github.com/urlooker/web/model" 14 | ) 15 | 16 | func StraRequired(r *http.Request) *model.Strategy { 17 | vars := mux.Vars(r) 18 | id, err := strconv.ParseInt(vars["id"], 10, 64) 19 | errors.MaybePanic(err) 20 | 21 | obj, err := model.GetStrategyById(id) 22 | errors.MaybePanic(err) 23 | if obj == nil { 24 | panic(errors.BadRequestError("no such item")) 25 | } 26 | return obj 27 | } 28 | 29 | func HostnameRequired(r *http.Request) string { 30 | vars := mux.Vars(r) 31 | hostname := vars["hostname"] 32 | 33 | if str.HasDangerousCharacters(hostname) { 34 | errors.Panic("hostname不合法") 35 | } 36 | 37 | return hostname 38 | } 39 | 40 | func LoginRequired(w http.ResponseWriter, r *http.Request) (int64, string) { 41 | userid, username, found := cookie.ReadUser(r) 42 | if !found { 43 | panic(errors.NotLoginError()) 44 | } 45 | 46 | return userid, username 47 | } 48 | 49 | func AdminRequired(id int64, name string) { 50 | user, err := model.GetUserById(id) 51 | if err != nil { 52 | panic(errors.InternalServerError(err.Error())) 53 | } 54 | 55 | if user == nil { 56 | panic(errors.NotLoginError()) 57 | } 58 | 59 | for _, admin := range g.Config.Admins { 60 | if user.Name == admin { 61 | return 62 | } 63 | } 64 | 65 | panic(errors.NotLoginError()) 66 | return 67 | } 68 | 69 | func MeRequired(id int64, name string) *model.User { 70 | user, err := model.GetUserById(id) 71 | if err != nil { 72 | panic(errors.InternalServerError(err.Error())) 73 | } 74 | 75 | if user == nil { 76 | panic(errors.NotLoginError()) 77 | } 78 | 79 | return user 80 | } 81 | 82 | func TeamRequired(r *http.Request) *model.Team { 83 | vars := mux.Vars(r) 84 | tid, err := strconv.ParseInt(vars["tid"], 10, 64) 85 | errors.MaybePanic(err) 86 | 87 | team, err := model.GetTeamById(tid) 88 | errors.MaybePanic(err) 89 | if team == nil { 90 | panic(errors.BadRequestError("no such team")) 91 | } 92 | 93 | return team 94 | } 95 | 96 | func UserMustBeMemberOfTeam(uid, tid int64) { 97 | is, err := model.IsMemberOfTeam(uid, tid) 98 | errors.MaybePanic(err) 99 | if is { 100 | return 101 | } 102 | 103 | team, err := model.GetTeamById(tid) 104 | errors.MaybePanic(err) 105 | if team != nil && team.Creator == uid { 106 | return 107 | } 108 | 109 | panic(errors.BadRequestError("用户不是团队的成员")) 110 | } 111 | 112 | func IsAdmin(username string) bool { 113 | for _, admin := range g.Config.Admins { 114 | if username == admin { 115 | return true 116 | } 117 | } 118 | return false 119 | } 120 | -------------------------------------------------------------------------------- /handler/status_handler.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/urlooker/web/g" 7 | "github.com/urlooker/web/http/errors" 8 | "github.com/urlooker/web/http/render" 9 | "github.com/urlooker/web/utils" 10 | ) 11 | 12 | func GetLog(w http.ResponseWriter, r *http.Request) { 13 | 14 | AdminRequired(LoginRequired(w, r)) 15 | appLog, err := utils.ReadLastLine("var/app.log") 16 | errors.MaybePanic(err) 17 | 18 | render.Put(r, "Log", appLog) 19 | 20 | render.HTML(r, w, "status/log") 21 | } 22 | 23 | func Version(w http.ResponseWriter, r *http.Request) { 24 | render.Data(w, g.VERSION) 25 | } 26 | -------------------------------------------------------------------------------- /http/cookie/cookie.go: -------------------------------------------------------------------------------- 1 | package cookie 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gorilla/securecookie" 7 | "github.com/urlooker/web/g" 8 | ) 9 | 10 | var SecureCookie *securecookie.SecureCookie 11 | 12 | func Init() { 13 | var hashKey = []byte(g.Config.Http.Secret) 14 | var blockKey = []byte(nil) 15 | SecureCookie = securecookie.New(hashKey, blockKey) 16 | } 17 | 18 | func ReadUser(r *http.Request) (id int64, name string, found bool) { 19 | if cookie, err := r.Cookie("u"); err == nil { 20 | value := make(map[string]interface{}) 21 | if err = SecureCookie.Decode("u", cookie.Value, &value); err == nil { 22 | id = value["id"].(int64) 23 | name = value["name"].(string) 24 | if id == 0 || name == "" { 25 | return 26 | } else { 27 | found = true 28 | return 29 | } 30 | } 31 | } 32 | return 33 | } 34 | 35 | func WriteUser(w http.ResponseWriter, id int64, name string) error { 36 | value := make(map[string]interface{}) 37 | value["id"] = id 38 | value["name"] = name 39 | encoded, err := SecureCookie.Encode("u", value) 40 | if err != nil { 41 | return err 42 | } 43 | 44 | cookie := &http.Cookie{ 45 | Name: "u", 46 | Value: encoded, 47 | Path: "/", 48 | MaxAge: 3600 * 24 * 7, 49 | HttpOnly: true, 50 | } 51 | http.SetCookie(w, cookie) 52 | 53 | return nil 54 | } 55 | 56 | func RemoveUser(w http.ResponseWriter) error { 57 | value := make(map[string]interface{}) 58 | value["id"] = "" 59 | value["name"] = "" 60 | encoded, err := SecureCookie.Encode("u", value) 61 | if err != nil { 62 | return err 63 | } 64 | 65 | cookie := &http.Cookie{ 66 | Name: "u", 67 | Value: encoded, 68 | Path: "/", 69 | MaxAge: -1, 70 | } 71 | http.SetCookie(w, cookie) 72 | 73 | return nil 74 | } 75 | -------------------------------------------------------------------------------- /http/errors/errors.go: -------------------------------------------------------------------------------- 1 | package errors 2 | 3 | import ( 4 | "net/http" 5 | "runtime" 6 | "strings" 7 | "time" 8 | ) 9 | 10 | type Error struct { 11 | Code int `json:"code"` 12 | Msg string `json:"msg"` 13 | Time string `json:"time"` 14 | File string `json:"file"` 15 | Line int `json:"line"` 16 | } 17 | 18 | // 401 19 | func NotLoginError(msg ...string) Error { 20 | return _build(http.StatusUnauthorized, "unauthorized", msg...) 21 | } 22 | 23 | // 400 24 | func BadRequestError(msg ...string) Error { 25 | return _build(http.StatusBadRequest, "bad request", msg...) 26 | } 27 | 28 | // 403 29 | func NoPrivError(msg ...string) Error { 30 | return _build(http.StatusForbidden, "forbidden", msg...) 31 | } 32 | 33 | // 500 34 | func InternalServerError(msg ...string) Error { 35 | return _build(http.StatusInternalServerError, "internal server error", msg...) 36 | } 37 | 38 | func _build(code int, defval string, custom ...string) Error { 39 | msg := defval 40 | if len(custom) > 0 { 41 | msg = custom[0] 42 | } 43 | return Error{ 44 | Code: code, 45 | Msg: msg, 46 | } 47 | } 48 | 49 | func MaybePanic(err error) { 50 | _, whichFile, line, _ := runtime.Caller(1) 51 | arr := strings.Split(whichFile, "/") 52 | file := arr[len(arr)-1] 53 | t := time.Unix(time.Now().Unix(), 0).Format("2006-01-02 15:04:05") 54 | 55 | if err != nil { 56 | panic(Error{Msg: err.Error(), Time: t, File: file, Line: line}) 57 | } 58 | } 59 | 60 | func Panic(msg string) { 61 | _, whichFile, line, _ := runtime.Caller(1) 62 | arr := strings.Split(whichFile, "/") 63 | file := arr[len(arr)-1] 64 | t := time.Unix(time.Now().Unix(), 0).Format("2006-01-02 15:04:05") 65 | 66 | panic(Error{Msg: msg, Time: t, File: file, Line: line}) 67 | } 68 | -------------------------------------------------------------------------------- /http/helper/helper.go: -------------------------------------------------------------------------------- 1 | package helper 2 | 3 | import ( 4 | "log" 5 | "strconv" 6 | "time" 7 | 8 | "github.com/urlooker/web/model" 9 | ) 10 | 11 | func Times1000(num int64) int64 { 12 | return (num + 3600*8) * 1000 13 | } 14 | 15 | func UsersOfTeam(tid int64) []*model.User { 16 | users, _ := model.UsersOfTeam(tid) 17 | return users 18 | } 19 | 20 | func TeamsOfStrategy(ids string) []*model.Team { 21 | teams, err := model.GetTeamsByIds(ids) 22 | if err != nil { 23 | log.Println("get teams err", err) 24 | } 25 | return teams 26 | } 27 | 28 | func HumenTime(ts int64) string { 29 | return time.Unix(ts, 0).Format("2006-01-02 15:04:05") 30 | } 31 | 32 | func GetFirst(items []*model.ItemStatus) string { 33 | if len(items) == 0 { 34 | return " , " 35 | } 36 | item := items[0] 37 | str := HumenTime(item.PushTime) + "," + strconv.Itoa(item.RespTime) 38 | return str 39 | } 40 | -------------------------------------------------------------------------------- /http/http.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "github.com/codegangsta/negroni" 5 | "github.com/gorilla/mux" 6 | 7 | "github.com/urlooker/web/g" 8 | //"github.com/xpharos/web/http/cookie" 9 | "github.com/urlooker/web/http/middleware" 10 | "github.com/urlooker/web/http/render" 11 | ) 12 | 13 | func Start() { 14 | render.Init() 15 | //cookie.Init() 16 | 17 | r := mux.NewRouter().StrictSlash(false) 18 | ConfigRouter(r) 19 | 20 | n := negroni.New() 21 | n.Use(middleware.NewLogger()) 22 | n.Use(middleware.NewRecovery()) 23 | n.UseHandler(r) 24 | n.Run(g.Config.Http.Listen) 25 | } 26 | -------------------------------------------------------------------------------- /http/middleware/logger.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | "os" 7 | "time" 8 | 9 | "github.com/codegangsta/negroni" 10 | ) 11 | 12 | // Logger is a middleware handler that logs the request as it goes in and the response as it goes out. 13 | type Logger struct { 14 | // Logger inherits from log.Logger used to log messages with the Logger middleware 15 | *log.Logger 16 | } 17 | 18 | // NewLogger returns a new Logger instance 19 | func NewLogger() *Logger { 20 | return &Logger{log.New(os.Stdout, "", 0)} 21 | } 22 | 23 | func (l *Logger) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { 24 | start := time.Now() 25 | l.Printf("%v %s %s %s", time.Now().Format("2006/01/02 15:04:05"), r.Method, r.URL.Path, r.RemoteAddr) 26 | 27 | next(rw, r) 28 | 29 | res := rw.(negroni.ResponseWriter) 30 | l.Printf("%v %v %s in %v", time.Now().Format("2006/01/02 15:04:05"), res.Status(), http.StatusText(res.Status()), time.Since(start)) 31 | } 32 | -------------------------------------------------------------------------------- /http/middleware/recovery.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | "os" 8 | "runtime" 9 | 10 | "github.com/urlooker/web/http/errors" 11 | "github.com/urlooker/web/http/render" 12 | ) 13 | 14 | // Recovery is a Negroni middleware that recovers from any panics and writes a 500 if there was one. 15 | type Recovery struct { 16 | Logger *log.Logger 17 | PrintStack bool 18 | StackAll bool 19 | StackSize int 20 | } 21 | 22 | // NewRecovery returns a new instance of Recovery 23 | func NewRecovery() *Recovery { 24 | return &Recovery{ 25 | Logger: log.New(os.Stdout, "[panic] ", 0), 26 | PrintStack: true, 27 | StackAll: false, 28 | StackSize: 1024 * 8, 29 | } 30 | } 31 | 32 | func (rec *Recovery) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { 33 | defer func() { 34 | if err := recover(); err != nil { 35 | if customError, ok := err.(errors.Error); ok { 36 | msg := fmt.Sprintf("[%s:%d] %s [Error:]%s", customError.File, customError.Line, customError.Time, customError.Msg) 37 | log.Printf(msg) 38 | 39 | if isAjax(r) { 40 | render.Message(w, customError.Msg) 41 | return 42 | } 43 | 44 | if customError.Code == http.StatusUnauthorized || customError.Code == http.StatusForbidden { 45 | http.Redirect(w, r, "/auth/login", 302) 46 | return 47 | } 48 | 49 | render.Put(r, "Error", customError.Msg) 50 | render.HTML(r, w, "inc/error") 51 | return 52 | } 53 | 54 | // Negroni part 55 | w.WriteHeader(http.StatusInternalServerError) 56 | stack := make([]byte, rec.StackSize) 57 | stack = stack[:runtime.Stack(stack, rec.StackAll)] 58 | 59 | f := "PANIC: %s\n%s" 60 | log.Printf(f, err, stack) 61 | 62 | if rec.PrintStack { 63 | fmt.Fprintf(w, f, err, stack) 64 | } 65 | } 66 | }() 67 | 68 | next(w, r) 69 | } 70 | 71 | func isAjax(r *http.Request) bool { 72 | return r.Header.Get("X-Requested-With") == "XMLHttpRequest" 73 | } 74 | -------------------------------------------------------------------------------- /http/render/render.go: -------------------------------------------------------------------------------- 1 | package render 2 | 3 | import ( 4 | "fmt" 5 | "html/template" 6 | "net/http" 7 | 8 | "github.com/urlooker/web/g" 9 | "github.com/urlooker/web/http/cookie" 10 | "github.com/urlooker/web/http/helper" 11 | 12 | "github.com/gorilla/context" 13 | "github.com/unrolled/render" 14 | ) 15 | 16 | var Render *render.Render 17 | var funcMap = template.FuncMap{ 18 | "Times1000": helper.Times1000, 19 | "UsersOfTeam": helper.UsersOfTeam, 20 | "TeamsOfStrategy": helper.TeamsOfStrategy, 21 | "HumenTime": helper.HumenTime, 22 | "GetFirst": helper.GetFirst, 23 | } 24 | 25 | func Init() { 26 | Render = render.New(render.Options{ 27 | Directory: "views", 28 | Extensions: []string{".html"}, 29 | Delims: render.Delims{"{{", "}}"}, 30 | Funcs: []template.FuncMap{funcMap}, 31 | IndentJSON: false, 32 | }) 33 | } 34 | 35 | func Put(r *http.Request, key string, val interface{}) { 36 | m, ok := context.GetOk(r, "_DATA_MAP_") 37 | if ok { 38 | mm := m.(map[string]interface{}) 39 | mm[key] = val 40 | context.Set(r, "_DATA_MAP_", mm) 41 | } else { 42 | context.Set(r, "_DATA_MAP_", map[string]interface{}{key: val}) 43 | } 44 | } 45 | 46 | func HTML(r *http.Request, w http.ResponseWriter, name string, htmlOpt ...render.HTMLOptions) { 47 | userid, username, found := cookie.ReadUser(r) 48 | 49 | Put(r, "Debug", g.Config.Debug) 50 | Put(r, "HasLogin", found) 51 | Put(r, "UserId", userid) 52 | Put(r, "UserName", username) 53 | Render.HTML(w, http.StatusOK, name, context.Get(r, "_DATA_MAP_"), htmlOpt...) 54 | } 55 | 56 | func Text(w http.ResponseWriter, v string, codes ...int) { 57 | code := http.StatusOK 58 | if len(codes) > 0 { 59 | code = codes[0] 60 | } 61 | Render.Text(w, code, v) 62 | } 63 | 64 | func MaybeError(w http.ResponseWriter, err error) { 65 | msg := "" 66 | if err != nil { 67 | msg = err.Error() 68 | } 69 | 70 | Render.JSON(w, http.StatusOK, map[string]string{"msg": msg}) 71 | } 72 | 73 | func Error(w http.ResponseWriter, err error) { 74 | msg := "" 75 | if err != nil { 76 | msg = err.Error() 77 | } 78 | 79 | Render.JSON(w, http.StatusOK, map[string]string{"msg": msg}) 80 | } 81 | 82 | func Message(w http.ResponseWriter, format string, args ...interface{}) { 83 | Render.JSON(w, http.StatusOK, map[string]string{"msg": fmt.Sprintf(format, args...)}) 84 | } 85 | 86 | func Data(w http.ResponseWriter, v interface{}, msg ...string) { 87 | m := "" 88 | if len(msg) > 0 { 89 | m = msg[0] 90 | } 91 | 92 | Render.JSON(w, http.StatusOK, map[string]interface{}{"msg": m, "data": v}) 93 | } 94 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "log" 7 | "os" 8 | "runtime" 9 | 10 | "github.com/urlooker/web/api" 11 | "github.com/urlooker/web/cron" 12 | "github.com/urlooker/web/g" 13 | "github.com/urlooker/web/http" 14 | "github.com/urlooker/web/http/cookie" 15 | "github.com/urlooker/web/model" 16 | "github.com/urlooker/web/sender" 17 | "github.com/urlooker/web/store" 18 | ) 19 | 20 | func prepare() { 21 | runtime.GOMAXPROCS(runtime.NumCPU()) 22 | log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) 23 | } 24 | 25 | func init() { 26 | prepare() 27 | 28 | cfg := flag.String("c", "cfg.json", "configuration file") 29 | version := flag.Bool("v", false, "show version") 30 | help := flag.Bool("h", false, "help") 31 | flag.Parse() 32 | 33 | handleVersion(*version) 34 | handleHelp(*help) 35 | handleConfig(*cfg) 36 | 37 | store.InitMysql() 38 | cron.Init() 39 | sender.Init() 40 | cookie.Init() 41 | } 42 | 43 | func main() { 44 | err := model.AdminRegister() 45 | if err != nil { 46 | log.Fatalln(err) 47 | } 48 | go api.Start() 49 | http.Start() 50 | } 51 | 52 | func handleVersion(displayVersion bool) { 53 | if displayVersion { 54 | fmt.Println(g.VERSION) 55 | os.Exit(0) 56 | } 57 | } 58 | 59 | func handleHelp(displayHelp bool) { 60 | if displayHelp { 61 | flag.Usage() 62 | os.Exit(0) 63 | } 64 | } 65 | 66 | func handleConfig(configFile string) { 67 | err := g.Parse(configFile) 68 | if err != nil { 69 | log.Fatalln(err) 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /model/event.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | . "github.com/urlooker/web/store" 8 | ) 9 | 10 | type Event struct { 11 | Id int64 `json:"id"` 12 | EventId string `json:"event_id"` 13 | Status string `json:"status"` 14 | Url string `json:"url"` 15 | Ip string `json:"ip"` 16 | EventTime int64 `json:"event_time"` 17 | StrategyId int64 `json:"strategy_id"` 18 | RespTime int `json:"resp_time"` 19 | RespCode string `json:"resp_code"` 20 | Result int64 `json:"result"` 21 | CurrentStep int `json:"current_step"` 22 | MaxStep int `json:"max_step"` 23 | } 24 | 25 | var EventRepo *Event 26 | 27 | func (this *Event) Insert() error { 28 | _, err := Orm.Insert(this) 29 | return err 30 | } 31 | 32 | func (this *Event) GetByStrategyId(strategyId int64, before int) ([]*Event, error) { 33 | events := make([]*Event, 0) 34 | ts := time.Now().Unix() - int64(before) 35 | err := Orm.Where("strategy_id = ? and event_time > ?", strategyId, ts).Desc("event_time").Find(&events) 36 | return events, err 37 | } 38 | 39 | func (this *Event) String() string { 40 | return fmt.Sprintf( 41 | "", 42 | this.Id, 43 | this.EventId, 44 | this.Ip, 45 | this.Url, 46 | this.EventTime, 47 | this.StrategyId, 48 | this.RespTime, 49 | this.RespCode, 50 | this.Status, 51 | this.CurrentStep, 52 | this.MaxStep, 53 | ) 54 | } 55 | -------------------------------------------------------------------------------- /model/item_status.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "crypto/md5" 5 | "fmt" 6 | "io" 7 | "time" 8 | 9 | "github.com/urlooker/web/g" 10 | . "github.com/urlooker/web/store" 11 | ) 12 | 13 | type ItemStatus struct { 14 | Id int64 `json:"id"` 15 | Sid int64 `json:"sid"` 16 | Ip string `json:"ip"` 17 | RespTime int `json:"resp_time"` 18 | RespCode string `json:"resp_code"` 19 | PushTime int64 `json:"push_time"` 20 | Result int64 `json:"result"` 21 | } 22 | 23 | var ItemStatusRepo *ItemStatus 24 | 25 | func (this *ItemStatus) Save() error { 26 | sql := fmt.Sprintf("insert into item_status00 (ip, sid, resp_time, resp_code, push_time, result) value(?,?,?,?,?,?)") 27 | _, err := Orm.Exec(sql, this.Ip, this.Sid, this.RespTime, this.RespCode, this.PushTime, this.Result) 28 | return err 29 | } 30 | 31 | func (this *ItemStatus) GetByIpAndSid(ip string, sid int64) ([]*ItemStatus, error) { 32 | itemStatusArr := make([]*ItemStatus, 0) 33 | ts := time.Now().Unix() - int64(g.Config.Past*60) 34 | sql := fmt.Sprintf("select * from item_status00 where ip=? and sid=? and push_time > ?") 35 | 36 | err := Orm.Sql(sql, ip, sid, ts).Find(&itemStatusArr) 37 | return itemStatusArr, err 38 | } 39 | 40 | func (this *ItemStatus) PK() string { 41 | h := md5.New() 42 | io.WriteString(h, fmt.Sprintf("%s/%s", this.Sid, this.Ip)) 43 | 44 | return fmt.Sprintf("%x", h.Sum(nil)) 45 | } 46 | 47 | func (this *ItemStatus) DeleteOld(d int64) error { 48 | ts := time.Now().Unix() - 12*60*60 49 | sql := fmt.Sprintf("delete from item_status00 where push_time < ?") 50 | _, err := Orm.Exec(sql, ts) 51 | return err 52 | } 53 | -------------------------------------------------------------------------------- /model/rel_sid_ip.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/urlooker/web/g" 7 | . "github.com/urlooker/web/store" 8 | ) 9 | 10 | type RelSidIp struct { 11 | Id int64 `json:"id"` 12 | Sid int64 `json:"sid"` 13 | Ip string `json:"ip"` 14 | Ts int64 `json:"ts"` 15 | } 16 | 17 | var RelSidIpRepo *RelSidIp 18 | 19 | func (this *RelSidIp) Save() error { 20 | has, err := Orm.Where("sid = ? and ip = ?", this.Sid, this.Ip).Get(new(RelSidIp)) 21 | if err != nil { 22 | return err 23 | } 24 | if !has { 25 | _, err = Orm.Insert(this) 26 | } else { 27 | this.Ts = time.Now().Unix() 28 | _, err = Orm.Cols("ts").Update(this) 29 | } 30 | return err 31 | } 32 | 33 | func (this *RelSidIp) GetBySid(sid int64) ([]*RelSidIp, error) { 34 | var relSidIps []*RelSidIp 35 | ts := time.Now().Unix() - int64(g.Config.Past*60) 36 | err := Orm.Where("sid = ? and ts > ?", sid, ts).Find(&relSidIps) 37 | return relSidIps, err 38 | } 39 | 40 | func (this *RelSidIp) DeleteOld(d int64) error { 41 | ts := time.Now().Unix() - d*60*60 42 | _, err := Orm.Where("ts < ?", ts).Delete(new(RelSidIp)) 43 | return err 44 | } 45 | -------------------------------------------------------------------------------- /model/strategy.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | . "github.com/urlooker/web/store" 5 | ) 6 | 7 | type Strategy struct { 8 | Id int64 `json:"id"` 9 | Url string `json:"url"` 10 | Enable int `json:"enable"` 11 | IP string `json:"ip" xorm:"ip"` 12 | Keywords string `json:"keywords"` 13 | Timeout int `json:"timeout"` 14 | Creator string `json:"creator"` 15 | ExpectCode string `json:"expect_code"` 16 | Note string `json:"note"` 17 | Data string `json:"data"` 18 | Tag string `json:"tag"` 19 | MaxStep int `json:"max_step"` 20 | Times int `json:"times"` 21 | Teams string `json:"teams"` 22 | } 23 | 24 | func GetAllStrategyCount(mine int, query, username string) (int64, error) { 25 | if mine == 1 { 26 | if query != "" { 27 | return Orm.Where("url LIKE ? AND creator = ? ORDER BY id", "%"+query+"%", username).Count(new(Strategy)) 28 | } else { 29 | num, err := Orm.Where("creator = ?", username).Count(new(Strategy)) 30 | return num, err 31 | } 32 | } else { 33 | if query != "" { 34 | return Orm.Where("url LIKE ? ORDER BY id", "%"+query+"%").Count(new(Strategy)) 35 | } else { 36 | num, err := Orm.Count(new(Strategy)) 37 | return num, err 38 | } 39 | } 40 | 41 | } 42 | 43 | func GetAllStrategy(mine, limit, offset int, query, username string) ([]*Strategy, error) { 44 | items := make([]*Strategy, 0) 45 | 46 | var err error 47 | if mine == 1 { 48 | if query != "" { 49 | err = Orm.Where("url LIKE ? AND creator = ? ORDER BY id", "%"+query+"%", username).Limit(limit, offset).Find(&items) 50 | } else { 51 | err = Orm.Where("creator = ?", username).Limit(limit, offset).Find(&items) 52 | } 53 | } else { 54 | if query != "" { 55 | err = Orm.Where("url LIKE ? ORDER BY id", "%"+query+"%").Limit(limit, offset).Find(&items) 56 | } else { 57 | err = Orm.Limit(limit, offset).Find(&items) 58 | } 59 | } 60 | return items, err 61 | } 62 | 63 | func GetAllStrategyByCron() ([]*Strategy, error) { 64 | strategies := make([]*Strategy, 0) 65 | err := Orm.Where("enable = 1").Find(&strategies) 66 | return strategies, err 67 | } 68 | 69 | func GetStrategyById(sid int64) (*Strategy, error) { 70 | strategy := new(Strategy) 71 | _, err := Orm.Where("id=?", sid).Get(strategy) 72 | 73 | return strategy, err 74 | } 75 | 76 | func (this *Strategy) Add() (int64, error) { 77 | _, err := Orm.Insert(this) 78 | return this.Id, err 79 | } 80 | 81 | func (this *Strategy) Update() error { 82 | _, err := Orm.Where("id=?", this.Id).Cols("times", "max_step", "expect_code", "timeout", "url", "enable", "ip", "keywords", "note", "data", "tag", "teams").Update(this) 83 | return err 84 | } 85 | 86 | func (this *Strategy) Delete() error { 87 | _, err := Orm.Where("id=?", this.Id).Delete(new(Strategy)) 88 | return err 89 | } 90 | -------------------------------------------------------------------------------- /sender/alarm.go: -------------------------------------------------------------------------------- 1 | package sender 2 | 3 | import ( 4 | "log" 5 | "time" 6 | 7 | "github.com/toolkits/container/list" 8 | 9 | "github.com/urlooker/web/backend" 10 | "github.com/urlooker/web/g" 11 | ) 12 | 13 | func SendToAlarm(Q *list.SafeListLimited, node string) { 14 | cfg := g.Config 15 | batch := cfg.Alarm.Batch 16 | addr := cfg.Alarm.Cluster[node] 17 | 18 | //todo:rpc 当数据量增大时,rpc调用改为并行方式 19 | for { 20 | items := Q.PopBackBy(batch) 21 | count := len(items) 22 | if count == 0 { 23 | time.Sleep(time.Duration(cfg.Alarm.SleepTime) * time.Second) 24 | continue 25 | } 26 | 27 | var resp string 28 | var err error 29 | sendOk := false 30 | for i := 0; i < 3; i++ { 31 | rpcClient := backend.NewRpcClient(addr) 32 | err = rpcClient.Call("Alarm.Send", items, &resp) 33 | if err == nil { 34 | sendOk = true 35 | break 36 | } 37 | time.Sleep(1) 38 | } 39 | 40 | if !sendOk { 41 | log.Printf("send alarm %s:%s fail: %v", node, addr, err) 42 | } 43 | if cfg.Debug { 44 | log.Println("<=", resp) 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /sender/init.go: -------------------------------------------------------------------------------- 1 | package sender 2 | 3 | import ( 4 | "github.com/urlooker/web/g" 5 | "github.com/urlooker/web/utils" 6 | 7 | "github.com/toolkits/container/list" 8 | ) 9 | 10 | var ( 11 | NodeRing *ConsistentHashNodeRing // 服务节点的一致性哈希环 12 | SendQueues map[string]*list.SafeListLimited // 发送缓存队列,减少发起连接次数 13 | ) 14 | 15 | func initRing() { 16 | NodeRing = NewConsistentHashNodeRing(g.Config.Alarm.Replicas, utils.KeysOfMap(g.Config.Alarm.Cluster)) 17 | } 18 | 19 | func initSendQueues() { 20 | SendQueues = make(map[string]*list.SafeListLimited) 21 | 22 | for node, _ := range g.Config.Alarm.Cluster { 23 | Q := list.NewSafeListLimited(10240) 24 | SendQueues[node] = Q 25 | } 26 | } 27 | 28 | func startSendTasks() { 29 | for node, _ := range g.Config.Alarm.Cluster { 30 | queue := SendQueues[node] 31 | go SendToAlarm(queue, node) 32 | } 33 | } 34 | 35 | func Init() { 36 | initRing() 37 | initSendQueues() 38 | 39 | startSendTasks() 40 | } 41 | -------------------------------------------------------------------------------- /sender/ring.go: -------------------------------------------------------------------------------- 1 | package sender 2 | 3 | import ( 4 | "stathat.com/c/consistent" 5 | ) 6 | 7 | type ConsistentHashNodeRing struct { 8 | ring *consistent.Consistent 9 | } 10 | 11 | func NewConsistentHashNodeRing(NumberOfReplicas int, nodes []string) *ConsistentHashNodeRing { 12 | ret := &ConsistentHashNodeRing{ring: consistent.New()} 13 | ret.SetNumberOfReplicas(NumberOfReplicas) 14 | ret.SetNodes(nodes) 15 | return ret 16 | } 17 | 18 | func (this *ConsistentHashNodeRing) SetNumberOfReplicas(num int) { 19 | this.ring.NumberOfReplicas = num 20 | } 21 | 22 | func (this *ConsistentHashNodeRing) SetNodes(nodes []string) { 23 | for _, node := range nodes { 24 | this.ring.Add(node) 25 | } 26 | } 27 | 28 | func (this *ConsistentHashNodeRing) GetNode(pk string) (string, error) { 29 | return this.ring.Get(pk) 30 | } 31 | -------------------------------------------------------------------------------- /static/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/URLooker/web/362a939a5ff973fcea885ed1641bb660fec6c301/static/.DS_Store -------------------------------------------------------------------------------- /static/css/error.css: -------------------------------------------------------------------------------- 1 | *{ padding: 0; margin: 0; } 2 | body{ background: #fff; font-family: '微软雅黑'; color: #333; font-size: 16px; } 3 | .system-message{ padding: 24px 48px; } 4 | .system-message h1{ font-size: 100px; font-weight: normal; line-height: 120px; margin-bottom: 12px; } 5 | .system-message .jump{ padding-top: 10px} 6 | .system-message .jump a{ color: #333;} 7 | .system-message .success,.system-message .error{ line-height: 1.8em; font-size: 36px } 8 | .system-message .detail{ font-size: 12px; line-height: 20px; margin-top: 12px; display:none} -------------------------------------------------------------------------------- /static/css/g.css: -------------------------------------------------------------------------------- 1 | .demo-container { 2 | box-sizing: border-box; 3 | width: 850px; 4 | height: 450px; 5 | padding: 20px 15px 15px 15px; 6 | margin: 15px auto 30px auto; 7 | border: 1px solid #ddd; 8 | background: #fff; 9 | background: linear-gradient(#f6f6f6 0, #fff 50px); 10 | background: -o-linear-gradient(#f6f6f6 0, #fff 50px); 11 | background: -ms-linear-gradient(#f6f6f6 0, #fff 50px); 12 | background: -moz-linear-gradient(#f6f6f6 0, #fff 50px); 13 | background: -webkit-linear-gradient(#f6f6f6 0, #fff 50px); 14 | box-shadow: 0 3px 10px rgba(0,0,0,0.15); 15 | -o-box-shadow: 0 3px 10px rgba(0,0,0,0.1); 16 | -ms-box-shadow: 0 3px 10px rgba(0,0,0,0.1); 17 | -moz-box-shadow: 0 3px 10px rgba(0,0,0,0.1); 18 | -webkit-box-shadow: 0 3px 10px rgba(0,0,0,0.1); 19 | } 20 | 21 | .demo-placeholder { 22 | width: 100%; 23 | height: 100%; 24 | font-size: 14px; 25 | line-height: 1.2em; 26 | } 27 | 28 | .table { 29 | font-size:12px; 30 | font-family: 'verdana', 'Microsoft YaHei', 'Consolas', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono'; 31 | margin-bottom: 0px; 32 | margin-top: 10px; 33 | } 34 | 35 | #main { 36 | margin:0px auto; 37 | text-align:center; 38 | width: 1300px; 39 | height:400px; 40 | } 41 | 42 | #event { 43 | padding-left:15px; 44 | padding-right:15px; 45 | padding-bottom:15px; 46 | } 47 | 48 | #alarm_title{ 49 | text-align:center; 50 | margin-top: 20px; 51 | } 52 | 53 | .col-sm-2 { 54 | padding-right:0px; 55 | padding-left:0px; 56 | } 57 | 58 | .all { 59 | padding-left:12px; 60 | padding-right:12px; 61 | } 62 | 63 | footer { 64 | clear: both; 65 | color: #9A9994; 66 | font-size: 12px; 67 | line-height: 15.4px; 68 | margin-top: 30px; 69 | overflow: hidden; 70 | padding: 20px 0 40px; 71 | } 72 | 73 | footer .sfc-member { 74 | float: right; 75 | text-align: right; 76 | padding-right: 15px; 77 | } 78 | 79 | footer a { 80 | color: #403F3C; 81 | } 82 | 83 | -------------------------------------------------------------------------------- /static/css/home.css: -------------------------------------------------------------------------------- 1 | #item_id { 2 | width: 3%; 3 | } 4 | 5 | #expect_code, #timeout, #creator, #note, #edit { 6 | width: 10%; 7 | } 8 | 9 | #team_name { 10 | width: 15%; 11 | } 12 | 13 | #item_target { 14 | width: 30%; 15 | word-wrap:break-word; 16 | word-break:break-all; 17 | } 18 | 19 | .edit_icon { 20 | text-decoration:none; 21 | } 22 | 23 | .cut-line { 24 | margin: 0 5px; 25 | color: #D6D6D6; 26 | } 27 | 28 | -------------------------------------------------------------------------------- /static/css/login.css: -------------------------------------------------------------------------------- 1 | #login { 2 | width: 300px; 3 | height: 200px; 4 | margin: 0 auto; 5 | margin-top: 60px; 6 | } 7 | 8 | #login .title { 9 | width: 100px; 10 | height: 100px; 11 | margin: 0 auto; 12 | display: block; 13 | } 14 | 15 | #login .line { 16 | margin-bottom: 10px; 17 | } 18 | 19 | #login .line .goto { 20 | color: #999; 21 | text-align: right; 22 | } -------------------------------------------------------------------------------- /static/css/strategy.css: -------------------------------------------------------------------------------- 1 | .form-group { 2 | width:100% 3 | } 4 | 5 | #tags,#url { 6 | width:540px 7 | } 8 | 9 | #submit { 10 | width:20%; 11 | margin-top:2px; 12 | margin-left:-25px 13 | } -------------------------------------------------------------------------------- /static/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/URLooker/web/362a939a5ff973fcea885ed1641bb660fec6c301/static/img/logo.png -------------------------------------------------------------------------------- /static/js/team.js: -------------------------------------------------------------------------------- 1 | function create_team() { 2 | $.post('/team/create', { 3 | 'name' : $("#name").val(), 4 | 'resume' : $("#resume").val(), 5 | 'users' : $("#users").val() 6 | }, function(json) { 7 | handle_json(json, function(){ 8 | location.href = '/teams'; 9 | }); 10 | }); 11 | } 12 | 13 | function edit_team(org_id, team_id) { 14 | $.post('/team/'+team_id+'/edit', { 15 | 'resume' : $("#resume").val(), 16 | 'users' : $("#users").val(), 17 | }, function(json) { 18 | handle_json(json, function(){ 19 | location.href = '/teams'; 20 | }); 21 | }); 22 | } -------------------------------------------------------------------------------- /static/lib/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/URLooker/web/362a939a5ff973fcea885ed1641bb660fec6c301/static/lib/.DS_Store -------------------------------------------------------------------------------- /static/lib/fa/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/URLooker/web/362a939a5ff973fcea885ed1641bb660fec6c301/static/lib/fa/.DS_Store -------------------------------------------------------------------------------- /static/lib/fa/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/URLooker/web/362a939a5ff973fcea885ed1641bb660fec6c301/static/lib/fa/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /static/lib/fa/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/URLooker/web/362a939a5ff973fcea885ed1641bb660fec6c301/static/lib/fa/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /static/lib/fa/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/URLooker/web/362a939a5ff973fcea885ed1641bb660fec6c301/static/lib/fa/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /static/lib/fa/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/URLooker/web/362a939a5ff973fcea885ed1641bb660fec6c301/static/lib/fa/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /static/lib/fa/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/URLooker/web/362a939a5ff973fcea885ed1641bb660fec6c301/static/lib/fa/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /static/lib/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/URLooker/web/362a939a5ff973fcea885ed1641bb660fec6c301/static/lib/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /static/lib/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/URLooker/web/362a939a5ff973fcea885ed1641bb660fec6c301/static/lib/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /static/lib/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/URLooker/web/362a939a5ff973fcea885ed1641bb660fec6c301/static/lib/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /static/lib/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/URLooker/web/362a939a5ff973fcea885ed1641bb660fec6c301/static/lib/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /static/lib/layer/skin/default/icon-ext.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/URLooker/web/362a939a5ff973fcea885ed1641bb660fec6c301/static/lib/layer/skin/default/icon-ext.png -------------------------------------------------------------------------------- /static/lib/layer/skin/default/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/URLooker/web/362a939a5ff973fcea885ed1641bb660fec6c301/static/lib/layer/skin/default/icon.png -------------------------------------------------------------------------------- /static/lib/layer/skin/default/loading-0.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/URLooker/web/362a939a5ff973fcea885ed1641bb660fec6c301/static/lib/layer/skin/default/loading-0.gif -------------------------------------------------------------------------------- /static/lib/layer/skin/default/loading-1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/URLooker/web/362a939a5ff973fcea885ed1641bb660fec6c301/static/lib/layer/skin/default/loading-1.gif -------------------------------------------------------------------------------- /static/lib/layer/skin/default/loading-2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/URLooker/web/362a939a5ff973fcea885ed1641bb660fec6c301/static/lib/layer/skin/default/loading-2.gif -------------------------------------------------------------------------------- /static/lib/layer/skin/layer.ext.css: -------------------------------------------------------------------------------- 1 | /*! 2 | 3 | @Name: layer拓展样式 4 | @Date: 2012.12.13 5 | @Author: 贤心 6 | @blog: sentsin.com 7 | 8 | */.layui-layer-imgbar,.layui-layer-imgtit a,.layui-layer-tab .layui-layer-title span{text-overflow:ellipsis;white-space:nowrap}.layui-layer-iconext{background:url(default/icon-ext.png) no-repeat}html #layui_layer_skinlayerextcss{display:none;position:absolute;width:1989px}.layui-layer-prompt .layui-layer-input{display:block;width:220px;height:30px;margin:0 auto;line-height:30px;padding:0 5px;border:1px solid #ccc;box-shadow:1px 1px 5px rgba(0,0,0,.1) inset;color:#333}.layui-layer-prompt textarea.layui-layer-input{width:300px;height:100px;line-height:20px}.layui-layer-tab{box-shadow:1px 1px 50px rgba(0,0,0,.4)}.layui-layer-tab .layui-layer-title{padding-left:0;border-bottom:1px solid #ccc;background-color:#eee;overflow:visible}.layui-layer-tab .layui-layer-title span{position:relative;float:left;min-width:80px;max-width:260px;padding:0 20px;text-align:center;cursor:default;overflow:hidden}.layui-layer-tab .layui-layer-title span.layui-layer-tabnow{height:43px;border-left:1px solid #ccc;border-right:1px solid #ccc;background-color:#fff;z-index:10}.layui-layer-tab .layui-layer-title span:first-child{border-left:none}.layui-layer-tabmain{line-height:24px;clear:both}.layui-layer-tabmain .layui-layer-tabli{display:none}.layui-layer-tabmain .layui-layer-tabli.xubox_tab_layer{display:block}.xubox_tabclose{position:absolute;right:10px;top:5px;cursor:pointer}.layui-layer-photos{-webkit-animation-duration:1s;animation-duration:1s;background:url(default/xubox_loading1.gif) center center no-repeat #000}.layui-layer-photos .layui-layer-content{overflow:hidden;text-align:center}.layui-layer-photos .layui-layer-phimg img{position:relative;width:100%;display:inline-block;*display:inline;*zoom:1;vertical-align:top}.layui-layer-imgbar,.layui-layer-imguide{display:none}.layui-layer-imgnext,.layui-layer-imgprev{position:absolute;top:50%;width:27px;_width:44px;height:44px;margin-top:-22px;outline:0;blr:expression(this.onFocus=this.blur())}.layui-layer-imgprev{left:10px;background-position:-5px -5px;_background-position:-70px -5px}.layui-layer-imgprev:hover{background-position:-33px -5px;_background-position:-120px -5px}.layui-layer-imgnext{right:10px;_right:8px;background-position:-5px -50px;_background-position:-70px -50px}.layui-layer-imgnext:hover{background-position:-33px -50px;_background-position:-120px -50px}.layui-layer-imgbar{position:absolute;left:0;bottom:0;width:100%;height:32px;line-height:32px;background-color:rgba(0,0,0,.8);background-color:#000\9;filter:Alpha(opacity=80);color:#fff;overflow:hidden;font-size:0}.layui-layer-imgtit *{display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:12px}.layui-layer-imgtit a{max-width:65%;overflow:hidden;color:#fff}.layui-layer-imgtit a:hover{color:#fff;text-decoration:underline}.layui-layer-imgtit em{padding-left:10px;font-style:normal} -------------------------------------------------------------------------------- /static/lib/select2/select2-spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/URLooker/web/362a939a5ff973fcea885ed1641bb660fec6c301/static/lib/select2/select2-spinner.gif -------------------------------------------------------------------------------- /static/lib/select2/select2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/URLooker/web/362a939a5ff973fcea885ed1641bb660fec6c301/static/lib/select2/select2.png -------------------------------------------------------------------------------- /static/lib/select2/select2x2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/URLooker/web/362a939a5ff973fcea885ed1641bb660fec6c301/static/lib/select2/select2x2.png -------------------------------------------------------------------------------- /store/mysql.go: -------------------------------------------------------------------------------- 1 | package store 2 | 3 | import ( 4 | "log" 5 | 6 | _ "github.com/go-sql-driver/mysql" 7 | "github.com/go-xorm/xorm" 8 | 9 | "github.com/urlooker/web/g" 10 | ) 11 | 12 | var Orm *xorm.Engine 13 | 14 | func InitMysql() { 15 | cfg := g.Config 16 | 17 | var err error 18 | Orm, err = xorm.NewEngine("mysql", cfg.Mysql.Addr) 19 | if err != nil { 20 | log.Fatalln("fail to connect mysql", err) 21 | } 22 | Orm.SetMaxIdleConns(cfg.Mysql.Idle) 23 | Orm.SetMaxOpenConns(cfg.Mysql.Max) 24 | 25 | } 26 | -------------------------------------------------------------------------------- /utils/dns.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "log" 7 | "strings" 8 | "time" 9 | 10 | "github.com/miekg/dns" 11 | 12 | "github.com/urlooker/web/g" 13 | ) 14 | 15 | func LookupIP(domain string, timeout int) ([]string, error) { 16 | var c dns.Client 17 | var err error 18 | ips := []string{} 19 | domain = strings.TrimRight(domain, ".") + "." 20 | c.DialTimeout = time.Duration(timeout) * time.Millisecond 21 | c.ReadTimeout = time.Duration(timeout) * time.Millisecond 22 | c.WriteTimeout = time.Duration(timeout) * time.Millisecond 23 | 24 | m := new(dns.Msg) 25 | m.SetQuestion(domain, dns.TypeA) 26 | 27 | ret, _, err := c.Exchange(m, "114.114.114.114:53") 28 | if err != nil { 29 | domain = strings.TrimRight(domain, ".") 30 | e := fmt.Sprintf("lookup error: %s, %s", domain, err.Error()) 31 | return ips, errors.New(e) 32 | } 33 | 34 | for _, i := range ret.Answer { 35 | result := strings.Split(i.String(), "\t") 36 | if result[3] == "A" && IsIP(result[4]) { 37 | ips = append(ips, result[4]) 38 | } 39 | } 40 | 41 | log.Println("ips:", ips) 42 | return ips, err 43 | } 44 | 45 | func InternalDns(domain string) []g.IpIdc { 46 | return []g.IpIdc{} 47 | } 48 | -------------------------------------------------------------------------------- /utils/falcon.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "log" 7 | "net/http" 8 | 9 | "github.com/astaxie/beego/httplib" 10 | 11 | "github.com/urlooker/web/g" 12 | ) 13 | 14 | var transport *http.Transport = &http.Transport{} 15 | 16 | type MetricValue struct { 17 | Endpoint string `json:"endpoint"` 18 | Metric string `json:"metric"` 19 | Tags string `json:"tags"` 20 | Value interface{} `json:"value"` 21 | Timestamp int64 `json:"timestamp"` 22 | Type string `json:"counterType"` 23 | Step int64 `json:"step"` 24 | } 25 | 26 | func PushFalcon(itemCheckedArray []*g.CheckResult, hostname string) { 27 | 28 | pushDatas := make([]*MetricValue, 0) 29 | for _, itemChecked := range itemCheckedArray { 30 | tags := fmt.Sprintf("ip=%s,domain=%s,creator=%s,from=%s", itemChecked.Ip, itemChecked.Domain, itemChecked.Creator, hostname) 31 | if len(itemChecked.Tag) > 0 { //补充用户自定义tag 32 | tags += "," + itemChecked.Tag 33 | } 34 | 35 | //url 状态 36 | data := getMetric(itemChecked, "url_status", tags, itemChecked.Status) 37 | pushDatas = append(pushDatas, &data) 38 | 39 | //url 响应时间 40 | data2 := getMetric(itemChecked, "url_resp_time", tags, int64(itemChecked.RespTime)) 41 | pushDatas = append(pushDatas, &data2) 42 | } 43 | 44 | err := push(pushDatas) 45 | if err != nil { 46 | log.Println("push error", err) 47 | } 48 | } 49 | 50 | func getMetric(item *g.CheckResult, metric, tags string, value int64) MetricValue { 51 | var data MetricValue 52 | data.Endpoint = fmt.Sprintf("url_%d", item.Sid) 53 | data.Timestamp = item.PushTime 54 | data.Metric = metric 55 | data.Type = "GAUGE" 56 | data.Step = int64(g.Config.Falcon.Interval) 57 | data.Tags = tags 58 | data.Value = value 59 | return data 60 | } 61 | 62 | func push(data []*MetricValue) error { 63 | d, err := json.Marshal(data) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | log.Println("to falcon: ", string(d)) 69 | 70 | _, err = httplib.Post(g.Config.Falcon.Addr).Body(d).String() 71 | if err != nil { 72 | return err 73 | } 74 | 75 | return nil 76 | } 77 | -------------------------------------------------------------------------------- /utils/ldap.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | 7 | "github.com/mmitton/ldap" 8 | ) 9 | 10 | func LdapBind(addr, 11 | BaseDN, 12 | BindDN, 13 | BindPasswd, 14 | UserField, 15 | user, 16 | password string) (sucess bool, err error) { 17 | 18 | filter := "(" + UserField + "=" + user + ")" 19 | conn, err := ldap.Dial("tcp", addr) 20 | 21 | if err != nil { 22 | return false, fmt.Errorf("dial ldap fail: %s", err.Error()) 23 | } 24 | 25 | defer conn.Close() 26 | if BindDN != "" { 27 | err = conn.Bind(BindDN, BindPasswd) 28 | } 29 | if err != nil { 30 | return false, fmt.Errorf("ldap Bind fail: %s", err.Error()) 31 | } 32 | search := ldap.NewSearchRequest( 33 | BaseDN, 34 | ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, 35 | filter, 36 | nil, 37 | nil) 38 | 39 | sr, err := conn.Search(search) 40 | 41 | if err != nil { 42 | return false, fmt.Errorf("ldap search fail: %s", err.Error()) 43 | } 44 | 45 | defer func() { 46 | if err := recover(); err != nil { 47 | log.Println("ERROR:", err) 48 | sucess = false 49 | } 50 | }() 51 | err = conn.Bind(sr.Entries[0].DN, password) 52 | return err == nil, err 53 | } 54 | 55 | func Ldapsearch(addr, 56 | BaseDN, 57 | BindDN, 58 | BindPasswd, 59 | UserField, 60 | user string, 61 | Attributes []string) (map[string]string, error) { 62 | 63 | filter := "(" + UserField + "=" + user + ")" 64 | conn, err := ldap.Dial("tcp", addr) 65 | 66 | if err != nil { 67 | return nil, fmt.Errorf("dial ldap fail: %s", err.Error()) 68 | } 69 | 70 | defer conn.Close() 71 | 72 | if BindDN != "" { 73 | err = conn.Bind(BindDN, BindPasswd) 74 | } 75 | if err != nil { 76 | return nil, fmt.Errorf("ldap Bind fail: %s", err.Error()) 77 | } 78 | search := ldap.NewSearchRequest( 79 | BaseDN, 80 | ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, 81 | filter, 82 | Attributes, 83 | nil) 84 | 85 | sr, err := conn.Search(search) 86 | defer func() { 87 | if err := recover(); err != nil { 88 | fmt.Println("ERROR:", err) 89 | } 90 | }() 91 | if err != nil { 92 | return nil, fmt.Errorf("ldap search fail: %s", err.Error()) 93 | } 94 | var UserAttributes map[string]string 95 | UserAttributes = make(map[string]string) 96 | 97 | userSn := sr.Entries[0].GetAttributeValue(Attributes[0]) 98 | userMail := sr.Entries[0].GetAttributeValue(Attributes[1]) 99 | userTel := sr.Entries[0].GetAttributeValue(Attributes[2]) 100 | 101 | UserAttributes["sn"] = userSn 102 | UserAttributes["telephoneNumber"] = userTel 103 | UserAttributes["mail"] = userMail 104 | return UserAttributes, err 105 | } 106 | -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2014 astaxie 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. -------------------------------------------------------------------------------- /vendor/github.com/astaxie/beego/httplib/README.md: -------------------------------------------------------------------------------- 1 | # httplib 2 | httplib is an libs help you to curl remote url. 3 | 4 | # How to use? 5 | 6 | ## GET 7 | you can use Get to crawl data. 8 | 9 | import "github.com/astaxie/beego/httplib" 10 | 11 | str, err := httplib.Get("http://beego.me/").String() 12 | if err != nil { 13 | // error 14 | } 15 | fmt.Println(str) 16 | 17 | ## POST 18 | POST data to remote url 19 | 20 | req := httplib.Post("http://beego.me/") 21 | req.Param("username","astaxie") 22 | req.Param("password","123456") 23 | str, err := req.String() 24 | if err != nil { 25 | // error 26 | } 27 | fmt.Println(str) 28 | 29 | ## Set timeout 30 | 31 | The default timeout is `60` seconds, function prototype: 32 | 33 | SetTimeout(connectTimeout, readWriteTimeout time.Duration) 34 | 35 | Exmaple: 36 | 37 | // GET 38 | httplib.Get("http://beego.me/").SetTimeout(100 * time.Second, 30 * time.Second) 39 | 40 | // POST 41 | httplib.Post("http://beego.me/").SetTimeout(100 * time.Second, 30 * time.Second) 42 | 43 | 44 | ## Debug 45 | 46 | If you want to debug the request info, set the debug on 47 | 48 | httplib.Get("http://beego.me/").Debug(true) 49 | 50 | ## Set HTTP Basic Auth 51 | 52 | str, err := Get("http://beego.me/").SetBasicAuth("user", "passwd").String() 53 | if err != nil { 54 | // error 55 | } 56 | fmt.Println(str) 57 | 58 | ## Set HTTPS 59 | 60 | If request url is https, You can set the client support TSL: 61 | 62 | httplib.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}) 63 | 64 | More info about the `tls.Config` please visit http://golang.org/pkg/crypto/tls/#Config 65 | 66 | ## Set HTTP Version 67 | 68 | some servers need to specify the protocol version of HTTP 69 | 70 | httplib.Get("http://beego.me/").SetProtocolVersion("HTTP/1.1") 71 | 72 | ## Set Cookie 73 | 74 | some http request need setcookie. So set it like this: 75 | 76 | cookie := &http.Cookie{} 77 | cookie.Name = "username" 78 | cookie.Value = "astaxie" 79 | httplib.Get("http://beego.me/").SetCookie(cookie) 80 | 81 | ## Upload file 82 | 83 | httplib support mutil file upload, use `req.PostFile()` 84 | 85 | req := httplib.Post("http://beego.me/") 86 | req.Param("username","astaxie") 87 | req.PostFile("uploadfile1", "httplib.pdf") 88 | str, err := req.String() 89 | if err != nil { 90 | // error 91 | } 92 | fmt.Println(str) 93 | 94 | 95 | See godoc for further documentation and examples. 96 | 97 | * [godoc.org/github.com/astaxie/beego/httplib](https://godoc.org/github.com/astaxie/beego/httplib) 98 | -------------------------------------------------------------------------------- /vendor/github.com/codegangsta/negroni/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Jeremy Saenz 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 | -------------------------------------------------------------------------------- /vendor/github.com/codegangsta/negroni/doc.go: -------------------------------------------------------------------------------- 1 | // Package negroni is an idiomatic approach to web middleware in Go. It is tiny, non-intrusive, and encourages use of net/http Handlers. 2 | // 3 | // If you like the idea of Martini, but you think it contains too much magic, then Negroni is a great fit. 4 | // 5 | // For a full guide visit http://github.com/codegangsta/negroni 6 | // 7 | // package main 8 | // 9 | // import ( 10 | // "github.com/codegangsta/negroni" 11 | // "net/http" 12 | // "fmt" 13 | // ) 14 | // 15 | // func main() { 16 | // mux := http.NewServeMux() 17 | // mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { 18 | // fmt.Fprintf(w, "Welcome to the home page!") 19 | // }) 20 | // 21 | // n := negroni.Classic() 22 | // n.UseHandler(mux) 23 | // n.Run(":3000") 24 | // } 25 | package negroni 26 | -------------------------------------------------------------------------------- /vendor/github.com/codegangsta/negroni/logger.go: -------------------------------------------------------------------------------- 1 | package negroni 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | "os" 7 | "time" 8 | ) 9 | 10 | // Logger is a middleware handler that logs the request as it goes in and the response as it goes out. 11 | type Logger struct { 12 | // Logger inherits from log.Logger used to log messages with the Logger middleware 13 | *log.Logger 14 | } 15 | 16 | // NewLogger returns a new Logger instance 17 | func NewLogger() *Logger { 18 | return &Logger{log.New(os.Stdout, "[negroni] ", 0)} 19 | } 20 | 21 | func (l *Logger) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { 22 | start := time.Now() 23 | l.Printf("Started %s %s", r.Method, r.URL.Path) 24 | 25 | next(rw, r) 26 | 27 | res := rw.(ResponseWriter) 28 | l.Printf("Completed %v %s in %v", res.Status(), http.StatusText(res.Status()), time.Since(start)) 29 | } 30 | -------------------------------------------------------------------------------- /vendor/github.com/codegangsta/negroni/recovery.go: -------------------------------------------------------------------------------- 1 | package negroni 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | "os" 8 | "runtime" 9 | ) 10 | 11 | // Recovery is a Negroni middleware that recovers from any panics and writes a 500 if there was one. 12 | type Recovery struct { 13 | Logger *log.Logger 14 | PrintStack bool 15 | StackAll bool 16 | StackSize int 17 | } 18 | 19 | // NewRecovery returns a new instance of Recovery 20 | func NewRecovery() *Recovery { 21 | return &Recovery{ 22 | Logger: log.New(os.Stdout, "[negroni] ", 0), 23 | PrintStack: true, 24 | StackAll: false, 25 | StackSize: 1024 * 8, 26 | } 27 | } 28 | 29 | func (rec *Recovery) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { 30 | defer func() { 31 | if err := recover(); err != nil { 32 | rw.WriteHeader(http.StatusInternalServerError) 33 | stack := make([]byte, rec.StackSize) 34 | stack = stack[:runtime.Stack(stack, rec.StackAll)] 35 | 36 | f := "PANIC: %s\n%s" 37 | rec.Logger.Printf(f, err, stack) 38 | 39 | if rec.PrintStack { 40 | fmt.Fprintf(rw, f, err, stack) 41 | } 42 | } 43 | }() 44 | 45 | next(rw, r) 46 | } 47 | -------------------------------------------------------------------------------- /vendor/github.com/codegangsta/negroni/static.go: -------------------------------------------------------------------------------- 1 | package negroni 2 | 3 | import ( 4 | "net/http" 5 | "path" 6 | "strings" 7 | ) 8 | 9 | // Static is a middleware handler that serves static files in the given directory/filesystem. 10 | type Static struct { 11 | // Dir is the directory to serve static files from 12 | Dir http.FileSystem 13 | // Prefix is the optional prefix used to serve the static directory content 14 | Prefix string 15 | // IndexFile defines which file to serve as index if it exists. 16 | IndexFile string 17 | } 18 | 19 | // NewStatic returns a new instance of Static 20 | func NewStatic(directory http.FileSystem) *Static { 21 | return &Static{ 22 | Dir: directory, 23 | Prefix: "", 24 | IndexFile: "index.html", 25 | } 26 | } 27 | 28 | func (s *Static) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { 29 | if r.Method != "GET" && r.Method != "HEAD" { 30 | next(rw, r) 31 | return 32 | } 33 | file := r.URL.Path 34 | // if we have a prefix, filter requests by stripping the prefix 35 | if s.Prefix != "" { 36 | if !strings.HasPrefix(file, s.Prefix) { 37 | next(rw, r) 38 | return 39 | } 40 | file = file[len(s.Prefix):] 41 | if file != "" && file[0] != '/' { 42 | next(rw, r) 43 | return 44 | } 45 | } 46 | f, err := s.Dir.Open(file) 47 | if err != nil { 48 | // discard the error? 49 | next(rw, r) 50 | return 51 | } 52 | defer f.Close() 53 | 54 | fi, err := f.Stat() 55 | if err != nil { 56 | next(rw, r) 57 | return 58 | } 59 | 60 | // try to serve index file 61 | if fi.IsDir() { 62 | // redirect if missing trailing slash 63 | if !strings.HasSuffix(r.URL.Path, "/") { 64 | http.Redirect(rw, r, r.URL.Path+"/", http.StatusFound) 65 | return 66 | } 67 | 68 | file = path.Join(file, s.IndexFile) 69 | f, err = s.Dir.Open(file) 70 | if err != nil { 71 | next(rw, r) 72 | return 73 | } 74 | defer f.Close() 75 | 76 | fi, err = f.Stat() 77 | if err != nil || fi.IsDir() { 78 | next(rw, r) 79 | return 80 | } 81 | } 82 | 83 | http.ServeContent(rw, r, file, fi.ModTime(), f) 84 | } 85 | -------------------------------------------------------------------------------- /vendor/github.com/go-sql-driver/mysql/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .DS_Store? 3 | ._* 4 | .Spotlight-V100 5 | .Trashes 6 | Icon? 7 | ehthumbs.db 8 | Thumbs.db 9 | -------------------------------------------------------------------------------- /vendor/github.com/go-sql-driver/mysql/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: go 3 | go: 4 | - 1.2 5 | - 1.3 6 | - 1.4 7 | - 1.5 8 | - 1.6 9 | - tip 10 | 11 | before_script: 12 | - mysql -e 'create database gotest;' 13 | -------------------------------------------------------------------------------- /vendor/github.com/go-sql-driver/mysql/AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the official list of Go-MySQL-Driver authors for copyright purposes. 2 | 3 | # If you are submitting a patch, please add your name or the name of the 4 | # organization which holds the copyright to this list in alphabetical order. 5 | 6 | # Names should be added to this file as 7 | # Name 8 | # The email address is not required for organizations. 9 | # Please keep the list sorted. 10 | 11 | 12 | # Individual Persons 13 | 14 | Aaron Hopkins 15 | Arne Hormann 16 | Carlos Nieto 17 | Chris Moos 18 | Daniel Nichter 19 | Daniël van Eeden 20 | DisposaBoy 21 | Frederick Mayle 22 | Gustavo Kristic 23 | Hanno Braun 24 | Henri Yandell 25 | Hirotaka Yamamoto 26 | INADA Naoki 27 | James Harr 28 | Jian Zhen 29 | Joshua Prunier 30 | Julien Lefevre 31 | Julien Schmidt 32 | Kamil Dziedzic 33 | Kevin Malachowski 34 | Leonardo YongUk Kim 35 | Luca Looz 36 | Lucas Liu 37 | Luke Scott 38 | Michael Woolnough 39 | Nicola Peduzzi 40 | Paul Bonser 41 | Runrioter Wung 42 | Soroush Pour 43 | Stan Putrya 44 | Stanley Gunawan 45 | Xiaobing Jiang 46 | Xiuming Chen 47 | 48 | # Organizations 49 | 50 | Barracuda Networks, Inc. 51 | Google Inc. 52 | Stripe Inc. 53 | -------------------------------------------------------------------------------- /vendor/github.com/go-sql-driver/mysql/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | ## Reporting Issues 4 | 5 | Before creating a new Issue, please check first if a similar Issue [already exists](https://github.com/go-sql-driver/mysql/issues?state=open) or was [recently closed](https://github.com/go-sql-driver/mysql/issues?direction=desc&page=1&sort=updated&state=closed). 6 | 7 | ## Contributing Code 8 | 9 | By contributing to this project, you share your code under the Mozilla Public License 2, as specified in the LICENSE file. 10 | Don't forget to add yourself to the AUTHORS file. 11 | 12 | ### Code Review 13 | 14 | Everyone is invited to review and comment on pull requests. 15 | If it looks fine to you, comment with "LGTM" (Looks good to me). 16 | 17 | If changes are required, notice the reviewers with "PTAL" (Please take another look) after committing the fixes. 18 | 19 | Before merging the Pull Request, at least one [team member](https://github.com/go-sql-driver?tab=members) must have commented with "LGTM". 20 | 21 | ## Development Ideas 22 | 23 | If you are looking for ideas for code contributions, please check our [Development Ideas](https://github.com/go-sql-driver/mysql/wiki/Development-Ideas) Wiki page. 24 | -------------------------------------------------------------------------------- /vendor/github.com/go-sql-driver/mysql/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Issue description 2 | Tell us what should happen and what happens instead 3 | 4 | ### Example code 5 | ```go 6 | If possible, please enter some example code here to reproduce the issue. 7 | ``` 8 | 9 | ### Error log 10 | ``` 11 | If you have an error log, please paste it here. 12 | ``` 13 | 14 | ### Configuration 15 | *Driver version (or git SHA):* 16 | 17 | *Go version:* run `go version` in your console 18 | 19 | *Server version:* E.g. MySQL 5.6, MariaDB 10.0.20 20 | 21 | *Server OS:* E.g. Debian 8.1 (Jessie), Windows 10 22 | -------------------------------------------------------------------------------- /vendor/github.com/go-sql-driver/mysql/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Description 2 | Please explain the changes you made here. 3 | 4 | ### Checklist 5 | - [ ] Code compiles correctly 6 | - [ ] Created tests which fail without the change (if possible) 7 | - [ ] All tests passing 8 | - [ ] Extended the README / documentation, if necessary 9 | - [ ] Added myself / the copyright holder to the AUTHORS file 10 | -------------------------------------------------------------------------------- /vendor/github.com/go-sql-driver/mysql/appengine.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | // +build appengine 10 | 11 | package mysql 12 | 13 | import ( 14 | "appengine/cloudsql" 15 | ) 16 | 17 | func init() { 18 | RegisterDial("cloudsql", cloudsql.Dial) 19 | } 20 | -------------------------------------------------------------------------------- /vendor/github.com/go-sql-driver/mysql/result.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | package mysql 10 | 11 | type mysqlResult struct { 12 | affectedRows int64 13 | insertId int64 14 | } 15 | 16 | func (res *mysqlResult) LastInsertId() (int64, error) { 17 | return res.insertId, nil 18 | } 19 | 20 | func (res *mysqlResult) RowsAffected() (int64, error) { 21 | return res.affectedRows, nil 22 | } 23 | -------------------------------------------------------------------------------- /vendor/github.com/go-sql-driver/mysql/rows.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | package mysql 10 | 11 | import ( 12 | "database/sql/driver" 13 | "io" 14 | ) 15 | 16 | type mysqlField struct { 17 | tableName string 18 | name string 19 | flags fieldFlag 20 | fieldType byte 21 | decimals byte 22 | } 23 | 24 | type mysqlRows struct { 25 | mc *mysqlConn 26 | columns []mysqlField 27 | } 28 | 29 | type binaryRows struct { 30 | mysqlRows 31 | } 32 | 33 | type textRows struct { 34 | mysqlRows 35 | } 36 | 37 | type emptyRows struct{} 38 | 39 | func (rows *mysqlRows) Columns() []string { 40 | columns := make([]string, len(rows.columns)) 41 | if rows.mc != nil && rows.mc.cfg.ColumnsWithAlias { 42 | for i := range columns { 43 | if tableName := rows.columns[i].tableName; len(tableName) > 0 { 44 | columns[i] = tableName + "." + rows.columns[i].name 45 | } else { 46 | columns[i] = rows.columns[i].name 47 | } 48 | } 49 | } else { 50 | for i := range columns { 51 | columns[i] = rows.columns[i].name 52 | } 53 | } 54 | return columns 55 | } 56 | 57 | func (rows *mysqlRows) Close() error { 58 | mc := rows.mc 59 | if mc == nil { 60 | return nil 61 | } 62 | if mc.netConn == nil { 63 | return ErrInvalidConn 64 | } 65 | 66 | // Remove unread packets from stream 67 | err := mc.readUntilEOF() 68 | if err == nil { 69 | if err = mc.discardResults(); err != nil { 70 | return err 71 | } 72 | } 73 | 74 | rows.mc = nil 75 | return err 76 | } 77 | 78 | func (rows *binaryRows) Next(dest []driver.Value) error { 79 | if mc := rows.mc; mc != nil { 80 | if mc.netConn == nil { 81 | return ErrInvalidConn 82 | } 83 | 84 | // Fetch next row from stream 85 | return rows.readRow(dest) 86 | } 87 | return io.EOF 88 | } 89 | 90 | func (rows *textRows) Next(dest []driver.Value) error { 91 | if mc := rows.mc; mc != nil { 92 | if mc.netConn == nil { 93 | return ErrInvalidConn 94 | } 95 | 96 | // Fetch next row from stream 97 | return rows.readRow(dest) 98 | } 99 | return io.EOF 100 | } 101 | 102 | func (rows emptyRows) Columns() []string { 103 | return nil 104 | } 105 | 106 | func (rows emptyRows) Close() error { 107 | return nil 108 | } 109 | 110 | func (rows emptyRows) Next(dest []driver.Value) error { 111 | return io.EOF 112 | } 113 | -------------------------------------------------------------------------------- /vendor/github.com/go-sql-driver/mysql/transaction.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | package mysql 10 | 11 | type mysqlTx struct { 12 | mc *mysqlConn 13 | } 14 | 15 | func (tx *mysqlTx) Commit() (err error) { 16 | if tx.mc == nil || tx.mc.netConn == nil { 17 | return ErrInvalidConn 18 | } 19 | err = tx.mc.exec("COMMIT") 20 | tx.mc = nil 21 | return 22 | } 23 | 24 | func (tx *mysqlTx) Rollback() (err error) { 25 | if tx.mc == nil || tx.mc.netConn == nil { 26 | return ErrInvalidConn 27 | } 28 | err = tx.mc.exec("ROLLBACK") 29 | tx.mc = nil 30 | return 31 | } 32 | -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/core/.gitignore: -------------------------------------------------------------------------------- 1 | *.db 2 | -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/core/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 - 2015 Lunny Xiao 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the {organization} nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (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/go-xorm/core/README.md: -------------------------------------------------------------------------------- 1 | Core is a lightweight wrapper of sql.DB. 2 | 3 | # Open 4 | ```Go 5 | db, _ := core.Open(db, connstr) 6 | ``` 7 | 8 | # SetMapper 9 | ```Go 10 | db.SetMapper(SameMapper()) 11 | ``` 12 | 13 | ## Scan usage 14 | 15 | ### Scan 16 | ```Go 17 | rows, _ := db.Query() 18 | for rows.Next() { 19 | rows.Scan() 20 | } 21 | ``` 22 | 23 | ### ScanMap 24 | ```Go 25 | rows, _ := db.Query() 26 | for rows.Next() { 27 | rows.ScanMap() 28 | ``` 29 | 30 | ### ScanSlice 31 | 32 | You can use `[]string`, `[][]byte`, `[]interface{}`, `[]*string`, `[]sql.NullString` to ScanSclice. Notice, slice's length should be equal or less than select columns. 33 | 34 | ```Go 35 | rows, _ := db.Query() 36 | cols, _ := rows.Columns() 37 | for rows.Next() { 38 | var s = make([]string, len(cols)) 39 | rows.ScanSlice(&s) 40 | } 41 | ``` 42 | 43 | ```Go 44 | rows, _ := db.Query() 45 | cols, _ := rows.Columns() 46 | for rows.Next() { 47 | var s = make([]*string, len(cols)) 48 | rows.ScanSlice(&s) 49 | } 50 | ``` 51 | 52 | ### ScanStruct 53 | ```Go 54 | rows, _ := db.Query() 55 | for rows.Next() { 56 | rows.ScanStructByName() 57 | rows.ScanStructByIndex() 58 | } 59 | ``` 60 | 61 | ## Query usage 62 | ```Go 63 | rows, err := db.Query("select * from table where name = ?", name) 64 | 65 | user = User{ 66 | Name:"lunny", 67 | } 68 | rows, err := db.QueryStruct("select * from table where name = ?Name", 69 | &user) 70 | 71 | var user = map[string]interface{}{ 72 | "name": "lunny", 73 | } 74 | rows, err = db.QueryMap("select * from table where name = ?name", 75 | &user) 76 | ``` 77 | 78 | ## QueryRow usage 79 | ```Go 80 | row := db.QueryRow("select * from table where name = ?", name) 81 | 82 | user = User{ 83 | Name:"lunny", 84 | } 85 | row := db.QueryRowStruct("select * from table where name = ?Name", 86 | &user) 87 | 88 | var user = map[string]interface{}{ 89 | "name": "lunny", 90 | } 91 | row = db.QueryRowMap("select * from table where name = ?name", 92 | &user) 93 | ``` 94 | 95 | ## Exec usage 96 | ```Go 97 | db.Exec("insert into user (`name`, title, age, alias, nick_name,created) values (?,?,?,?,?,?)", name, title, age, alias...) 98 | 99 | user = User{ 100 | Name:"lunny", 101 | Title:"test", 102 | Age: 18, 103 | } 104 | result, err = db.ExecStruct("insert into user (`name`, title, age, alias, nick_name,created) values (?Name,?Title,?Age,?Alias,?NickName,?Created)", 105 | &user) 106 | 107 | var user = map[string]interface{}{ 108 | "Name": "lunny", 109 | "Title": "test", 110 | "Age": 18, 111 | } 112 | result, err = db.ExecMap("insert into user (`name`, title, age, alias, nick_name,created) values (?Name,?Title,?Age,?Alias,?NickName,?Created)", 113 | &user) 114 | ``` -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/core/benchmark.sh: -------------------------------------------------------------------------------- 1 | go test -v -bench=. -run=XXX 2 | -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/core/cache.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "time" 7 | "bytes" 8 | "encoding/gob" 9 | ) 10 | 11 | const ( 12 | // default cache expired time 13 | CacheExpired = 60 * time.Minute 14 | // not use now 15 | CacheMaxMemory = 256 16 | // evey ten minutes to clear all expired nodes 17 | CacheGcInterval = 10 * time.Minute 18 | // each time when gc to removed max nodes 19 | CacheGcMaxRemoved = 20 20 | ) 21 | 22 | var ( 23 | ErrCacheMiss = errors.New("xorm/cache: key not found.") 24 | ErrNotStored = errors.New("xorm/cache: not stored.") 25 | ) 26 | 27 | // CacheStore is a interface to store cache 28 | type CacheStore interface { 29 | // key is primary key or composite primary key 30 | // value is struct's pointer 31 | // key format : -p--... 32 | Put(key string, value interface{}) error 33 | Get(key string) (interface{}, error) 34 | Del(key string) error 35 | } 36 | 37 | // Cacher is an interface to provide cache 38 | // id format : u--... 39 | type Cacher interface { 40 | GetIds(tableName, sql string) interface{} 41 | GetBean(tableName string, id string) interface{} 42 | PutIds(tableName, sql string, ids interface{}) 43 | PutBean(tableName string, id string, obj interface{}) 44 | DelIds(tableName, sql string) 45 | DelBean(tableName string, id string) 46 | ClearIds(tableName string) 47 | ClearBeans(tableName string) 48 | } 49 | 50 | func encodeIds(ids []PK) (string, error) { 51 | buf := new(bytes.Buffer) 52 | enc := gob.NewEncoder(buf) 53 | err := enc.Encode(ids) 54 | 55 | return buf.String(), err 56 | } 57 | 58 | 59 | func decodeIds(s string) ([]PK, error) { 60 | pks := make([]PK, 0) 61 | 62 | dec := gob.NewDecoder(bytes.NewBufferString(s)) 63 | err := dec.Decode(&pks) 64 | 65 | return pks, err 66 | } 67 | 68 | func GetCacheSql(m Cacher, tableName, sql string, args interface{}) ([]PK, error) { 69 | bytes := m.GetIds(tableName, GenSqlKey(sql, args)) 70 | if bytes == nil { 71 | return nil, errors.New("Not Exist") 72 | } 73 | return decodeIds(bytes.(string)) 74 | } 75 | 76 | func PutCacheSql(m Cacher, ids []PK, tableName, sql string, args interface{}) error { 77 | bytes, err := encodeIds(ids) 78 | if err != nil { 79 | return err 80 | } 81 | m.PutIds(tableName, GenSqlKey(sql, args), bytes) 82 | return nil 83 | } 84 | 85 | func GenSqlKey(sql string, args interface{}) string { 86 | return fmt.Sprintf("%v-%v", sql, args) 87 | } 88 | -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/core/converstion.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | // Conversion is an interface. A type implements Conversion will according 4 | // the custom method to fill into database and retrieve from database. 5 | type Conversion interface { 6 | FromDB([]byte) error 7 | ToDB() ([]byte, error) 8 | } 9 | -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/core/driver.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type Driver interface { 4 | Parse(string, string) (*Uri, error) 5 | } 6 | 7 | var ( 8 | drivers = map[string]Driver{} 9 | ) 10 | 11 | func RegisterDriver(driverName string, driver Driver) { 12 | if driver == nil { 13 | panic("core: Register driver is nil") 14 | } 15 | if _, dup := drivers[driverName]; dup { 16 | panic("core: Register called twice for driver " + driverName) 17 | } 18 | drivers[driverName] = driver 19 | } 20 | 21 | func QueryDriver(driverName string) Driver { 22 | return drivers[driverName] 23 | } 24 | 25 | func RegisteredDriverSize() int { 26 | return len(drivers) 27 | } 28 | -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/core/error.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import "errors" 4 | 5 | var ( 6 | ErrNoMapPointer = errors.New("mp should be a map's pointer") 7 | ErrNoStructPointer = errors.New("mp should be a struct's pointer") 8 | ) 9 | -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/core/filter.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | // Filter is an interface to filter SQL 9 | type Filter interface { 10 | Do(sql string, dialect Dialect, table *Table) string 11 | } 12 | 13 | // QuoteFilter filter SQL replace ` to database's own quote character 14 | type QuoteFilter struct { 15 | } 16 | 17 | func (s *QuoteFilter) Do(sql string, dialect Dialect, table *Table) string { 18 | return strings.Replace(sql, "`", dialect.QuoteStr(), -1) 19 | } 20 | 21 | // IdFilter filter SQL replace (id) to primary key column name 22 | type IdFilter struct { 23 | } 24 | 25 | type Quoter struct { 26 | dialect Dialect 27 | } 28 | 29 | func NewQuoter(dialect Dialect) *Quoter { 30 | return &Quoter{dialect} 31 | } 32 | 33 | func (q *Quoter) Quote(content string) string { 34 | return q.dialect.QuoteStr() + content + q.dialect.QuoteStr() 35 | } 36 | 37 | func (i *IdFilter) Do(sql string, dialect Dialect, table *Table) string { 38 | quoter := NewQuoter(dialect) 39 | if table != nil && len(table.PrimaryKeys) == 1 { 40 | sql = strings.Replace(sql, "`(id)`", quoter.Quote(table.PrimaryKeys[0]), -1) 41 | sql = strings.Replace(sql, quoter.Quote("(id)"), quoter.Quote(table.PrimaryKeys[0]), -1) 42 | return strings.Replace(sql, "(id)", quoter.Quote(table.PrimaryKeys[0]), -1) 43 | } 44 | return sql 45 | } 46 | 47 | // SeqFilter filter SQL replace ?, ? ... to $1, $2 ... 48 | type SeqFilter struct { 49 | Prefix string 50 | Start int 51 | } 52 | 53 | func (s *SeqFilter) Do(sql string, dialect Dialect, table *Table) string { 54 | segs := strings.Split(sql, "?") 55 | size := len(segs) 56 | res := "" 57 | for i, c := range segs { 58 | if i < size-1 { 59 | res += c + fmt.Sprintf("%s%v", s.Prefix, i+s.Start) 60 | } 61 | } 62 | res += segs[size-1] 63 | return res 64 | } 65 | -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/core/ilogger.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | type LogLevel int 4 | 5 | const ( 6 | // !nashtsai! following level also match syslog.Priority value 7 | LOG_DEBUG LogLevel = iota 8 | LOG_INFO 9 | LOG_WARNING 10 | LOG_ERR 11 | LOG_OFF 12 | LOG_UNKNOWN 13 | ) 14 | 15 | // logger interface 16 | type ILogger interface { 17 | Debug(v ...interface{}) 18 | Debugf(format string, v ...interface{}) 19 | Error(v ...interface{}) 20 | Errorf(format string, v ...interface{}) 21 | Info(v ...interface{}) 22 | Infof(format string, v ...interface{}) 23 | Warn(v ...interface{}) 24 | Warnf(format string, v ...interface{}) 25 | 26 | Level() LogLevel 27 | SetLevel(l LogLevel) 28 | 29 | ShowSQL(show ...bool) 30 | IsShowSQL() bool 31 | } 32 | -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/core/index.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | "strings" 7 | ) 8 | 9 | const ( 10 | IndexType = iota + 1 11 | UniqueType 12 | ) 13 | 14 | // database index 15 | type Index struct { 16 | IsRegular bool 17 | Name string 18 | Type int 19 | Cols []string 20 | } 21 | 22 | func (index *Index) XName(tableName string) string { 23 | if !strings.HasPrefix(index.Name, "UQE_") && 24 | !strings.HasPrefix(index.Name, "IDX_") { 25 | if index.Type == UniqueType { 26 | return fmt.Sprintf("UQE_%v_%v", tableName, index.Name) 27 | } 28 | return fmt.Sprintf("IDX_%v_%v", tableName, index.Name) 29 | } 30 | return index.Name 31 | } 32 | 33 | // add columns which will be composite index 34 | func (index *Index) AddColumn(cols ...string) { 35 | for _, col := range cols { 36 | index.Cols = append(index.Cols, col) 37 | } 38 | } 39 | 40 | func (index *Index) Equal(dst *Index) bool { 41 | if index.Type != dst.Type { 42 | return false 43 | } 44 | if len(index.Cols) != len(dst.Cols) { 45 | return false 46 | } 47 | sort.StringSlice(index.Cols).Sort() 48 | sort.StringSlice(dst.Cols).Sort() 49 | 50 | for i := 0; i < len(index.Cols); i++ { 51 | if index.Cols[i] != dst.Cols[i] { 52 | return false 53 | } 54 | } 55 | return true 56 | } 57 | 58 | // new an index 59 | func NewIndex(name string, indexType int) *Index { 60 | return &Index{true, name, indexType, make([]string, 0)} 61 | } 62 | -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/core/pk.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "bytes" 5 | "encoding/gob" 6 | ) 7 | 8 | type PK []interface{} 9 | 10 | func NewPK(pks ...interface{}) *PK { 11 | p := PK(pks) 12 | return &p 13 | } 14 | 15 | func (p *PK) ToString() (string, error) { 16 | buf := new(bytes.Buffer) 17 | enc := gob.NewEncoder(buf) 18 | err := enc.Encode(*p) 19 | return buf.String(), err 20 | } 21 | 22 | func (p *PK) FromString(content string) error { 23 | dec := gob.NewDecoder(bytes.NewBufferString(content)) 24 | err := dec.Decode(p) 25 | return err 26 | } 27 | -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/core/scan.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "database/sql/driver" 5 | "fmt" 6 | "time" 7 | ) 8 | 9 | type NullTime time.Time 10 | 11 | var ( 12 | _ driver.Valuer = NullTime{} 13 | ) 14 | 15 | func (ns *NullTime) Scan(value interface{}) error { 16 | if value == nil { 17 | return nil 18 | } 19 | return convertTime(ns, value) 20 | } 21 | 22 | // Value implements the driver Valuer interface. 23 | func (ns NullTime) Value() (driver.Value, error) { 24 | if (time.Time)(ns).IsZero() { 25 | return nil, nil 26 | } 27 | return (time.Time)(ns).Format("2006-01-02 15:04:05"), nil 28 | } 29 | 30 | func convertTime(dest *NullTime, src interface{}) error { 31 | // Common cases, without reflect. 32 | switch s := src.(type) { 33 | case string: 34 | t, err := time.Parse("2006-01-02 15:04:05", s) 35 | if err != nil { 36 | return err 37 | } 38 | *dest = NullTime(t) 39 | return nil 40 | case []uint8: 41 | t, err := time.Parse("2006-01-02 15:04:05", string(s)) 42 | if err != nil { 43 | return err 44 | } 45 | *dest = NullTime(t) 46 | return nil 47 | case nil: 48 | default: 49 | return fmt.Errorf("unsupported driver -> Scan pair: %T -> %T", src, dest) 50 | } 51 | return nil 52 | } 53 | -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/xorm/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | *.db 6 | 7 | # Folders 8 | _obj 9 | _test 10 | 11 | # Architecture specific extensions/prefixes 12 | *.[568vq] 13 | [568vq].out 14 | 15 | *.cgo1.go 16 | *.cgo2.c 17 | _cgo_defun.c 18 | _cgo_gotypes.go 19 | _cgo_export.* 20 | 21 | _testmain.go 22 | 23 | *.exe 24 | vendor 25 | 26 | *.log 27 | .vendor 28 | temp_test.go 29 | -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/xorm/.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "docs/manual-en-US"] 2 | path = docs/manual-en-US 3 | url = https://github.com/go-xorm/manual-en-US.git 4 | [submodule "docs/manual-zh-CN"] 5 | path = docs/manual-zh-CN 6 | url = https://github.com/go-xorm/manual-zh-CN.git 7 | -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/xorm/.gopmfile: -------------------------------------------------------------------------------- 1 | [target] 2 | path = github.com/go-xorm/xorm -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/xorm/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing to xorm 2 | 3 | `xorm` has a backlog of [pull requests](https://help.github.com/articles/using-pull-requests), but contributions are still very 4 | much welcome. You can help with patch review, submitting bug reports, 5 | or adding new functionality. There is no formal style guide, but 6 | please conform to the style of existing code and general Go formatting 7 | conventions when submitting patches. 8 | 9 | * [fork a repo](https://help.github.com/articles/fork-a-repo) 10 | * [creating a pull request ](https://help.github.com/articles/creating-a-pull-request) 11 | 12 | ### Sign your codes with comments 13 | ``` 14 | // !! your comments 15 | 16 | e.g., 17 | 18 | // !lunny! this is comments made by lunny 19 | ``` 20 | 21 | ### Patch review 22 | 23 | Help review existing open [pull requests](https://help.github.com/articles/using-pull-requests) by commenting on the code or 24 | proposed functionality. 25 | 26 | ### Bug reports 27 | 28 | We appreciate any bug reports, but especially ones with self-contained 29 | (doesn't depend on code outside of xorm), minimal (can't be simplified 30 | further) test cases. It's especially helpful if you can submit a pull 31 | request with just the failing test case (you'll probably want to 32 | pattern it after the tests in 33 | [base.go](https://github.com/go-xorm/tests/blob/master/base.go) AND 34 | [benchmark.go](https://github.com/go-xorm/tests/blob/master/benchmark.go). 35 | 36 | If you implements a new database interface, you maybe need to add a _test.go file. 37 | For example, [mysql_test.go](https://github.com/go-xorm/tests/blob/master/mysql/mysql_test.go) 38 | 39 | ### New functionality 40 | 41 | There are a number of pending patches for new functionality, so 42 | additional feature patches will take a while to merge. Still, patches 43 | are generally reviewed based on usefulness and complexity in addition 44 | to time-in-queue, so if you have a knockout idea, take a shot. Feel 45 | free to open an issue discussion your proposed patch beforehand. 46 | -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/xorm/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 - 2015 The Xorm Authors 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the {organization} nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (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/go-xorm/xorm/VERSION: -------------------------------------------------------------------------------- 1 | xorm v0.5.3.0407 2 | -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/xorm/error.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Xorm 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 xorm 6 | 7 | import ( 8 | "errors" 9 | ) 10 | 11 | var ( 12 | ErrParamsType error = errors.New("Params type error") 13 | ErrTableNotFound error = errors.New("Not found table") 14 | ErrUnSupportedType error = errors.New("Unsupported type error") 15 | ErrNotExist error = errors.New("Not exist error") 16 | ErrCacheFailed error = errors.New("Cache failed") 17 | ErrNeedDeletedCond error = errors.New("Delete need at least one condition") 18 | ErrNotImplemented error = errors.New("Not implemented.") 19 | ) 20 | -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/xorm/gen_reserved.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ -f $1 ];then 3 | cat $1| awk '{printf("\""$1"\":true,\n")}' 4 | else 5 | echo "argument $1 if not a file!" 6 | fi 7 | -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/xorm/goracle_driver.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Xorm 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 xorm 6 | 7 | import ( 8 | "errors" 9 | "regexp" 10 | 11 | "github.com/go-xorm/core" 12 | ) 13 | 14 | // func init() { 15 | // core.RegisterDriver("goracle", &goracleDriver{}) 16 | // } 17 | 18 | type goracleDriver struct { 19 | } 20 | 21 | func (cfg *goracleDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) { 22 | db := &core.Uri{DbType: core.ORACLE} 23 | dsnPattern := regexp.MustCompile( 24 | `^(?:(?P.*?)(?::(?P.*))?@)?` + // [user[:password]@] 25 | `(?:(?P[^\(]*)(?:\((?P[^\)]*)\))?)?` + // [net[(addr)]] 26 | `\/(?P.*?)` + // /dbname 27 | `(?:\?(?P[^\?]*))?$`) // [?param1=value1¶mN=valueN] 28 | matches := dsnPattern.FindStringSubmatch(dataSourceName) 29 | //tlsConfigRegister := make(map[string]*tls.Config) 30 | names := dsnPattern.SubexpNames() 31 | 32 | for i, match := range matches { 33 | switch names[i] { 34 | case "dbname": 35 | db.DbName = match 36 | } 37 | } 38 | if db.DbName == "" { 39 | return nil, errors.New("dbname is empty") 40 | } 41 | return db, nil 42 | } 43 | -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/xorm/memory_store.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Xorm 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 xorm 6 | 7 | import ( 8 | "sync" 9 | 10 | "github.com/go-xorm/core" 11 | ) 12 | 13 | var _ core.CacheStore = NewMemoryStore() 14 | 15 | // memory store 16 | type MemoryStore struct { 17 | store map[interface{}]interface{} 18 | mutex sync.RWMutex 19 | } 20 | 21 | func NewMemoryStore() *MemoryStore { 22 | return &MemoryStore{store: make(map[interface{}]interface{})} 23 | } 24 | 25 | func (s *MemoryStore) Put(key string, value interface{}) error { 26 | s.mutex.Lock() 27 | defer s.mutex.Unlock() 28 | s.store[key] = value 29 | return nil 30 | } 31 | 32 | func (s *MemoryStore) Get(key string) (interface{}, error) { 33 | s.mutex.RLock() 34 | defer s.mutex.RUnlock() 35 | if v, ok := s.store[key]; ok { 36 | return v, nil 37 | } 38 | 39 | return nil, ErrNotExist 40 | } 41 | 42 | func (s *MemoryStore) Del(key string) error { 43 | s.mutex.Lock() 44 | defer s.mutex.Unlock() 45 | delete(s.store, key) 46 | return nil 47 | } 48 | -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/xorm/mymysql_driver.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Xorm 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 xorm 6 | 7 | import ( 8 | "errors" 9 | "strings" 10 | "time" 11 | 12 | "github.com/go-xorm/core" 13 | ) 14 | 15 | // func init() { 16 | // core.RegisterDriver("mymysql", &mymysqlDriver{}) 17 | // } 18 | 19 | type mymysqlDriver struct { 20 | } 21 | 22 | func (p *mymysqlDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) { 23 | db := &core.Uri{DbType: core.MYSQL} 24 | 25 | pd := strings.SplitN(dataSourceName, "*", 2) 26 | if len(pd) == 2 { 27 | // Parse protocol part of URI 28 | p := strings.SplitN(pd[0], ":", 2) 29 | if len(p) != 2 { 30 | return nil, errors.New("Wrong protocol part of URI") 31 | } 32 | db.Proto = p[0] 33 | options := strings.Split(p[1], ",") 34 | db.Raddr = options[0] 35 | for _, o := range options[1:] { 36 | kv := strings.SplitN(o, "=", 2) 37 | var k, v string 38 | if len(kv) == 2 { 39 | k, v = kv[0], kv[1] 40 | } else { 41 | k, v = o, "true" 42 | } 43 | switch k { 44 | case "laddr": 45 | db.Laddr = v 46 | case "timeout": 47 | to, err := time.ParseDuration(v) 48 | if err != nil { 49 | return nil, err 50 | } 51 | db.Timeout = to 52 | default: 53 | return nil, errors.New("Unknown option: " + k) 54 | } 55 | } 56 | // Remove protocol part 57 | pd = pd[1:] 58 | } 59 | // Parse database part of URI 60 | dup := strings.SplitN(pd[0], "/", 3) 61 | if len(dup) != 3 { 62 | return nil, errors.New("Wrong database part of URI") 63 | } 64 | db.DbName = dup[0] 65 | db.User = dup[1] 66 | db.Passwd = dup[2] 67 | 68 | return db, nil 69 | } 70 | -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/xorm/mysql_driver.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Xorm 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 xorm 6 | 7 | import ( 8 | "regexp" 9 | "strings" 10 | 11 | "github.com/go-xorm/core" 12 | ) 13 | 14 | // func init() { 15 | // core.RegisterDriver("mysql", &mysqlDriver{}) 16 | // } 17 | 18 | type mysqlDriver struct { 19 | } 20 | 21 | func (p *mysqlDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) { 22 | dsnPattern := regexp.MustCompile( 23 | `^(?:(?P.*?)(?::(?P.*))?@)?` + // [user[:password]@] 24 | `(?:(?P[^\(]*)(?:\((?P[^\)]*)\))?)?` + // [net[(addr)]] 25 | `\/(?P.*?)` + // /dbname 26 | `(?:\?(?P[^\?]*))?$`) // [?param1=value1¶mN=valueN] 27 | matches := dsnPattern.FindStringSubmatch(dataSourceName) 28 | //tlsConfigRegister := make(map[string]*tls.Config) 29 | names := dsnPattern.SubexpNames() 30 | 31 | uri := &core.Uri{DbType: core.MYSQL} 32 | 33 | for i, match := range matches { 34 | switch names[i] { 35 | case "dbname": 36 | uri.DbName = match 37 | case "params": 38 | if len(match) > 0 { 39 | kvs := strings.Split(match, "&") 40 | for _, kv := range kvs { 41 | splits := strings.Split(kv, "=") 42 | if len(splits) == 2 { 43 | switch splits[0] { 44 | case "charset": 45 | uri.Charset = splits[1] 46 | } 47 | } 48 | } 49 | } 50 | 51 | } 52 | } 53 | return uri, nil 54 | } 55 | -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/xorm/oci8_driver.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Xorm 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 xorm 6 | 7 | import ( 8 | "errors" 9 | "regexp" 10 | 11 | "github.com/go-xorm/core" 12 | ) 13 | 14 | // func init() { 15 | // core.RegisterDriver("oci8", &oci8Driver{}) 16 | // } 17 | 18 | type oci8Driver struct { 19 | } 20 | 21 | //dataSourceName=user/password@ipv4:port/dbname 22 | //dataSourceName=user/password@[ipv6]:port/dbname 23 | func (p *oci8Driver) Parse(driverName, dataSourceName string) (*core.Uri, error) { 24 | db := &core.Uri{DbType: core.ORACLE} 25 | dsnPattern := regexp.MustCompile( 26 | `^(?P.*)\/(?P.*)@` + // user:password@ 27 | `(?P.*)` + // ip:port 28 | `\/(?P.*)`) // dbname 29 | matches := dsnPattern.FindStringSubmatch(dataSourceName) 30 | names := dsnPattern.SubexpNames() 31 | for i, match := range matches { 32 | switch names[i] { 33 | case "dbname": 34 | db.DbName = match 35 | } 36 | } 37 | if db.DbName == "" { 38 | return nil, errors.New("dbname is empty") 39 | } 40 | return db, nil 41 | } 42 | -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/xorm/odbc_driver.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Xorm 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 xorm 6 | 7 | import ( 8 | "errors" 9 | "strings" 10 | 11 | "github.com/go-xorm/core" 12 | ) 13 | 14 | // func init() { 15 | // core.RegisterDriver("odbc", &odbcDriver{}) 16 | // } 17 | 18 | type odbcDriver struct { 19 | } 20 | 21 | func (p *odbcDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) { 22 | kv := strings.Split(dataSourceName, ";") 23 | var dbName string 24 | 25 | for _, c := range kv { 26 | vv := strings.Split(strings.TrimSpace(c), "=") 27 | if len(vv) == 2 { 28 | switch strings.ToLower(vv[0]) { 29 | case "database": 30 | dbName = vv[1] 31 | } 32 | } 33 | } 34 | if dbName == "" { 35 | return nil, errors.New("no db name provided") 36 | } 37 | return &core.Uri{DbName: dbName, DbType: core.MSSQL}, nil 38 | } 39 | -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/xorm/processors.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Xorm 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 xorm 6 | 7 | // Executed before an object is initially persisted to the database 8 | type BeforeInsertProcessor interface { 9 | BeforeInsert() 10 | } 11 | 12 | // Executed before an object is updated 13 | type BeforeUpdateProcessor interface { 14 | BeforeUpdate() 15 | } 16 | 17 | // Executed before an object is deleted 18 | type BeforeDeleteProcessor interface { 19 | BeforeDelete() 20 | } 21 | 22 | type BeforeSetProcessor interface { 23 | BeforeSet(string, Cell) 24 | } 25 | 26 | type AfterSetProcessor interface { 27 | AfterSet(string, Cell) 28 | } 29 | 30 | // !nashtsai! TODO enable BeforeValidateProcessor when xorm start to support validations 31 | //// Executed before an object is validated 32 | //type BeforeValidateProcessor interface { 33 | // BeforeValidate() 34 | //} 35 | // -- 36 | 37 | // Executed after an object is persisted to the database 38 | type AfterInsertProcessor interface { 39 | AfterInsert() 40 | } 41 | 42 | // Executed after an object has been updated 43 | type AfterUpdateProcessor interface { 44 | AfterUpdate() 45 | } 46 | 47 | // Executed after an object has been deleted 48 | type AfterDeleteProcessor interface { 49 | AfterDelete() 50 | } 51 | -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/xorm/sqlite3_driver.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Xorm 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 xorm 6 | 7 | import ( 8 | "github.com/go-xorm/core" 9 | ) 10 | 11 | // func init() { 12 | // core.RegisterDriver("sqlite3", &sqlite3Driver{}) 13 | // } 14 | 15 | type sqlite3Driver struct { 16 | } 17 | 18 | func (p *sqlite3Driver) Parse(driverName, dataSourceName string) (*core.Uri, error) { 19 | return &core.Uri{DbType: core.SQLITE, DbName: dataSourceName}, nil 20 | } 21 | -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/xorm/syslogger.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Xorm 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 !windows,!nacl,!plan9 6 | 7 | package xorm 8 | 9 | import ( 10 | "fmt" 11 | "log/syslog" 12 | 13 | "github.com/go-xorm/core" 14 | ) 15 | 16 | var _ core.ILogger = &SyslogLogger{} 17 | 18 | // SyslogLogger will be depricated 19 | type SyslogLogger struct { 20 | w *syslog.Writer 21 | showSQL bool 22 | } 23 | 24 | func NewSyslogLogger(w *syslog.Writer) *SyslogLogger { 25 | return &SyslogLogger{w: w} 26 | } 27 | 28 | func (s *SyslogLogger) Debug(v ...interface{}) { 29 | s.w.Debug(fmt.Sprint(v...)) 30 | } 31 | 32 | func (s *SyslogLogger) Debugf(format string, v ...interface{}) { 33 | s.w.Debug(fmt.Sprintf(format, v...)) 34 | } 35 | 36 | func (s *SyslogLogger) Error(v ...interface{}) { 37 | s.w.Err(fmt.Sprint(v...)) 38 | } 39 | 40 | func (s *SyslogLogger) Errorf(format string, v ...interface{}) { 41 | s.w.Err(fmt.Sprintf(format, v...)) 42 | } 43 | 44 | func (s *SyslogLogger) Info(v ...interface{}) { 45 | s.w.Info(fmt.Sprint(v...)) 46 | } 47 | 48 | func (s *SyslogLogger) Infof(format string, v ...interface{}) { 49 | s.w.Info(fmt.Sprintf(format, v...)) 50 | } 51 | 52 | func (s *SyslogLogger) Warn(v ...interface{}) { 53 | s.w.Warning(fmt.Sprint(v...)) 54 | } 55 | 56 | func (s *SyslogLogger) Warnf(format string, v ...interface{}) { 57 | s.w.Warning(fmt.Sprintf(format, v...)) 58 | } 59 | 60 | func (s *SyslogLogger) Level() core.LogLevel { 61 | return core.LOG_UNKNOWN 62 | } 63 | 64 | // SetLevel always return error, as current log/syslog package doesn't allow to set priority level after syslog.Writer created 65 | func (s *SyslogLogger) SetLevel(l core.LogLevel) {} 66 | 67 | func (s *SyslogLogger) ShowSQL(show ...bool) { 68 | if len(show) == 0 { 69 | s.showSQL = true 70 | return 71 | } 72 | s.showSQL = show[0] 73 | } 74 | 75 | func (s *SyslogLogger) IsShowSQL() bool { 76 | return s.showSQL 77 | } 78 | -------------------------------------------------------------------------------- /vendor/github.com/go-xorm/xorm/types.go: -------------------------------------------------------------------------------- 1 | package xorm 2 | 3 | import ( 4 | "reflect" 5 | 6 | "github.com/go-xorm/core" 7 | ) 8 | 9 | var ( 10 | ptrPkType = reflect.TypeOf(&core.PK{}) 11 | pkType = reflect.TypeOf(core.PK{}) 12 | ) 13 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/context/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | 4 | matrix: 5 | include: 6 | - go: 1.3 7 | - go: 1.4 8 | - go: 1.5 9 | - go: 1.6 10 | - go: tip 11 | 12 | install: 13 | - go get golang.org/x/tools/cmd/vet 14 | 15 | script: 16 | - go get -t -v ./... 17 | - diff -u <(echo -n) <(gofmt -d .) 18 | - go tool vet . 19 | - go test -v -race ./... 20 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/context/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Rodrigo Moraes. 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/github.com/gorilla/context/README.md: -------------------------------------------------------------------------------- 1 | context 2 | ======= 3 | [![Build Status](https://travis-ci.org/gorilla/context.png?branch=master)](https://travis-ci.org/gorilla/context) 4 | 5 | gorilla/context is a general purpose registry for global request variables. 6 | 7 | Read the full documentation here: http://www.gorillatoolkit.org/pkg/context 8 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/context/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Gorilla 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 context stores values shared during a request lifetime. 7 | 8 | For example, a router can set variables extracted from the URL and later 9 | application handlers can access those values, or it can be used to store 10 | sessions values to be saved at the end of a request. There are several 11 | others common uses. 12 | 13 | The idea was posted by Brad Fitzpatrick to the go-nuts mailing list: 14 | 15 | http://groups.google.com/group/golang-nuts/msg/e2d679d303aa5d53 16 | 17 | Here's the basic usage: first define the keys that you will need. The key 18 | type is interface{} so a key can be of any type that supports equality. 19 | Here we define a key using a custom int type to avoid name collisions: 20 | 21 | package foo 22 | 23 | import ( 24 | "github.com/gorilla/context" 25 | ) 26 | 27 | type key int 28 | 29 | const MyKey key = 0 30 | 31 | Then set a variable. Variables are bound to an http.Request object, so you 32 | need a request instance to set a value: 33 | 34 | context.Set(r, MyKey, "bar") 35 | 36 | The application can later access the variable using the same key you provided: 37 | 38 | func MyHandler(w http.ResponseWriter, r *http.Request) { 39 | // val is "bar". 40 | val := context.Get(r, foo.MyKey) 41 | 42 | // returns ("bar", true) 43 | val, ok := context.GetOk(r, foo.MyKey) 44 | // ... 45 | } 46 | 47 | And that's all about the basic usage. We discuss some other ideas below. 48 | 49 | Any type can be stored in the context. To enforce a given type, make the key 50 | private and wrap Get() and Set() to accept and return values of a specific 51 | type: 52 | 53 | type key int 54 | 55 | const mykey key = 0 56 | 57 | // GetMyKey returns a value for this package from the request values. 58 | func GetMyKey(r *http.Request) SomeType { 59 | if rv := context.Get(r, mykey); rv != nil { 60 | return rv.(SomeType) 61 | } 62 | return nil 63 | } 64 | 65 | // SetMyKey sets a value for this package in the request values. 66 | func SetMyKey(r *http.Request, val SomeType) { 67 | context.Set(r, mykey, val) 68 | } 69 | 70 | Variables must be cleared at the end of a request, to remove all values 71 | that were stored. This can be done in an http.Handler, after a request was 72 | served. Just call Clear() passing the request: 73 | 74 | context.Clear(r) 75 | 76 | ...or use ClearHandler(), which conveniently wraps an http.Handler to clear 77 | variables at the end of a request lifetime. 78 | 79 | The Routers from the packages gorilla/mux and gorilla/pat call Clear() 80 | so if you are using either of them you don't need to clear the context manually. 81 | */ 82 | package context 83 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | 4 | matrix: 5 | include: 6 | - go: 1.2 7 | - go: 1.3 8 | - go: 1.4 9 | - go: 1.5 10 | - go: 1.6 11 | - go: tip 12 | 13 | install: 14 | - go get golang.org/x/tools/cmd/vet 15 | 16 | script: 17 | - go get -t -v ./... 18 | - diff -u <(echo -n) <(gofmt -d .) 19 | - go tool vet . 20 | - go test -v -race ./... 21 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Rodrigo Moraes. 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/github.com/gorilla/securecookie/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | 4 | matrix: 5 | include: 6 | - go: 1.3 7 | - go: 1.4 8 | - go: 1.5 9 | - go: 1.6 10 | - go: tip 11 | allow_failures: 12 | - go: tip 13 | 14 | script: 15 | - go get -t -v ./... 16 | - diff -u <(echo -n) <(gofmt -d .) 17 | - go vet $(go list ./... | grep -v /vendor/) 18 | - go test -v -race ./... 19 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/securecookie/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Rodrigo Moraes. 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/github.com/gorilla/securecookie/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Gorilla 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 securecookie encodes and decodes authenticated and optionally 7 | encrypted cookie values. 8 | 9 | Secure cookies can't be forged, because their values are validated using HMAC. 10 | When encrypted, the content is also inaccessible to malicious eyes. 11 | 12 | To use it, first create a new SecureCookie instance: 13 | 14 | var hashKey = []byte("very-secret") 15 | var blockKey = []byte("a-lot-secret") 16 | var s = securecookie.New(hashKey, blockKey) 17 | 18 | The hashKey is required, used to authenticate the cookie value using HMAC. 19 | It is recommended to use a key with 32 or 64 bytes. 20 | 21 | The blockKey is optional, used to encrypt the cookie value -- set it to nil 22 | to not use encryption. If set, the length must correspond to the block size 23 | of the encryption algorithm. For AES, used by default, valid lengths are 24 | 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256. 25 | 26 | Strong keys can be created using the convenience function GenerateRandomKey(). 27 | 28 | Once a SecureCookie instance is set, use it to encode a cookie value: 29 | 30 | func SetCookieHandler(w http.ResponseWriter, r *http.Request) { 31 | value := map[string]string{ 32 | "foo": "bar", 33 | } 34 | if encoded, err := s.Encode("cookie-name", value); err == nil { 35 | cookie := &http.Cookie{ 36 | Name: "cookie-name", 37 | Value: encoded, 38 | Path: "/", 39 | } 40 | http.SetCookie(w, cookie) 41 | } 42 | } 43 | 44 | Later, use the same SecureCookie instance to decode and validate a cookie 45 | value: 46 | 47 | func ReadCookieHandler(w http.ResponseWriter, r *http.Request) { 48 | if cookie, err := r.Cookie("cookie-name"); err == nil { 49 | value := make(map[string]string) 50 | if err = s2.Decode("cookie-name", cookie.Value, &value); err == nil { 51 | fmt.Fprintf(w, "The value of foo is %q", value["foo"]) 52 | } 53 | } 54 | } 55 | 56 | We stored a map[string]string, but secure cookies can hold any value that 57 | can be encoded using encoding/gob. To store custom types, they must be 58 | registered first using gob.Register(). For basic types this is not needed; 59 | it works out of the box. 60 | */ 61 | package securecookie 62 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/securecookie/fuzz.go: -------------------------------------------------------------------------------- 1 | // +build gofuzz 2 | 3 | package securecookie 4 | 5 | var hashKey = []byte("very-secret12345") 6 | var blockKey = []byte("a-lot-secret1234") 7 | var s = New(hashKey, blockKey) 8 | 9 | type Cookie struct { 10 | B bool 11 | I int 12 | S string 13 | } 14 | 15 | func Fuzz(data []byte) int { 16 | datas := string(data) 17 | var c Cookie 18 | if err := s.Decode("fuzz", datas, &c); err != nil { 19 | return 0 20 | } 21 | if _, err := s.Encode("fuzz", c); err != nil { 22 | panic(err) 23 | } 24 | return 1 25 | } 26 | -------------------------------------------------------------------------------- /vendor/github.com/miekg/dns/.gitignore: -------------------------------------------------------------------------------- 1 | *.6 2 | tags 3 | test.out 4 | a.out 5 | -------------------------------------------------------------------------------- /vendor/github.com/miekg/dns/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | go: 4 | - 1.5 5 | - 1.6 6 | script: 7 | - go test -race -v -bench=. 8 | -------------------------------------------------------------------------------- /vendor/github.com/miekg/dns/AUTHORS: -------------------------------------------------------------------------------- 1 | Miek Gieben 2 | -------------------------------------------------------------------------------- /vendor/github.com/miekg/dns/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | Alex A. Skinner 2 | Andrew Tunnell-Jones 3 | Ask Bjørn Hansen 4 | Dave Cheney 5 | Dusty Wilson 6 | Marek Majkowski 7 | Peter van Dijk 8 | Omri Bahumi 9 | Alex Sergeyev 10 | -------------------------------------------------------------------------------- /vendor/github.com/miekg/dns/COPYRIGHT: -------------------------------------------------------------------------------- 1 | Copyright 2009 The Go Authors. All rights reserved. Use of this source code 2 | is governed by a BSD-style license that can be found in the LICENSE file. 3 | Extensions of the original work are copyright (c) 2011 Miek Gieben 4 | 5 | Copyright 2011 Miek Gieben. All rights reserved. Use of this source code is 6 | governed by a BSD-style license that can be found in the LICENSE file. 7 | 8 | Copyright 2014 CloudFlare. All rights reserved. Use of this source code is 9 | governed by a BSD-style license that can be found in the LICENSE file. 10 | -------------------------------------------------------------------------------- /vendor/github.com/miekg/dns/LICENSE: -------------------------------------------------------------------------------- 1 | Extensions of the original work are copyright (c) 2011 Miek Gieben 2 | 3 | As this is fork of the official Go code the same license applies: 4 | 5 | Copyright (c) 2009 The Go Authors. All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are 9 | met: 10 | 11 | * Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | * Redistributions in binary form must reproduce the above 14 | copyright notice, this list of conditions and the following disclaimer 15 | in the documentation and/or other materials provided with the 16 | distribution. 17 | * Neither the name of Google Inc. nor the names of its 18 | contributors may be used to endorse or promote products derived from 19 | this software without specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | -------------------------------------------------------------------------------- /vendor/github.com/miekg/dns/clientconfig.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | import ( 4 | "bufio" 5 | "os" 6 | "strconv" 7 | "strings" 8 | ) 9 | 10 | // ClientConfig wraps the contents of the /etc/resolv.conf file. 11 | type ClientConfig struct { 12 | Servers []string // servers to use 13 | Search []string // suffixes to append to local name 14 | Port string // what port to use 15 | Ndots int // number of dots in name to trigger absolute lookup 16 | Timeout int // seconds before giving up on packet 17 | Attempts int // lost packets before giving up on server, not used in the package dns 18 | } 19 | 20 | // ClientConfigFromFile parses a resolv.conf(5) like file and returns 21 | // a *ClientConfig. 22 | func ClientConfigFromFile(resolvconf string) (*ClientConfig, error) { 23 | file, err := os.Open(resolvconf) 24 | if err != nil { 25 | return nil, err 26 | } 27 | defer file.Close() 28 | c := new(ClientConfig) 29 | scanner := bufio.NewScanner(file) 30 | c.Servers = make([]string, 0) 31 | c.Search = make([]string, 0) 32 | c.Port = "53" 33 | c.Ndots = 1 34 | c.Timeout = 5 35 | c.Attempts = 2 36 | 37 | for scanner.Scan() { 38 | if err := scanner.Err(); err != nil { 39 | return nil, err 40 | } 41 | line := scanner.Text() 42 | f := strings.Fields(line) 43 | if len(f) < 1 { 44 | continue 45 | } 46 | switch f[0] { 47 | case "nameserver": // add one name server 48 | if len(f) > 1 { 49 | // One more check: make sure server name is 50 | // just an IP address. Otherwise we need DNS 51 | // to look it up. 52 | name := f[1] 53 | c.Servers = append(c.Servers, name) 54 | } 55 | 56 | case "domain": // set search path to just this domain 57 | if len(f) > 1 { 58 | c.Search = make([]string, 1) 59 | c.Search[0] = f[1] 60 | } else { 61 | c.Search = make([]string, 0) 62 | } 63 | 64 | case "search": // set search path to given servers 65 | c.Search = make([]string, len(f)-1) 66 | for i := 0; i < len(c.Search); i++ { 67 | c.Search[i] = f[i+1] 68 | } 69 | 70 | case "options": // magic options 71 | for i := 1; i < len(f); i++ { 72 | s := f[i] 73 | switch { 74 | case len(s) >= 6 && s[:6] == "ndots:": 75 | n, _ := strconv.Atoi(s[6:]) 76 | if n < 1 { 77 | n = 1 78 | } 79 | c.Ndots = n 80 | case len(s) >= 8 && s[:8] == "timeout:": 81 | n, _ := strconv.Atoi(s[8:]) 82 | if n < 1 { 83 | n = 1 84 | } 85 | c.Timeout = n 86 | case len(s) >= 8 && s[:9] == "attempts:": 87 | n, _ := strconv.Atoi(s[9:]) 88 | if n < 1 { 89 | n = 1 90 | } 91 | c.Attempts = n 92 | case s == "rotate": 93 | /* not imp */ 94 | } 95 | } 96 | } 97 | } 98 | return c, nil 99 | } 100 | -------------------------------------------------------------------------------- /vendor/github.com/miekg/dns/rawmsg.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | // These raw* functions do not use reflection, they directly set the values 4 | // in the buffer. There are faster than their reflection counterparts. 5 | 6 | // RawSetId sets the message id in buf. 7 | func rawSetId(msg []byte, i uint16) bool { 8 | if len(msg) < 2 { 9 | return false 10 | } 11 | msg[0], msg[1] = packUint16(i) 12 | return true 13 | } 14 | 15 | // rawSetQuestionLen sets the length of the question section. 16 | func rawSetQuestionLen(msg []byte, i uint16) bool { 17 | if len(msg) < 6 { 18 | return false 19 | } 20 | msg[4], msg[5] = packUint16(i) 21 | return true 22 | } 23 | 24 | // rawSetAnswerLen sets the length of the answer section. 25 | func rawSetAnswerLen(msg []byte, i uint16) bool { 26 | if len(msg) < 8 { 27 | return false 28 | } 29 | msg[6], msg[7] = packUint16(i) 30 | return true 31 | } 32 | 33 | // rawSetsNsLen sets the length of the authority section. 34 | func rawSetNsLen(msg []byte, i uint16) bool { 35 | if len(msg) < 10 { 36 | return false 37 | } 38 | msg[8], msg[9] = packUint16(i) 39 | return true 40 | } 41 | 42 | // rawSetExtraLen sets the length of the additional section. 43 | func rawSetExtraLen(msg []byte, i uint16) bool { 44 | if len(msg) < 12 { 45 | return false 46 | } 47 | msg[10], msg[11] = packUint16(i) 48 | return true 49 | } 50 | 51 | // rawSetRdlength sets the rdlength in the header of 52 | // the RR. The offset 'off' must be positioned at the 53 | // start of the header of the RR, 'end' must be the 54 | // end of the RR. 55 | func rawSetRdlength(msg []byte, off, end int) bool { 56 | l := len(msg) 57 | Loop: 58 | for { 59 | if off+1 > l { 60 | return false 61 | } 62 | c := int(msg[off]) 63 | off++ 64 | switch c & 0xC0 { 65 | case 0x00: 66 | if c == 0x00 { 67 | // End of the domainname 68 | break Loop 69 | } 70 | if off+c > l { 71 | return false 72 | } 73 | off += c 74 | 75 | case 0xC0: 76 | // pointer, next byte included, ends domainname 77 | off++ 78 | break Loop 79 | } 80 | } 81 | // The domainname has been seen, we at the start of the fixed part in the header. 82 | // Type is 2 bytes, class is 2 bytes, ttl 4 and then 2 bytes for the length. 83 | off += 2 + 2 + 4 84 | if off+2 > l { 85 | return false 86 | } 87 | //off+1 is the end of the header, 'end' is the end of the rr 88 | //so 'end' - 'off+2' is the length of the rdata 89 | rdatalen := end - (off + 2) 90 | if rdatalen > 0xFFFF { 91 | return false 92 | } 93 | msg[off], msg[off+1] = packUint16(uint16(rdatalen)) 94 | return true 95 | } 96 | -------------------------------------------------------------------------------- /vendor/github.com/miekg/dns/sanitize.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | // Dedup removes identical RRs from rrs. It preserves the original ordering. 4 | // The lowest TTL of any duplicates is used in the remaining one. Dedup modifies 5 | // rrs. 6 | // m is used to store the RRs temporay. If it is nil a new map will be allocated. 7 | func Dedup(rrs []RR, m map[string]RR) []RR { 8 | if m == nil { 9 | m = make(map[string]RR) 10 | } 11 | // Save the keys, so we don't have to call normalizedString twice. 12 | keys := make([]*string, 0, len(rrs)) 13 | 14 | for _, r := range rrs { 15 | key := normalizedString(r) 16 | keys = append(keys, &key) 17 | if _, ok := m[key]; ok { 18 | // Shortest TTL wins. 19 | if m[key].Header().Ttl > r.Header().Ttl { 20 | m[key].Header().Ttl = r.Header().Ttl 21 | } 22 | continue 23 | } 24 | 25 | m[key] = r 26 | } 27 | // If the length of the result map equals the amount of RRs we got, 28 | // it means they were all different. We can then just return the original rrset. 29 | if len(m) == len(rrs) { 30 | return rrs 31 | } 32 | 33 | j := 0 34 | for i, r := range rrs { 35 | // If keys[i] lives in the map, we should copy and remove it. 36 | if _, ok := m[*keys[i]]; ok { 37 | delete(m, *keys[i]) 38 | rrs[j] = r 39 | j++ 40 | } 41 | 42 | if len(m) == 0 { 43 | break 44 | } 45 | } 46 | 47 | return rrs[:j] 48 | } 49 | 50 | // normalizedString returns a normalized string from r. The TTL 51 | // is removed and the domain name is lowercased. We go from this: 52 | // DomainNameTTLCLASSTYPERDATA to: 53 | // lowercasenameCLASSTYPE... 54 | func normalizedString(r RR) string { 55 | // A string Go DNS makes has: domainnameTTL... 56 | b := []byte(r.String()) 57 | 58 | // find the first non-escaped tab, then another, so we capture where the TTL lives. 59 | esc := false 60 | ttlStart, ttlEnd := 0, 0 61 | for i := 0; i < len(b) && ttlEnd == 0; i++ { 62 | switch { 63 | case b[i] == '\\': 64 | esc = !esc 65 | case b[i] == '\t' && !esc: 66 | if ttlStart == 0 { 67 | ttlStart = i 68 | continue 69 | } 70 | if ttlEnd == 0 { 71 | ttlEnd = i 72 | } 73 | case b[i] >= 'A' && b[i] <= 'Z' && !esc: 74 | b[i] += 32 75 | default: 76 | esc = false 77 | } 78 | } 79 | 80 | // remove TTL. 81 | copy(b[ttlStart:], b[ttlEnd:]) 82 | cut := ttlEnd - ttlStart 83 | return string(b[:len(b)-cut]) 84 | } 85 | -------------------------------------------------------------------------------- /vendor/github.com/miekg/dns/scanner.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | // Implement a simple scanner, return a byte stream from an io reader. 4 | 5 | import ( 6 | "bufio" 7 | "io" 8 | "text/scanner" 9 | ) 10 | 11 | type scan struct { 12 | src *bufio.Reader 13 | position scanner.Position 14 | eof bool // Have we just seen a eof 15 | } 16 | 17 | func scanInit(r io.Reader) *scan { 18 | s := new(scan) 19 | s.src = bufio.NewReader(r) 20 | s.position.Line = 1 21 | return s 22 | } 23 | 24 | // tokenText returns the next byte from the input 25 | func (s *scan) tokenText() (byte, error) { 26 | c, err := s.src.ReadByte() 27 | if err != nil { 28 | return c, err 29 | } 30 | // delay the newline handling until the next token is delivered, 31 | // fixes off-by-one errors when reporting a parse error. 32 | if s.eof == true { 33 | s.position.Line++ 34 | s.position.Column = 0 35 | s.eof = false 36 | } 37 | if c == '\n' { 38 | s.eof = true 39 | return c, nil 40 | } 41 | s.position.Column++ 42 | return c, nil 43 | } 44 | -------------------------------------------------------------------------------- /vendor/github.com/miekg/dns/singleinflight.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 | // Adapted for dns package usage by Miek Gieben. 6 | 7 | package dns 8 | 9 | import "sync" 10 | import "time" 11 | 12 | // call is an in-flight or completed singleflight.Do call 13 | type call struct { 14 | wg sync.WaitGroup 15 | val *Msg 16 | rtt time.Duration 17 | err error 18 | dups int 19 | } 20 | 21 | // singleflight represents a class of work and forms a namespace in 22 | // which units of work can be executed with duplicate suppression. 23 | type singleflight struct { 24 | sync.Mutex // protects m 25 | m map[string]*call // lazily initialized 26 | } 27 | 28 | // Do executes and returns the results of the given function, making 29 | // sure that only one execution is in-flight for a given key at a 30 | // time. If a duplicate comes in, the duplicate caller waits for the 31 | // original to complete and receives the same results. 32 | // The return value shared indicates whether v was given to multiple callers. 33 | func (g *singleflight) Do(key string, fn func() (*Msg, time.Duration, error)) (v *Msg, rtt time.Duration, err error, shared bool) { 34 | g.Lock() 35 | if g.m == nil { 36 | g.m = make(map[string]*call) 37 | } 38 | if c, ok := g.m[key]; ok { 39 | c.dups++ 40 | g.Unlock() 41 | c.wg.Wait() 42 | return c.val, c.rtt, c.err, true 43 | } 44 | c := new(call) 45 | c.wg.Add(1) 46 | g.m[key] = c 47 | g.Unlock() 48 | 49 | c.val, c.rtt, c.err = fn() 50 | c.wg.Done() 51 | 52 | g.Lock() 53 | delete(g.m, key) 54 | g.Unlock() 55 | 56 | return c.val, c.rtt, c.err, c.dups > 0 57 | } 58 | -------------------------------------------------------------------------------- /vendor/github.com/miekg/dns/tlsa.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | import ( 4 | "crypto/sha256" 5 | "crypto/sha512" 6 | "crypto/x509" 7 | "encoding/hex" 8 | "errors" 9 | "io" 10 | "net" 11 | "strconv" 12 | ) 13 | 14 | // CertificateToDANE converts a certificate to a hex string as used in the TLSA record. 15 | func CertificateToDANE(selector, matchingType uint8, cert *x509.Certificate) (string, error) { 16 | switch matchingType { 17 | case 0: 18 | switch selector { 19 | case 0: 20 | return hex.EncodeToString(cert.Raw), nil 21 | case 1: 22 | return hex.EncodeToString(cert.RawSubjectPublicKeyInfo), nil 23 | } 24 | case 1: 25 | h := sha256.New() 26 | switch selector { 27 | case 0: 28 | io.WriteString(h, string(cert.Raw)) 29 | return hex.EncodeToString(h.Sum(nil)), nil 30 | case 1: 31 | io.WriteString(h, string(cert.RawSubjectPublicKeyInfo)) 32 | return hex.EncodeToString(h.Sum(nil)), nil 33 | } 34 | case 2: 35 | h := sha512.New() 36 | switch selector { 37 | case 0: 38 | io.WriteString(h, string(cert.Raw)) 39 | return hex.EncodeToString(h.Sum(nil)), nil 40 | case 1: 41 | io.WriteString(h, string(cert.RawSubjectPublicKeyInfo)) 42 | return hex.EncodeToString(h.Sum(nil)), nil 43 | } 44 | } 45 | return "", errors.New("dns: bad TLSA MatchingType or TLSA Selector") 46 | } 47 | 48 | // Sign creates a TLSA record from an SSL certificate. 49 | func (r *TLSA) Sign(usage, selector, matchingType int, cert *x509.Certificate) (err error) { 50 | r.Hdr.Rrtype = TypeTLSA 51 | r.Usage = uint8(usage) 52 | r.Selector = uint8(selector) 53 | r.MatchingType = uint8(matchingType) 54 | 55 | r.Certificate, err = CertificateToDANE(r.Selector, r.MatchingType, cert) 56 | if err != nil { 57 | return err 58 | } 59 | return nil 60 | } 61 | 62 | // Verify verifies a TLSA record against an SSL certificate. If it is OK 63 | // a nil error is returned. 64 | func (r *TLSA) Verify(cert *x509.Certificate) error { 65 | c, err := CertificateToDANE(r.Selector, r.MatchingType, cert) 66 | if err != nil { 67 | return err // Not also ErrSig? 68 | } 69 | if r.Certificate == c { 70 | return nil 71 | } 72 | return ErrSig // ErrSig, really? 73 | } 74 | 75 | // TLSAName returns the ownername of a TLSA resource record as per the 76 | // rules specified in RFC 6698, Section 3. 77 | func TLSAName(name, service, network string) (string, error) { 78 | if !IsFqdn(name) { 79 | return "", ErrFqdn 80 | } 81 | p, e := net.LookupPort(network, service) 82 | if e != nil { 83 | return "", e 84 | } 85 | return "_" + strconv.Itoa(p) + "._" + network + "." + name, nil 86 | } 87 | -------------------------------------------------------------------------------- /vendor/github.com/miekg/dns/udp.go: -------------------------------------------------------------------------------- 1 | // +build !windows,!plan9 2 | 3 | package dns 4 | 5 | import ( 6 | "net" 7 | "syscall" 8 | ) 9 | 10 | // SessionUDP holds the remote address and the associated 11 | // out-of-band data. 12 | type SessionUDP struct { 13 | raddr *net.UDPAddr 14 | context []byte 15 | } 16 | 17 | // RemoteAddr returns the remote network address. 18 | func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr } 19 | 20 | // setUDPSocketOptions sets the UDP socket options. 21 | // This function is implemented on a per platform basis. See udp_*.go for more details 22 | func setUDPSocketOptions(conn *net.UDPConn) error { 23 | sa, err := getUDPSocketName(conn) 24 | if err != nil { 25 | return err 26 | } 27 | switch sa.(type) { 28 | case *syscall.SockaddrInet6: 29 | v6only, err := getUDPSocketOptions6Only(conn) 30 | if err != nil { 31 | return err 32 | } 33 | setUDPSocketOptions6(conn) 34 | if !v6only { 35 | setUDPSocketOptions4(conn) 36 | } 37 | case *syscall.SockaddrInet4: 38 | setUDPSocketOptions4(conn) 39 | } 40 | return nil 41 | } 42 | 43 | // ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a 44 | // net.UDPAddr. 45 | func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) { 46 | oob := make([]byte, 40) 47 | n, oobn, _, raddr, err := conn.ReadMsgUDP(b, oob) 48 | if err != nil { 49 | return n, nil, err 50 | } 51 | return n, &SessionUDP{raddr, oob[:oobn]}, err 52 | } 53 | 54 | // WriteToSessionUDP acts just like net.UDPConn.WritetTo(), but uses a *SessionUDP instead of a net.Addr. 55 | func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) { 56 | n, _, err := conn.WriteMsgUDP(b, session.context, session.raddr) 57 | return n, err 58 | } 59 | -------------------------------------------------------------------------------- /vendor/github.com/miekg/dns/udp_linux.go: -------------------------------------------------------------------------------- 1 | // +build linux 2 | 3 | package dns 4 | 5 | // See: 6 | // * http://stackoverflow.com/questions/3062205/setting-the-source-ip-for-a-udp-socket and 7 | // * http://blog.powerdns.com/2012/10/08/on-binding-datagram-udp-sockets-to-the-any-addresses/ 8 | // 9 | // Why do we need this: When listening on 0.0.0.0 with UDP so kernel decides what is the outgoing 10 | // interface, this might not always be the correct one. This code will make sure the egress 11 | // packet's interface matched the ingress' one. 12 | 13 | import ( 14 | "net" 15 | "syscall" 16 | ) 17 | 18 | // setUDPSocketOptions4 prepares the v4 socket for sessions. 19 | func setUDPSocketOptions4(conn *net.UDPConn) error { 20 | file, err := conn.File() 21 | if err != nil { 22 | return err 23 | } 24 | if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IP, syscall.IP_PKTINFO, 1); err != nil { 25 | return err 26 | } 27 | // Calling File() above results in the connection becoming blocking, we must fix that. 28 | // See https://github.com/miekg/dns/issues/279 29 | err = syscall.SetNonblock(int(file.Fd()), true) 30 | if err != nil { 31 | return err 32 | } 33 | return nil 34 | } 35 | 36 | // setUDPSocketOptions6 prepares the v6 socket for sessions. 37 | func setUDPSocketOptions6(conn *net.UDPConn) error { 38 | file, err := conn.File() 39 | if err != nil { 40 | return err 41 | } 42 | if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_RECVPKTINFO, 1); err != nil { 43 | return err 44 | } 45 | err = syscall.SetNonblock(int(file.Fd()), true) 46 | if err != nil { 47 | return err 48 | } 49 | return nil 50 | } 51 | 52 | // getUDPSocketOption6Only return true if the socket is v6 only and false when it is v4/v6 combined 53 | // (dualstack). 54 | func getUDPSocketOptions6Only(conn *net.UDPConn) (bool, error) { 55 | file, err := conn.File() 56 | if err != nil { 57 | return false, err 58 | } 59 | // dual stack. See http://stackoverflow.com/questions/1618240/how-to-support-both-ipv4-and-ipv6-connections 60 | v6only, err := syscall.GetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY) 61 | if err != nil { 62 | return false, err 63 | } 64 | return v6only == 1, nil 65 | } 66 | 67 | func getUDPSocketName(conn *net.UDPConn) (syscall.Sockaddr, error) { 68 | file, err := conn.File() 69 | if err != nil { 70 | return nil, err 71 | } 72 | return syscall.Getsockname(int(file.Fd())) 73 | } 74 | -------------------------------------------------------------------------------- /vendor/github.com/miekg/dns/udp_other.go: -------------------------------------------------------------------------------- 1 | // +build !linux,!plan9 2 | 3 | package dns 4 | 5 | import ( 6 | "net" 7 | "syscall" 8 | ) 9 | 10 | // These do nothing. See udp_linux.go for an example of how to implement this. 11 | 12 | // We tried to adhire to some kind of naming scheme. 13 | 14 | func setUDPSocketOptions4(conn *net.UDPConn) error { return nil } 15 | func setUDPSocketOptions6(conn *net.UDPConn) error { return nil } 16 | func getUDPSocketOptions6Only(conn *net.UDPConn) (bool, error) { return false, nil } 17 | func getUDPSocketName(conn *net.UDPConn) (syscall.Sockaddr, error) { return nil, nil } 18 | -------------------------------------------------------------------------------- /vendor/github.com/miekg/dns/udp_plan9.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | import ( 4 | "net" 5 | ) 6 | 7 | func setUDPSocketOptions(conn *net.UDPConn) error { return nil } 8 | 9 | // SessionUDP holds the remote address and the associated 10 | // out-of-band data. 11 | type SessionUDP struct { 12 | raddr *net.UDPAddr 13 | context []byte 14 | } 15 | 16 | // RemoteAddr returns the remote network address. 17 | func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr } 18 | 19 | // ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a 20 | // net.UDPAddr. 21 | func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) { 22 | oob := make([]byte, 40) 23 | n, oobn, _, raddr, err := conn.ReadMsgUDP(b, oob) 24 | if err != nil { 25 | return n, nil, err 26 | } 27 | return n, &SessionUDP{raddr, oob[:oobn]}, err 28 | } 29 | 30 | // WriteToSessionUDP acts just like net.UDPConn.WritetTo(), but uses a *SessionUDP instead of a net.Addr. 31 | func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) { 32 | n, _, err := conn.WriteMsgUDP(b, session.context, session.raddr) 33 | return n, err 34 | } 35 | -------------------------------------------------------------------------------- /vendor/github.com/miekg/dns/udp_windows.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package dns 4 | 5 | import "net" 6 | 7 | type SessionUDP struct { 8 | raddr *net.UDPAddr 9 | } 10 | 11 | // ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a 12 | // net.UDPAddr. 13 | func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) { 14 | n, raddr, err := conn.ReadFrom(b) 15 | if err != nil { 16 | return n, nil, err 17 | } 18 | session := &SessionUDP{raddr.(*net.UDPAddr)} 19 | return n, session, err 20 | } 21 | 22 | // WriteToSessionUDP acts just like net.UDPConn.WritetTo(), but uses a *SessionUDP instead of a net.Addr. 23 | func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) { 24 | n, err := conn.WriteTo(b, session.raddr) 25 | return n, err 26 | } 27 | 28 | func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr } 29 | 30 | // setUDPSocketOptions sets the UDP socket options. 31 | // This function is implemented on a per platform basis. See udp_*.go for more details 32 | func setUDPSocketOptions(conn *net.UDPConn) error { 33 | return nil 34 | } 35 | -------------------------------------------------------------------------------- /vendor/github.com/mmitton/ldap/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/URLooker/web/362a939a5ff973fcea885ed1641bb660fec6c301/vendor/github.com/mmitton/ldap/.gitignore -------------------------------------------------------------------------------- /vendor/github.com/mmitton/ldap/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | env: 3 | global: 4 | - VET_VERSIONS="1.6 1.7 1.8 1.9 tip" 5 | - LINT_VERSIONS="1.6 1.7 1.8 1.9 tip" 6 | go: 7 | - 1.2 8 | - 1.3 9 | - 1.4 10 | - 1.5 11 | - 1.6 12 | - 1.7 13 | - 1.8 14 | - 1.9 15 | - tip 16 | matrix: 17 | fast_finish: true 18 | allow_failures: 19 | - go: tip 20 | go_import_path: gopkg.in/ldap.v2 21 | install: 22 | - go get gopkg.in/asn1-ber.v1 23 | - go get gopkg.in/ldap.v2 24 | - go get code.google.com/p/go.tools/cmd/cover || go get golang.org/x/tools/cmd/cover 25 | - go get github.com/golang/lint/golint || true 26 | - go build -v ./... 27 | script: 28 | - make test 29 | - make fmt 30 | - if [[ "$VET_VERSIONS" == *"$TRAVIS_GO_VERSION"* ]]; then make vet; fi 31 | - if [[ "$LINT_VERSIONS" == *"$TRAVIS_GO_VERSION"* ]]; then make lint; fi 32 | -------------------------------------------------------------------------------- /vendor/github.com/mmitton/ldap/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011-2015 Michael Mitton (mmitton@gmail.com) 4 | Portions copyright (c) 2015-2016 go-ldap Authors 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /vendor/github.com/mmitton/ldap/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: default install build test quicktest fmt vet lint 2 | 3 | GO_VERSION := $(shell go version | cut -d' ' -f3 | cut -d. -f2) 4 | 5 | # Only use the `-race` flag on newer versions of Go 6 | IS_OLD_GO := $(shell test $(GO_VERSION) -le 2 && echo true) 7 | ifeq ($(IS_OLD_GO),true) 8 | RACE_FLAG := 9 | else 10 | RACE_FLAG := -race -cpu 1,2,4 11 | endif 12 | 13 | default: fmt vet lint build quicktest 14 | 15 | install: 16 | go get -t -v ./... 17 | 18 | build: 19 | go build -v ./... 20 | 21 | test: 22 | go test -v $(RACE_FLAG) -cover ./... 23 | 24 | quicktest: 25 | go test ./... 26 | 27 | # Capture output and force failure when there is non-empty output 28 | fmt: 29 | @echo gofmt -l . 30 | @OUTPUT=`gofmt -l . 2>&1`; \ 31 | if [ "$$OUTPUT" ]; then \ 32 | echo "gofmt must be run on the following files:"; \ 33 | echo "$$OUTPUT"; \ 34 | exit 1; \ 35 | fi 36 | 37 | # Only run on go1.5+ 38 | vet: 39 | go tool vet -atomic -bool -copylocks -nilfunc -printf -shadow -rangeloops -unreachable -unsafeptr -unusedresult . 40 | 41 | # https://github.com/golang/lint 42 | # go get github.com/golang/lint/golint 43 | # Capture output and force failure when there is non-empty output 44 | # Only run on go1.5+ 45 | lint: 46 | @echo golint ./... 47 | @OUTPUT=`golint ./... 2>&1`; \ 48 | if [ "$$OUTPUT" ]; then \ 49 | echo "golint errors:"; \ 50 | echo "$$OUTPUT"; \ 51 | exit 1; \ 52 | fi 53 | -------------------------------------------------------------------------------- /vendor/github.com/mmitton/ldap/README: -------------------------------------------------------------------------------- 1 | Basic LDAP v3 functionality for the GO programming language. 2 | 3 | Required Libraries: 4 | github.com/mmitton/asn1-ber 5 | 6 | Working: 7 | Connecting to LDAP server 8 | Binding to LDAP server 9 | Searching for entries 10 | Compiling string filters to LDAP filters 11 | Paging Search Results 12 | Mulitple internal goroutines to handle network traffic 13 | Makes library goroutine safe 14 | Can perform multiple search requests at the same time and return 15 | the results to the proper goroutine. All requests are blocking 16 | requests, so the goroutine does not need special handling 17 | 18 | Tests Implemented: 19 | Filter Compile / Decompile 20 | 21 | TODO: 22 | Modify Requests / Responses 23 | Add Requests / Responses 24 | Delete Requests / Responses 25 | Modify DN Requests / Responses 26 | Compare Requests / Responses 27 | Implement Tests / Benchmarks 28 | -------------------------------------------------------------------------------- /vendor/github.com/mmitton/ldap/README.md: -------------------------------------------------------------------------------- 1 | [![GoDoc](https://godoc.org/gopkg.in/ldap.v2?status.svg)](https://godoc.org/gopkg.in/ldap.v2) 2 | [![Build Status](https://travis-ci.org/go-ldap/ldap.svg)](https://travis-ci.org/go-ldap/ldap) 3 | 4 | # Basic LDAP v3 functionality for the GO programming language. 5 | 6 | ## Install 7 | 8 | For the latest version use: 9 | 10 | go get gopkg.in/ldap.v2 11 | 12 | Import the latest version with: 13 | 14 | import "gopkg.in/ldap.v2" 15 | 16 | ## Required Libraries: 17 | 18 | - gopkg.in/asn1-ber.v1 19 | 20 | ## Features: 21 | 22 | - Connecting to LDAP server (non-TLS, TLS, STARTTLS) 23 | - Binding to LDAP server 24 | - Searching for entries 25 | - Filter Compile / Decompile 26 | - Paging Search Results 27 | - Modify Requests / Responses 28 | - Add Requests / Responses 29 | - Delete Requests / Responses 30 | 31 | ## Examples: 32 | 33 | - search 34 | - modify 35 | 36 | ## Contributing: 37 | 38 | Bug reports and pull requests are welcome! 39 | 40 | Before submitting a pull request, please make sure tests and verification scripts pass: 41 | ``` 42 | make all 43 | ``` 44 | 45 | To set up a pre-push hook to run the tests and verify scripts before pushing: 46 | ``` 47 | ln -s ../../.githooks/pre-push .git/hooks/pre-push 48 | ``` 49 | 50 | --- 51 | The Go gopher was designed by Renee French. (http://reneefrench.blogspot.com/) 52 | The design is licensed under the Creative Commons 3.0 Attributions license. 53 | Read this article for more details: http://blog.golang.org/gopher 54 | -------------------------------------------------------------------------------- /vendor/github.com/mmitton/ldap/atomic_value.go: -------------------------------------------------------------------------------- 1 | // +build go1.4 2 | 3 | package ldap 4 | 5 | import ( 6 | "sync/atomic" 7 | ) 8 | 9 | // For compilers that support it, we just use the underlying sync/atomic.Value 10 | // type. 11 | type atomicValue struct { 12 | atomic.Value 13 | } 14 | -------------------------------------------------------------------------------- /vendor/github.com/mmitton/ldap/atomic_value_go13.go: -------------------------------------------------------------------------------- 1 | // +build !go1.4 2 | 3 | package ldap 4 | 5 | import ( 6 | "sync" 7 | ) 8 | 9 | // This is a helper type that emulates the use of the "sync/atomic.Value" 10 | // struct that's available in Go 1.4 and up. 11 | type atomicValue struct { 12 | value interface{} 13 | lock sync.RWMutex 14 | } 15 | 16 | func (av *atomicValue) Store(val interface{}) { 17 | av.lock.Lock() 18 | av.value = val 19 | av.lock.Unlock() 20 | } 21 | 22 | func (av *atomicValue) Load() interface{} { 23 | av.lock.RLock() 24 | ret := av.value 25 | av.lock.RUnlock() 26 | 27 | return ret 28 | } 29 | -------------------------------------------------------------------------------- /vendor/github.com/mmitton/ldap/client.go: -------------------------------------------------------------------------------- 1 | package ldap 2 | 3 | import ( 4 | "crypto/tls" 5 | "time" 6 | ) 7 | 8 | // Client knows how to interact with an LDAP server 9 | type Client interface { 10 | Start() 11 | StartTLS(config *tls.Config) error 12 | Close() 13 | SetTimeout(time.Duration) 14 | 15 | Bind(username, password string) error 16 | SimpleBind(simpleBindRequest *SimpleBindRequest) (*SimpleBindResult, error) 17 | 18 | Add(addRequest *AddRequest) error 19 | Del(delRequest *DelRequest) error 20 | Modify(modifyRequest *ModifyRequest) error 21 | 22 | Compare(dn, attribute, value string) (bool, error) 23 | PasswordModify(passwordModifyRequest *PasswordModifyRequest) (*PasswordModifyResult, error) 24 | 25 | Search(searchRequest *SearchRequest) (*SearchResult, error) 26 | SearchWithPaging(searchRequest *SearchRequest, pagingSize uint32) (*SearchResult, error) 27 | } 28 | -------------------------------------------------------------------------------- /vendor/github.com/mmitton/ldap/debug.go: -------------------------------------------------------------------------------- 1 | package ldap 2 | 3 | import ( 4 | "log" 5 | 6 | "gopkg.in/asn1-ber.v1" 7 | ) 8 | 9 | // debugging type 10 | // - has a Printf method to write the debug output 11 | type debugging bool 12 | 13 | // write debug output 14 | func (debug debugging) Printf(format string, args ...interface{}) { 15 | if debug { 16 | log.Printf(format, args...) 17 | } 18 | } 19 | 20 | func (debug debugging) PrintPacket(packet *ber.Packet) { 21 | if debug { 22 | ber.PrintPacket(packet) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /vendor/github.com/mmitton/ldap/del.go: -------------------------------------------------------------------------------- 1 | // 2 | // https://tools.ietf.org/html/rfc4511 3 | // 4 | // DelRequest ::= [APPLICATION 10] LDAPDN 5 | 6 | package ldap 7 | 8 | import ( 9 | "errors" 10 | "log" 11 | 12 | "gopkg.in/asn1-ber.v1" 13 | ) 14 | 15 | // DelRequest implements an LDAP deletion request 16 | type DelRequest struct { 17 | // DN is the name of the directory entry to delete 18 | DN string 19 | // Controls hold optional controls to send with the request 20 | Controls []Control 21 | } 22 | 23 | func (d DelRequest) encode() *ber.Packet { 24 | request := ber.Encode(ber.ClassApplication, ber.TypePrimitive, ApplicationDelRequest, d.DN, "Del Request") 25 | request.Data.Write([]byte(d.DN)) 26 | return request 27 | } 28 | 29 | // NewDelRequest creates a delete request for the given DN and controls 30 | func NewDelRequest(DN string, 31 | Controls []Control) *DelRequest { 32 | return &DelRequest{ 33 | DN: DN, 34 | Controls: Controls, 35 | } 36 | } 37 | 38 | // Del executes the given delete request 39 | func (l *Conn) Del(delRequest *DelRequest) error { 40 | packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request") 41 | packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID")) 42 | packet.AppendChild(delRequest.encode()) 43 | if delRequest.Controls != nil { 44 | packet.AppendChild(encodeControls(delRequest.Controls)) 45 | } 46 | 47 | l.Debug.PrintPacket(packet) 48 | 49 | msgCtx, err := l.sendMessage(packet) 50 | if err != nil { 51 | return err 52 | } 53 | defer l.finishMessage(msgCtx) 54 | 55 | l.Debug.Printf("%d: waiting for response", msgCtx.id) 56 | packetResponse, ok := <-msgCtx.responses 57 | if !ok { 58 | return NewError(ErrorNetwork, errors.New("ldap: response channel closed")) 59 | } 60 | packet, err = packetResponse.ReadPacket() 61 | l.Debug.Printf("%d: got response %p", msgCtx.id, packet) 62 | if err != nil { 63 | return err 64 | } 65 | 66 | if l.Debug { 67 | if err := addLDAPDescriptions(packet); err != nil { 68 | return err 69 | } 70 | ber.PrintPacket(packet) 71 | } 72 | 73 | if packet.Children[1].Tag == ApplicationDelResponse { 74 | resultCode, resultDescription := getLDAPResultCode(packet) 75 | if resultCode != 0 { 76 | return NewError(resultCode, errors.New(resultDescription)) 77 | } 78 | } else { 79 | log.Printf("Unexpected Response: %d", packet.Children[1].Tag) 80 | } 81 | 82 | l.Debug.Printf("%d: returning", msgCtx.id) 83 | return nil 84 | } 85 | -------------------------------------------------------------------------------- /vendor/github.com/mmitton/ldap/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package ldap provides basic LDAP v3 functionality. 3 | */ 4 | package ldap 5 | -------------------------------------------------------------------------------- /vendor/github.com/toolkits/container/list/safelinkedlist.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | import ( 4 | "container/list" 5 | "sync" 6 | ) 7 | 8 | type SafeLinkedList struct { 9 | sync.RWMutex 10 | L *list.List 11 | } 12 | 13 | func NewSafeLinkedList() *SafeLinkedList { 14 | return &SafeLinkedList{L: list.New()} 15 | } 16 | 17 | func (this *SafeLinkedList) PopBack(max int) []interface{} { 18 | this.Lock() 19 | defer this.Unlock() 20 | 21 | count := this.L.Len() 22 | if count == 0 { 23 | return []interface{}{} 24 | } 25 | 26 | if count > max { 27 | count = max 28 | } 29 | 30 | items := make([]interface{}, 0, count) 31 | 32 | for i := 0; i < count; i++ { 33 | item := this.L.Remove(this.L.Back()) 34 | items = append(items, item) 35 | } 36 | 37 | return items 38 | } 39 | 40 | func (this *SafeLinkedList) PushFront(v interface{}) *list.Element { 41 | this.Lock() 42 | defer this.Unlock() 43 | return this.L.PushFront(v) 44 | } 45 | 46 | func (this *SafeLinkedList) Front() *list.Element { 47 | this.RLock() 48 | defer this.RUnlock() 49 | return this.L.Front() 50 | } 51 | 52 | // TODO 异步rcu锁 53 | func (this *SafeLinkedList) Len() int { 54 | this.RLock() 55 | defer this.RUnlock() 56 | return this.L.Len() 57 | } 58 | 59 | // SafeLinkedList with Limited Size 60 | type SafeLinkedListLimited struct { 61 | MaxSize int 62 | SL *SafeLinkedList 63 | } 64 | 65 | func NewSafeLinkedListLimited(maxSize int) *SafeLinkedListLimited { 66 | return &SafeLinkedListLimited{SL: NewSafeLinkedList(), MaxSize: maxSize} 67 | } 68 | 69 | func (this *SafeLinkedListLimited) PopBack(max int) []interface{} { 70 | return this.SL.PopBack(max) 71 | } 72 | 73 | func (this *SafeLinkedListLimited) PushFront(v interface{}) bool { 74 | if this.SL.Len() >= this.MaxSize { 75 | return false 76 | } 77 | 78 | this.SL.PushFront(v) 79 | return true 80 | } 81 | 82 | func (this *SafeLinkedListLimited) Front() *list.Element { 83 | return this.SL.Front() 84 | } 85 | 86 | func (this *SafeLinkedListLimited) Len() int { 87 | return this.SL.Len() 88 | } 89 | -------------------------------------------------------------------------------- /vendor/github.com/toolkits/core/convert.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | ) 7 | 8 | // convert any numeric value to int64 9 | func ToInt64(value interface{}) (d int64, err error) { 10 | val := reflect.ValueOf(value) 11 | switch value.(type) { 12 | case int, int8, int16, int32, int64: 13 | d = val.Int() 14 | case uint, uint8, uint16, uint32, uint64: 15 | d = int64(val.Uint()) 16 | default: 17 | err = fmt.Errorf("ToInt64 need numeric not `%T`", value) 18 | } 19 | return 20 | } 21 | -------------------------------------------------------------------------------- /vendor/github.com/toolkits/core/format.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func ReadableSize(raw float64) string { 8 | var t float64 = 1024 9 | var d float64 = 1 10 | 11 | if raw < t { 12 | return fmt.Sprintf("%.1fB", raw/d) 13 | } 14 | 15 | d *= 1024 16 | t *= 1024 17 | 18 | if raw < t { 19 | return fmt.Sprintf("%.1fK", raw/d) 20 | } 21 | 22 | d *= 1024 23 | t *= 1024 24 | 25 | if raw < t { 26 | return fmt.Sprintf("%.1fM", raw/d) 27 | } 28 | 29 | d *= 1024 30 | t *= 1024 31 | 32 | if raw < t { 33 | return fmt.Sprintf("%.1fG", raw/d) 34 | } 35 | 36 | d *= 1024 37 | t *= 1024 38 | 39 | if raw < t { 40 | return fmt.Sprintf("%.1fT", raw/d) 41 | } 42 | 43 | d *= 1024 44 | t *= 1024 45 | 46 | if raw < t { 47 | return fmt.Sprintf("%.1fP", raw/d) 48 | } 49 | 50 | return "TooLarge" 51 | } 52 | -------------------------------------------------------------------------------- /vendor/github.com/toolkits/file/downloader.go: -------------------------------------------------------------------------------- 1 | package file 2 | 3 | import ( 4 | "io" 5 | "net/http" 6 | "os" 7 | ) 8 | 9 | func Download(toFile, url string) error { 10 | out, err := os.Create(toFile) 11 | if err != nil { 12 | return err 13 | } 14 | 15 | defer out.Close() 16 | 17 | resp, err := http.Get(url) 18 | if err != nil { 19 | return err 20 | } 21 | 22 | defer resp.Body.Close() 23 | 24 | _, err = io.Copy(out, resp.Body) 25 | return err 26 | } 27 | -------------------------------------------------------------------------------- /vendor/github.com/toolkits/file/reader.go: -------------------------------------------------------------------------------- 1 | package file 2 | 3 | import ( 4 | "bufio" 5 | "io/ioutil" 6 | "strconv" 7 | "strings" 8 | ) 9 | 10 | func ToBytes(filePath string) ([]byte, error) { 11 | return ioutil.ReadFile(filePath) 12 | } 13 | 14 | func ToString(filePath string) (string, error) { 15 | b, err := ioutil.ReadFile(filePath) 16 | if err != nil { 17 | return "", err 18 | } 19 | return string(b), nil 20 | } 21 | 22 | func ToTrimString(filePath string) (string, error) { 23 | str, err := ToString(filePath) 24 | if err != nil { 25 | return "", err 26 | } 27 | 28 | return strings.TrimSpace(str), nil 29 | } 30 | 31 | func ToUint64(filePath string) (uint64, error) { 32 | content, err := ToTrimString(filePath) 33 | if err != nil { 34 | return 0, err 35 | } 36 | 37 | var ret uint64 38 | if ret, err = strconv.ParseUint(content, 10, 64); err != nil { 39 | return 0, err 40 | } 41 | return ret, nil 42 | } 43 | 44 | func ToInt64(filePath string) (int64, error) { 45 | content, err := ToTrimString(filePath) 46 | if err != nil { 47 | return 0, err 48 | } 49 | 50 | var ret int64 51 | if ret, err = strconv.ParseInt(content, 10, 64); err != nil { 52 | return 0, err 53 | } 54 | return ret, nil 55 | } 56 | 57 | func ReadLine(r *bufio.Reader) ([]byte, error) { 58 | line, isPrefix, err := r.ReadLine() 59 | for isPrefix && err == nil { 60 | var bs []byte 61 | bs, isPrefix, err = r.ReadLine() 62 | line = append(line, bs...) 63 | } 64 | 65 | return line, err 66 | } 67 | -------------------------------------------------------------------------------- /vendor/github.com/toolkits/file/writer.go: -------------------------------------------------------------------------------- 1 | package file 2 | 3 | import ( 4 | "os" 5 | "path" 6 | ) 7 | 8 | func WriteBytes(filePath string, b []byte) (int, error) { 9 | os.MkdirAll(path.Dir(filePath), os.ModePerm) 10 | fw, err := os.Create(filePath) 11 | if err != nil { 12 | return 0, err 13 | } 14 | defer fw.Close() 15 | return fw.Write(b) 16 | } 17 | 18 | func WriteString(filePath string, s string) (int, error) { 19 | return WriteBytes(filePath, []byte(s)) 20 | } 21 | -------------------------------------------------------------------------------- /vendor/github.com/toolkits/str/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.swo 3 | /main.go 4 | -------------------------------------------------------------------------------- /vendor/github.com/toolkits/str/base64.go: -------------------------------------------------------------------------------- 1 | package str 2 | 3 | import ( 4 | "encoding/base64" 5 | ) 6 | 7 | // base64 encode 8 | func Base64Encode(str string) string { 9 | return base64.StdEncoding.EncodeToString([]byte(str)) 10 | } 11 | 12 | // base64 decode 13 | func Base64Decode(str string) (string, error) { 14 | s, e := base64.StdEncoding.DecodeString(str) 15 | return string(s), e 16 | } 17 | -------------------------------------------------------------------------------- /vendor/github.com/toolkits/str/ids.go: -------------------------------------------------------------------------------- 1 | package str 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | "strings" 7 | ) 8 | 9 | func IdsInt64(ids string) []int64 { 10 | if ids == "" { 11 | return []int64{} 12 | } 13 | 14 | arr := strings.Split(ids, ",") 15 | count := len(arr) 16 | ret := make([]int64, 0, count) 17 | for i := 0; i < count; i++ { 18 | if arr[i] != "" { 19 | id, err := strconv.ParseInt(arr[i], 10, 64) 20 | if err == nil { 21 | ret = append(ret, id) 22 | } 23 | } 24 | } 25 | 26 | return ret 27 | } 28 | 29 | func IdsString(ids []int64) string { 30 | count := len(ids) 31 | arr := make([]string, count) 32 | for i := 0; i < count; i++ { 33 | arr[i] = fmt.Sprintf("%d", ids[i]) 34 | } 35 | return strings.Join(arr, ",") 36 | } 37 | -------------------------------------------------------------------------------- /vendor/github.com/toolkits/str/md5.go: -------------------------------------------------------------------------------- 1 | package str 2 | 3 | import ( 4 | "crypto/md5" 5 | "fmt" 6 | ) 7 | 8 | func Md5Encode(s string) string { 9 | h := md5.New() 10 | h.Write([]byte(s)) 11 | return fmt.Sprintf("%x", h.Sum(nil)) 12 | } 13 | -------------------------------------------------------------------------------- /vendor/github.com/toolkits/str/rand.go: -------------------------------------------------------------------------------- 1 | package str 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "time" 7 | ) 8 | 9 | var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") 10 | var digits = []rune("0123456789") 11 | 12 | const size = 62 13 | 14 | func RandSeq(n int) string { 15 | 16 | seed := time.Now().UnixNano() 17 | rand.Seed(seed) 18 | 19 | b := make([]rune, n) 20 | for i := range b { 21 | b[i] = letters[rand.Intn(size)] 22 | } 23 | 24 | return fmt.Sprintf("%d_%s", seed, string(b)) 25 | 26 | } 27 | 28 | func RandStr(n int) string { 29 | 30 | seed := time.Now().UnixNano() 31 | rand.Seed(seed) 32 | 33 | b := make([]rune, n) 34 | for i := range b { 35 | b[i] = letters[rand.Intn(size)] 36 | } 37 | 38 | return fmt.Sprintf("%s", string(b)) 39 | } 40 | 41 | func RandDigits(n int) string { 42 | 43 | seed := time.Now().UnixNano() 44 | rand.Seed(seed) 45 | 46 | b := make([]rune, n) 47 | for i := range b { 48 | b[i] = digits[rand.Intn(10)] 49 | } 50 | 51 | return fmt.Sprintf("%s", string(b)) 52 | } 53 | -------------------------------------------------------------------------------- /vendor/github.com/toolkits/str/regexp.go: -------------------------------------------------------------------------------- 1 | package str 2 | 3 | import ( 4 | "regexp" 5 | "strings" 6 | ) 7 | 8 | func IsMatch(val, pattern string) bool { 9 | match, err := regexp.Match(pattern, []byte(val)) 10 | if err != nil { 11 | return false 12 | } 13 | 14 | return match 15 | } 16 | 17 | func IsEnglishIdentifier(val string, pattern ...string) bool { 18 | defpattern := "^[a-zA-Z0-9\\-\\_\\.]+$" 19 | if len(pattern) > 0 { 20 | defpattern = pattern[0] 21 | } 22 | 23 | return IsMatch(val, defpattern) 24 | } 25 | 26 | func IsMail(val string) bool { 27 | return IsMatch(val, `\w[-._\w]*@\w[-._\w]*\.\w+`) 28 | } 29 | 30 | func IsPhone(val string) bool { 31 | if strings.HasPrefix(val, "+") { 32 | return IsMatch(val[1:], `\d{13}`) 33 | } else { 34 | return IsMatch(val, `\d{11}`) 35 | } 36 | } 37 | 38 | func HasDangerousCharacters(str string) bool { 39 | if strings.Contains(str, "<") { 40 | return true 41 | } 42 | 43 | if strings.Contains(str, ">") { 44 | return true 45 | } 46 | 47 | if strings.Contains(str, "&") { 48 | return true 49 | } 50 | 51 | if strings.Contains(str, "'") { 52 | return true 53 | } 54 | 55 | if strings.Contains(str, "\"") { 56 | return true 57 | } 58 | 59 | return false 60 | } 61 | 62 | func Dangerous(str string) bool { 63 | return HasDangerousCharacters(str) 64 | } 65 | -------------------------------------------------------------------------------- /vendor/github.com/unrolled/render/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | 25 | 26 | *.pem 27 | .DS_Store 28 | -------------------------------------------------------------------------------- /vendor/github.com/unrolled/render/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.3 5 | - 1.4 6 | - 1.5 7 | - 1.6 8 | - tip 9 | 10 | install: 11 | - go get github.com/eknkc/amber 12 | 13 | script: 14 | - go test -v -race -tags=integration 15 | 16 | -------------------------------------------------------------------------------- /vendor/github.com/unrolled/render/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Cory Jacobsen 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/unrolled/render/buffer.go: -------------------------------------------------------------------------------- 1 | package render 2 | 3 | import "bytes" 4 | 5 | // bufPool represents a reusable buffer pool for executing templates into. 6 | var bufPool *BufferPool 7 | 8 | // BufferPool implements a pool of bytes.Buffers in the form of a bounded channel. 9 | // Pulled from the github.com/oxtoacart/bpool package (Apache licensed). 10 | type BufferPool struct { 11 | c chan *bytes.Buffer 12 | } 13 | 14 | // NewBufferPool creates a new BufferPool bounded to the given size. 15 | func NewBufferPool(size int) (bp *BufferPool) { 16 | return &BufferPool{ 17 | c: make(chan *bytes.Buffer, size), 18 | } 19 | } 20 | 21 | // Get gets a Buffer from the BufferPool, or creates a new one if none are 22 | // available in the pool. 23 | func (bp *BufferPool) Get() (b *bytes.Buffer) { 24 | select { 25 | case b = <-bp.c: 26 | // reuse existing buffer 27 | default: 28 | // create new buffer 29 | b = bytes.NewBuffer([]byte{}) 30 | } 31 | return 32 | } 33 | 34 | // Put returns the given Buffer to the BufferPool. 35 | func (bp *BufferPool) Put(b *bytes.Buffer) { 36 | b.Reset() 37 | select { 38 | case bp.c <- b: 39 | default: // Discard the buffer if the pool is full. 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /vendor/github.com/unrolled/render/doc.go: -------------------------------------------------------------------------------- 1 | /*Package render is a package that provides functionality for easily rendering JSON, XML, binary data, and HTML templates. 2 | 3 | package main 4 | 5 | import ( 6 | "encoding/xml" 7 | "net/http" 8 | 9 | "github.com/unrolled/render" // or "gopkg.in/unrolled/render.v1" 10 | ) 11 | 12 | type ExampleXml struct { 13 | XMLName xml.Name `xml:"example"` 14 | One string `xml:"one,attr"` 15 | Two string `xml:"two,attr"` 16 | } 17 | 18 | func main() { 19 | r := render.New() 20 | mux := http.NewServeMux() 21 | 22 | mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { 23 | w.Write([]byte("Welcome, visit sub pages now.")) 24 | }) 25 | 26 | mux.HandleFunc("/data", func(w http.ResponseWriter, req *http.Request) { 27 | r.Data(w, http.StatusOK, []byte("Some binary data here.")) 28 | }) 29 | 30 | mux.HandleFunc("/text", func(w http.ResponseWriter, req *http.Request) { 31 | r.Text(w, http.StatusOK, "Plain text here") 32 | }) 33 | 34 | mux.HandleFunc("/json", func(w http.ResponseWriter, req *http.Request) { 35 | r.JSON(w, http.StatusOK, map[string]string{"hello": "json"}) 36 | }) 37 | 38 | mux.HandleFunc("/jsonp", func(w http.ResponseWriter, req *http.Request) { 39 | r.JSONP(w, http.StatusOK, "callbackName", map[string]string{"hello": "jsonp"}) 40 | }) 41 | 42 | mux.HandleFunc("/xml", func(w http.ResponseWriter, req *http.Request) { 43 | r.XML(w, http.StatusOK, ExampleXml{One: "hello", Two: "xml"}) 44 | }) 45 | 46 | mux.HandleFunc("/html", func(w http.ResponseWriter, req *http.Request) { 47 | // Assumes you have a template in ./templates called "example.tmpl". 48 | // $ mkdir -p templates && echo "

Hello HTML world.

" > templates/example.tmpl 49 | r.HTML(w, http.StatusOK, "example", nil) 50 | }) 51 | 52 | http.ListenAndServe("0.0.0.0:3000", mux) 53 | } 54 | */ 55 | package render 56 | -------------------------------------------------------------------------------- /vendor/github.com/unrolled/render/helpers.go: -------------------------------------------------------------------------------- 1 | // +build go1.6 2 | 3 | package render 4 | 5 | import ( 6 | "fmt" 7 | "html/template" 8 | ) 9 | 10 | // Included helper functions for use when rendering HTML. 11 | var helperFuncs = template.FuncMap{ 12 | "yield": func() (string, error) { 13 | return "", fmt.Errorf("yield called with no layout defined") 14 | }, 15 | "partial": func() (string, error) { 16 | return "", fmt.Errorf("block called with no layout defined") 17 | }, 18 | "current": func() (string, error) { 19 | return "", nil 20 | }, 21 | } 22 | -------------------------------------------------------------------------------- /vendor/github.com/unrolled/render/helpers_pre16.go: -------------------------------------------------------------------------------- 1 | // +build !go1.6 2 | 3 | package render 4 | 5 | import ( 6 | "fmt" 7 | "html/template" 8 | ) 9 | 10 | // Included helper functions for use when rendering HTML. 11 | var helperFuncs = template.FuncMap{ 12 | "yield": func() (string, error) { 13 | return "", fmt.Errorf("yield called with no layout defined") 14 | }, 15 | // `block` is deprecated! Use the `partial` below if you need this functionality still. 16 | // Otherwise, checkout Go's `block` implementation introduced in 1.6 17 | "block": func() (string, error) { 18 | return "", fmt.Errorf("block called with no layout defined") 19 | }, 20 | "partial": func() (string, error) { 21 | return "", fmt.Errorf("block called with no layout defined") 22 | }, 23 | "current": func() (string, error) { 24 | return "", nil 25 | }, 26 | } 27 | -------------------------------------------------------------------------------- /vendor/gopkg.in/asn1-ber.v1/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.2 4 | - 1.3 5 | - 1.4 6 | - 1.5 7 | - 1.6 8 | - 1.7 9 | - 1.8 10 | - tip 11 | go_import_path: gopkg.in/asn-ber.v1 12 | install: 13 | - go list -f '{{range .Imports}}{{.}} {{end}}' ./... | xargs go get -v 14 | - go list -f '{{range .TestImports}}{{.}} {{end}}' ./... | xargs go get -v 15 | - go get code.google.com/p/go.tools/cmd/cover || go get golang.org/x/tools/cmd/cover 16 | - go build -v ./... 17 | script: 18 | - go test -v -cover ./... 19 | -------------------------------------------------------------------------------- /vendor/gopkg.in/asn1-ber.v1/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011-2015 Michael Mitton (mmitton@gmail.com) 4 | Portions copyright (c) 2015-2016 go-asn1-ber Authors 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /vendor/gopkg.in/asn1-ber.v1/README.md: -------------------------------------------------------------------------------- 1 | [![GoDoc](https://godoc.org/gopkg.in/asn1-ber.v1?status.svg)](https://godoc.org/gopkg.in/asn1-ber.v1) [![Build Status](https://travis-ci.org/go-asn1-ber/asn1-ber.svg)](https://travis-ci.org/go-asn1-ber/asn1-ber) 2 | 3 | 4 | ASN1 BER Encoding / Decoding Library for the GO programming language. 5 | --------------------------------------------------------------------- 6 | 7 | Required libraries: 8 | None 9 | 10 | Working: 11 | Very basic encoding / decoding needed for LDAP protocol 12 | 13 | Tests Implemented: 14 | A few 15 | 16 | TODO: 17 | Fix all encoding / decoding to conform to ASN1 BER spec 18 | Implement Tests / Benchmarks 19 | 20 | --- 21 | 22 | The Go gopher was designed by Renee French. (http://reneefrench.blogspot.com/) 23 | The design is licensed under the Creative Commons 3.0 Attributions license. 24 | Read this article for more details: http://blog.golang.org/gopher 25 | -------------------------------------------------------------------------------- /vendor/gopkg.in/asn1-ber.v1/content_int.go: -------------------------------------------------------------------------------- 1 | package ber 2 | 3 | func encodeUnsignedInteger(i uint64) []byte { 4 | n := uint64Length(i) 5 | out := make([]byte, n) 6 | 7 | var j int 8 | for ; n > 0; n-- { 9 | out[j] = (byte(i >> uint((n-1)*8))) 10 | j++ 11 | } 12 | 13 | return out 14 | } 15 | 16 | func uint64Length(i uint64) (numBytes int) { 17 | numBytes = 1 18 | 19 | for i > 255 { 20 | numBytes++ 21 | i >>= 8 22 | } 23 | 24 | return 25 | } 26 | -------------------------------------------------------------------------------- /vendor/gopkg.in/asn1-ber.v1/header.go: -------------------------------------------------------------------------------- 1 | package ber 2 | 3 | import ( 4 | "errors" 5 | "io" 6 | ) 7 | 8 | func readHeader(reader io.Reader) (identifier Identifier, length int, read int, err error) { 9 | if i, c, err := readIdentifier(reader); err != nil { 10 | return Identifier{}, 0, read, err 11 | } else { 12 | identifier = i 13 | read += c 14 | } 15 | 16 | if l, c, err := readLength(reader); err != nil { 17 | return Identifier{}, 0, read, err 18 | } else { 19 | length = l 20 | read += c 21 | } 22 | 23 | // Validate length type with identifier (x.600, 8.1.3.2.a) 24 | if length == LengthIndefinite && identifier.TagType == TypePrimitive { 25 | return Identifier{}, 0, read, errors.New("indefinite length used with primitive type") 26 | } 27 | 28 | return identifier, length, read, nil 29 | } 30 | -------------------------------------------------------------------------------- /vendor/gopkg.in/asn1-ber.v1/identifier.go: -------------------------------------------------------------------------------- 1 | package ber 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io" 7 | "math" 8 | ) 9 | 10 | func readIdentifier(reader io.Reader) (Identifier, int, error) { 11 | identifier := Identifier{} 12 | read := 0 13 | 14 | // identifier byte 15 | b, err := readByte(reader) 16 | if err != nil { 17 | if Debug { 18 | fmt.Printf("error reading identifier byte: %v\n", err) 19 | } 20 | return Identifier{}, read, err 21 | } 22 | read++ 23 | 24 | identifier.ClassType = Class(b) & ClassBitmask 25 | identifier.TagType = Type(b) & TypeBitmask 26 | 27 | if tag := Tag(b) & TagBitmask; tag != HighTag { 28 | // short-form tag 29 | identifier.Tag = tag 30 | return identifier, read, nil 31 | } 32 | 33 | // high-tag-number tag 34 | tagBytes := 0 35 | for { 36 | b, err := readByte(reader) 37 | if err != nil { 38 | if Debug { 39 | fmt.Printf("error reading high-tag-number tag byte %d: %v\n", tagBytes, err) 40 | } 41 | return Identifier{}, read, err 42 | } 43 | tagBytes++ 44 | read++ 45 | 46 | // Lowest 7 bits get appended to the tag value (x.690, 8.1.2.4.2.b) 47 | identifier.Tag <<= 7 48 | identifier.Tag |= Tag(b) & HighTagValueBitmask 49 | 50 | // First byte may not be all zeros (x.690, 8.1.2.4.2.c) 51 | if tagBytes == 1 && identifier.Tag == 0 { 52 | return Identifier{}, read, errors.New("invalid first high-tag-number tag byte") 53 | } 54 | // Overflow of int64 55 | // TODO: support big int tags? 56 | if tagBytes > 9 { 57 | return Identifier{}, read, errors.New("high-tag-number tag overflow") 58 | } 59 | 60 | // Top bit of 0 means this is the last byte in the high-tag-number tag (x.690, 8.1.2.4.2.a) 61 | if Tag(b)&HighTagContinueBitmask == 0 { 62 | break 63 | } 64 | } 65 | 66 | return identifier, read, nil 67 | } 68 | 69 | func encodeIdentifier(identifier Identifier) []byte { 70 | b := []byte{0x0} 71 | b[0] |= byte(identifier.ClassType) 72 | b[0] |= byte(identifier.TagType) 73 | 74 | if identifier.Tag < HighTag { 75 | // Short-form 76 | b[0] |= byte(identifier.Tag) 77 | } else { 78 | // high-tag-number 79 | b[0] |= byte(HighTag) 80 | 81 | tag := identifier.Tag 82 | 83 | highBit := uint(63) 84 | for { 85 | if tag&(1<= 0; i-- { 93 | offset := uint(i) * 7 94 | mask := Tag(0x7f) << offset 95 | tagByte := (tag & mask) >> offset 96 | if i != 0 { 97 | tagByte |= 0x80 98 | } 99 | b = append(b, byte(tagByte)) 100 | } 101 | } 102 | return b 103 | } 104 | -------------------------------------------------------------------------------- /vendor/gopkg.in/asn1-ber.v1/length.go: -------------------------------------------------------------------------------- 1 | package ber 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io" 7 | ) 8 | 9 | func readLength(reader io.Reader) (length int, read int, err error) { 10 | // length byte 11 | b, err := readByte(reader) 12 | if err != nil { 13 | if Debug { 14 | fmt.Printf("error reading length byte: %v\n", err) 15 | } 16 | return 0, 0, err 17 | } 18 | read++ 19 | 20 | switch { 21 | case b == 0xFF: 22 | // Invalid 0xFF (x.600, 8.1.3.5.c) 23 | return 0, read, errors.New("invalid length byte 0xff") 24 | 25 | case b == LengthLongFormBitmask: 26 | // Indefinite form, we have to decode packets until we encounter an EOC packet (x.600, 8.1.3.6) 27 | length = LengthIndefinite 28 | 29 | case b&LengthLongFormBitmask == 0: 30 | // Short definite form, extract the length from the bottom 7 bits (x.600, 8.1.3.4) 31 | length = int(b) & LengthValueBitmask 32 | 33 | case b&LengthLongFormBitmask != 0: 34 | // Long definite form, extract the number of length bytes to follow from the bottom 7 bits (x.600, 8.1.3.5.b) 35 | lengthBytes := int(b) & LengthValueBitmask 36 | // Protect against overflow 37 | // TODO: support big int length? 38 | if lengthBytes > 8 { 39 | return 0, read, errors.New("long-form length overflow") 40 | } 41 | 42 | // Accumulate into a 64-bit variable 43 | var length64 int64 44 | for i := 0; i < lengthBytes; i++ { 45 | b, err = readByte(reader) 46 | if err != nil { 47 | if Debug { 48 | fmt.Printf("error reading long-form length byte %d: %v\n", i, err) 49 | } 50 | return 0, read, err 51 | } 52 | read++ 53 | 54 | // x.600, 8.1.3.5 55 | length64 <<= 8 56 | length64 |= int64(b) 57 | } 58 | 59 | // Cast to a platform-specific integer 60 | length = int(length64) 61 | // Ensure we didn't overflow 62 | if int64(length) != length64 { 63 | return 0, read, errors.New("long-form length overflow") 64 | } 65 | 66 | default: 67 | return 0, read, errors.New("invalid length byte") 68 | } 69 | 70 | return length, read, nil 71 | } 72 | 73 | func encodeLength(length int) []byte { 74 | length_bytes := encodeUnsignedInteger(uint64(length)) 75 | if length > 127 || len(length_bytes) > 1 { 76 | longFormBytes := []byte{(LengthLongFormBitmask | byte(len(length_bytes)))} 77 | longFormBytes = append(longFormBytes, length_bytes...) 78 | length_bytes = longFormBytes 79 | } 80 | return length_bytes 81 | } 82 | -------------------------------------------------------------------------------- /vendor/gopkg.in/asn1-ber.v1/util.go: -------------------------------------------------------------------------------- 1 | package ber 2 | 3 | import "io" 4 | 5 | func readByte(reader io.Reader) (byte, error) { 6 | bytes := make([]byte, 1, 1) 7 | _, err := io.ReadFull(reader, bytes) 8 | if err != nil { 9 | if err == io.EOF { 10 | return 0, io.ErrUnexpectedEOF 11 | } 12 | return 0, err 13 | } 14 | return bytes[0], nil 15 | } 16 | 17 | func isEOCPacket(p *Packet) bool { 18 | return p != nil && 19 | p.Tag == TagEOC && 20 | p.ClassType == ClassUniversal && 21 | p.TagType == TypePrimitive && 22 | len(p.ByteValue) == 0 && 23 | len(p.Children) == 0 24 | } 25 | -------------------------------------------------------------------------------- /vendor/stathat.com/c/consistent/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2012 Numerotron Inc. 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/stathat.com/c/consistent/README.md: -------------------------------------------------------------------------------- 1 | consistent 2 | ========== 3 | 4 | Consistent hash package for Go. 5 | 6 | Installation 7 | ------------ 8 | 9 | go get stathat.com/c/consistent 10 | 11 | Examples 12 | -------- 13 | 14 | Look at the [godoc](http://godoc.org/stathat.com/c/consistent). 15 | 16 | Status 17 | ------ 18 | 19 | This package was extracted from production code powering [StatHat](http://www.stathat.com), 20 | so clearly we feel that it is production-ready, but it should still be considered 21 | experimental as other uses of it could reveal issues we aren't experiencing. 22 | 23 | Contact us 24 | ---------- 25 | 26 | We'd love to hear from you if you are using `consistent`. 27 | Get in touch: [@stathat](http://twitter.com/stathat) or [contact us here](http://www.stathat.com/docs/contact). 28 | 29 | About 30 | ----- 31 | 32 | Written by Patrick Crosby at [StatHat](http://www.stathat.com). Twitter: [@stathat](http://twitter.com/stathat) 33 | -------------------------------------------------------------------------------- /views/auth/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ template "inc/head" . }} 5 | 6 | 7 | 8 | 9 |
10 | 11 |
12 | 13 |
14 |
15 | 16 |
17 |
18 | 19 |
20 |
21 |
22 | no account? sign up 23 |
24 |
25 |
26 | 27 | 28 | 38 | {{ template "inc/footer" . }} 39 | 40 | -------------------------------------------------------------------------------- /views/auth/register.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ template "inc/head" . }} 5 | 6 | 7 | 8 | 9 |
10 | 11 |
12 | 13 |
14 |
15 | 16 |
17 |
18 | 19 |
20 |
21 | 22 |
23 |
24 |
25 | has account? sign in 26 |
27 |
28 |
29 | 30 | 31 | 41 | {{ template "inc/footer" . }} 42 | 43 | -------------------------------------------------------------------------------- /views/chart/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ template "inc/head" . }} 5 | 6 | 7 | {{ template "inc/nav_chart" . }} 8 | 9 | 10 |
11 | {{ if .AlarmOn }} 12 |
13 |
告警历史
14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | {{range .Events}} 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | {{end}} 38 | 39 |
Status上报值UrlIp返回码响应时间(ms)时间
{{.Status}}{{.Result}}{{.Url}}{{.Ip}}{{.RespCode}}{{.RespTime}}{{HumenTime .EventTime}}
40 | 41 |
42 | {{ end }} 43 | 44 | 45 | 84 | 85 | {{ template "inc/footer" . }} 86 | 87 | -------------------------------------------------------------------------------- /views/inc/chpwd.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /views/inc/error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 出错了 7 | 8 | 9 | 10 |
11 |

:(

12 |

{{.Error}}

13 |

14 | 返回上页 15 | | 16 | 返回首页

17 |
18 | 19 | -------------------------------------------------------------------------------- /views/inc/footer.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | Powered by 710leo 4 |
5 |
6 | -------------------------------------------------------------------------------- /views/inc/head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | URLooker 5 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /views/inc/pager.html: -------------------------------------------------------------------------------- 1 | {{if gt .Pager.PageNums 1}} 2 |
    3 | {{if .Pager.HasPrev}} 4 |
  • 首页
  • 5 |
  • <
  • 6 | {{else}} 7 |
  • 首页
  • 8 |
  • <
  • 9 | {{end}} 10 | {{range $index, $page := .Pager.Pages}} 11 | 12 | {{$page}} 13 | 14 | {{end}} 15 | {{if .Pager.HasNext}} 16 |
  • >
  • 17 |
  • 尾页
  • 18 | {{else}} 19 |
  • >
  • 21 |
  • 尾页
  • 23 | {{end}} 24 |
25 | {{end}} -------------------------------------------------------------------------------- /views/inc/profile.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 | 6 |
7 |
8 |
9 | 10 |
11 | 12 |
13 |
14 |
15 | 16 |
17 | 18 |
19 |
20 |
21 | 22 |
23 | 24 |
25 |
26 |
-------------------------------------------------------------------------------- /views/inc/select2.html: -------------------------------------------------------------------------------- 1 | {{ template "inc/head" . }} 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /views/status/log.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ template "inc/head" . }} 5 | 6 | 7 | 8 | {{ template "inc/nav" . }} 9 |
10 |
11 |
12 |
13 |
14 | 15 | 16 |
17 |
18 |
19 | 20 | 21 | {{ template "inc/footer" . }} 22 | 23 | -------------------------------------------------------------------------------- /views/team/create.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ template "inc/select2" . }} 5 | 6 | 7 | {{ template "inc/nav" . }} 8 | 9 |
10 |
11 |
12 |

Create Team

13 |
14 |
15 |
16 | 18 |
19 |
20 | 22 |
23 |
24 | 26 |
27 | 31 | 32 | 33 | 返回 34 | 35 |
36 |
37 |
38 | 39 | 66 | 67 | {{ template "inc/footer" . }} 68 | 69 | 70 | -------------------------------------------------------------------------------- /views/team/edit.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ template "inc/select2" . }} 5 | 6 | 7 | {{ template "inc/nav" . }} 8 | 9 |
10 |
11 |
12 |

Edit Team

13 |
14 |
15 |
16 | 18 |
19 |
20 | 22 |
23 |
24 | 26 |
27 | 31 | 32 | 33 | 返回 34 | 35 |
36 |
37 |
38 | 39 | 71 | 72 | {{ template "inc/footer" . }} 73 | 74 | 75 | -------------------------------------------------------------------------------- /views/team/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ template "inc/head" . }} 5 | 6 | 7 | {{ template "inc/nav" . }} 8 |
9 | 10 |
11 |
12 | 13 |
14 | 17 | 18 | 19 | 创建 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | {{range .Teams}} 35 | 36 | 37 | 38 | 45 | 46 | 51 | 52 | {{end}} 53 | 54 |
告警组描述成员创建人操作
{{.Name}}{{.Resume}} 39 |
40 | {{range UsersOfTeam .Id}} 41 | {{.Name}} 42 | {{end}} 43 |
44 |
{{.CreatorName}} 47 | 48 | 49 | 50 |
55 | 56 | {{ template "inc/pager" . }} 57 |
58 | 59 | 72 | {{ template "inc/footer" . }} 73 | 74 | 75 | 76 | --------------------------------------------------------------------------------