├── .gitignore ├── Godeps ├── Godeps.json ├── Readme └── _workspace │ ├── .gitignore │ └── src │ ├── code.google.com │ └── p │ │ └── go-uuid │ │ └── uuid │ │ ├── LICENSE │ │ ├── dce.go │ │ ├── doc.go │ │ ├── hash.go │ │ ├── json.go │ │ ├── node.go │ │ ├── time.go │ │ ├── util.go │ │ ├── uuid.go │ │ ├── version1.go │ │ └── version4.go │ ├── github.com │ ├── auth0 │ │ └── go-jwt-middleware │ │ │ ├── LICENSE.txt │ │ │ ├── README.md │ │ │ ├── examples │ │ │ ├── martini-example │ │ │ │ ├── README.md │ │ │ │ └── main.go │ │ │ └── negroni-example │ │ │ │ ├── README.md │ │ │ │ └── main.go │ │ │ ├── jwtmiddleware.go │ │ │ └── keys │ │ │ └── sample-key │ ├── boltdb │ │ └── bolt │ │ │ ├── .gitignore │ │ │ ├── LICENSE │ │ │ ├── Makefile │ │ │ ├── README.md │ │ │ ├── batch.go │ │ │ ├── bolt_386.go │ │ │ ├── bolt_amd64.go │ │ │ ├── bolt_arm.go │ │ │ ├── bolt_arm64.go │ │ │ ├── bolt_linux.go │ │ │ ├── bolt_openbsd.go │ │ │ ├── bolt_ppc64le.go │ │ │ ├── bolt_s390x.go │ │ │ ├── bolt_unix.go │ │ │ ├── bolt_unix_solaris.go │ │ │ ├── bolt_windows.go │ │ │ ├── boltsync_unix.go │ │ │ ├── bucket.go │ │ │ ├── cmd │ │ │ └── bolt │ │ │ │ └── main.go │ │ │ ├── cursor.go │ │ │ ├── db.go │ │ │ ├── doc.go │ │ │ ├── errors.go │ │ │ ├── freelist.go │ │ │ ├── node.go │ │ │ ├── page.go │ │ │ └── tx.go │ ├── codegangsta │ │ └── negroni │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── doc.go │ │ │ ├── logger.go │ │ │ ├── negroni.go │ │ │ ├── recovery.go │ │ │ ├── response_writer.go │ │ │ ├── static.go │ │ │ └── translations │ │ │ └── README_pt_br.md │ ├── dgrijalva │ │ └── jwt-go │ │ │ ├── .gitignore │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── VERSION_HISTORY.md │ │ │ ├── cmd │ │ │ └── jwt │ │ │ │ └── app.go │ │ │ ├── doc.go │ │ │ ├── ecdsa.go │ │ │ ├── ecdsa_utils.go │ │ │ ├── errors.go │ │ │ ├── hmac.go │ │ │ ├── jwt.go │ │ │ ├── rsa.go │ │ │ ├── rsa_pss.go │ │ │ ├── rsa_utils.go │ │ │ ├── signing_method.go │ │ │ └── test │ │ │ ├── hmacTestKey │ │ │ ├── sample_key │ │ │ └── sample_key.pub │ ├── 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 │ ├── jinzhu │ │ └── copier │ │ │ ├── Guardfile │ │ │ ├── License │ │ │ ├── README.md │ │ │ └── copier.go │ ├── jmcvetta │ │ └── randutil │ │ │ ├── .travis.yml │ │ │ ├── LICENSE.txt │ │ │ ├── README.md │ │ │ └── randutil.go │ ├── mholt │ │ └── binding │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── binding.go │ │ │ └── errors.go │ ├── nlf │ │ └── boltons │ │ │ ├── .gitignore │ │ │ └── boltons.go │ └── unrolled │ │ └── render │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── README.md │ │ ├── buffer.go │ │ ├── doc.go │ │ ├── engine.go │ │ ├── fixtures │ │ ├── amber │ │ │ ├── example.amber │ │ │ └── layouts │ │ │ │ └── base.amber │ │ ├── basic │ │ │ ├── admin │ │ │ │ └── index.tmpl │ │ │ ├── another_layout.tmpl │ │ │ ├── content.tmpl │ │ │ ├── current_layout.tmpl │ │ │ ├── delims.tmpl │ │ │ ├── hello.tmpl │ │ │ ├── hypertext.html │ │ │ └── layout.tmpl │ │ ├── blocks │ │ │ ├── content-partial.tmpl │ │ │ ├── content.tmpl │ │ │ └── layout.tmpl │ │ ├── custom_funcs │ │ │ └── index.tmpl │ │ └── template-dir-test │ │ │ ├── 0.tmpl │ │ │ ├── dedicated.tmpl │ │ │ └── notbad.tmpl │ │ │ └── subdir │ │ │ └── 1.tmpl │ │ └── render.go │ └── golang.org │ └── x │ └── crypto │ ├── bcrypt │ ├── base64.go │ └── bcrypt.go │ └── blowfish │ ├── block.go │ ├── cipher.go │ └── const.go ├── LICENSE ├── README.md ├── app └── app.go ├── config.json ├── config └── config.go ├── handlers ├── info.go ├── proxy.go ├── record.go ├── token.go └── user.go ├── main.go ├── middleware └── middleware.go ├── models ├── record.go └── user.go └── release.sh /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.pem 3 | *.db 4 | static 5 | shellsquid 6 | -------------------------------------------------------------------------------- /Godeps/Godeps.json: -------------------------------------------------------------------------------- 1 | { 2 | "ImportPath": "github.com/tomsteele/shellsquid", 3 | "GoVersion": "go1.5", 4 | "Deps": [ 5 | { 6 | "ImportPath": "code.google.com/p/go-uuid/uuid", 7 | "Comment": "null-15", 8 | "Rev": "35bc42037350f0078e3c974c6ea690f1926603ab" 9 | }, 10 | { 11 | "ImportPath": "github.com/auth0/go-jwt-middleware", 12 | "Rev": "8c897f7c3631a9e9405b9496fd8ce241acdef230" 13 | }, 14 | { 15 | "ImportPath": "github.com/boltdb/bolt", 16 | "Comment": "v1.1.0-2-gb4e2091", 17 | "Rev": "b4e20916f62da6837bd349ea75d58c475e1f9fe1" 18 | }, 19 | { 20 | "ImportPath": "github.com/codegangsta/negroni", 21 | "Comment": "v0.1-70-gc7477ad", 22 | "Rev": "c7477ad8e330bef55bf1ebe300cf8aa67c492d1b" 23 | }, 24 | { 25 | "ImportPath": "github.com/dgrijalva/jwt-go", 26 | "Comment": "v2.3.0-7-gacc5a5f", 27 | "Rev": "acc5a5f31e3493f1992315fd85aa49226372b810" 28 | }, 29 | { 30 | "ImportPath": "github.com/gorilla/context", 31 | "Rev": "1c83b3eabd45b6d76072b66b746c20815fb2872d" 32 | }, 33 | { 34 | "ImportPath": "github.com/gorilla/mux", 35 | "Rev": "ad4d7a5882b961e07e2626045eb995c022ac6664" 36 | }, 37 | { 38 | "ImportPath": "github.com/jinzhu/copier", 39 | "Rev": "004b63018d8272ac37f16e58c1e80401d67f7a06" 40 | }, 41 | { 42 | "ImportPath": "github.com/jmcvetta/randutil", 43 | "Rev": "2bb1b664bcff821e02b2a0644cd29c7e824d54f8" 44 | }, 45 | { 46 | "ImportPath": "github.com/mholt/binding", 47 | "Rev": "81bd1588a68d30e93c9c598098ed25be0cd0ef27" 48 | }, 49 | { 50 | "ImportPath": "github.com/nlf/boltons", 51 | "Rev": "e61029dbac0216824a7ec632480ec80e445924d6" 52 | }, 53 | { 54 | "ImportPath": "github.com/unrolled/render", 55 | "Rev": "d7c3df429697d42cc63332fa9ab88fef7a0fa6f7" 56 | }, 57 | { 58 | "ImportPath": "golang.org/x/crypto/bcrypt", 59 | "Rev": "c8b9e6388ef638d5a8a9d865c634befdc46a6784" 60 | }, 61 | { 62 | "ImportPath": "golang.org/x/crypto/blowfish", 63 | "Rev": "c8b9e6388ef638d5a8a9d865c634befdc46a6784" 64 | } 65 | ] 66 | } 67 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /Godeps/_workspace/.gitignore: -------------------------------------------------------------------------------- 1 | /pkg 2 | /bin 3 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009,2014 Google Inc. 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 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/dce.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. 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 uuid 6 | 7 | import ( 8 | "encoding/binary" 9 | "fmt" 10 | "os" 11 | ) 12 | 13 | // A Domain represents a Version 2 domain 14 | type Domain byte 15 | 16 | // Domain constants for DCE Security (Version 2) UUIDs. 17 | const ( 18 | Person = Domain(0) 19 | Group = Domain(1) 20 | Org = Domain(2) 21 | ) 22 | 23 | // NewDCESecurity returns a DCE Security (Version 2) UUID. 24 | // 25 | // The domain should be one of Person, Group or Org. 26 | // On a POSIX system the id should be the users UID for the Person 27 | // domain and the users GID for the Group. The meaning of id for 28 | // the domain Org or on non-POSIX systems is site defined. 29 | // 30 | // For a given domain/id pair the same token may be returned for up to 31 | // 7 minutes and 10 seconds. 32 | func NewDCESecurity(domain Domain, id uint32) UUID { 33 | uuid := NewUUID() 34 | if uuid != nil { 35 | uuid[6] = (uuid[6] & 0x0f) | 0x20 // Version 2 36 | uuid[9] = byte(domain) 37 | binary.BigEndian.PutUint32(uuid[0:], id) 38 | } 39 | return uuid 40 | } 41 | 42 | // NewDCEPerson returns a DCE Security (Version 2) UUID in the person 43 | // domain with the id returned by os.Getuid. 44 | // 45 | // NewDCEPerson(Person, uint32(os.Getuid())) 46 | func NewDCEPerson() UUID { 47 | return NewDCESecurity(Person, uint32(os.Getuid())) 48 | } 49 | 50 | // NewDCEGroup returns a DCE Security (Version 2) UUID in the group 51 | // domain with the id returned by os.Getgid. 52 | // 53 | // NewDCEGroup(Group, uint32(os.Getgid())) 54 | func NewDCEGroup() UUID { 55 | return NewDCESecurity(Group, uint32(os.Getgid())) 56 | } 57 | 58 | // Domain returns the domain for a Version 2 UUID or false. 59 | func (uuid UUID) Domain() (Domain, bool) { 60 | if v, _ := uuid.Version(); v != 2 { 61 | return 0, false 62 | } 63 | return Domain(uuid[9]), true 64 | } 65 | 66 | // Id returns the id for a Version 2 UUID or false. 67 | func (uuid UUID) Id() (uint32, bool) { 68 | if v, _ := uuid.Version(); v != 2 { 69 | return 0, false 70 | } 71 | return binary.BigEndian.Uint32(uuid[0:4]), true 72 | } 73 | 74 | func (d Domain) String() string { 75 | switch d { 76 | case Person: 77 | return "Person" 78 | case Group: 79 | return "Group" 80 | case Org: 81 | return "Org" 82 | } 83 | return fmt.Sprintf("Domain%d", int(d)) 84 | } 85 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. 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 | // The uuid package generates and inspects UUIDs. 6 | // 7 | // UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security Services. 8 | package uuid 9 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/hash.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. 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 uuid 6 | 7 | import ( 8 | "crypto/md5" 9 | "crypto/sha1" 10 | "hash" 11 | ) 12 | 13 | // Well known Name Space IDs and UUIDs 14 | var ( 15 | NameSpace_DNS = Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8") 16 | NameSpace_URL = Parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8") 17 | NameSpace_OID = Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8") 18 | NameSpace_X500 = Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8") 19 | NIL = Parse("00000000-0000-0000-0000-000000000000") 20 | ) 21 | 22 | // NewHash returns a new UUID dervied from the hash of space concatenated with 23 | // data generated by h. The hash should be at least 16 byte in length. The 24 | // first 16 bytes of the hash are used to form the UUID. The version of the 25 | // UUID will be the lower 4 bits of version. NewHash is used to implement 26 | // NewMD5 and NewSHA1. 27 | func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID { 28 | h.Reset() 29 | h.Write(space) 30 | h.Write([]byte(data)) 31 | s := h.Sum(nil) 32 | uuid := make([]byte, 16) 33 | copy(uuid, s) 34 | uuid[6] = (uuid[6] & 0x0f) | uint8((version&0xf)<<4) 35 | uuid[8] = (uuid[8] & 0x3f) | 0x80 // RFC 4122 variant 36 | return uuid 37 | } 38 | 39 | // NewMD5 returns a new MD5 (Version 3) UUID based on the 40 | // supplied name space and data. 41 | // 42 | // NewHash(md5.New(), space, data, 3) 43 | func NewMD5(space UUID, data []byte) UUID { 44 | return NewHash(md5.New(), space, data, 3) 45 | } 46 | 47 | // NewSHA1 returns a new SHA1 (Version 5) UUID based on the 48 | // supplied name space and data. 49 | // 50 | // NewHash(sha1.New(), space, data, 5) 51 | func NewSHA1(space UUID, data []byte) UUID { 52 | return NewHash(sha1.New(), space, data, 5) 53 | } 54 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/json.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Google Inc. 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 uuid 6 | 7 | import "errors" 8 | 9 | func (u UUID) MarshalJSON() ([]byte, error) { 10 | if len(u) == 0 { 11 | return []byte(`""`), nil 12 | } 13 | return []byte(`"` + u.String() + `"`), nil 14 | } 15 | 16 | func (u *UUID) UnmarshalJSON(data []byte) error { 17 | if len(data) == 0 || string(data) == `""` { 18 | return nil 19 | } 20 | if len(data) < 2 || data[0] != '"' || data[len(data)-1] != '"' { 21 | return errors.New("invalid UUID format") 22 | } 23 | data = data[1 : len(data)-1] 24 | uu := Parse(string(data)) 25 | if uu == nil { 26 | return errors.New("invalid UUID format") 27 | } 28 | *u = uu 29 | return nil 30 | } 31 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/node.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. 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 uuid 6 | 7 | import "net" 8 | 9 | var ( 10 | interfaces []net.Interface // cached list of interfaces 11 | ifname string // name of interface being used 12 | nodeID []byte // hardware for version 1 UUIDs 13 | ) 14 | 15 | // NodeInterface returns the name of the interface from which the NodeID was 16 | // derived. The interface "user" is returned if the NodeID was set by 17 | // SetNodeID. 18 | func NodeInterface() string { 19 | return ifname 20 | } 21 | 22 | // SetNodeInterface selects the hardware address to be used for Version 1 UUIDs. 23 | // If name is "" then the first usable interface found will be used or a random 24 | // Node ID will be generated. If a named interface cannot be found then false 25 | // is returned. 26 | // 27 | // SetNodeInterface never fails when name is "". 28 | func SetNodeInterface(name string) bool { 29 | if interfaces == nil { 30 | var err error 31 | interfaces, err = net.Interfaces() 32 | if err != nil && name != "" { 33 | return false 34 | } 35 | } 36 | 37 | for _, ifs := range interfaces { 38 | if len(ifs.HardwareAddr) >= 6 && (name == "" || name == ifs.Name) { 39 | if setNodeID(ifs.HardwareAddr) { 40 | ifname = ifs.Name 41 | return true 42 | } 43 | } 44 | } 45 | 46 | // We found no interfaces with a valid hardware address. If name 47 | // does not specify a specific interface generate a random Node ID 48 | // (section 4.1.6) 49 | if name == "" { 50 | if nodeID == nil { 51 | nodeID = make([]byte, 6) 52 | } 53 | randomBits(nodeID) 54 | return true 55 | } 56 | return false 57 | } 58 | 59 | // NodeID returns a slice of a copy of the current Node ID, setting the Node ID 60 | // if not already set. 61 | func NodeID() []byte { 62 | if nodeID == nil { 63 | SetNodeInterface("") 64 | } 65 | nid := make([]byte, 6) 66 | copy(nid, nodeID) 67 | return nid 68 | } 69 | 70 | // SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes 71 | // of id are used. If id is less than 6 bytes then false is returned and the 72 | // Node ID is not set. 73 | func SetNodeID(id []byte) bool { 74 | if setNodeID(id) { 75 | ifname = "user" 76 | return true 77 | } 78 | return false 79 | } 80 | 81 | func setNodeID(id []byte) bool { 82 | if len(id) < 6 { 83 | return false 84 | } 85 | if nodeID == nil { 86 | nodeID = make([]byte, 6) 87 | } 88 | copy(nodeID, id) 89 | return true 90 | } 91 | 92 | // NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is 93 | // not valid. The NodeID is only well defined for version 1 and 2 UUIDs. 94 | func (uuid UUID) NodeID() []byte { 95 | if len(uuid) != 16 { 96 | return nil 97 | } 98 | node := make([]byte, 6) 99 | copy(node, uuid[10:]) 100 | return node 101 | } 102 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/time.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Google Inc. 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 uuid 6 | 7 | import ( 8 | "encoding/binary" 9 | "sync" 10 | "time" 11 | ) 12 | 13 | // A Time represents a time as the number of 100's of nanoseconds since 15 Oct 14 | // 1582. 15 | type Time int64 16 | 17 | const ( 18 | lillian = 2299160 // Julian day of 15 Oct 1582 19 | unix = 2440587 // Julian day of 1 Jan 1970 20 | epoch = unix - lillian // Days between epochs 21 | g1582 = epoch * 86400 // seconds between epochs 22 | g1582ns100 = g1582 * 10000000 // 100s of a nanoseconds between epochs 23 | ) 24 | 25 | var ( 26 | mu sync.Mutex 27 | lasttime uint64 // last time we returned 28 | clock_seq uint16 // clock sequence for this run 29 | 30 | timeNow = time.Now // for testing 31 | ) 32 | 33 | // UnixTime converts t the number of seconds and nanoseconds using the Unix 34 | // epoch of 1 Jan 1970. 35 | func (t Time) UnixTime() (sec, nsec int64) { 36 | sec = int64(t - g1582ns100) 37 | nsec = (sec % 10000000) * 100 38 | sec /= 10000000 39 | return sec, nsec 40 | } 41 | 42 | // GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and 43 | // clock sequence as well as adjusting the clock sequence as needed. An error 44 | // is returned if the current time cannot be determined. 45 | func GetTime() (Time, uint16, error) { 46 | defer mu.Unlock() 47 | mu.Lock() 48 | return getTime() 49 | } 50 | 51 | func getTime() (Time, uint16, error) { 52 | t := timeNow() 53 | 54 | // If we don't have a clock sequence already, set one. 55 | if clock_seq == 0 { 56 | setClockSequence(-1) 57 | } 58 | now := uint64(t.UnixNano()/100) + g1582ns100 59 | 60 | // If time has gone backwards with this clock sequence then we 61 | // increment the clock sequence 62 | if now <= lasttime { 63 | clock_seq = ((clock_seq + 1) & 0x3fff) | 0x8000 64 | } 65 | lasttime = now 66 | return Time(now), clock_seq, nil 67 | } 68 | 69 | // ClockSequence returns the current clock sequence, generating one if not 70 | // already set. The clock sequence is only used for Version 1 UUIDs. 71 | // 72 | // The uuid package does not use global static storage for the clock sequence or 73 | // the last time a UUID was generated. Unless SetClockSequence a new random 74 | // clock sequence is generated the first time a clock sequence is requested by 75 | // ClockSequence, GetTime, or NewUUID. (section 4.2.1.1) sequence is generated 76 | // for 77 | func ClockSequence() int { 78 | defer mu.Unlock() 79 | mu.Lock() 80 | return clockSequence() 81 | } 82 | 83 | func clockSequence() int { 84 | if clock_seq == 0 { 85 | setClockSequence(-1) 86 | } 87 | return int(clock_seq & 0x3fff) 88 | } 89 | 90 | // SetClockSeq sets the clock sequence to the lower 14 bits of seq. Setting to 91 | // -1 causes a new sequence to be generated. 92 | func SetClockSequence(seq int) { 93 | defer mu.Unlock() 94 | mu.Lock() 95 | setClockSequence(seq) 96 | } 97 | 98 | func setClockSequence(seq int) { 99 | if seq == -1 { 100 | var b [2]byte 101 | randomBits(b[:]) // clock sequence 102 | seq = int(b[0])<<8 | int(b[1]) 103 | } 104 | old_seq := clock_seq 105 | clock_seq = uint16(seq&0x3fff) | 0x8000 // Set our variant 106 | if old_seq != clock_seq { 107 | lasttime = 0 108 | } 109 | } 110 | 111 | // Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in 112 | // uuid. It returns false if uuid is not valid. The time is only well defined 113 | // for version 1 and 2 UUIDs. 114 | func (uuid UUID) Time() (Time, bool) { 115 | if len(uuid) != 16 { 116 | return 0, false 117 | } 118 | time := int64(binary.BigEndian.Uint32(uuid[0:4])) 119 | time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32 120 | time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48 121 | return Time(time), true 122 | } 123 | 124 | // ClockSequence returns the clock sequence encoded in uuid. It returns false 125 | // if uuid is not valid. The clock sequence is only well defined for version 1 126 | // and 2 UUIDs. 127 | func (uuid UUID) ClockSequence() (int, bool) { 128 | if len(uuid) != 16 { 129 | return 0, false 130 | } 131 | return int(binary.BigEndian.Uint16(uuid[8:10])) & 0x3fff, true 132 | } 133 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/util.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. 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 uuid 6 | 7 | import ( 8 | "io" 9 | ) 10 | 11 | // randomBits completely fills slice b with random data. 12 | func randomBits(b []byte) { 13 | if _, err := io.ReadFull(rander, b); err != nil { 14 | panic(err.Error()) // rand should never fail 15 | } 16 | } 17 | 18 | // xvalues returns the value of a byte as a hexadecimal digit or 255. 19 | var xvalues = []byte{ 20 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 21 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 22 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 23 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255, 24 | 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, 25 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 26 | 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, 27 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 28 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 29 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 30 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 31 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 32 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 33 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 34 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 35 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 36 | } 37 | 38 | // xtob converts the the first two hex bytes of x into a byte. 39 | func xtob(x string) (byte, bool) { 40 | b1 := xvalues[x[0]] 41 | b2 := xvalues[x[1]] 42 | return (b1 << 4) | b2, b1 != 255 && b2 != 255 43 | } 44 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/uuid.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. 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 uuid 6 | 7 | import ( 8 | "bytes" 9 | "crypto/rand" 10 | "fmt" 11 | "io" 12 | "strings" 13 | ) 14 | 15 | // A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC 16 | // 4122. 17 | type UUID []byte 18 | 19 | // A Version represents a UUIDs version. 20 | type Version byte 21 | 22 | // A Variant represents a UUIDs variant. 23 | type Variant byte 24 | 25 | // Constants returned by Variant. 26 | const ( 27 | Invalid = Variant(iota) // Invalid UUID 28 | RFC4122 // The variant specified in RFC4122 29 | Reserved // Reserved, NCS backward compatibility. 30 | Microsoft // Reserved, Microsoft Corporation backward compatibility. 31 | Future // Reserved for future definition. 32 | ) 33 | 34 | var rander = rand.Reader // random function 35 | 36 | // New returns a new random (version 4) UUID as a string. It is a convenience 37 | // function for NewRandom().String(). 38 | func New() string { 39 | return NewRandom().String() 40 | } 41 | 42 | // Parse decodes s into a UUID or returns nil. Both the UUID form of 43 | // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and 44 | // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded. 45 | func Parse(s string) UUID { 46 | if len(s) == 36+9 { 47 | if strings.ToLower(s[:9]) != "urn:uuid:" { 48 | return nil 49 | } 50 | s = s[9:] 51 | } else if len(s) != 36 { 52 | return nil 53 | } 54 | if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' { 55 | return nil 56 | } 57 | uuid := make([]byte, 16) 58 | for i, x := range []int{ 59 | 0, 2, 4, 6, 60 | 9, 11, 61 | 14, 16, 62 | 19, 21, 63 | 24, 26, 28, 30, 32, 34} { 64 | if v, ok := xtob(s[x:]); !ok { 65 | return nil 66 | } else { 67 | uuid[i] = v 68 | } 69 | } 70 | return uuid 71 | } 72 | 73 | // Equal returns true if uuid1 and uuid2 are equal. 74 | func Equal(uuid1, uuid2 UUID) bool { 75 | return bytes.Equal(uuid1, uuid2) 76 | } 77 | 78 | // String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 79 | // , or "" if uuid is invalid. 80 | func (uuid UUID) String() string { 81 | if uuid == nil || len(uuid) != 16 { 82 | return "" 83 | } 84 | b := []byte(uuid) 85 | return fmt.Sprintf("%08x-%04x-%04x-%04x-%012x", 86 | b[:4], b[4:6], b[6:8], b[8:10], b[10:]) 87 | } 88 | 89 | // URN returns the RFC 2141 URN form of uuid, 90 | // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, or "" if uuid is invalid. 91 | func (uuid UUID) URN() string { 92 | if uuid == nil || len(uuid) != 16 { 93 | return "" 94 | } 95 | b := []byte(uuid) 96 | return fmt.Sprintf("urn:uuid:%08x-%04x-%04x-%04x-%012x", 97 | b[:4], b[4:6], b[6:8], b[8:10], b[10:]) 98 | } 99 | 100 | // Variant returns the variant encoded in uuid. It returns Invalid if 101 | // uuid is invalid. 102 | func (uuid UUID) Variant() Variant { 103 | if len(uuid) != 16 { 104 | return Invalid 105 | } 106 | switch { 107 | case (uuid[8] & 0xc0) == 0x80: 108 | return RFC4122 109 | case (uuid[8] & 0xe0) == 0xc0: 110 | return Microsoft 111 | case (uuid[8] & 0xe0) == 0xe0: 112 | return Future 113 | default: 114 | return Reserved 115 | } 116 | panic("unreachable") 117 | } 118 | 119 | // Version returns the verison of uuid. It returns false if uuid is not 120 | // valid. 121 | func (uuid UUID) Version() (Version, bool) { 122 | if len(uuid) != 16 { 123 | return 0, false 124 | } 125 | return Version(uuid[6] >> 4), true 126 | } 127 | 128 | func (v Version) String() string { 129 | if v > 15 { 130 | return fmt.Sprintf("BAD_VERSION_%d", v) 131 | } 132 | return fmt.Sprintf("VERSION_%d", v) 133 | } 134 | 135 | func (v Variant) String() string { 136 | switch v { 137 | case RFC4122: 138 | return "RFC4122" 139 | case Reserved: 140 | return "Reserved" 141 | case Microsoft: 142 | return "Microsoft" 143 | case Future: 144 | return "Future" 145 | case Invalid: 146 | return "Invalid" 147 | } 148 | return fmt.Sprintf("BadVariant%d", int(v)) 149 | } 150 | 151 | // SetRand sets the random number generator to r, which implents io.Reader. 152 | // If r.Read returns an error when the package requests random data then 153 | // a panic will be issued. 154 | // 155 | // Calling SetRand with nil sets the random number generator to the default 156 | // generator. 157 | func SetRand(r io.Reader) { 158 | if r == nil { 159 | rander = rand.Reader 160 | return 161 | } 162 | rander = r 163 | } 164 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/version1.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. 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 uuid 6 | 7 | import ( 8 | "encoding/binary" 9 | ) 10 | 11 | // NewUUID returns a Version 1 UUID based on the current NodeID and clock 12 | // sequence, and the current time. If the NodeID has not been set by SetNodeID 13 | // or SetNodeInterface then it will be set automatically. If the NodeID cannot 14 | // be set NewUUID returns nil. If clock sequence has not been set by 15 | // SetClockSequence then it will be set automatically. If GetTime fails to 16 | // return the current NewUUID returns nil. 17 | func NewUUID() UUID { 18 | if nodeID == nil { 19 | SetNodeInterface("") 20 | } 21 | 22 | now, seq, err := GetTime() 23 | if err != nil { 24 | return nil 25 | } 26 | 27 | uuid := make([]byte, 16) 28 | 29 | time_low := uint32(now & 0xffffffff) 30 | time_mid := uint16((now >> 32) & 0xffff) 31 | time_hi := uint16((now >> 48) & 0x0fff) 32 | time_hi |= 0x1000 // Version 1 33 | 34 | binary.BigEndian.PutUint32(uuid[0:], time_low) 35 | binary.BigEndian.PutUint16(uuid[4:], time_mid) 36 | binary.BigEndian.PutUint16(uuid[6:], time_hi) 37 | binary.BigEndian.PutUint16(uuid[8:], seq) 38 | copy(uuid[10:], nodeID) 39 | 40 | return uuid 41 | } 42 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/code.google.com/p/go-uuid/uuid/version4.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. 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 uuid 6 | 7 | // Random returns a Random (Version 4) UUID or panics. 8 | // 9 | // The strength of the UUIDs is based on the strength of the crypto/rand 10 | // package. 11 | // 12 | // A note about uniqueness derived from from the UUID Wikipedia entry: 13 | // 14 | // Randomly generated UUIDs have 122 random bits. One's annual risk of being 15 | // hit by a meteorite is estimated to be one chance in 17 billion, that 16 | // means the probability is about 0.00000000006 (6 × 10−11), 17 | // equivalent to the odds of creating a few tens of trillions of UUIDs in a 18 | // year and having one duplicate. 19 | func NewRandom() UUID { 20 | uuid := make([]byte, 16) 21 | randomBits([]byte(uuid)) 22 | uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4 23 | uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10 24 | return uuid 25 | } 26 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/auth0/go-jwt-middleware/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Auth0, Inc. (http://auth0.com) 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 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/auth0/go-jwt-middleware/examples/martini-example/README.md: -------------------------------------------------------------------------------- 1 | # Martini example 2 | 3 | This is an example of how to use the middleware with Martini. 4 | 5 | # Using it 6 | 7 | To try this out, first install all dependencies with `go install` and then run `go run main.go` to start the app. 8 | 9 | * Call `http://localhost:3001/ping` to get a JSon response without the need of a JWT. 10 | * Call `http://localhost:3001/secured/ping` with a JWT signed with `My Secret` to get a response back. 11 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/auth0/go-jwt-middleware/examples/martini-example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "github.com/auth0/go-jwt-middleware" 6 | "github.com/go-martini/martini" 7 | "github.com/dgrijalva/jwt-go" 8 | "net/http" 9 | ) 10 | 11 | func main() { 12 | 13 | StartServer() 14 | 15 | } 16 | 17 | func StartServer() { 18 | m := martini.Classic() 19 | 20 | jwtMiddleware := jwtmiddleware.New(jwtmiddleware.Options{ 21 | ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) { 22 | return []byte("My Secret"), nil 23 | }, 24 | }); 25 | 26 | m.Get("/ping", PingHandler); 27 | m.Get("/secured/ping", jwtMiddleware.CheckJWT, SecuredPingHandler); 28 | 29 | m.Run(); 30 | } 31 | 32 | type Response struct { 33 | Text string `json:"text"` 34 | } 35 | 36 | func respondJson(text string, w http.ResponseWriter) { 37 | response := Response{text} 38 | 39 | jsonResponse, err := json.Marshal(response) 40 | if err != nil { 41 | http.Error(w, err.Error(), http.StatusInternalServerError) 42 | return 43 | } 44 | 45 | w.Header().Set("Content-Type", "application/json") 46 | w.Write(jsonResponse) 47 | } 48 | 49 | func PingHandler(w http.ResponseWriter, r *http.Request) { 50 | respondJson("All good. You don't need to be authenticated to call this", w) 51 | } 52 | 53 | func SecuredPingHandler(w http.ResponseWriter, r *http.Request) { 54 | respondJson("All good. You only get this message if you're authenticated", w) 55 | } 56 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/auth0/go-jwt-middleware/examples/negroni-example/README.md: -------------------------------------------------------------------------------- 1 | # Negroni example 2 | 3 | This is an example of how to use the Negroni middleware. 4 | 5 | # Using it 6 | 7 | To try this out, first install all dependencies with `go install` and then run `go run main.go` to start the app. 8 | 9 | * Call `http://localhost:3001/ping` to get a JSon response without the need of a JWT. 10 | * Call `http://localhost:3001/secured/ping` with a JWT signed with `My Secret` to get a response back. -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/auth0/go-jwt-middleware/examples/negroni-example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "github.com/auth0/go-jwt-middleware" 6 | "github.com/codegangsta/negroni" 7 | "github.com/dgrijalva/jwt-go" 8 | "github.com/gorilla/mux" 9 | "net/http" 10 | ) 11 | 12 | func main() { 13 | 14 | StartServer() 15 | 16 | } 17 | 18 | func StartServer() { 19 | r := mux.NewRouter() 20 | 21 | jwtMiddleware := jwtmiddleware.New(jwtmiddleware.Options{ 22 | ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) { 23 | return []byte("My Secret"), nil 24 | }, 25 | }) 26 | 27 | r.HandleFunc("/ping", PingHandler) 28 | r.Handle("/secured/ping", negroni.New( 29 | negroni.HandlerFunc(jwtMiddleware.HandlerWithNext), 30 | negroni.Wrap(http.HandlerFunc(SecuredPingHandler)), 31 | )) 32 | http.Handle("/", r) 33 | http.ListenAndServe(":3001", nil) 34 | } 35 | 36 | type Response struct { 37 | Text string `json:"text"` 38 | } 39 | 40 | func respondJson(text string, w http.ResponseWriter) { 41 | response := Response{text} 42 | 43 | jsonResponse, err := json.Marshal(response) 44 | if err != nil { 45 | http.Error(w, err.Error(), http.StatusInternalServerError) 46 | return 47 | } 48 | 49 | w.Header().Set("Content-Type", "application/json") 50 | w.Write(jsonResponse) 51 | } 52 | 53 | func PingHandler(w http.ResponseWriter, r *http.Request) { 54 | respondJson("All good. You don't need to be authenticated to call this", w) 55 | } 56 | 57 | func SecuredPingHandler(w http.ResponseWriter, r *http.Request) { 58 | respondJson("All good. You only get this message if you're authenticated", w) 59 | } 60 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/auth0/go-jwt-middleware/keys/sample-key: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2p3dC1pZHAuZXhhbXBsZS5jb20iLCJzdWIiOiJtYWlsdG86bWlrZUBleGFtcGxlLmNvbSIsIm5iZiI6MTQzMDc3OTMwNSwiZXhwIjoxNDYyMzE1MzA1LCJpYXQiOjE0MzA3NzkzMDUsImp0aSI6ImlkMTIzNDU2IiwidHlwIjoiaHR0cHM6Ly9leGFtcGxlLmNvbS9yZWdpc3RlciJ9.KbVlagrOLiy-R65eUrVuno_IAjW-J5i_ySoSrs2SgjU 2 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/.gitignore: -------------------------------------------------------------------------------- 1 | *.prof 2 | *.test 3 | *.swp 4 | /bin/ 5 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Ben Johnson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/Makefile: -------------------------------------------------------------------------------- 1 | TEST=. 2 | BENCH=. 3 | COVERPROFILE=/tmp/c.out 4 | BRANCH=`git rev-parse --abbrev-ref HEAD` 5 | COMMIT=`git rev-parse --short HEAD` 6 | GOLDFLAGS="-X main.branch $(BRANCH) -X main.commit $(COMMIT)" 7 | 8 | default: build 9 | 10 | bench: 11 | go test -v -test.run=NOTHINCONTAINSTHIS -test.bench=$(BENCH) 12 | 13 | # http://cloc.sourceforge.net/ 14 | cloc: 15 | @cloc --not-match-f='Makefile|_test.go' . 16 | 17 | cover: fmt 18 | go test -coverprofile=$(COVERPROFILE) -test.run=$(TEST) $(COVERFLAG) . 19 | go tool cover -html=$(COVERPROFILE) 20 | rm $(COVERPROFILE) 21 | 22 | cpuprofile: fmt 23 | @go test -c 24 | @./bolt.test -test.v -test.run=$(TEST) -test.cpuprofile cpu.prof 25 | 26 | # go get github.com/kisielk/errcheck 27 | errcheck: 28 | @echo "=== errcheck ===" 29 | @errcheck github.com/boltdb/bolt 30 | 31 | fmt: 32 | @go fmt ./... 33 | 34 | get: 35 | @go get -d ./... 36 | 37 | build: get 38 | @mkdir -p bin 39 | @go build -ldflags=$(GOLDFLAGS) -a -o bin/bolt ./cmd/bolt 40 | 41 | test: fmt 42 | @go get github.com/stretchr/testify/assert 43 | @echo "=== TESTS ===" 44 | @go test -v -cover -test.run=$(TEST) 45 | @echo "" 46 | @echo "" 47 | @echo "=== CLI ===" 48 | @go test -v -test.run=$(TEST) ./cmd/bolt 49 | @echo "" 50 | @echo "" 51 | @echo "=== RACE DETECTOR ===" 52 | @go test -v -race -test.run="TestSimulate_(100op|1000op)" 53 | 54 | .PHONY: bench cloc cover cpuprofile fmt memprofile test 55 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/batch.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "sync" 7 | "time" 8 | ) 9 | 10 | // Batch calls fn as part of a batch. It behaves similar to Update, 11 | // except: 12 | // 13 | // 1. concurrent Batch calls can be combined into a single Bolt 14 | // transaction. 15 | // 16 | // 2. the function passed to Batch may be called multiple times, 17 | // regardless of whether it returns error or not. 18 | // 19 | // This means that Batch function side effects must be idempotent and 20 | // take permanent effect only after a successful return is seen in 21 | // caller. 22 | // 23 | // The maximum batch size and delay can be adjusted with DB.MaxBatchSize 24 | // and DB.MaxBatchDelay, respectively. 25 | // 26 | // Batch is only useful when there are multiple goroutines calling it. 27 | func (db *DB) Batch(fn func(*Tx) error) error { 28 | errCh := make(chan error, 1) 29 | 30 | db.batchMu.Lock() 31 | if (db.batch == nil) || (db.batch != nil && len(db.batch.calls) >= db.MaxBatchSize) { 32 | // There is no existing batch, or the existing batch is full; start a new one. 33 | db.batch = &batch{ 34 | db: db, 35 | } 36 | db.batch.timer = time.AfterFunc(db.MaxBatchDelay, db.batch.trigger) 37 | } 38 | db.batch.calls = append(db.batch.calls, call{fn: fn, err: errCh}) 39 | if len(db.batch.calls) >= db.MaxBatchSize { 40 | // wake up batch, it's ready to run 41 | go db.batch.trigger() 42 | } 43 | db.batchMu.Unlock() 44 | 45 | err := <-errCh 46 | if err == trySolo { 47 | err = db.Update(fn) 48 | } 49 | return err 50 | } 51 | 52 | type call struct { 53 | fn func(*Tx) error 54 | err chan<- error 55 | } 56 | 57 | type batch struct { 58 | db *DB 59 | timer *time.Timer 60 | start sync.Once 61 | calls []call 62 | } 63 | 64 | // trigger runs the batch if it hasn't already been run. 65 | func (b *batch) trigger() { 66 | b.start.Do(b.run) 67 | } 68 | 69 | // run performs the transactions in the batch and communicates results 70 | // back to DB.Batch. 71 | func (b *batch) run() { 72 | b.db.batchMu.Lock() 73 | b.timer.Stop() 74 | // Make sure no new work is added to this batch, but don't break 75 | // other batches. 76 | if b.db.batch == b { 77 | b.db.batch = nil 78 | } 79 | b.db.batchMu.Unlock() 80 | 81 | retry: 82 | for len(b.calls) > 0 { 83 | var failIdx = -1 84 | err := b.db.Update(func(tx *Tx) error { 85 | for i, c := range b.calls { 86 | if err := safelyCall(c.fn, tx); err != nil { 87 | failIdx = i 88 | return err 89 | } 90 | } 91 | return nil 92 | }) 93 | 94 | if failIdx >= 0 { 95 | // take the failing transaction out of the batch. it's 96 | // safe to shorten b.calls here because db.batch no longer 97 | // points to us, and we hold the mutex anyway. 98 | c := b.calls[failIdx] 99 | b.calls[failIdx], b.calls = b.calls[len(b.calls)-1], b.calls[:len(b.calls)-1] 100 | // tell the submitter re-run it solo, continue with the rest of the batch 101 | c.err <- trySolo 102 | continue retry 103 | } 104 | 105 | // pass success, or bolt internal errors, to all callers 106 | for _, c := range b.calls { 107 | if c.err != nil { 108 | c.err <- err 109 | } 110 | } 111 | break retry 112 | } 113 | } 114 | 115 | // trySolo is a special sentinel error value used for signaling that a 116 | // transaction function should be re-run. It should never be seen by 117 | // callers. 118 | var trySolo = errors.New("batch function returned an error and should be re-run solo") 119 | 120 | type panicked struct { 121 | reason interface{} 122 | } 123 | 124 | func (p panicked) Error() string { 125 | if err, ok := p.reason.(error); ok { 126 | return err.Error() 127 | } 128 | return fmt.Sprintf("panic: %v", p.reason) 129 | } 130 | 131 | func safelyCall(fn func(*Tx) error, tx *Tx) (err error) { 132 | defer func() { 133 | if p := recover(); p != nil { 134 | err = panicked{p} 135 | } 136 | }() 137 | return fn(tx) 138 | } 139 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/bolt_386.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | // maxMapSize represents the largest mmap size supported by Bolt. 4 | const maxMapSize = 0x7FFFFFFF // 2GB 5 | 6 | // maxAllocSize is the size used when creating array pointers. 7 | const maxAllocSize = 0xFFFFFFF 8 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/bolt_amd64.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | // maxMapSize represents the largest mmap size supported by Bolt. 4 | const maxMapSize = 0xFFFFFFFFFFFF // 256TB 5 | 6 | // maxAllocSize is the size used when creating array pointers. 7 | const maxAllocSize = 0x7FFFFFFF 8 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/bolt_arm.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | // maxMapSize represents the largest mmap size supported by Bolt. 4 | const maxMapSize = 0x7FFFFFFF // 2GB 5 | 6 | // maxAllocSize is the size used when creating array pointers. 7 | const maxAllocSize = 0xFFFFFFF 8 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/bolt_arm64.go: -------------------------------------------------------------------------------- 1 | // +build arm64 2 | 3 | package bolt 4 | 5 | // maxMapSize represents the largest mmap size supported by Bolt. 6 | const maxMapSize = 0xFFFFFFFFFFFF // 256TB 7 | 8 | // maxAllocSize is the size used when creating array pointers. 9 | const maxAllocSize = 0x7FFFFFFF 10 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/bolt_linux.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | import ( 4 | "syscall" 5 | ) 6 | 7 | var odirect = syscall.O_DIRECT 8 | 9 | // fdatasync flushes written data to a file descriptor. 10 | func fdatasync(db *DB) error { 11 | return syscall.Fdatasync(int(db.file.Fd())) 12 | } 13 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/bolt_openbsd.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | import ( 4 | "syscall" 5 | "unsafe" 6 | ) 7 | 8 | const ( 9 | msAsync = 1 << iota // perform asynchronous writes 10 | msSync // perform synchronous writes 11 | msInvalidate // invalidate cached data 12 | ) 13 | 14 | var odirect int 15 | 16 | func msync(db *DB) error { 17 | _, _, errno := syscall.Syscall(syscall.SYS_MSYNC, uintptr(unsafe.Pointer(db.data)), uintptr(db.datasz), msInvalidate) 18 | if errno != 0 { 19 | return errno 20 | } 21 | return nil 22 | } 23 | 24 | func fdatasync(db *DB) error { 25 | if db.data != nil { 26 | return msync(db) 27 | } 28 | return db.file.Sync() 29 | } 30 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/bolt_ppc64le.go: -------------------------------------------------------------------------------- 1 | // +build ppc64le 2 | 3 | package bolt 4 | 5 | // maxMapSize represents the largest mmap size supported by Bolt. 6 | const maxMapSize = 0xFFFFFFFFFFFF // 256TB 7 | 8 | // maxAllocSize is the size used when creating array pointers. 9 | const maxAllocSize = 0x7FFFFFFF 10 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/bolt_s390x.go: -------------------------------------------------------------------------------- 1 | // +build s390x 2 | 3 | package bolt 4 | 5 | // maxMapSize represents the largest mmap size supported by Bolt. 6 | const maxMapSize = 0xFFFFFFFFFFFF // 256TB 7 | 8 | // maxAllocSize is the size used when creating array pointers. 9 | const maxAllocSize = 0x7FFFFFFF 10 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/bolt_unix.go: -------------------------------------------------------------------------------- 1 | // +build !windows,!plan9,!solaris 2 | 3 | package bolt 4 | 5 | import ( 6 | "fmt" 7 | "os" 8 | "syscall" 9 | "time" 10 | "unsafe" 11 | ) 12 | 13 | // flock acquires an advisory lock on a file descriptor. 14 | func flock(f *os.File, exclusive bool, timeout time.Duration) error { 15 | var t time.Time 16 | for { 17 | // If we're beyond our timeout then return an error. 18 | // This can only occur after we've attempted a flock once. 19 | if t.IsZero() { 20 | t = time.Now() 21 | } else if timeout > 0 && time.Since(t) > timeout { 22 | return ErrTimeout 23 | } 24 | flag := syscall.LOCK_SH 25 | if exclusive { 26 | flag = syscall.LOCK_EX 27 | } 28 | 29 | // Otherwise attempt to obtain an exclusive lock. 30 | err := syscall.Flock(int(f.Fd()), flag|syscall.LOCK_NB) 31 | if err == nil { 32 | return nil 33 | } else if err != syscall.EWOULDBLOCK { 34 | return err 35 | } 36 | 37 | // Wait for a bit and try again. 38 | time.Sleep(50 * time.Millisecond) 39 | } 40 | } 41 | 42 | // funlock releases an advisory lock on a file descriptor. 43 | func funlock(f *os.File) error { 44 | return syscall.Flock(int(f.Fd()), syscall.LOCK_UN) 45 | } 46 | 47 | // mmap memory maps a DB's data file. 48 | func mmap(db *DB, sz int) error { 49 | // Truncate and fsync to ensure file size metadata is flushed. 50 | // https://github.com/boltdb/bolt/issues/284 51 | if !db.NoGrowSync && !db.readOnly { 52 | if err := db.file.Truncate(int64(sz)); err != nil { 53 | return fmt.Errorf("file resize error: %s", err) 54 | } 55 | if err := db.file.Sync(); err != nil { 56 | return fmt.Errorf("file sync error: %s", err) 57 | } 58 | } 59 | 60 | // Map the data file to memory. 61 | b, err := syscall.Mmap(int(db.file.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED) 62 | if err != nil { 63 | return err 64 | } 65 | 66 | // Advise the kernel that the mmap is accessed randomly. 67 | if err := madvise(b, syscall.MADV_RANDOM); err != nil { 68 | return fmt.Errorf("madvise: %s", err) 69 | } 70 | 71 | // Save the original byte slice and convert to a byte array pointer. 72 | db.dataref = b 73 | db.data = (*[maxMapSize]byte)(unsafe.Pointer(&b[0])) 74 | db.datasz = sz 75 | return nil 76 | } 77 | 78 | // munmap unmaps a DB's data file from memory. 79 | func munmap(db *DB) error { 80 | // Ignore the unmap if we have no mapped data. 81 | if db.dataref == nil { 82 | return nil 83 | } 84 | 85 | // Unmap using the original byte slice. 86 | err := syscall.Munmap(db.dataref) 87 | db.dataref = nil 88 | db.data = nil 89 | db.datasz = 0 90 | return err 91 | } 92 | 93 | // NOTE: This function is copied from stdlib because it is not available on darwin. 94 | func madvise(b []byte, advice int) (err error) { 95 | _, _, e1 := syscall.Syscall(syscall.SYS_MADVISE, uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), uintptr(advice)) 96 | if e1 != 0 { 97 | err = e1 98 | } 99 | return 100 | } 101 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/bolt_unix_solaris.go: -------------------------------------------------------------------------------- 1 | 2 | package bolt 3 | 4 | import ( 5 | "fmt" 6 | "os" 7 | "syscall" 8 | "time" 9 | "unsafe" 10 | "golang.org/x/sys/unix" 11 | ) 12 | 13 | // flock acquires an advisory lock on a file descriptor. 14 | func flock(f *os.File, exclusive bool, timeout time.Duration) error { 15 | var t time.Time 16 | for { 17 | // If we're beyond our timeout then return an error. 18 | // This can only occur after we've attempted a flock once. 19 | if t.IsZero() { 20 | t = time.Now() 21 | } else if timeout > 0 && time.Since(t) > timeout { 22 | return ErrTimeout 23 | } 24 | var lock syscall.Flock_t 25 | lock.Start = 0 26 | lock.Len = 0 27 | lock.Pid = 0 28 | lock.Whence = 0 29 | lock.Pid = 0 30 | if exclusive { 31 | lock.Type = syscall.F_WRLCK 32 | } else { 33 | lock.Type = syscall.F_RDLCK 34 | } 35 | err := syscall.FcntlFlock(f.Fd(), syscall.F_SETLK, &lock) 36 | if err == nil { 37 | return nil 38 | } else if err != syscall.EAGAIN { 39 | return err 40 | } 41 | 42 | // Wait for a bit and try again. 43 | time.Sleep(50 * time.Millisecond) 44 | } 45 | } 46 | 47 | // funlock releases an advisory lock on a file descriptor. 48 | func funlock(f *os.File) error { 49 | var lock syscall.Flock_t 50 | lock.Start = 0 51 | lock.Len = 0 52 | lock.Type = syscall.F_UNLCK 53 | lock.Whence = 0 54 | return syscall.FcntlFlock(uintptr(f.Fd()), syscall.F_SETLK, &lock) 55 | } 56 | 57 | // mmap memory maps a DB's data file. 58 | func mmap(db *DB, sz int) error { 59 | // Truncate and fsync to ensure file size metadata is flushed. 60 | // https://github.com/boltdb/bolt/issues/284 61 | if !db.NoGrowSync && !db.readOnly { 62 | if err := db.file.Truncate(int64(sz)); err != nil { 63 | return fmt.Errorf("file resize error: %s", err) 64 | } 65 | if err := db.file.Sync(); err != nil { 66 | return fmt.Errorf("file sync error: %s", err) 67 | } 68 | } 69 | 70 | // Map the data file to memory. 71 | b, err := unix.Mmap(int(db.file.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED) 72 | if err != nil { 73 | return err 74 | } 75 | 76 | // Advise the kernel that the mmap is accessed randomly. 77 | if err := unix.Madvise(b, syscall.MADV_RANDOM); err != nil { 78 | return fmt.Errorf("madvise: %s", err) 79 | } 80 | 81 | // Save the original byte slice and convert to a byte array pointer. 82 | db.dataref = b 83 | db.data = (*[maxMapSize]byte)(unsafe.Pointer(&b[0])) 84 | db.datasz = sz 85 | return nil 86 | } 87 | 88 | // munmap unmaps a DB's data file from memory. 89 | func munmap(db *DB) error { 90 | // Ignore the unmap if we have no mapped data. 91 | if db.dataref == nil { 92 | return nil 93 | } 94 | 95 | // Unmap using the original byte slice. 96 | err := unix.Munmap(db.dataref) 97 | db.dataref = nil 98 | db.data = nil 99 | db.datasz = 0 100 | return err 101 | } 102 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/bolt_windows.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "syscall" 7 | "time" 8 | "unsafe" 9 | ) 10 | 11 | var odirect int 12 | 13 | // fdatasync flushes written data to a file descriptor. 14 | func fdatasync(db *DB) error { 15 | return db.file.Sync() 16 | } 17 | 18 | // flock acquires an advisory lock on a file descriptor. 19 | func flock(f *os.File, _ bool, _ time.Duration) error { 20 | return nil 21 | } 22 | 23 | // funlock releases an advisory lock on a file descriptor. 24 | func funlock(f *os.File) error { 25 | return nil 26 | } 27 | 28 | // mmap memory maps a DB's data file. 29 | // Based on: https://github.com/edsrzf/mmap-go 30 | func mmap(db *DB, sz int) error { 31 | if !db.readOnly { 32 | // Truncate the database to the size of the mmap. 33 | if err := db.file.Truncate(int64(sz)); err != nil { 34 | return fmt.Errorf("truncate: %s", err) 35 | } 36 | } 37 | 38 | // Open a file mapping handle. 39 | sizelo := uint32(sz >> 32) 40 | sizehi := uint32(sz) & 0xffffffff 41 | h, errno := syscall.CreateFileMapping(syscall.Handle(db.file.Fd()), nil, syscall.PAGE_READONLY, sizelo, sizehi, nil) 42 | if h == 0 { 43 | return os.NewSyscallError("CreateFileMapping", errno) 44 | } 45 | 46 | // Create the memory map. 47 | addr, errno := syscall.MapViewOfFile(h, syscall.FILE_MAP_READ, 0, 0, uintptr(sz)) 48 | if addr == 0 { 49 | return os.NewSyscallError("MapViewOfFile", errno) 50 | } 51 | 52 | // Close mapping handle. 53 | if err := syscall.CloseHandle(syscall.Handle(h)); err != nil { 54 | return os.NewSyscallError("CloseHandle", err) 55 | } 56 | 57 | // Convert to a byte array. 58 | db.data = ((*[maxMapSize]byte)(unsafe.Pointer(addr))) 59 | db.datasz = sz 60 | 61 | return nil 62 | } 63 | 64 | // munmap unmaps a pointer from a file. 65 | // Based on: https://github.com/edsrzf/mmap-go 66 | func munmap(db *DB) error { 67 | if db.data == nil { 68 | return nil 69 | } 70 | 71 | addr := (uintptr)(unsafe.Pointer(&db.data[0])) 72 | if err := syscall.UnmapViewOfFile(addr); err != nil { 73 | return os.NewSyscallError("UnmapViewOfFile", err) 74 | } 75 | return nil 76 | } 77 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/boltsync_unix.go: -------------------------------------------------------------------------------- 1 | // +build !windows,!plan9,!linux,!openbsd 2 | 3 | package bolt 4 | 5 | var odirect int 6 | 7 | // fdatasync flushes written data to a file descriptor. 8 | func fdatasync(db *DB) error { 9 | return db.file.Sync() 10 | } 11 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package bolt implements a low-level key/value store in pure Go. It supports 3 | fully serializable transactions, ACID semantics, and lock-free MVCC with 4 | multiple readers and a single writer. Bolt can be used for projects that 5 | want a simple data store without the need to add large dependencies such as 6 | Postgres or MySQL. 7 | 8 | Bolt is a single-level, zero-copy, B+tree data store. This means that Bolt is 9 | optimized for fast read access and does not require recovery in the event of a 10 | system crash. Transactions which have not finished committing will simply be 11 | rolled back in the event of a crash. 12 | 13 | The design of Bolt is based on Howard Chu's LMDB database project. 14 | 15 | Bolt currently works on Windows, Mac OS X, and Linux. 16 | 17 | 18 | Basics 19 | 20 | There are only a few types in Bolt: DB, Bucket, Tx, and Cursor. The DB is 21 | a collection of buckets and is represented by a single file on disk. A bucket is 22 | a collection of unique keys that are associated with values. 23 | 24 | Transactions provide either read-only or read-write access to the database. 25 | Read-only transactions can retrieve key/value pairs and can use Cursors to 26 | iterate over the dataset sequentially. Read-write transactions can create and 27 | delete buckets and can insert and remove keys. Only one read-write transaction 28 | is allowed at a time. 29 | 30 | 31 | Caveats 32 | 33 | The database uses a read-only, memory-mapped data file to ensure that 34 | applications cannot corrupt the database, however, this means that keys and 35 | values returned from Bolt cannot be changed. Writing to a read-only byte slice 36 | will cause Go to panic. 37 | 38 | Keys and values retrieved from the database are only valid for the life of 39 | the transaction. When used outside the transaction, these byte slices can 40 | point to different data or can point to invalid memory which will cause a panic. 41 | 42 | 43 | */ 44 | package bolt 45 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/errors.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | import "errors" 4 | 5 | // These errors can be returned when opening or calling methods on a DB. 6 | var ( 7 | // ErrDatabaseNotOpen is returned when a DB instance is accessed before it 8 | // is opened or after it is closed. 9 | ErrDatabaseNotOpen = errors.New("database not open") 10 | 11 | // ErrDatabaseOpen is returned when opening a database that is 12 | // already open. 13 | ErrDatabaseOpen = errors.New("database already open") 14 | 15 | // ErrInvalid is returned when a data file is not a Bolt-formatted database. 16 | ErrInvalid = errors.New("invalid database") 17 | 18 | // ErrVersionMismatch is returned when the data file was created with a 19 | // different version of Bolt. 20 | ErrVersionMismatch = errors.New("version mismatch") 21 | 22 | // ErrChecksum is returned when either meta page checksum does not match. 23 | ErrChecksum = errors.New("checksum error") 24 | 25 | // ErrTimeout is returned when a database cannot obtain an exclusive lock 26 | // on the data file after the timeout passed to Open(). 27 | ErrTimeout = errors.New("timeout") 28 | ) 29 | 30 | // These errors can occur when beginning or committing a Tx. 31 | var ( 32 | // ErrTxNotWritable is returned when performing a write operation on a 33 | // read-only transaction. 34 | ErrTxNotWritable = errors.New("tx not writable") 35 | 36 | // ErrTxClosed is returned when committing or rolling back a transaction 37 | // that has already been committed or rolled back. 38 | ErrTxClosed = errors.New("tx closed") 39 | 40 | // ErrDatabaseReadOnly is returned when a mutating transaction is started on a 41 | // read-only database. 42 | ErrDatabaseReadOnly = errors.New("database is in read-only mode") 43 | ) 44 | 45 | // These errors can occur when putting or deleting a value or a bucket. 46 | var ( 47 | // ErrBucketNotFound is returned when trying to access a bucket that has 48 | // not been created yet. 49 | ErrBucketNotFound = errors.New("bucket not found") 50 | 51 | // ErrBucketExists is returned when creating a bucket that already exists. 52 | ErrBucketExists = errors.New("bucket already exists") 53 | 54 | // ErrBucketNameRequired is returned when creating a bucket with a blank name. 55 | ErrBucketNameRequired = errors.New("bucket name required") 56 | 57 | // ErrKeyRequired is returned when inserting a zero-length key. 58 | ErrKeyRequired = errors.New("key required") 59 | 60 | // ErrKeyTooLarge is returned when inserting a key that is larger than MaxKeySize. 61 | ErrKeyTooLarge = errors.New("key too large") 62 | 63 | // ErrValueTooLarge is returned when inserting a value that is larger than MaxValueSize. 64 | ErrValueTooLarge = errors.New("value too large") 65 | 66 | // ErrIncompatibleValue is returned when trying create or delete a bucket 67 | // on an existing non-bucket key or when trying to create or delete a 68 | // non-bucket key on an existing bucket key. 69 | ErrIncompatibleValue = errors.New("incompatible value") 70 | ) 71 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/boltdb/bolt/page.go: -------------------------------------------------------------------------------- 1 | package bolt 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "sort" 7 | "unsafe" 8 | ) 9 | 10 | const pageHeaderSize = int(unsafe.Offsetof(((*page)(nil)).ptr)) 11 | 12 | const minKeysPerPage = 2 13 | 14 | const branchPageElementSize = int(unsafe.Sizeof(branchPageElement{})) 15 | const leafPageElementSize = int(unsafe.Sizeof(leafPageElement{})) 16 | 17 | const ( 18 | branchPageFlag = 0x01 19 | leafPageFlag = 0x02 20 | metaPageFlag = 0x04 21 | freelistPageFlag = 0x10 22 | ) 23 | 24 | const ( 25 | bucketLeafFlag = 0x01 26 | ) 27 | 28 | type pgid uint64 29 | 30 | type page struct { 31 | id pgid 32 | flags uint16 33 | count uint16 34 | overflow uint32 35 | ptr uintptr 36 | } 37 | 38 | // typ returns a human readable page type string used for debugging. 39 | func (p *page) typ() string { 40 | if (p.flags & branchPageFlag) != 0 { 41 | return "branch" 42 | } else if (p.flags & leafPageFlag) != 0 { 43 | return "leaf" 44 | } else if (p.flags & metaPageFlag) != 0 { 45 | return "meta" 46 | } else if (p.flags & freelistPageFlag) != 0 { 47 | return "freelist" 48 | } 49 | return fmt.Sprintf("unknown<%02x>", p.flags) 50 | } 51 | 52 | // meta returns a pointer to the metadata section of the page. 53 | func (p *page) meta() *meta { 54 | return (*meta)(unsafe.Pointer(&p.ptr)) 55 | } 56 | 57 | // leafPageElement retrieves the leaf node by index 58 | func (p *page) leafPageElement(index uint16) *leafPageElement { 59 | n := &((*[0x7FFFFFF]leafPageElement)(unsafe.Pointer(&p.ptr)))[index] 60 | return n 61 | } 62 | 63 | // leafPageElements retrieves a list of leaf nodes. 64 | func (p *page) leafPageElements() []leafPageElement { 65 | return ((*[0x7FFFFFF]leafPageElement)(unsafe.Pointer(&p.ptr)))[:] 66 | } 67 | 68 | // branchPageElement retrieves the branch node by index 69 | func (p *page) branchPageElement(index uint16) *branchPageElement { 70 | return &((*[0x7FFFFFF]branchPageElement)(unsafe.Pointer(&p.ptr)))[index] 71 | } 72 | 73 | // branchPageElements retrieves a list of branch nodes. 74 | func (p *page) branchPageElements() []branchPageElement { 75 | return ((*[0x7FFFFFF]branchPageElement)(unsafe.Pointer(&p.ptr)))[:] 76 | } 77 | 78 | // dump writes n bytes of the page to STDERR as hex output. 79 | func (p *page) hexdump(n int) { 80 | buf := (*[maxAllocSize]byte)(unsafe.Pointer(p))[:n] 81 | fmt.Fprintf(os.Stderr, "%x\n", buf) 82 | } 83 | 84 | type pages []*page 85 | 86 | func (s pages) Len() int { return len(s) } 87 | func (s pages) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 88 | func (s pages) Less(i, j int) bool { return s[i].id < s[j].id } 89 | 90 | // branchPageElement represents a node on a branch page. 91 | type branchPageElement struct { 92 | pos uint32 93 | ksize uint32 94 | pgid pgid 95 | } 96 | 97 | // key returns a byte slice of the node key. 98 | func (n *branchPageElement) key() []byte { 99 | buf := (*[maxAllocSize]byte)(unsafe.Pointer(n)) 100 | return (*[maxAllocSize]byte)(unsafe.Pointer(&buf[n.pos]))[:n.ksize] 101 | } 102 | 103 | // leafPageElement represents a node on a leaf page. 104 | type leafPageElement struct { 105 | flags uint32 106 | pos uint32 107 | ksize uint32 108 | vsize uint32 109 | } 110 | 111 | // key returns a byte slice of the node key. 112 | func (n *leafPageElement) key() []byte { 113 | buf := (*[maxAllocSize]byte)(unsafe.Pointer(n)) 114 | return (*[maxAllocSize]byte)(unsafe.Pointer(&buf[n.pos]))[:n.ksize] 115 | } 116 | 117 | // value returns a byte slice of the node value. 118 | func (n *leafPageElement) value() []byte { 119 | buf := (*[maxAllocSize]byte)(unsafe.Pointer(n)) 120 | return (*[maxAllocSize]byte)(unsafe.Pointer(&buf[n.pos+n.ksize]))[:n.vsize] 121 | } 122 | 123 | // PageInfo represents human readable information about a page. 124 | type PageInfo struct { 125 | ID int 126 | Type string 127 | Count int 128 | OverflowCount int 129 | } 130 | 131 | type pgids []pgid 132 | 133 | func (s pgids) Len() int { return len(s) } 134 | func (s pgids) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 135 | func (s pgids) Less(i, j int) bool { return s[i] < s[j] } 136 | 137 | // merge returns the sorted union of a and b. 138 | func (a pgids) merge(b pgids) pgids { 139 | // Return the opposite slice if one is nil. 140 | if len(a) == 0 { 141 | return b 142 | } else if len(b) == 0 { 143 | return a 144 | } 145 | 146 | // Create a list to hold all elements from both lists. 147 | merged := make(pgids, 0, len(a)+len(b)) 148 | 149 | // Assign lead to the slice with a lower starting value, follow to the higher value. 150 | lead, follow := a, b 151 | if b[0] < a[0] { 152 | lead, follow = b, a 153 | } 154 | 155 | // Continue while there are elements in the lead. 156 | for len(lead) > 0 { 157 | // Merge largest prefix of lead that is ahead of follow[0]. 158 | n := sort.Search(len(lead), func(i int) bool { return lead[i] > follow[0] }) 159 | merged = append(merged, lead[:n]...) 160 | if n >= len(lead) { 161 | break 162 | } 163 | 164 | // Swap lead and follow. 165 | lead, follow = follow, lead[n:] 166 | } 167 | 168 | // Append what's left in follow. 169 | merged = append(merged, follow...) 170 | 171 | return merged 172 | } 173 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/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 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/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 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/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 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/codegangsta/negroni/negroni.go: -------------------------------------------------------------------------------- 1 | package negroni 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | "os" 7 | ) 8 | 9 | // Handler handler is an interface that objects can implement to be registered to serve as middleware 10 | // in the Negroni middleware stack. 11 | // ServeHTTP should yield to the next middleware in the chain by invoking the next http.HandlerFunc 12 | // passed in. 13 | // 14 | // If the Handler writes to the ResponseWriter, the next http.HandlerFunc should not be invoked. 15 | type Handler interface { 16 | ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) 17 | } 18 | 19 | // HandlerFunc is an adapter to allow the use of ordinary functions as Negroni handlers. 20 | // If f is a function with the appropriate signature, HandlerFunc(f) is a Handler object that calls f. 21 | type HandlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) 22 | 23 | func (h HandlerFunc) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { 24 | h(rw, r, next) 25 | } 26 | 27 | type middleware struct { 28 | handler Handler 29 | next *middleware 30 | } 31 | 32 | func (m middleware) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 33 | m.handler.ServeHTTP(rw, r, m.next.ServeHTTP) 34 | } 35 | 36 | // Wrap converts a http.Handler into a negroni.Handler so it can be used as a Negroni 37 | // middleware. The next http.HandlerFunc is automatically called after the Handler 38 | // is executed. 39 | func Wrap(handler http.Handler) Handler { 40 | return HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { 41 | handler.ServeHTTP(rw, r) 42 | next(rw, r) 43 | }) 44 | } 45 | 46 | // Negroni is a stack of Middleware Handlers that can be invoked as an http.Handler. 47 | // Negroni middleware is evaluated in the order that they are added to the stack using 48 | // the Use and UseHandler methods. 49 | type Negroni struct { 50 | middleware middleware 51 | handlers []Handler 52 | } 53 | 54 | // New returns a new Negroni instance with no middleware preconfigured. 55 | func New(handlers ...Handler) *Negroni { 56 | return &Negroni{ 57 | handlers: handlers, 58 | middleware: build(handlers), 59 | } 60 | } 61 | 62 | // Classic returns a new Negroni instance with the default middleware already 63 | // in the stack. 64 | // 65 | // Recovery - Panic Recovery Middleware 66 | // Logger - Request/Response Logging 67 | // Static - Static File Serving 68 | func Classic() *Negroni { 69 | return New(NewRecovery(), NewLogger(), NewStatic(http.Dir("public"))) 70 | } 71 | 72 | func (n *Negroni) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 73 | n.middleware.ServeHTTP(NewResponseWriter(rw), r) 74 | } 75 | 76 | // Use adds a Handler onto the middleware stack. Handlers are invoked in the order they are added to a Negroni. 77 | func (n *Negroni) Use(handler Handler) { 78 | n.handlers = append(n.handlers, handler) 79 | n.middleware = build(n.handlers) 80 | } 81 | 82 | // UseFunc adds a Negroni-style handler function onto the middleware stack. 83 | func (n *Negroni) UseFunc(handlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)) { 84 | n.Use(HandlerFunc(handlerFunc)) 85 | } 86 | 87 | // UseHandler adds a http.Handler onto the middleware stack. Handlers are invoked in the order they are added to a Negroni. 88 | func (n *Negroni) UseHandler(handler http.Handler) { 89 | n.Use(Wrap(handler)) 90 | } 91 | 92 | // UseHandler adds a http.HandlerFunc-style handler function onto the middleware stack. 93 | func (n *Negroni) UseHandlerFunc(handlerFunc func(rw http.ResponseWriter, r *http.Request)) { 94 | n.UseHandler(http.HandlerFunc(handlerFunc)) 95 | } 96 | 97 | // Run is a convenience function that runs the negroni stack as an HTTP 98 | // server. The addr string takes the same format as http.ListenAndServe. 99 | func (n *Negroni) Run(addr string) { 100 | l := log.New(os.Stdout, "[negroni] ", 0) 101 | l.Printf("listening on %s", addr) 102 | l.Fatal(http.ListenAndServe(addr, n)) 103 | } 104 | 105 | // Returns a list of all the handlers in the current Negroni middleware chain. 106 | func (n *Negroni) Handlers() []Handler { 107 | return n.handlers 108 | } 109 | 110 | func build(handlers []Handler) middleware { 111 | var next middleware 112 | 113 | if len(handlers) == 0 { 114 | return voidMiddleware() 115 | } else if len(handlers) > 1 { 116 | next = build(handlers[1:]) 117 | } else { 118 | next = voidMiddleware() 119 | } 120 | 121 | return middleware{handlers[0], &next} 122 | } 123 | 124 | func voidMiddleware() middleware { 125 | return middleware{ 126 | HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {}), 127 | &middleware{}, 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/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 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/codegangsta/negroni/response_writer.go: -------------------------------------------------------------------------------- 1 | package negroni 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "net" 7 | "net/http" 8 | ) 9 | 10 | // ResponseWriter is a wrapper around http.ResponseWriter that provides extra information about 11 | // the response. It is recommended that middleware handlers use this construct to wrap a responsewriter 12 | // if the functionality calls for it. 13 | type ResponseWriter interface { 14 | http.ResponseWriter 15 | http.Flusher 16 | // Status returns the status code of the response or 0 if the response has not been written. 17 | Status() int 18 | // Written returns whether or not the ResponseWriter has been written. 19 | Written() bool 20 | // Size returns the size of the response body. 21 | Size() int 22 | // Before allows for a function to be called before the ResponseWriter has been written to. This is 23 | // useful for setting headers or any other operations that must happen before a response has been written. 24 | Before(func(ResponseWriter)) 25 | } 26 | 27 | type beforeFunc func(ResponseWriter) 28 | 29 | // NewResponseWriter creates a ResponseWriter that wraps an http.ResponseWriter 30 | func NewResponseWriter(rw http.ResponseWriter) ResponseWriter { 31 | return &responseWriter{rw, 0, 0, nil} 32 | } 33 | 34 | type responseWriter struct { 35 | http.ResponseWriter 36 | status int 37 | size int 38 | beforeFuncs []beforeFunc 39 | } 40 | 41 | func (rw *responseWriter) WriteHeader(s int) { 42 | rw.status = s 43 | rw.callBefore() 44 | rw.ResponseWriter.WriteHeader(s) 45 | } 46 | 47 | func (rw *responseWriter) Write(b []byte) (int, error) { 48 | if !rw.Written() { 49 | // The status will be StatusOK if WriteHeader has not been called yet 50 | rw.WriteHeader(http.StatusOK) 51 | } 52 | size, err := rw.ResponseWriter.Write(b) 53 | rw.size += size 54 | return size, err 55 | } 56 | 57 | func (rw *responseWriter) Status() int { 58 | return rw.status 59 | } 60 | 61 | func (rw *responseWriter) Size() int { 62 | return rw.size 63 | } 64 | 65 | func (rw *responseWriter) Written() bool { 66 | return rw.status != 0 67 | } 68 | 69 | func (rw *responseWriter) Before(before func(ResponseWriter)) { 70 | rw.beforeFuncs = append(rw.beforeFuncs, before) 71 | } 72 | 73 | func (rw *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { 74 | hijacker, ok := rw.ResponseWriter.(http.Hijacker) 75 | if !ok { 76 | return nil, nil, fmt.Errorf("the ResponseWriter doesn't support the Hijacker interface") 77 | } 78 | return hijacker.Hijack() 79 | } 80 | 81 | func (rw *responseWriter) CloseNotify() <-chan bool { 82 | return rw.ResponseWriter.(http.CloseNotifier).CloseNotify() 83 | } 84 | 85 | func (rw *responseWriter) callBefore() { 86 | for i := len(rw.beforeFuncs) - 1; i >= 0; i-- { 87 | rw.beforeFuncs[i](rw) 88 | } 89 | } 90 | 91 | func (rw *responseWriter) Flush() { 92 | flusher, ok := rw.ResponseWriter.(http.Flusher) 93 | if ok { 94 | flusher.Flush() 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/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 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/dgrijalva/jwt-go/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | bin 3 | 4 | 5 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/dgrijalva/jwt-go/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.3.3 5 | - 1.4.2 6 | - 1.5 7 | - tip 8 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/dgrijalva/jwt-go/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Dave Grijalva 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/dgrijalva/jwt-go/README.md: -------------------------------------------------------------------------------- 1 | A [go](http://www.golang.org) (or 'golang' for search engine friendliness) implementation of [JSON Web Tokens](http://self-issued.info/docs/draft-jones-json-web-token.html) 2 | 3 | [![Build Status](https://travis-ci.org/dgrijalva/jwt-go.svg?branch=master)](https://travis-ci.org/dgrijalva/jwt-go) 4 | 5 | **NOTICE:** A vulnerability in JWT was [recently published](https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/). As this library doesn't force users to validate the `alg` is what they expected, it's possible your usage is effected. There will be an update soon to remedy this, and it will likey require backwards-incompatible changes to the API. In the short term, please make sure your implementation verifies the `alg` is what you expect. 6 | 7 | ## What the heck is a JWT? 8 | 9 | In short, it's a signed JSON object that does something useful (for example, authentication). It's commonly used for `Bearer` tokens in Oauth 2. A token is made of three parts, separated by `.`'s. The first two parts are JSON objects, that have been [base64url](http://tools.ietf.org/html/rfc4648) encoded. The last part is the signature, encoded the same way. 10 | 11 | The first part is called the header. It contains the necessary information for verifying the last part, the signature. For example, which encryption method was used for signing and what key was used. 12 | 13 | The part in the middle is the interesting bit. It's called the Claims and contains the actual stuff you care about. Refer to [the RFC](http://self-issued.info/docs/draft-jones-json-web-token.html) for information about reserved keys and the proper way to add your own. 14 | 15 | ## What's in the box? 16 | 17 | This library supports the parsing and verification as well as the generation and signing of JWTs. Current supported signing algorithms are RSA256 and HMAC SHA256, though hooks are present for adding your own. 18 | 19 | ## Parse and Verify 20 | 21 | Parsing and verifying tokens is pretty straight forward. You pass in the token and a function for looking up the key. This is done as a callback since you may need to parse the token to find out what signing method and key was used. 22 | 23 | ```go 24 | token, err := jwt.Parse(myToken, func(token *jwt.Token) (interface{}, error) { 25 | // Don't forget to validate the alg is what you expect: 26 | if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok { 27 | return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"]) 28 | } 29 | return myLookupKey(token.Header["kid"]) 30 | }) 31 | 32 | if err == nil && token.Valid { 33 | deliverGoodness("!") 34 | } else { 35 | deliverUtterRejection(":(") 36 | } 37 | ``` 38 | 39 | ## Create a token 40 | 41 | ```go 42 | // Create the token 43 | token := jwt.New(jwt.SigningMethodHS256) 44 | // Set some claims 45 | token.Claims["foo"] = "bar" 46 | token.Claims["exp"] = time.Now().Add(time.Hour * 72).Unix() 47 | // Sign and get the complete encoded token as a string 48 | tokenString, err := token.SignedString(mySigningKey) 49 | ``` 50 | 51 | ## Extensions 52 | 53 | This library publishes all the necessary components for adding your own signing methods. Simply implement the `SigningMethod` interface and register a factory method using `RegisterSigningMethod`. 54 | 55 | Here's an example of an extension that integrates with the Google App Engine signing tools: https://github.com/someone1/gcp-jwt-go 56 | 57 | ## Project Status & Versioning 58 | 59 | This library is considered production ready. Feedback and feature requests are appreciated. The API should be considered stable. There should be very few backwards-incompatible changes outside of major version updates (and only with good reason). 60 | 61 | This project uses [Semantic Versioning 2.0.0](http://semver.org). Accepted pull requests will land on `master`. Periodically, versions will be tagged from `master`. You can find all the releases on [the project releases page](https://github.com/dgrijalva/jwt-go/releases). 62 | 63 | While we try to make it obvious when we make breaking changes, there isn't a great mechanism for pushing announcements out to users. You may want to use this alternative package include: `gopkg.in/dgrijalva/jwt-go.v2`. It will do the right thing WRT semantic versioning. 64 | 65 | ## More 66 | 67 | Documentation can be found [on godoc.org](http://godoc.org/github.com/dgrijalva/jwt-go). 68 | 69 | The command line utility included in this project (cmd/jwt) provides a straightforward example of token creation and parsing as well as a useful tool for debugging your own integration. For a more http centric example, see [this gist](https://gist.github.com/cryptix/45c33ecf0ae54828e63b). 70 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/dgrijalva/jwt-go/VERSION_HISTORY.md: -------------------------------------------------------------------------------- 1 | ## `jwt-go` Version History 2 | 3 | #### 2.3.0 4 | 5 | * Added support for ECDSA signing methods 6 | * Added support for RSA PSS signing methods (requires go v1.4) 7 | 8 | #### 2.2.0 9 | 10 | * Gracefully handle a `nil` `Keyfunc` being passed to `Parse`. Result will now be the parsed token and an error, instead of a panic. 11 | 12 | #### 2.1.0 13 | 14 | Backwards compatible API change that was missed in 2.0.0. 15 | 16 | * The `SignedString` method on `Token` now takes `interface{}` instead of `[]byte` 17 | 18 | #### 2.0.0 19 | 20 | There were two major reasons for breaking backwards compatibility with this update. The first was a refactor required to expand the width of the RSA and HMAC-SHA signing implementations. There will likely be no required code changes to support this change. 21 | 22 | The second update, while unfortunately requiring a small change in integration, is required to open up this library to other signing methods. Not all keys used for all signing methods have a single standard on-disk representation. Requiring `[]byte` as the type for all keys proved too limiting. Additionally, this implementation allows for pre-parsed tokens to be reused, which might matter in an application that parses a high volume of tokens with a small set of keys. Backwards compatibilty has been maintained for passing `[]byte` to the RSA signing methods, but they will also accept `*rsa.PublicKey` and `*rsa.PrivateKey`. 23 | 24 | It is likely the only integration change required here will be to change `func(t *jwt.Token) ([]byte, error)` to `func(t *jwt.Token) (interface{}, error)` when calling `Parse`. 25 | 26 | * **Compatibility Breaking Changes** 27 | * `SigningMethodHS256` is now `*SigningMethodHMAC` instead of `type struct` 28 | * `SigningMethodRS256` is now `*SigningMethodRSA` instead of `type struct` 29 | * `KeyFunc` now returns `interface{}` instead of `[]byte` 30 | * `SigningMethod.Sign` now takes `interface{}` instead of `[]byte` for the key 31 | * `SigningMethod.Verify` now takes `interface{}` instead of `[]byte` for the key 32 | * Renamed type `SigningMethodHS256` to `SigningMethodHMAC`. Specific sizes are now just instances of this type. 33 | * Added public package global `SigningMethodHS256` 34 | * Added public package global `SigningMethodHS384` 35 | * Added public package global `SigningMethodHS512` 36 | * Renamed type `SigningMethodRS256` to `SigningMethodRSA`. Specific sizes are now just instances of this type. 37 | * Added public package global `SigningMethodRS256` 38 | * Added public package global `SigningMethodRS384` 39 | * Added public package global `SigningMethodRS512` 40 | * Moved sample private key for HMAC tests from an inline value to a file on disk. Value is unchanged. 41 | * Refactored the RSA implementation to be easier to read 42 | * Exposed helper methods `ParseRSAPrivateKeyFromPEM` and `ParseRSAPublicKeyFromPEM` 43 | 44 | #### 1.0.2 45 | 46 | * Fixed bug in parsing public keys from certificates 47 | * Added more tests around the parsing of keys for RS256 48 | * Code refactoring in RS256 implementation. No functional changes 49 | 50 | #### 1.0.1 51 | 52 | * Fixed panic if RS256 signing method was passed an invalid key 53 | 54 | #### 1.0.0 55 | 56 | * First versioned release 57 | * API stabilized 58 | * Supports creating, signing, parsing, and validating JWT tokens 59 | * Supports RS256 and HS256 signing methods -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/dgrijalva/jwt-go/cmd/jwt/app.go: -------------------------------------------------------------------------------- 1 | // A useful example app. You can use this to debug your tokens on the command line. 2 | // This is also a great place to look at how you might use this library. 3 | // 4 | // Example usage: 5 | // The following will create and sign a token, then verify it and output the original claims. 6 | // echo {\"foo\":\"bar\"} | bin/jwt -key test/sample_key -alg RS256 -sign - | bin/jwt -key test/sample_key.pub -verify - 7 | package main 8 | 9 | import ( 10 | "encoding/json" 11 | "flag" 12 | "fmt" 13 | "io" 14 | "io/ioutil" 15 | "os" 16 | "regexp" 17 | 18 | "github.com/dgrijalva/jwt-go" 19 | ) 20 | 21 | var ( 22 | // Options 23 | flagAlg = flag.String("alg", "", "signing algorithm identifier") 24 | flagKey = flag.String("key", "", "path to key file or '-' to read from stdin") 25 | flagCompact = flag.Bool("compact", false, "output compact JSON") 26 | flagDebug = flag.Bool("debug", false, "print out all kinds of debug data") 27 | 28 | // Modes - exactly one of these is required 29 | flagSign = flag.String("sign", "", "path to claims object to sign or '-' to read from stdin") 30 | flagVerify = flag.String("verify", "", "path to JWT token to verify or '-' to read from stdin") 31 | ) 32 | 33 | func main() { 34 | // Usage message if you ask for -help or if you mess up inputs. 35 | flag.Usage = func() { 36 | fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) 37 | fmt.Fprintf(os.Stderr, " One of the following flags is required: sign, verify\n") 38 | flag.PrintDefaults() 39 | } 40 | 41 | // Parse command line options 42 | flag.Parse() 43 | 44 | // Do the thing. If something goes wrong, print error to stderr 45 | // and exit with a non-zero status code 46 | if err := start(); err != nil { 47 | fmt.Fprintf(os.Stderr, "Error: %v\n", err) 48 | os.Exit(1) 49 | } 50 | } 51 | 52 | // Figure out which thing to do and then do that 53 | func start() error { 54 | if *flagSign != "" { 55 | return signToken() 56 | } else if *flagVerify != "" { 57 | return verifyToken() 58 | } else { 59 | flag.Usage() 60 | return fmt.Errorf("None of the required flags are present. What do you want me to do?") 61 | } 62 | } 63 | 64 | // Helper func: Read input from specified file or stdin 65 | func loadData(p string) ([]byte, error) { 66 | if p == "" { 67 | return nil, fmt.Errorf("No path specified") 68 | } 69 | 70 | var rdr io.Reader 71 | if p == "-" { 72 | rdr = os.Stdin 73 | } else { 74 | if f, err := os.Open(p); err == nil { 75 | rdr = f 76 | defer f.Close() 77 | } else { 78 | return nil, err 79 | } 80 | } 81 | return ioutil.ReadAll(rdr) 82 | } 83 | 84 | // Print a json object in accordance with the prophecy (or the command line options) 85 | func printJSON(j interface{}) error { 86 | var out []byte 87 | var err error 88 | 89 | if *flagCompact == false { 90 | out, err = json.MarshalIndent(j, "", " ") 91 | } else { 92 | out, err = json.Marshal(j) 93 | } 94 | 95 | if err == nil { 96 | fmt.Println(string(out)) 97 | } 98 | 99 | return err 100 | } 101 | 102 | // Verify a token and output the claims. This is a great example 103 | // of how to verify and view a token. 104 | func verifyToken() error { 105 | // get the token 106 | tokData, err := loadData(*flagVerify) 107 | if err != nil { 108 | return fmt.Errorf("Couldn't read token: %v", err) 109 | } 110 | 111 | // trim possible whitespace from token 112 | tokData = regexp.MustCompile(`\s*$`).ReplaceAll(tokData, []byte{}) 113 | if *flagDebug { 114 | fmt.Fprintf(os.Stderr, "Token len: %v bytes\n", len(tokData)) 115 | } 116 | 117 | // Parse the token. Load the key from command line option 118 | token, err := jwt.Parse(string(tokData), func(t *jwt.Token) (interface{}, error) { 119 | return loadData(*flagKey) 120 | }) 121 | 122 | // Print some debug data 123 | if *flagDebug && token != nil { 124 | fmt.Fprintf(os.Stderr, "Header:\n%v\n", token.Header) 125 | fmt.Fprintf(os.Stderr, "Claims:\n%v\n", token.Claims) 126 | } 127 | 128 | // Print an error if we can't parse for some reason 129 | if err != nil { 130 | return fmt.Errorf("Couldn't parse token: %v", err) 131 | } 132 | 133 | // Is token invalid? 134 | if !token.Valid { 135 | return fmt.Errorf("Token is invalid") 136 | } 137 | 138 | // Print the token details 139 | if err := printJSON(token.Claims); err != nil { 140 | return fmt.Errorf("Failed to output claims: %v", err) 141 | } 142 | 143 | return nil 144 | } 145 | 146 | // Create, sign, and output a token. This is a great, simple example of 147 | // how to use this library to create and sign a token. 148 | func signToken() error { 149 | // get the token data from command line arguments 150 | tokData, err := loadData(*flagSign) 151 | if err != nil { 152 | return fmt.Errorf("Couldn't read token: %v", err) 153 | } else if *flagDebug { 154 | fmt.Fprintf(os.Stderr, "Token: %v bytes", len(tokData)) 155 | } 156 | 157 | // parse the JSON of the claims 158 | var claims map[string]interface{} 159 | if err := json.Unmarshal(tokData, &claims); err != nil { 160 | return fmt.Errorf("Couldn't parse claims JSON: %v", err) 161 | } 162 | 163 | // get the key 164 | keyData, err := loadData(*flagKey) 165 | if err != nil { 166 | return fmt.Errorf("Couldn't read key: %v", err) 167 | } 168 | 169 | // get the signing alg 170 | alg := jwt.GetSigningMethod(*flagAlg) 171 | if alg == nil { 172 | return fmt.Errorf("Couldn't find signing method: %v", *flagAlg) 173 | } 174 | 175 | // create a new token 176 | token := jwt.New(alg) 177 | token.Claims = claims 178 | 179 | if out, err := token.SignedString(keyData); err == nil { 180 | fmt.Println(out) 181 | } else { 182 | return fmt.Errorf("Error signing token: %v", err) 183 | } 184 | 185 | return nil 186 | } 187 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/dgrijalva/jwt-go/doc.go: -------------------------------------------------------------------------------- 1 | // Package jwt is a Go implementation of JSON Web Tokens: http://self-issued.info/docs/draft-jones-json-web-token.html 2 | // 3 | // See README.md for more info. 4 | package jwt 5 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/dgrijalva/jwt-go/ecdsa.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "crypto" 5 | "crypto/ecdsa" 6 | "crypto/rand" 7 | "errors" 8 | "math/big" 9 | ) 10 | 11 | var ( 12 | // Sadly this is missing from crypto/ecdsa compared to crypto/rsa 13 | ErrECDSAVerification = errors.New("crypto/ecdsa: verification error") 14 | ) 15 | 16 | // Implements the ECDSA family of signing methods signing methods 17 | type SigningMethodECDSA struct { 18 | Name string 19 | Hash crypto.Hash 20 | KeySize int 21 | CurveBits int 22 | } 23 | 24 | // Specific instances for EC256 and company 25 | var ( 26 | SigningMethodES256 *SigningMethodECDSA 27 | SigningMethodES384 *SigningMethodECDSA 28 | SigningMethodES512 *SigningMethodECDSA 29 | ) 30 | 31 | func init() { 32 | // ES256 33 | SigningMethodES256 = &SigningMethodECDSA{"ES256", crypto.SHA256, 32, 256} 34 | RegisterSigningMethod(SigningMethodES256.Alg(), func() SigningMethod { 35 | return SigningMethodES256 36 | }) 37 | 38 | // ES384 39 | SigningMethodES384 = &SigningMethodECDSA{"ES384", crypto.SHA384, 48, 384} 40 | RegisterSigningMethod(SigningMethodES384.Alg(), func() SigningMethod { 41 | return SigningMethodES384 42 | }) 43 | 44 | // ES512 45 | SigningMethodES512 = &SigningMethodECDSA{"ES512", crypto.SHA512, 66, 521} 46 | RegisterSigningMethod(SigningMethodES512.Alg(), func() SigningMethod { 47 | return SigningMethodES512 48 | }) 49 | } 50 | 51 | func (m *SigningMethodECDSA) Alg() string { 52 | return m.Name 53 | } 54 | 55 | // Implements the Verify method from SigningMethod 56 | // For this verify method, key must be an ecdsa.PublicKey struct 57 | func (m *SigningMethodECDSA) Verify(signingString, signature string, key interface{}) error { 58 | var err error 59 | 60 | // Decode the signature 61 | var sig []byte 62 | if sig, err = DecodeSegment(signature); err != nil { 63 | return err 64 | } 65 | 66 | // Get the key 67 | var ecdsaKey *ecdsa.PublicKey 68 | switch k := key.(type) { 69 | case *ecdsa.PublicKey: 70 | ecdsaKey = k 71 | default: 72 | return ErrInvalidKey 73 | } 74 | 75 | if len(sig) != 2*m.KeySize { 76 | return ErrECDSAVerification 77 | } 78 | 79 | r := big.NewInt(0).SetBytes(sig[:m.KeySize]) 80 | s := big.NewInt(0).SetBytes(sig[m.KeySize:]) 81 | 82 | // Create hasher 83 | if !m.Hash.Available() { 84 | return ErrHashUnavailable 85 | } 86 | hasher := m.Hash.New() 87 | hasher.Write([]byte(signingString)) 88 | 89 | // Verify the signature 90 | if verifystatus := ecdsa.Verify(ecdsaKey, hasher.Sum(nil), r, s); verifystatus == true { 91 | return nil 92 | } else { 93 | return ErrECDSAVerification 94 | } 95 | } 96 | 97 | // Implements the Sign method from SigningMethod 98 | // For this signing method, key must be an ecdsa.PrivateKey struct 99 | func (m *SigningMethodECDSA) Sign(signingString string, key interface{}) (string, error) { 100 | // Get the key 101 | var ecdsaKey *ecdsa.PrivateKey 102 | switch k := key.(type) { 103 | case *ecdsa.PrivateKey: 104 | ecdsaKey = k 105 | default: 106 | return "", ErrInvalidKey 107 | } 108 | 109 | // Create the hasher 110 | if !m.Hash.Available() { 111 | return "", ErrHashUnavailable 112 | } 113 | 114 | hasher := m.Hash.New() 115 | hasher.Write([]byte(signingString)) 116 | 117 | // Sign the string and return r, s 118 | if r, s, err := ecdsa.Sign(rand.Reader, ecdsaKey, hasher.Sum(nil)); err == nil { 119 | curveBits := ecdsaKey.Curve.Params().BitSize 120 | 121 | if m.CurveBits != curveBits { 122 | return "", ErrInvalidKey 123 | } 124 | 125 | keyBytes := curveBits / 8 126 | if curveBits%8 > 0 { 127 | keyBytes += 1 128 | } 129 | 130 | // We serialize the outpus (r and s) into big-endian byte arrays and pad 131 | // them with zeros on the left to make sure the sizes work out. Both arrays 132 | // must be keyBytes long, and the output must be 2*keyBytes long. 133 | rBytes := r.Bytes() 134 | rBytesPadded := make([]byte, keyBytes) 135 | copy(rBytesPadded[keyBytes-len(rBytes):], rBytes) 136 | 137 | sBytes := s.Bytes() 138 | sBytesPadded := make([]byte, keyBytes) 139 | copy(sBytesPadded[keyBytes-len(sBytes):], sBytes) 140 | 141 | out := append(rBytesPadded, sBytesPadded...) 142 | 143 | return EncodeSegment(out), nil 144 | } else { 145 | return "", err 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/dgrijalva/jwt-go/ecdsa_utils.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "crypto/ecdsa" 5 | "crypto/x509" 6 | "encoding/pem" 7 | "errors" 8 | ) 9 | 10 | var ( 11 | ErrNotECPublicKey = errors.New("Key is not a valid ECDSA public key") 12 | ErrNotECPrivateKey = errors.New("Key is not a valid ECDSA private key") 13 | ) 14 | 15 | // Parse PEM encoded Elliptic Curve Private Key Structure 16 | func ParseECPrivateKeyFromPEM(key []byte) (*ecdsa.PrivateKey, error) { 17 | var err error 18 | 19 | // Parse PEM block 20 | var block *pem.Block 21 | if block, _ = pem.Decode(key); block == nil { 22 | return nil, ErrKeyMustBePEMEncoded 23 | } 24 | 25 | // Parse the key 26 | var parsedKey interface{} 27 | if parsedKey, err = x509.ParseECPrivateKey(block.Bytes); err != nil { 28 | return nil, err 29 | } 30 | 31 | var pkey *ecdsa.PrivateKey 32 | var ok bool 33 | if pkey, ok = parsedKey.(*ecdsa.PrivateKey); !ok { 34 | return nil, ErrNotECPrivateKey 35 | } 36 | 37 | return pkey, nil 38 | } 39 | 40 | // Parse PEM encoded PKCS1 or PKCS8 public key 41 | func ParseECPublicKeyFromPEM(key []byte) (*ecdsa.PublicKey, error) { 42 | var err error 43 | 44 | // Parse PEM block 45 | var block *pem.Block 46 | if block, _ = pem.Decode(key); block == nil { 47 | return nil, ErrKeyMustBePEMEncoded 48 | } 49 | 50 | // Parse the key 51 | var parsedKey interface{} 52 | if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil { 53 | if cert, err := x509.ParseCertificate(block.Bytes); err == nil { 54 | parsedKey = cert.PublicKey 55 | } else { 56 | return nil, err 57 | } 58 | } 59 | 60 | var pkey *ecdsa.PublicKey 61 | var ok bool 62 | if pkey, ok = parsedKey.(*ecdsa.PublicKey); !ok { 63 | return nil, ErrNotECPublicKey 64 | } 65 | 66 | return pkey, nil 67 | } 68 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/dgrijalva/jwt-go/errors.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | // Error constants 8 | var ( 9 | ErrInvalidKey = errors.New("key is invalid or of invalid type") 10 | ErrHashUnavailable = errors.New("the requested hash function is unavailable") 11 | ErrNoTokenInRequest = errors.New("no token present in request") 12 | ) 13 | 14 | // The errors that might occur when parsing and validating a token 15 | const ( 16 | ValidationErrorMalformed uint32 = 1 << iota // Token is malformed 17 | ValidationErrorUnverifiable // Token could not be verified because of signing problems 18 | ValidationErrorSignatureInvalid // Signature validation failed 19 | ValidationErrorExpired // Exp validation failed 20 | ValidationErrorNotValidYet // NBF validation failed 21 | ) 22 | 23 | // The error from Parse if token is not valid 24 | type ValidationError struct { 25 | err string 26 | Errors uint32 // bitfield. see ValidationError... constants 27 | } 28 | 29 | // Validation error is an error type 30 | func (e ValidationError) Error() string { 31 | if e.err == "" { 32 | return "token is invalid" 33 | } 34 | return e.err 35 | } 36 | 37 | // No errors 38 | func (e *ValidationError) valid() bool { 39 | if e.Errors > 0 { 40 | return false 41 | } 42 | return true 43 | } 44 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/dgrijalva/jwt-go/hmac.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "crypto" 5 | "crypto/hmac" 6 | "errors" 7 | ) 8 | 9 | // Implements the HMAC-SHA family of signing methods signing methods 10 | type SigningMethodHMAC struct { 11 | Name string 12 | Hash crypto.Hash 13 | } 14 | 15 | // Specific instances for HS256 and company 16 | var ( 17 | SigningMethodHS256 *SigningMethodHMAC 18 | SigningMethodHS384 *SigningMethodHMAC 19 | SigningMethodHS512 *SigningMethodHMAC 20 | ErrSignatureInvalid = errors.New("signature is invalid") 21 | ) 22 | 23 | func init() { 24 | // HS256 25 | SigningMethodHS256 = &SigningMethodHMAC{"HS256", crypto.SHA256} 26 | RegisterSigningMethod(SigningMethodHS256.Alg(), func() SigningMethod { 27 | return SigningMethodHS256 28 | }) 29 | 30 | // HS384 31 | SigningMethodHS384 = &SigningMethodHMAC{"HS384", crypto.SHA384} 32 | RegisterSigningMethod(SigningMethodHS384.Alg(), func() SigningMethod { 33 | return SigningMethodHS384 34 | }) 35 | 36 | // HS512 37 | SigningMethodHS512 = &SigningMethodHMAC{"HS512", crypto.SHA512} 38 | RegisterSigningMethod(SigningMethodHS512.Alg(), func() SigningMethod { 39 | return SigningMethodHS512 40 | }) 41 | } 42 | 43 | func (m *SigningMethodHMAC) Alg() string { 44 | return m.Name 45 | } 46 | 47 | func (m *SigningMethodHMAC) Verify(signingString, signature string, key interface{}) error { 48 | if keyBytes, ok := key.([]byte); ok { 49 | var sig []byte 50 | var err error 51 | if sig, err = DecodeSegment(signature); err == nil { 52 | if !m.Hash.Available() { 53 | return ErrHashUnavailable 54 | } 55 | 56 | hasher := hmac.New(m.Hash.New, keyBytes) 57 | hasher.Write([]byte(signingString)) 58 | 59 | if !hmac.Equal(sig, hasher.Sum(nil)) { 60 | err = ErrSignatureInvalid 61 | } 62 | } 63 | return err 64 | } 65 | 66 | return ErrInvalidKey 67 | } 68 | 69 | // Implements the Sign method from SigningMethod for this signing method. 70 | // Key must be []byte 71 | func (m *SigningMethodHMAC) Sign(signingString string, key interface{}) (string, error) { 72 | if keyBytes, ok := key.([]byte); ok { 73 | if !m.Hash.Available() { 74 | return "", ErrHashUnavailable 75 | } 76 | 77 | hasher := hmac.New(m.Hash.New, keyBytes) 78 | hasher.Write([]byte(signingString)) 79 | 80 | return EncodeSegment(hasher.Sum(nil)), nil 81 | } 82 | 83 | return "", ErrInvalidKey 84 | } 85 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/dgrijalva/jwt-go/rsa.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "crypto" 5 | "crypto/rand" 6 | "crypto/rsa" 7 | ) 8 | 9 | // Implements the RSA family of signing methods signing methods 10 | type SigningMethodRSA struct { 11 | Name string 12 | Hash crypto.Hash 13 | } 14 | 15 | // Specific instances for RS256 and company 16 | var ( 17 | SigningMethodRS256 *SigningMethodRSA 18 | SigningMethodRS384 *SigningMethodRSA 19 | SigningMethodRS512 *SigningMethodRSA 20 | ) 21 | 22 | func init() { 23 | // RS256 24 | SigningMethodRS256 = &SigningMethodRSA{"RS256", crypto.SHA256} 25 | RegisterSigningMethod(SigningMethodRS256.Alg(), func() SigningMethod { 26 | return SigningMethodRS256 27 | }) 28 | 29 | // RS384 30 | SigningMethodRS384 = &SigningMethodRSA{"RS384", crypto.SHA384} 31 | RegisterSigningMethod(SigningMethodRS384.Alg(), func() SigningMethod { 32 | return SigningMethodRS384 33 | }) 34 | 35 | // RS512 36 | SigningMethodRS512 = &SigningMethodRSA{"RS512", crypto.SHA512} 37 | RegisterSigningMethod(SigningMethodRS512.Alg(), func() SigningMethod { 38 | return SigningMethodRS512 39 | }) 40 | } 41 | 42 | func (m *SigningMethodRSA) Alg() string { 43 | return m.Name 44 | } 45 | 46 | // Implements the Verify method from SigningMethod 47 | // For this signing method, must be either a PEM encoded PKCS1 or PKCS8 RSA public key as 48 | // []byte, or an rsa.PublicKey structure. 49 | func (m *SigningMethodRSA) Verify(signingString, signature string, key interface{}) error { 50 | var err error 51 | 52 | // Decode the signature 53 | var sig []byte 54 | if sig, err = DecodeSegment(signature); err != nil { 55 | return err 56 | } 57 | 58 | var rsaKey *rsa.PublicKey 59 | 60 | switch k := key.(type) { 61 | case []byte: 62 | if rsaKey, err = ParseRSAPublicKeyFromPEM(k); err != nil { 63 | return err 64 | } 65 | case *rsa.PublicKey: 66 | rsaKey = k 67 | default: 68 | return ErrInvalidKey 69 | } 70 | 71 | // Create hasher 72 | if !m.Hash.Available() { 73 | return ErrHashUnavailable 74 | } 75 | hasher := m.Hash.New() 76 | hasher.Write([]byte(signingString)) 77 | 78 | // Verify the signature 79 | return rsa.VerifyPKCS1v15(rsaKey, m.Hash, hasher.Sum(nil), sig) 80 | } 81 | 82 | // Implements the Sign method from SigningMethod 83 | // For this signing method, must be either a PEM encoded PKCS1 or PKCS8 RSA private key as 84 | // []byte, or an rsa.PrivateKey structure. 85 | func (m *SigningMethodRSA) Sign(signingString string, key interface{}) (string, error) { 86 | var err error 87 | var rsaKey *rsa.PrivateKey 88 | 89 | switch k := key.(type) { 90 | case []byte: 91 | if rsaKey, err = ParseRSAPrivateKeyFromPEM(k); err != nil { 92 | return "", err 93 | } 94 | case *rsa.PrivateKey: 95 | rsaKey = k 96 | default: 97 | return "", ErrInvalidKey 98 | } 99 | 100 | // Create the hasher 101 | if !m.Hash.Available() { 102 | return "", ErrHashUnavailable 103 | } 104 | 105 | hasher := m.Hash.New() 106 | hasher.Write([]byte(signingString)) 107 | 108 | // Sign the string and return the encoded bytes 109 | if sigBytes, err := rsa.SignPKCS1v15(rand.Reader, rsaKey, m.Hash, hasher.Sum(nil)); err == nil { 110 | return EncodeSegment(sigBytes), nil 111 | } else { 112 | return "", err 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/dgrijalva/jwt-go/rsa_pss.go: -------------------------------------------------------------------------------- 1 | // +build go1.4 2 | 3 | package jwt 4 | 5 | import ( 6 | "crypto" 7 | "crypto/rand" 8 | "crypto/rsa" 9 | ) 10 | 11 | // Implements the RSAPSS family of signing methods signing methods 12 | type SigningMethodRSAPSS struct { 13 | *SigningMethodRSA 14 | Options *rsa.PSSOptions 15 | } 16 | 17 | // Specific instances for RS/PS and company 18 | var ( 19 | SigningMethodPS256 *SigningMethodRSAPSS 20 | SigningMethodPS384 *SigningMethodRSAPSS 21 | SigningMethodPS512 *SigningMethodRSAPSS 22 | ) 23 | 24 | func init() { 25 | // PS256 26 | SigningMethodPS256 = &SigningMethodRSAPSS{ 27 | &SigningMethodRSA{ 28 | Name: "PS256", 29 | Hash: crypto.SHA256, 30 | }, 31 | &rsa.PSSOptions{ 32 | SaltLength: rsa.PSSSaltLengthAuto, 33 | Hash: crypto.SHA256, 34 | }, 35 | } 36 | RegisterSigningMethod(SigningMethodPS256.Alg(), func() SigningMethod { 37 | return SigningMethodPS256 38 | }) 39 | 40 | // PS384 41 | SigningMethodPS384 = &SigningMethodRSAPSS{ 42 | &SigningMethodRSA{ 43 | Name: "PS384", 44 | Hash: crypto.SHA384, 45 | }, 46 | &rsa.PSSOptions{ 47 | SaltLength: rsa.PSSSaltLengthAuto, 48 | Hash: crypto.SHA384, 49 | }, 50 | } 51 | RegisterSigningMethod(SigningMethodPS384.Alg(), func() SigningMethod { 52 | return SigningMethodPS384 53 | }) 54 | 55 | // PS512 56 | SigningMethodPS512 = &SigningMethodRSAPSS{ 57 | &SigningMethodRSA{ 58 | Name: "PS512", 59 | Hash: crypto.SHA512, 60 | }, 61 | &rsa.PSSOptions{ 62 | SaltLength: rsa.PSSSaltLengthAuto, 63 | Hash: crypto.SHA512, 64 | }, 65 | } 66 | RegisterSigningMethod(SigningMethodPS512.Alg(), func() SigningMethod { 67 | return SigningMethodPS512 68 | }) 69 | } 70 | 71 | // Implements the Verify method from SigningMethod 72 | // For this verify method, key must be an rsa.PublicKey struct 73 | func (m *SigningMethodRSAPSS) Verify(signingString, signature string, key interface{}) error { 74 | var err error 75 | 76 | // Decode the signature 77 | var sig []byte 78 | if sig, err = DecodeSegment(signature); err != nil { 79 | return err 80 | } 81 | 82 | var rsaKey *rsa.PublicKey 83 | switch k := key.(type) { 84 | case *rsa.PublicKey: 85 | rsaKey = k 86 | default: 87 | return ErrInvalidKey 88 | } 89 | 90 | // Create hasher 91 | if !m.Hash.Available() { 92 | return ErrHashUnavailable 93 | } 94 | hasher := m.Hash.New() 95 | hasher.Write([]byte(signingString)) 96 | 97 | return rsa.VerifyPSS(rsaKey, m.Hash, hasher.Sum(nil), sig, m.Options) 98 | } 99 | 100 | // Implements the Sign method from SigningMethod 101 | // For this signing method, key must be an rsa.PrivateKey struct 102 | func (m *SigningMethodRSAPSS) Sign(signingString string, key interface{}) (string, error) { 103 | var rsaKey *rsa.PrivateKey 104 | 105 | switch k := key.(type) { 106 | case *rsa.PrivateKey: 107 | rsaKey = k 108 | default: 109 | return "", ErrInvalidKey 110 | } 111 | 112 | // Create the hasher 113 | if !m.Hash.Available() { 114 | return "", ErrHashUnavailable 115 | } 116 | 117 | hasher := m.Hash.New() 118 | hasher.Write([]byte(signingString)) 119 | 120 | // Sign the string and return the encoded bytes 121 | if sigBytes, err := rsa.SignPSS(rand.Reader, rsaKey, m.Hash, hasher.Sum(nil), m.Options); err == nil { 122 | return EncodeSegment(sigBytes), nil 123 | } else { 124 | return "", err 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/dgrijalva/jwt-go/rsa_utils.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "crypto/rsa" 5 | "crypto/x509" 6 | "encoding/pem" 7 | "errors" 8 | ) 9 | 10 | var ( 11 | ErrKeyMustBePEMEncoded = errors.New("Invalid Key: Key must be PEM encoded PKCS1 or PKCS8 private key") 12 | ErrNotRSAPrivateKey = errors.New("Key is not a valid RSA private key") 13 | ) 14 | 15 | // Parse PEM encoded PKCS1 or PKCS8 private key 16 | func ParseRSAPrivateKeyFromPEM(key []byte) (*rsa.PrivateKey, error) { 17 | var err error 18 | 19 | // Parse PEM block 20 | var block *pem.Block 21 | if block, _ = pem.Decode(key); block == nil { 22 | return nil, ErrKeyMustBePEMEncoded 23 | } 24 | 25 | var parsedKey interface{} 26 | if parsedKey, err = x509.ParsePKCS1PrivateKey(block.Bytes); err != nil { 27 | if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil { 28 | return nil, err 29 | } 30 | } 31 | 32 | var pkey *rsa.PrivateKey 33 | var ok bool 34 | if pkey, ok = parsedKey.(*rsa.PrivateKey); !ok { 35 | return nil, ErrNotRSAPrivateKey 36 | } 37 | 38 | return pkey, nil 39 | } 40 | 41 | // Parse PEM encoded PKCS1 or PKCS8 public key 42 | func ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error) { 43 | var err error 44 | 45 | // Parse PEM block 46 | var block *pem.Block 47 | if block, _ = pem.Decode(key); block == nil { 48 | return nil, ErrKeyMustBePEMEncoded 49 | } 50 | 51 | // Parse the key 52 | var parsedKey interface{} 53 | if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil { 54 | if cert, err := x509.ParseCertificate(block.Bytes); err == nil { 55 | parsedKey = cert.PublicKey 56 | } else { 57 | return nil, err 58 | } 59 | } 60 | 61 | var pkey *rsa.PublicKey 62 | var ok bool 63 | if pkey, ok = parsedKey.(*rsa.PublicKey); !ok { 64 | return nil, ErrNotRSAPrivateKey 65 | } 66 | 67 | return pkey, nil 68 | } 69 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/dgrijalva/jwt-go/signing_method.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | var signingMethods = map[string]func() SigningMethod{} 4 | 5 | // Signing method 6 | type SigningMethod interface { 7 | Verify(signingString, signature string, key interface{}) error 8 | Sign(signingString string, key interface{}) (string, error) 9 | Alg() string 10 | } 11 | 12 | // Register the "alg" name and a factory function for signing method. 13 | // This is typically done during init() in the method's implementation 14 | func RegisterSigningMethod(alg string, f func() SigningMethod) { 15 | signingMethods[alg] = f 16 | } 17 | 18 | // Get a signing method from an "alg" string 19 | func GetSigningMethod(alg string) (method SigningMethod) { 20 | if methodF, ok := signingMethods[alg]; ok { 21 | method = methodF() 22 | } 23 | return 24 | } 25 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/dgrijalva/jwt-go/test/hmacTestKey: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomsteele/shellsquid/6aab6d3b0432ff61818e74942e255f6bca6787e6/Godeps/_workspace/src/github.com/dgrijalva/jwt-go/test/hmacTestKey -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/dgrijalva/jwt-go/test/sample_key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEA4f5wg5l2hKsTeNem/V41fGnJm6gOdrj8ym3rFkEU/wT8RDtn 3 | SgFEZOQpHEgQ7JL38xUfU0Y3g6aYw9QT0hJ7mCpz9Er5qLaMXJwZxzHzAahlfA0i 4 | cqabvJOMvQtzD6uQv6wPEyZtDTWiQi9AXwBpHssPnpYGIn20ZZuNlX2BrClciHhC 5 | PUIIZOQn/MmqTD31jSyjoQoV7MhhMTATKJx2XrHhR+1DcKJzQBSTAGnpYVaqpsAR 6 | ap+nwRipr3nUTuxyGohBTSmjJ2usSeQXHI3bODIRe1AuTyHceAbewn8b462yEWKA 7 | Rdpd9AjQW5SIVPfdsz5B6GlYQ5LdYKtznTuy7wIDAQABAoIBAQCwia1k7+2oZ2d3 8 | n6agCAbqIE1QXfCmh41ZqJHbOY3oRQG3X1wpcGH4Gk+O+zDVTV2JszdcOt7E5dAy 9 | MaomETAhRxB7hlIOnEN7WKm+dGNrKRvV0wDU5ReFMRHg31/Lnu8c+5BvGjZX+ky9 10 | POIhFFYJqwCRlopGSUIxmVj5rSgtzk3iWOQXr+ah1bjEXvlxDOWkHN6YfpV5ThdE 11 | KdBIPGEVqa63r9n2h+qazKrtiRqJqGnOrHzOECYbRFYhexsNFz7YT02xdfSHn7gM 12 | IvabDDP/Qp0PjE1jdouiMaFHYnLBbgvlnZW9yuVf/rpXTUq/njxIXMmvmEyyvSDn 13 | FcFikB8pAoGBAPF77hK4m3/rdGT7X8a/gwvZ2R121aBcdPwEaUhvj/36dx596zvY 14 | mEOjrWfZhF083/nYWE2kVquj2wjs+otCLfifEEgXcVPTnEOPO9Zg3uNSL0nNQghj 15 | FuD3iGLTUBCtM66oTe0jLSslHe8gLGEQqyMzHOzYxNqibxcOZIe8Qt0NAoGBAO+U 16 | I5+XWjWEgDmvyC3TrOSf/KCGjtu0TSv30ipv27bDLMrpvPmD/5lpptTFwcxvVhCs 17 | 2b+chCjlghFSWFbBULBrfci2FtliClOVMYrlNBdUSJhf3aYSG2Doe6Bgt1n2CpNn 18 | /iu37Y3NfemZBJA7hNl4dYe+f+uzM87cdQ214+jrAoGAXA0XxX8ll2+ToOLJsaNT 19 | OvNB9h9Uc5qK5X5w+7G7O998BN2PC/MWp8H+2fVqpXgNENpNXttkRm1hk1dych86 20 | EunfdPuqsX+as44oCyJGFHVBnWpm33eWQw9YqANRI+pCJzP08I5WK3osnPiwshd+ 21 | hR54yjgfYhBFNI7B95PmEQkCgYBzFSz7h1+s34Ycr8SvxsOBWxymG5zaCsUbPsL0 22 | 4aCgLScCHb9J+E86aVbbVFdglYa5Id7DPTL61ixhl7WZjujspeXZGSbmq0Kcnckb 23 | mDgqkLECiOJW2NHP/j0McAkDLL4tysF8TLDO8gvuvzNC+WQ6drO2ThrypLVZQ+ry 24 | eBIPmwKBgEZxhqa0gVvHQG/7Od69KWj4eJP28kq13RhKay8JOoN0vPmspXJo1HY3 25 | CKuHRG+AP579dncdUnOMvfXOtkdM4vk0+hWASBQzM9xzVcztCa+koAugjVaLS9A+ 26 | 9uQoqEeVNTckxx0S2bYevRy7hGQmUJTyQm3j1zEUR5jpdbL83Fbq 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/dgrijalva/jwt-go/test/sample_key.pub: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4f5wg5l2hKsTeNem/V41 3 | fGnJm6gOdrj8ym3rFkEU/wT8RDtnSgFEZOQpHEgQ7JL38xUfU0Y3g6aYw9QT0hJ7 4 | mCpz9Er5qLaMXJwZxzHzAahlfA0icqabvJOMvQtzD6uQv6wPEyZtDTWiQi9AXwBp 5 | HssPnpYGIn20ZZuNlX2BrClciHhCPUIIZOQn/MmqTD31jSyjoQoV7MhhMTATKJx2 6 | XrHhR+1DcKJzQBSTAGnpYVaqpsARap+nwRipr3nUTuxyGohBTSmjJ2usSeQXHI3b 7 | ODIRe1AuTyHceAbewn8b462yEWKARdpd9AjQW5SIVPfdsz5B6GlYQ5LdYKtznTuy 8 | 7wIDAQAB 9 | -----END PUBLIC KEY----- 10 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/gorilla/context/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | 4 | go: 5 | - 1.3 6 | - 1.4 7 | - 1.5 8 | - tip 9 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/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 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/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 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/gorilla/context/context.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 | package context 6 | 7 | import ( 8 | "net/http" 9 | "sync" 10 | "time" 11 | ) 12 | 13 | var ( 14 | mutex sync.RWMutex 15 | data = make(map[*http.Request]map[interface{}]interface{}) 16 | datat = make(map[*http.Request]int64) 17 | ) 18 | 19 | // Set stores a value for a given key in a given request. 20 | func Set(r *http.Request, key, val interface{}) { 21 | mutex.Lock() 22 | if data[r] == nil { 23 | data[r] = make(map[interface{}]interface{}) 24 | datat[r] = time.Now().Unix() 25 | } 26 | data[r][key] = val 27 | mutex.Unlock() 28 | } 29 | 30 | // Get returns a value stored for a given key in a given request. 31 | func Get(r *http.Request, key interface{}) interface{} { 32 | mutex.RLock() 33 | if ctx := data[r]; ctx != nil { 34 | value := ctx[key] 35 | mutex.RUnlock() 36 | return value 37 | } 38 | mutex.RUnlock() 39 | return nil 40 | } 41 | 42 | // GetOk returns stored value and presence state like multi-value return of map access. 43 | func GetOk(r *http.Request, key interface{}) (interface{}, bool) { 44 | mutex.RLock() 45 | if _, ok := data[r]; ok { 46 | value, ok := data[r][key] 47 | mutex.RUnlock() 48 | return value, ok 49 | } 50 | mutex.RUnlock() 51 | return nil, false 52 | } 53 | 54 | // GetAll returns all stored values for the request as a map. Nil is returned for invalid requests. 55 | func GetAll(r *http.Request) map[interface{}]interface{} { 56 | mutex.RLock() 57 | if context, ok := data[r]; ok { 58 | result := make(map[interface{}]interface{}, len(context)) 59 | for k, v := range context { 60 | result[k] = v 61 | } 62 | mutex.RUnlock() 63 | return result 64 | } 65 | mutex.RUnlock() 66 | return nil 67 | } 68 | 69 | // GetAllOk returns all stored values for the request as a map and a boolean value that indicates if 70 | // the request was registered. 71 | func GetAllOk(r *http.Request) (map[interface{}]interface{}, bool) { 72 | mutex.RLock() 73 | context, ok := data[r] 74 | result := make(map[interface{}]interface{}, len(context)) 75 | for k, v := range context { 76 | result[k] = v 77 | } 78 | mutex.RUnlock() 79 | return result, ok 80 | } 81 | 82 | // Delete removes a value stored for a given key in a given request. 83 | func Delete(r *http.Request, key interface{}) { 84 | mutex.Lock() 85 | if data[r] != nil { 86 | delete(data[r], key) 87 | } 88 | mutex.Unlock() 89 | } 90 | 91 | // Clear removes all values stored for a given request. 92 | // 93 | // This is usually called by a handler wrapper to clean up request 94 | // variables at the end of a request lifetime. See ClearHandler(). 95 | func Clear(r *http.Request) { 96 | mutex.Lock() 97 | clear(r) 98 | mutex.Unlock() 99 | } 100 | 101 | // clear is Clear without the lock. 102 | func clear(r *http.Request) { 103 | delete(data, r) 104 | delete(datat, r) 105 | } 106 | 107 | // Purge removes request data stored for longer than maxAge, in seconds. 108 | // It returns the amount of requests removed. 109 | // 110 | // If maxAge <= 0, all request data is removed. 111 | // 112 | // This is only used for sanity check: in case context cleaning was not 113 | // properly set some request data can be kept forever, consuming an increasing 114 | // amount of memory. In case this is detected, Purge() must be called 115 | // periodically until the problem is fixed. 116 | func Purge(maxAge int) int { 117 | mutex.Lock() 118 | count := 0 119 | if maxAge <= 0 { 120 | count = len(data) 121 | data = make(map[*http.Request]map[interface{}]interface{}) 122 | datat = make(map[*http.Request]int64) 123 | } else { 124 | min := time.Now().Unix() - int64(maxAge) 125 | for r := range data { 126 | if datat[r] < min { 127 | clear(r) 128 | count++ 129 | } 130 | } 131 | } 132 | mutex.Unlock() 133 | return count 134 | } 135 | 136 | // ClearHandler wraps an http.Handler and clears request values at the end 137 | // of a request lifetime. 138 | func ClearHandler(h http.Handler) http.Handler { 139 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 140 | defer Clear(r) 141 | h.ServeHTTP(w, r) 142 | }) 143 | } 144 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/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 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/gorilla/mux/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | 4 | go: 5 | - 1.3 6 | - 1.4 7 | - 1.5 8 | - tip 9 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/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 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jinzhu/copier/Guardfile: -------------------------------------------------------------------------------- 1 | guard 'gotest' do 2 | watch(%r{\.go$}) 3 | end 4 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jinzhu/copier/License: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Jinzhu 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 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jinzhu/copier/README.md: -------------------------------------------------------------------------------- 1 | # Copier 2 | 3 | I am a copier, I copy everything from a struct to another struct 4 | 5 | ## Features 6 | 7 | * Copy field to field if name exactly match 8 | * Copy from method to field if method name and field name exactly match 9 | * Copy from field to method if field name and method name exactly match 10 | * Copy slice to slice 11 | * Copy struct to slice 12 | 13 | ## Usage 14 | 15 | ```go 16 | import . "github.com/jinzhu/copier" 17 | 18 | type User struct { 19 | Name string 20 | Role string 21 | Age int32 22 | } 23 | 24 | func (user *User) DoubleAge() int32 { 25 | return 2 * user.Age 26 | } 27 | 28 | type Employee struct { 29 | Name string 30 | Age int32 31 | DoubleAge int32 32 | EmployeId int64 33 | SuperRule string 34 | } 35 | 36 | func (employee *Employee) Role(role string) { 37 | employee.SuperRule = "Super " + role 38 | } 39 | 40 | user := User{Name: "Jinzhu", Age: 18, Role: "Admin"} 41 | employee := Employee{} 42 | 43 | Copy(&employee, &user) 44 | 45 | // employee => Employee{ Name: "Jinzhu", // Copy from field 46 | // Age: 18, // Copy from field 47 | // DoubleAge: 36, // Copy from method 48 | // EmployeeId: 0, // Just ignored 49 | // SuperRule: "Super Admin", // Copy to method 50 | // } 51 | 52 | // Copy struct to slice 53 | user := User{Name: "hello", Age: 18, Role: "User"} 54 | employees := []Employee{} 55 | Copy(&employees, &user) 56 | // employees => [{hello 18 0 36 Super User}] 57 | 58 | 59 | // Copy slice to slice 60 | users := []User{{Name: "Jinzhu", Age: 18, Role: "Admin"}, {Name: "jinzhu 2", Age: 30, Role: "Dev"}} 61 | employees := []Employee{} 62 | Copy(&employees, &users) 63 | 64 | // employees => [{hello 18 0 36 Super User} {Jinzhu 18 0 36 Super Admin} {jinzhu 2 30 0 60 Super Dev}] 65 | ``` 66 | 67 | # Author 68 | 69 | **jinzhu** 70 | 71 | * 72 | * 73 | * 74 | 75 | ## License 76 | 77 | Released under the [MIT License](https://github.com/jinzhu/copier/blob/master/License). 78 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jinzhu/copier/copier.go: -------------------------------------------------------------------------------- 1 | package copier 2 | 3 | import "reflect" 4 | 5 | func Copy(toValue interface{}, fromValue interface{}) (err error) { 6 | var ( 7 | isSlice bool 8 | fromType reflect.Type 9 | isFromPtr bool 10 | toType reflect.Type 11 | isToPtr bool 12 | amount int 13 | ) 14 | 15 | from := reflect.Indirect(reflect.ValueOf(fromValue)) 16 | to := reflect.Indirect(reflect.ValueOf(toValue)) 17 | 18 | if to.Kind() == reflect.Slice { 19 | isSlice = true 20 | if from.Kind() == reflect.Slice { 21 | fromType = from.Type().Elem() 22 | if fromType.Kind() == reflect.Ptr { 23 | fromType = fromType.Elem() 24 | isFromPtr = true 25 | } 26 | amount = from.Len() 27 | } else { 28 | fromType = from.Type() 29 | amount = 1 30 | } 31 | 32 | toType = to.Type().Elem() 33 | if toType.Kind() == reflect.Ptr { 34 | toType = toType.Elem() 35 | isToPtr = true 36 | } 37 | } else { 38 | fromType = from.Type() 39 | toType = to.Type() 40 | amount = 1 41 | } 42 | 43 | for e := 0; e < amount; e++ { 44 | var dest, source reflect.Value 45 | if isSlice { 46 | if from.Kind() == reflect.Slice { 47 | source = from.Index(e) 48 | if isFromPtr { 49 | source = source.Elem() 50 | } 51 | } else { 52 | source = from 53 | } 54 | } else { 55 | source = from 56 | } 57 | 58 | if isSlice { 59 | dest = reflect.New(toType).Elem() 60 | } else { 61 | dest = to 62 | } 63 | 64 | for i := 0; i < fromType.NumField(); i++ { 65 | field := fromType.Field(i) 66 | if !field.Anonymous { 67 | name := field.Name 68 | fromField := source.FieldByName(name) 69 | toField := dest.FieldByName(name) 70 | toMethod := dest.Addr().MethodByName(name) 71 | if fromField.IsValid() && toField.IsValid() { 72 | toField.Set(fromField) 73 | } 74 | 75 | if fromField.IsValid() && toMethod.IsValid() { 76 | toMethod.Call([]reflect.Value{fromField}) 77 | } 78 | } 79 | } 80 | 81 | for i := 0; i < toType.NumField(); i++ { 82 | field := toType.Field(i) 83 | if !field.Anonymous { 84 | name := field.Name 85 | fromMethod := source.Addr().MethodByName(name) 86 | toField := dest.FieldByName(name) 87 | 88 | if fromMethod.IsValid() && toField.IsValid() { 89 | values := fromMethod.Call([]reflect.Value{}) 90 | if len(values) >= 1 { 91 | toField.Set(values[0]) 92 | } 93 | } 94 | } 95 | } 96 | 97 | if isSlice { 98 | if isToPtr { 99 | to.Set(reflect.Append(to, dest.Addr())) 100 | } else { 101 | to.Set(reflect.Append(to, dest)) 102 | } 103 | } 104 | } 105 | return 106 | } 107 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jmcvetta/randutil/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | notificaitons: 3 | email: 4 | recipients: jason.mcvetta@gmail.com 5 | on_success: change 6 | on_failure: always 7 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jmcvetta/randutil/README.md: -------------------------------------------------------------------------------- 1 | # randutil - Random number/string utilities for the Go language 2 | 3 | This package contains assorted utility functions for creating random numbers 4 | and strings. I use this package quite a bit, especially when testing other 5 | projects. However I make no claims about the cryptographic security or other 6 | properties of the random(-ish?) numbers and strings it produces. Use at your 7 | own risk. 8 | 9 | ## API Documentation 10 | 11 | See GoDoc for [automatically generated 12 | documentation](http://godoc.org/github.com/jmcvetta/randutil). 13 | 14 | 15 | ## Status 16 | 17 | [![Build Status](https://drone.io/github.com/jmcvetta/randutil/status.png)](https://drone.io/github.com/jmcvetta/randutil/latest) 18 | [![Travis Build Status](https://travis-ci.org/jmcvetta/randutil.png)](https://travis-ci.org/jmcvetta/randutil) 19 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jmcvetta/randutil/randutil.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 Jason McVetta. This is Free Software, released under the 2 | // terms of the GPL v3. See http://www.gnu.org/copyleft/gpl.html for details. 3 | 4 | // Package randutil provides various convenience functions for dealing with 5 | // random numbers and strings. 6 | package randutil 7 | 8 | import ( 9 | "crypto/rand" 10 | "errors" 11 | "math/big" 12 | ) 13 | 14 | const ( 15 | // Set of characters to use for generating random strings 16 | Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 17 | Numerals = "1234567890" 18 | Alphanumeric = Alphabet + Numerals 19 | Ascii = Alphanumeric + "~!@#$%^&*()-_+={}[]\\|<,>.?/\"';:`" 20 | ) 21 | 22 | var MinMaxError = errors.New("Min cannot be greater than max.") 23 | 24 | // IntRange returns a random integer in the range from min to max. 25 | func IntRange(min, max int) (int, error) { 26 | var result int 27 | switch { 28 | case min > max: 29 | // Fail with error 30 | return result, MinMaxError 31 | case max == min: 32 | result = max 33 | case max > min: 34 | maxRand := max - min 35 | b, err := rand.Int(rand.Reader, big.NewInt(int64(maxRand))) 36 | if err != nil { 37 | return result, err 38 | } 39 | result = min + int(b.Int64()) 40 | } 41 | return result, nil 42 | } 43 | 44 | // String returns a random string n characters long, composed of entities 45 | // from charset. 46 | func String(n int, charset string) (string, error) { 47 | randstr := make([]byte, n) // Random string to return 48 | charlen := big.NewInt(int64(len(charset))) 49 | for i := 0; i < n; i++ { 50 | b, err := rand.Int(rand.Reader, charlen) 51 | if err != nil { 52 | return "", err 53 | } 54 | r := int(b.Int64()) 55 | randstr[i] = charset[r] 56 | } 57 | return string(randstr), nil 58 | } 59 | 60 | // StringRange returns a random string at least min and no more than max 61 | // characters long, composed of entitites from charset. 62 | func StringRange(min, max int, charset string) (string, error) { 63 | // 64 | // First determine the length of string to be generated 65 | // 66 | var err error // Holds errors 67 | var strlen int // Length of random string to generate 68 | var randstr string // Random string to return 69 | strlen, err = IntRange(min, max) 70 | if err != nil { 71 | return randstr, err 72 | } 73 | randstr, err = String(strlen, charset) 74 | if err != nil { 75 | return randstr, err 76 | } 77 | return randstr, nil 78 | } 79 | 80 | // AlphaRange returns a random alphanumeric string at least min and no more 81 | // than max characters long. 82 | func AlphaStringRange(min, max int) (string, error) { 83 | return StringRange(min, max, Alphanumeric) 84 | } 85 | 86 | // AlphaString returns a random alphanumeric string n characters long. 87 | func AlphaString(n int) (string, error) { 88 | return String(n, Alphanumeric) 89 | } 90 | 91 | // ChoiceString returns a random selection from an array of strings. 92 | func ChoiceString(choices []string) (string, error) { 93 | var winner string 94 | length := len(choices) 95 | i, err := IntRange(0, length) 96 | winner = choices[i] 97 | return winner, err 98 | } 99 | 100 | // ChoiceInt returns a random selection from an array of integers. 101 | func ChoiceInt(choices []int) (int, error) { 102 | var winner int 103 | length := len(choices) 104 | i, err := IntRange(0, length) 105 | winner = choices[i] 106 | return winner, err 107 | } 108 | 109 | // A Choice contains a generic item and a weight controlling the frequency with 110 | // which it will be selected. 111 | type Choice struct { 112 | Weight int 113 | Item interface{} 114 | } 115 | 116 | // WeightedChoice used weighted random selection to return one of the supplied 117 | // choices. Weights of 0 are never selected. All other weight values are 118 | // relative. E.g. if you have two choices both weighted 3, they will be 119 | // returned equally often; and each will be returned 3 times as often as a 120 | // choice weighted 1. 121 | func WeightedChoice(choices []Choice) (Choice, error) { 122 | // Based on this algorithm: 123 | // http://eli.thegreenplace.net/2010/01/22/weighted-random-generation-in-python/ 124 | var ret Choice 125 | sum := 0 126 | for _, c := range choices { 127 | sum += c.Weight 128 | } 129 | r, err := IntRange(0, sum) 130 | if err != nil { 131 | return ret, err 132 | } 133 | for _, c := range choices { 134 | r -= c.Weight 135 | if r < 0 { 136 | return c, nil 137 | } 138 | } 139 | err = errors.New("Internal error - code should not reach this point") 140 | return ret, err 141 | } 142 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/mholt/binding/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Matt 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. -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/mholt/binding/README.md: -------------------------------------------------------------------------------- 1 | [binding is reflectionless data binding for Go](http://mholt.github.io/binding) 2 | 3 | 4 | binding 5 | ======= 6 | 7 | Reflectionless data binding for Go's net/http 8 | 9 | 10 | 11 | Features 12 | --------- 13 | 14 | - HTTP request data binding 15 | - Data validation (custom and built-in) 16 | - Error handling 17 | 18 | 19 | 20 | Benefits 21 | --------- 22 | 23 | - Moves data binding, validation, and error handling out of your application's handler 24 | - Reads Content-Type to deserialize form, multipart form, and JSON data from requests 25 | - No middleware: just a function call 26 | - Usable in any setting where `net/http` is present (Negroni, gocraft/web, std lib, etc.) 27 | - No reflection 28 | 29 | 30 | 31 | Usage example 32 | -------------- 33 | 34 | ```go 35 | package main 36 | 37 | import ( 38 | "fmt" 39 | "net/http" 40 | 41 | "github.com/mholt/binding" 42 | ) 43 | 44 | // First define a type to hold the data 45 | // (If the data comes from JSON, see: http://mholt.github.io/json-to-go) 46 | type ContactForm struct { 47 | User struct { 48 | ID int 49 | } 50 | Email string 51 | Message string 52 | } 53 | 54 | // Then provide a field mapping (pointer receiver is vital) 55 | func (cf *ContactForm) FieldMap(req *http.Request) binding.FieldMap { 56 | return binding.FieldMap{ 57 | &cf.User.ID: "user_id", 58 | &cf.Email: "email", 59 | &cf.Message: binding.Field{ 60 | Form: "message", 61 | Required: true, 62 | }, 63 | } 64 | } 65 | 66 | // Now your handlers can stay clean and simple 67 | func handler(resp http.ResponseWriter, req *http.Request) { 68 | contactForm := new(ContactForm) 69 | errs := binding.Bind(req, contactForm) 70 | if errs.Handle(resp) { 71 | return 72 | } 73 | fmt.Fprintf(resp, "From: %d\n", contactForm.User.ID) 74 | fmt.Fprintf(resp, "Message: %s\n", contactForm.Message) 75 | } 76 | 77 | func main() { 78 | http.HandleFunc("/contact", handler) 79 | http.ListenAndServe(":3000", nil) 80 | } 81 | ``` 82 | 83 | Multipart/form-data usage example 84 | --------------------------------- 85 | 86 | ```go 87 | package main 88 | 89 | import ( 90 | "bytes" 91 | "fmt" 92 | "github.com/mholt/binding" 93 | "io" 94 | "log" 95 | "mime/multipart" 96 | "net/http" 97 | ) 98 | 99 | // We expect a multipart/form-data upload with 100 | // a file field named 'data' 101 | type MultipartForm struct { 102 | Data *multipart.FileHeader `json:"data"` 103 | } 104 | 105 | func (f *MultipartForm) FieldMap(req *http.Request) binding.FieldMap { 106 | return binding.FieldMap{ 107 | &f.Data: "data", 108 | } 109 | } 110 | 111 | // Handlers are still clean and simple 112 | func handler(resp http.ResponseWriter, req *http.Request) { 113 | multipartForm := new(MultipartForm) 114 | errs := binding.Bind(req, multipartForm) 115 | if errs.Handle(resp) { 116 | return 117 | } 118 | 119 | // To access the file data you need to Open the file 120 | // handler and read the bytes out. 121 | var fh io.ReadCloser 122 | var err error 123 | if fh, err = multipartForm.Data.Open(); err != nil { 124 | http.Error(resp, 125 | fmt.Sprint("Error opening Mime::Data %+v", err), 126 | http.StatusInternalServerError) 127 | return 128 | } 129 | defer fh.Close() 130 | dataBytes := bytes.Buffer{} 131 | var size int64 132 | if size, err = dataBytes.ReadFrom(fh); err != nil { 133 | http.Error(resp, 134 | fmt.Sprint("Error reading Mime::Data %+v", err), 135 | http.StatusInternalServerError) 136 | return 137 | } 138 | // Now you have the attachment in databytes. 139 | // Maximum size is default is 10MB. 140 | log.Printf("Read %v bytes with filename %s", 141 | size, multipartForm.Data.Filename) 142 | } 143 | 144 | func main() { 145 | http.HandleFunc("/upload", handler) 146 | http.ListenAndServe(":3000", nil) 147 | } 148 | 149 | ``` 150 | 151 | You can test from CLI using the excellent httpie client 152 | 153 | `http -f POST localhost:3000/upload data@myupload` 154 | 155 | Custom data validation 156 | ----------------------- 157 | 158 | You may optionally have your type implement the `binding.Validator` interface to perform your own data validation. The `.Validate()` method is called after the struct is populated. 159 | 160 | ```go 161 | func (cf ContactForm) Validate(req *http.Request, errs binding.Errors) binding.Errors { 162 | if cf.Message == "Go needs generics" { 163 | errs = append(errs, binding.Error{ 164 | FieldNames: []string{"message"}, 165 | Classification: "ComplaintError", 166 | Message: "Go has generics. They're called interfaces.", 167 | }) 168 | } 169 | return errs 170 | } 171 | ``` 172 | 173 | 174 | 175 | Error Handling 176 | --------------- 177 | 178 | `binding.Bind()` and each deserializer returns errors. You don't have to use them, but the `binding.Errors` type comes with a kind of built-in "handler" to write the errors to the response as JSON for you. For example, you might do this in your HTTP handler: 179 | 180 | ```go 181 | if binding.Bind(req, contactForm).Handle(resp) { 182 | return 183 | } 184 | ``` 185 | 186 | As you can see, if `.Handle(resp)` wrote errors to the response, your handler may gracefully exit. 187 | 188 | 189 | 190 | Binding custom types 191 | --------------------- 192 | 193 | For types you've defined, you can bind form data to it by implementing the `Binder` interface. Here's a contrived example: 194 | 195 | 196 | ```go 197 | type MyType map[string]string 198 | 199 | func (t *MyType) Bind(fieldName string, strVals []string, errs binding.Errors) binding.Errors { 200 | t["formData"] = strVals[0] 201 | return errs 202 | } 203 | ``` 204 | 205 | If you can't add a method to the type, you can still specify a `Binder` func in the field spec. Here's a contrived example that binds an integer (not necessary, but you get the idea): 206 | 207 | ```go 208 | func (t *MyType) FieldMap() binding.FieldMap { 209 | return binding.FieldMap{ 210 | "number": binding.Field{ 211 | Binder: func(fieldName string, formVals []string, errs binding.Errors) binding.Errors { 212 | val, err := strconv.Atoi(formVals[0]) 213 | if err != nil { 214 | errs.Add([]string{fieldName}, binding.DeserializationError, err.Error()) 215 | } 216 | t.SomeNumber = val 217 | return errs 218 | }, 219 | }, 220 | } 221 | } 222 | ``` 223 | 224 | Notice that the `binding.Errors` type has a convenience method `.Add()` which you can use to append to the slice if you prefer. 225 | 226 | 227 | Supported types (forms) 228 | ------------------------ 229 | 230 | The following types are supported in form deserialization by default. (JSON requests are delegated to `encoding/json`.) 231 | 232 | - uint, *uint, []uint, uint8, *uint8, []uint8, uint16, *uint16, []uint16, uint32, *uint32, []uint32, uint64, *uint64, []uint64 233 | - int, *int, []int, int8, *int8, []int8, int16, *int16, []int16, int32, *int32, []int32, int64, *int64, []int64 234 | - float32, *float32, []float32, float64, *float64, []float64 235 | - bool, *bool, []bool 236 | - string, *string, []string 237 | - time.Time, *time.Time, []time.Time 238 | - *multipart.FileHeader, []*multipart.FileHeader 239 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/mholt/binding/errors.go: -------------------------------------------------------------------------------- 1 | package binding 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | "strings" 7 | ) 8 | 9 | // This file shamelessly adapted from martini-contrib/binding 10 | 11 | type ( 12 | // Errors may be generated during deserialization, binding, 13 | // or validation. It implements the built-in error interface. 14 | Errors []Error 15 | 16 | // Error is a powerful implementation of the built-in error 17 | // interface that allows for error classification, custom error 18 | // messages associated with specific fields, or with no 19 | // associations at all. 20 | Error struct { 21 | // An error supports zero or more field names, because an 22 | // error can morph three ways: (1) it can indicate something 23 | // wrong with the request as a whole, (2) it can point to a 24 | // specific problem with a particular input field, or (3) it 25 | // can span multiple related input fields. 26 | FieldNames []string `json:"fieldNames,omitempty"` 27 | 28 | // The classification is like an error code, convenient to 29 | // use when processing or categorizing an error programmatically. 30 | // It may also be called the "kind" of error. 31 | Classification string `json:"classification,omitempty"` 32 | 33 | // Message should be human-readable and detailed enough to 34 | // pinpoint and resolve the problem, but it should be brief. For 35 | // example, a payload of 100 objects in a JSON array might have 36 | // an error in the 41st object. The message should help the 37 | // end user find and fix the error with their request. 38 | Message string `json:"message,omitempty"` 39 | } 40 | ) 41 | 42 | // Add adds an error associated with the fields indicated 43 | // by fieldNames, with the given classification and message. 44 | func (e *Errors) Add(fieldNames []string, classification, message string) { 45 | *e = append(*e, Error{ 46 | FieldNames: fieldNames, 47 | Classification: classification, 48 | Message: message, 49 | }) 50 | } 51 | 52 | // Len returns the number of errors. 53 | func (e *Errors) Len() int { 54 | return len(*e) 55 | } 56 | 57 | // Has determines whether an Errors slice has an Error with 58 | // a given classification in it; it does not search on messages 59 | // or field names. 60 | func (e *Errors) Has(class string) bool { 61 | for _, err := range *e { 62 | if err.Kind() == class { 63 | return true 64 | } 65 | } 66 | return false 67 | } 68 | 69 | // Handle writes the errors to response in JSON form if any errors 70 | // are contained, and it will return true. Otherwise, nothing happens 71 | // and false is returned. 72 | // (The value receiver is due to issue 8: https://github.com/mholt/binding/issues/8) 73 | func (e Errors) Handle(response http.ResponseWriter) bool { 74 | if e.Len() > 0 { 75 | response.Header().Set("Content-Type", jsonContentType) 76 | if e.Has(ContentTypeError) { 77 | response.WriteHeader(http.StatusUnsupportedMediaType) 78 | } else { 79 | response.WriteHeader(http.StatusBadRequest) 80 | } 81 | errOutput, _ := json.Marshal(e) 82 | response.Write(errOutput) 83 | return true 84 | } 85 | return false 86 | } 87 | 88 | // Error returns a concatenation of all its error messages. 89 | func (e Errors) Error() string { 90 | messages := []string{} 91 | for _, err := range e { 92 | messages = append(messages, err.Error()) 93 | } 94 | return strings.Join(messages, ", ") 95 | } 96 | 97 | // Fields returns the list of field names this error is 98 | // associated with. 99 | func (e Error) Fields() []string { 100 | return e.FieldNames 101 | } 102 | 103 | // Kind returns this error's classification. 104 | func (e Error) Kind() string { 105 | return e.Classification 106 | } 107 | 108 | // Error returns this error's message. 109 | func (e Error) Error() string { 110 | return e.Message 111 | } 112 | 113 | const ( 114 | RequiredError = "RequiredError" 115 | ContentTypeError = "ContentTypeError" 116 | DeserializationError = "DeserializationError" 117 | TypeError = "TypeError" 118 | ) 119 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/nlf/boltons/.gitignore: -------------------------------------------------------------------------------- 1 | test.db 2 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/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 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/unrolled/render/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.3 5 | - 1.4 6 | - 1.5 7 | 8 | install: 9 | - go get github.com/eknkc/amber 10 | 11 | script: 12 | - go test -v -race -tags=integration 13 | 14 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/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 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/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 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/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 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/unrolled/render/engine.go: -------------------------------------------------------------------------------- 1 | package render 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "encoding/xml" 7 | "html/template" 8 | "net/http" 9 | ) 10 | 11 | // Engine is the generic interface for all responses. 12 | type Engine interface { 13 | Render(http.ResponseWriter, interface{}) error 14 | } 15 | 16 | // Head defines the basic ContentType and Status fields. 17 | type Head struct { 18 | ContentType string 19 | Status int 20 | } 21 | 22 | // Data built-in renderer. 23 | type Data struct { 24 | Head 25 | } 26 | 27 | // HTML built-in renderer. 28 | type HTML struct { 29 | Head 30 | Name string 31 | Templates *template.Template 32 | } 33 | 34 | // JSON built-in renderer. 35 | type JSON struct { 36 | Head 37 | Indent bool 38 | UnEscapeHTML bool 39 | Prefix []byte 40 | StreamingJSON bool 41 | } 42 | 43 | // JSONP built-in renderer. 44 | type JSONP struct { 45 | Head 46 | Indent bool 47 | Callback string 48 | } 49 | 50 | // Text built-in renderer. 51 | type Text struct { 52 | Head 53 | } 54 | 55 | // XML built-in renderer. 56 | type XML struct { 57 | Head 58 | Indent bool 59 | Prefix []byte 60 | } 61 | 62 | // Write outputs the header content. 63 | func (h Head) Write(w http.ResponseWriter) { 64 | w.Header().Set(ContentType, h.ContentType) 65 | w.WriteHeader(h.Status) 66 | } 67 | 68 | // Render a data response. 69 | func (d Data) Render(w http.ResponseWriter, v interface{}) error { 70 | c := w.Header().Get(ContentType) 71 | if c != "" { 72 | d.Head.ContentType = c 73 | } 74 | 75 | d.Head.Write(w) 76 | w.Write(v.([]byte)) 77 | return nil 78 | } 79 | 80 | // Render a HTML response. 81 | func (h HTML) Render(w http.ResponseWriter, binding interface{}) error { 82 | // Retrieve a buffer from the pool to write to. 83 | out := bufPool.Get() 84 | err := h.Templates.ExecuteTemplate(out, h.Name, binding) 85 | if err != nil { 86 | return err 87 | } 88 | 89 | h.Head.Write(w) 90 | out.WriteTo(w) 91 | 92 | // Return the buffer to the pool. 93 | bufPool.Put(out) 94 | return nil 95 | } 96 | 97 | // Render a JSON response. 98 | func (j JSON) Render(w http.ResponseWriter, v interface{}) error { 99 | if j.StreamingJSON { 100 | return j.renderStreamingJSON(w, v) 101 | } 102 | 103 | var result []byte 104 | var err error 105 | 106 | if j.Indent { 107 | result, err = json.MarshalIndent(v, "", " ") 108 | result = append(result, '\n') 109 | } else { 110 | result, err = json.Marshal(v) 111 | } 112 | if err != nil { 113 | return err 114 | } 115 | 116 | // Unescape HTML if needed. 117 | if j.UnEscapeHTML { 118 | result = bytes.Replace(result, []byte("\\u003c"), []byte("<"), -1) 119 | result = bytes.Replace(result, []byte("\\u003e"), []byte(">"), -1) 120 | result = bytes.Replace(result, []byte("\\u0026"), []byte("&"), -1) 121 | } 122 | 123 | // JSON marshaled fine, write out the result. 124 | j.Head.Write(w) 125 | if len(j.Prefix) > 0 { 126 | w.Write(j.Prefix) 127 | } 128 | w.Write(result) 129 | return nil 130 | } 131 | 132 | func (j JSON) renderStreamingJSON(w http.ResponseWriter, v interface{}) error { 133 | j.Head.Write(w) 134 | if len(j.Prefix) > 0 { 135 | w.Write(j.Prefix) 136 | } 137 | 138 | return json.NewEncoder(w).Encode(v) 139 | } 140 | 141 | // Render a JSONP response. 142 | func (j JSONP) Render(w http.ResponseWriter, v interface{}) error { 143 | var result []byte 144 | var err error 145 | 146 | if j.Indent { 147 | result, err = json.MarshalIndent(v, "", " ") 148 | } else { 149 | result, err = json.Marshal(v) 150 | } 151 | if err != nil { 152 | return err 153 | } 154 | 155 | // JSON marshaled fine, write out the result. 156 | j.Head.Write(w) 157 | w.Write([]byte(j.Callback + "(")) 158 | w.Write(result) 159 | w.Write([]byte(");")) 160 | 161 | // If indenting, append a new line. 162 | if j.Indent { 163 | w.Write([]byte("\n")) 164 | } 165 | return nil 166 | } 167 | 168 | // Render a text response. 169 | func (t Text) Render(w http.ResponseWriter, v interface{}) error { 170 | c := w.Header().Get(ContentType) 171 | if c != "" { 172 | t.Head.ContentType = c 173 | } 174 | 175 | t.Head.Write(w) 176 | w.Write([]byte(v.(string))) 177 | return nil 178 | } 179 | 180 | // Render an XML response. 181 | func (x XML) Render(w http.ResponseWriter, v interface{}) error { 182 | var result []byte 183 | var err error 184 | 185 | if x.Indent { 186 | result, err = xml.MarshalIndent(v, "", " ") 187 | result = append(result, '\n') 188 | } else { 189 | result, err = xml.Marshal(v) 190 | } 191 | if err != nil { 192 | return err 193 | } 194 | 195 | // XML marshaled fine, write out the result. 196 | x.Head.Write(w) 197 | if len(x.Prefix) > 0 { 198 | w.Write(x.Prefix) 199 | } 200 | w.Write(result) 201 | return nil 202 | } 203 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/unrolled/render/fixtures/amber/example.amber: -------------------------------------------------------------------------------- 1 | extends layouts/base 2 | 3 | block content 4 | p This is the page content! 5 | ul 6 | li This is 7 | li Some more 8 | li #{VarTwo} -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/unrolled/render/fixtures/amber/layouts/base.amber: -------------------------------------------------------------------------------- 1 | html 2 | head 3 | title Page Title 4 | body 5 | div#header 6 | ul 7 | li Home 8 | li Menu 9 | li About 10 | li #{VarOne} 11 | block content -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/unrolled/render/fixtures/basic/admin/index.tmpl: -------------------------------------------------------------------------------- 1 |

Admin {{.}}

2 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/unrolled/render/fixtures/basic/another_layout.tmpl: -------------------------------------------------------------------------------- 1 | another head 2 | {{ yield }} 3 | another foot 4 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/unrolled/render/fixtures/basic/content.tmpl: -------------------------------------------------------------------------------- 1 |

{{ . }}

2 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/unrolled/render/fixtures/basic/current_layout.tmpl: -------------------------------------------------------------------------------- 1 | {{ current }} head 2 | {{ yield }} 3 | {{ current }} foot 4 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/unrolled/render/fixtures/basic/delims.tmpl: -------------------------------------------------------------------------------- 1 |

Hello {[{.}]}

-------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/unrolled/render/fixtures/basic/hello.tmpl: -------------------------------------------------------------------------------- 1 |

Hello {{.}}

2 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/unrolled/render/fixtures/basic/hypertext.html: -------------------------------------------------------------------------------- 1 | Hypertext! 2 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/unrolled/render/fixtures/basic/layout.tmpl: -------------------------------------------------------------------------------- 1 | head 2 | {{ yield }} 3 | foot 4 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/unrolled/render/fixtures/blocks/content-partial.tmpl: -------------------------------------------------------------------------------- 1 | {{define "after-content-partial"}}after {{ . }}{{end}} 2 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/unrolled/render/fixtures/blocks/content.tmpl: -------------------------------------------------------------------------------- 1 | {{define "before-content"}}before {{ . }}{{end}} 2 | {{define "after-content"}}after {{ . }}{{end}} 3 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/unrolled/render/fixtures/blocks/layout.tmpl: -------------------------------------------------------------------------------- 1 | {{ block "before" }} 2 |

during

3 | {{ block "after" }} 4 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/unrolled/render/fixtures/custom_funcs/index.tmpl: -------------------------------------------------------------------------------- 1 | {{ myCustomFunc }} 2 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/unrolled/render/fixtures/template-dir-test/0.tmpl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomsteele/shellsquid/6aab6d3b0432ff61818e74942e255f6bca6787e6/Godeps/_workspace/src/github.com/unrolled/render/fixtures/template-dir-test/0.tmpl -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/unrolled/render/fixtures/template-dir-test/dedicated.tmpl/notbad.tmpl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomsteele/shellsquid/6aab6d3b0432ff61818e74942e255f6bca6787e6/Godeps/_workspace/src/github.com/unrolled/render/fixtures/template-dir-test/dedicated.tmpl/notbad.tmpl -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/unrolled/render/fixtures/template-dir-test/subdir/1.tmpl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomsteele/shellsquid/6aab6d3b0432ff61818e74942e255f6bca6787e6/Godeps/_workspace/src/github.com/unrolled/render/fixtures/template-dir-test/subdir/1.tmpl -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/crypto/bcrypt/base64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package bcrypt 6 | 7 | import "encoding/base64" 8 | 9 | const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" 10 | 11 | var bcEncoding = base64.NewEncoding(alphabet) 12 | 13 | func base64Encode(src []byte) []byte { 14 | n := bcEncoding.EncodedLen(len(src)) 15 | dst := make([]byte, n) 16 | bcEncoding.Encode(dst, src) 17 | for dst[n-1] == '=' { 18 | n-- 19 | } 20 | return dst[:n] 21 | } 22 | 23 | func base64Decode(src []byte) ([]byte, error) { 24 | numOfEquals := 4 - (len(src) % 4) 25 | for i := 0; i < numOfEquals; i++ { 26 | src = append(src, '=') 27 | } 28 | 29 | dst := make([]byte, bcEncoding.DecodedLen(len(src))) 30 | n, err := bcEncoding.Decode(dst, src) 31 | if err != nil { 32 | return nil, err 33 | } 34 | return dst[:n], nil 35 | } 36 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/crypto/blowfish/block.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package blowfish 6 | 7 | // getNextWord returns the next big-endian uint32 value from the byte slice 8 | // at the given position in a circular manner, updating the position. 9 | func getNextWord(b []byte, pos *int) uint32 { 10 | var w uint32 11 | j := *pos 12 | for i := 0; i < 4; i++ { 13 | w = w<<8 | uint32(b[j]) 14 | j++ 15 | if j >= len(b) { 16 | j = 0 17 | } 18 | } 19 | *pos = j 20 | return w 21 | } 22 | 23 | // ExpandKey performs a key expansion on the given *Cipher. Specifically, it 24 | // performs the Blowfish algorithm's key schedule which sets up the *Cipher's 25 | // pi and substitution tables for calls to Encrypt. This is used, primarily, 26 | // by the bcrypt package to reuse the Blowfish key schedule during its 27 | // set up. It's unlikely that you need to use this directly. 28 | func ExpandKey(key []byte, c *Cipher) { 29 | j := 0 30 | for i := 0; i < 18; i++ { 31 | // Using inlined getNextWord for performance. 32 | var d uint32 33 | for k := 0; k < 4; k++ { 34 | d = d<<8 | uint32(key[j]) 35 | j++ 36 | if j >= len(key) { 37 | j = 0 38 | } 39 | } 40 | c.p[i] ^= d 41 | } 42 | 43 | var l, r uint32 44 | for i := 0; i < 18; i += 2 { 45 | l, r = encryptBlock(l, r, c) 46 | c.p[i], c.p[i+1] = l, r 47 | } 48 | 49 | for i := 0; i < 256; i += 2 { 50 | l, r = encryptBlock(l, r, c) 51 | c.s0[i], c.s0[i+1] = l, r 52 | } 53 | for i := 0; i < 256; i += 2 { 54 | l, r = encryptBlock(l, r, c) 55 | c.s1[i], c.s1[i+1] = l, r 56 | } 57 | for i := 0; i < 256; i += 2 { 58 | l, r = encryptBlock(l, r, c) 59 | c.s2[i], c.s2[i+1] = l, r 60 | } 61 | for i := 0; i < 256; i += 2 { 62 | l, r = encryptBlock(l, r, c) 63 | c.s3[i], c.s3[i+1] = l, r 64 | } 65 | } 66 | 67 | // This is similar to ExpandKey, but folds the salt during the key 68 | // schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero 69 | // salt passed in, reusing ExpandKey turns out to be a place of inefficiency 70 | // and specializing it here is useful. 71 | func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) { 72 | j := 0 73 | for i := 0; i < 18; i++ { 74 | c.p[i] ^= getNextWord(key, &j) 75 | } 76 | 77 | j = 0 78 | var l, r uint32 79 | for i := 0; i < 18; i += 2 { 80 | l ^= getNextWord(salt, &j) 81 | r ^= getNextWord(salt, &j) 82 | l, r = encryptBlock(l, r, c) 83 | c.p[i], c.p[i+1] = l, r 84 | } 85 | 86 | for i := 0; i < 256; i += 2 { 87 | l ^= getNextWord(salt, &j) 88 | r ^= getNextWord(salt, &j) 89 | l, r = encryptBlock(l, r, c) 90 | c.s0[i], c.s0[i+1] = l, r 91 | } 92 | 93 | for i := 0; i < 256; i += 2 { 94 | l ^= getNextWord(salt, &j) 95 | r ^= getNextWord(salt, &j) 96 | l, r = encryptBlock(l, r, c) 97 | c.s1[i], c.s1[i+1] = l, r 98 | } 99 | 100 | for i := 0; i < 256; i += 2 { 101 | l ^= getNextWord(salt, &j) 102 | r ^= getNextWord(salt, &j) 103 | l, r = encryptBlock(l, r, c) 104 | c.s2[i], c.s2[i+1] = l, r 105 | } 106 | 107 | for i := 0; i < 256; i += 2 { 108 | l ^= getNextWord(salt, &j) 109 | r ^= getNextWord(salt, &j) 110 | l, r = encryptBlock(l, r, c) 111 | c.s3[i], c.s3[i+1] = l, r 112 | } 113 | } 114 | 115 | func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) { 116 | xl, xr := l, r 117 | xl ^= c.p[0] 118 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[1] 119 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[2] 120 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[3] 121 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[4] 122 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[5] 123 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[6] 124 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[7] 125 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[8] 126 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[9] 127 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[10] 128 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[11] 129 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[12] 130 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[13] 131 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[14] 132 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[15] 133 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[16] 134 | xr ^= c.p[17] 135 | return xr, xl 136 | } 137 | 138 | func decryptBlock(l, r uint32, c *Cipher) (uint32, uint32) { 139 | xl, xr := l, r 140 | xl ^= c.p[17] 141 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[16] 142 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[15] 143 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[14] 144 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[13] 145 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[12] 146 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[11] 147 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[10] 148 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[9] 149 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[8] 150 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[7] 151 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[6] 152 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[5] 153 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[4] 154 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[3] 155 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[2] 156 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[1] 157 | xr ^= c.p[0] 158 | return xr, xl 159 | } 160 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/crypto/blowfish/cipher.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package blowfish implements Bruce Schneier's Blowfish encryption algorithm. 6 | package blowfish 7 | 8 | // The code is a port of Bruce Schneier's C implementation. 9 | // See http://www.schneier.com/blowfish.html. 10 | 11 | import "strconv" 12 | 13 | // The Blowfish block size in bytes. 14 | const BlockSize = 8 15 | 16 | // A Cipher is an instance of Blowfish encryption using a particular key. 17 | type Cipher struct { 18 | p [18]uint32 19 | s0, s1, s2, s3 [256]uint32 20 | } 21 | 22 | type KeySizeError int 23 | 24 | func (k KeySizeError) Error() string { 25 | return "crypto/blowfish: invalid key size " + strconv.Itoa(int(k)) 26 | } 27 | 28 | // NewCipher creates and returns a Cipher. 29 | // The key argument should be the Blowfish key, from 1 to 56 bytes. 30 | func NewCipher(key []byte) (*Cipher, error) { 31 | var result Cipher 32 | if k := len(key); k < 1 || k > 56 { 33 | return nil, KeySizeError(k) 34 | } 35 | initCipher(&result) 36 | ExpandKey(key, &result) 37 | return &result, nil 38 | } 39 | 40 | // NewSaltedCipher creates a returns a Cipher that folds a salt into its key 41 | // schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is 42 | // sufficient and desirable. For bcrypt compatiblity, the key can be over 56 43 | // bytes. 44 | func NewSaltedCipher(key, salt []byte) (*Cipher, error) { 45 | if len(salt) == 0 { 46 | return NewCipher(key) 47 | } 48 | var result Cipher 49 | if k := len(key); k < 1 { 50 | return nil, KeySizeError(k) 51 | } 52 | initCipher(&result) 53 | expandKeyWithSalt(key, salt, &result) 54 | return &result, nil 55 | } 56 | 57 | // BlockSize returns the Blowfish block size, 8 bytes. 58 | // It is necessary to satisfy the Block interface in the 59 | // package "crypto/cipher". 60 | func (c *Cipher) BlockSize() int { return BlockSize } 61 | 62 | // Encrypt encrypts the 8-byte buffer src using the key k 63 | // and stores the result in dst. 64 | // Note that for amounts of data larger than a block, 65 | // it is not safe to just call Encrypt on successive blocks; 66 | // instead, use an encryption mode like CBC (see crypto/cipher/cbc.go). 67 | func (c *Cipher) Encrypt(dst, src []byte) { 68 | l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) 69 | r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) 70 | l, r = encryptBlock(l, r, c) 71 | dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l) 72 | dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r) 73 | } 74 | 75 | // Decrypt decrypts the 8-byte buffer src using the key k 76 | // and stores the result in dst. 77 | func (c *Cipher) Decrypt(dst, src []byte) { 78 | l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) 79 | r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) 80 | l, r = decryptBlock(l, r, c) 81 | dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l) 82 | dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r) 83 | } 84 | 85 | func initCipher(c *Cipher) { 86 | copy(c.p[0:], p[0:]) 87 | copy(c.s0[0:], s0[0:]) 88 | copy(c.s1[0:], s1[0:]) 89 | copy(c.s2[0:], s2[0:]) 90 | copy(c.s3[0:], s3[0:]) 91 | } 92 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Tom Steele 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 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | shellsquid 2 | ========== 3 | 4 | At its core, shellsquid is a database driven HTTP(S) and DNS reverse proxy. The intended purpose is to enable teams to share a single Internet facing interface and port when handling multiple reverse payloads. The original version of shellsquid used customized payloads to determine routing, and was overly complex. This version uses hostnames and is much more straight forward. 5 | 6 | For HTTP(S), a common way of configuring payload routing is to register a single domain with a wildcard DNS record, and then use subdomains to route payloads. 7 | 8 | For DNS payloads, a domain can be registered and a authoritative DNS server setup, using the shellsquid host IP. You can then use multiple subdomains to route to different internal handlers. [dnscat2](https://github.com/iagox86/dnscat2) was the payload used for testing, consult it's documentation for more information on configuring authoritative DNS. 9 | 10 | ### Download 11 | Binary packages for every supported operating system are availble [here](https://github.com/tomsteele/shellsquid/releases/latest). 12 | 13 | This package does not provide a web client. The recommended client is [shellsquid-ui](https://github.com/tomsteele/shellsquid-ui). 14 | 15 | ### Dependencies 16 | None, shellsquid is written in [Go](https://golang.org) and uses [boltdb](https://github.com/boltdb/bolt). 17 | 18 | ### Configuration 19 | Configuration is done via a JSON file in `config.json`. The following values are supported: 20 | 21 | ``` 22 | { 23 | "proxy": { 24 | "dns": { 25 | "enabled": true, 26 | "listener": ":53" 27 | }, 28 | "ssl": { 29 | "enabled": true, 30 | "listener": ":443", 31 | "key": "key.pem", 32 | "cert": "cert.pem" 33 | }, 34 | "http": { 35 | "enabled": true, 36 | "listener": ":80" 37 | } 38 | }, 39 | 40 | "admin": { 41 | "listener": ":1337", 42 | "key": "key.pem", 43 | "cert": "cert.pem" 44 | }, 45 | "jwt_key": "something secret", 46 | "bolt_db_file": "squid.db" 47 | } 48 | ``` 49 | 50 | You will need to generate a certificate and key files separately. Do whatever is best for your needs and environment. For example, a self signed certificate can be generated using the the following syntax and should be stored in the root of the project directory: 51 | ``` 52 | $ openssl req -x509 -newkey rsa:2048 -nodes -keyout key.pem -out cert.pem -days XXX 53 | ``` 54 | 55 | ### Starting the server 56 | Starting the server is as easy as running the compiled binary. If started for the first time, an initial user `admin@localhost` will be created with a random password, this will be output to stdout. 57 | 58 | `$ ./shellsquid` 59 | 60 | You can now login to the admin interface, by default this is an HTTPS service on TCP 1337. 61 | 62 | ### Adding a Record 63 | Records are used to tell shellsquid how to route incoming traffic. On each request, shellsquid will lookup the FQDN provided in the database. If a record is found, the traffic will be routed to the configured handler. 64 | 65 | If using the suggested web UI: 66 | * Click "Add Record" 67 | * Fields 68 | * FQDN - This is the hostname that your payload will use. This can be a fully qualified domain name. Can also be a domain name (e.g."example.com", "foo.baz") if using dns as your handler protocol. For http(s) handlers, this may also be the IP of the incoming client. When in doubt, use a FQDN (e.g. "foo.example.com", "bar.foo.baz"). 69 | * Handler Host - This is the IP address where your handler is listening. 70 | * Handler Port - This is the port number that your handler is listening on. 71 | * Handler Protocol - Should be either http, https, or dns. 72 | * Click "Submit" 73 | 74 | ### Metasploit Configuration 75 | This version of shellsquid does not require any special handlers! There are still some considerations to make when configuring your multi-handler. The reason for this is to control the `payload_uri` that is generated by the handler, we need that to output the address of our proxy and not the actual handler. Configuration steps: 76 | * set `LHOST` to the fqdn of your record. 77 | * set `LPORT` to the listening port of the proxy. For example, if it's an HTTPS payload and your proxy is configured to listen on 443, then set it to 443. 78 | * use the advanced options of `ReverseListenerBindPort` and `ReverseListenerBindAddress` to set the actual interface and port for the handler to use. 79 | * run like normal. 80 | 81 | ***You can not set your `ReverseListenerBindAddress` to `localhost` or `127.0.0.1` because of a bug in Metasploit.*** 82 | 83 | #### MSF Configuration Example 84 | It is easier to think of shellsquid as a reverse HTTP proxy, such as nginx. For example, an HTTP request is sent to nginx based on a fqdn (e.g., foo.bar.com) along with the respective HTTP Host header. The nginx proxy then routes the request to the appropriate application content. 85 | 86 | shellsquid is similar; the HTTP based reverse shell fires and connects back to shellsquid with the `LHOST` payload set to a FQDN. It is important to note that shellsquid can route numerous shells based on subdomain. So say we have the following list: 87 | 88 | * foo.bar.com 89 | * baz.bar.com 90 | * fud.bar.com 91 | 92 | All of the these FQDNs would route based on their subdomain components. shellsquid would then parse the HTTP Host header and route the connection to the actual MSF multi-handler designated by the "show advanced" syntax within MetaSploit. The following images provide a sample configuration: 93 | 94 | ***Setting `LHOST` and `LPORT` to use the FQDN of your record and port of the proxy*** 95 | ![](https://github.com/tomsteele/shellsquid-ui/blob/master/app/images/msf_fqdn.png) 96 | 97 | ***Setting the Backend (i.e., shoveled/proxied) listener to the actual `LHOST` and `LPORT` established in shellsquid*** 98 | ![](https://github.com/tomsteele/shellsquid-ui/blob/master/app/images/msf_advanced.png) 99 | 100 | 101 | ### Security 102 | Authentication and authorization is performed using JSON Web Tokens ("JWT"). The administrative portion of the application is configured by default to listen on a separate port and interface than the HTTP and HTTPS proxy handler. Access to the administrative interface is done using a username and password. Currently, all users have the same permissions and can change the passwords of other users. This is fully intentional, everyone is an admin. There didn't seem like there was much to be gained by having a finegrained permissions model. 103 | 104 | ### Development 105 | 106 | #### Server 107 | The server is written in Go and uses boltdb. Configuration is done in `config.json`. This project uses godep for dependency management. To start the server: 108 | 109 | ``` 110 | # Install godep 111 | $ go get github.com/tools/godep 112 | # Run the server, all dependencies are managed and stored in the using godep in the Godeps directory 113 | $ sudo -E godep go run main.go 114 | ``` 115 | 116 | #### Client 117 | Shellsquid is bring your own client. The recommended client is [shellsquid-ui](https://github.com/tomsteele/shellsquid-ui). 118 | -------------------------------------------------------------------------------- /app/app.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "github.com/nlf/boltons" 5 | "github.com/tomsteele/shellsquid/config" 6 | "github.com/unrolled/render" 7 | ) 8 | 9 | // App is used by the server to pass around global data structures need by handlers. 10 | type App struct { 11 | DB *boltons.DB 12 | JWTSecret []byte 13 | Render *render.Render 14 | Config *config.Config 15 | } 16 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "proxy": { 3 | "dns": { 4 | "enabled": true, 5 | "listener": ":53" 6 | }, 7 | "ssl": { 8 | "enabled": true, 9 | "listener": ":443", 10 | "key": "key.pem", 11 | "cert": "cert.pem" 12 | }, 13 | "http": { 14 | "enabled": true, 15 | "listener": ":80" 16 | } 17 | }, 18 | 19 | "admin": { 20 | "listener": ":1337", 21 | "key": "key.pem", 22 | "cert": "cert.pem" 23 | }, 24 | "jwt_key": "secret", 25 | "bolt_db_file": "squid.db" 26 | } 27 | -------------------------------------------------------------------------------- /config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "encoding/json" 5 | "io/ioutil" 6 | ) 7 | 8 | // Config holds all the required information for server. 9 | type Config struct { 10 | Proxy struct { 11 | DNS struct { 12 | Enabled bool `json:"enabled"` 13 | Listener string `json:"listener"` 14 | } `json:"dns"` 15 | SSL struct { 16 | Enabled bool `json:"enabled"` 17 | Listener string `json:"listener"` 18 | Key string `json:"key"` 19 | Cert string `json:"cert"` 20 | } `json:"ssl"` 21 | HTTP struct { 22 | Enabled bool `json:"enabled"` 23 | Listener string `json:"listener"` 24 | } `json:"http"` 25 | } `json:"proxy"` 26 | Admin struct { 27 | Listener string `json:"listener"` 28 | Key string `json:"key"` 29 | Cert string `json:"cert"` 30 | } `json:"admin"` 31 | JWTKey string `json:"jwt_key"` 32 | BoltDBFile string `json:"bolt_db_file"` 33 | } 34 | 35 | // New parses JSON from the file provided by filename into a Config struct. 36 | func New(filename string) (*Config, error) { 37 | config := &Config{} 38 | file, err := ioutil.ReadFile(filename) 39 | if err != nil { 40 | return config, err 41 | } 42 | 43 | if err := json.Unmarshal(file, &config); err != nil { 44 | return config, err 45 | } 46 | 47 | return config, nil 48 | } 49 | -------------------------------------------------------------------------------- /handlers/info.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/tomsteele/shellsquid/app" 7 | ) 8 | 9 | // Infos struct holds version and proxy info. 10 | type Infos struct { 11 | Version string `json:"version"` 12 | Proxy struct { 13 | DNS struct { 14 | Enabled bool `json:"enabled"` 15 | Listener string `json:"listener"` 16 | } `json:"dns"` 17 | SSL struct { 18 | Enabled bool `json:"enabled"` 19 | Listener string `json:"listener"` 20 | } `json:"ssl"` 21 | HTTP struct { 22 | Enabled bool `json:"enabled"` 23 | Listener string `json:"listener"` 24 | } `json:"http"` 25 | } `json:"proxy"` 26 | } 27 | 28 | // Info returns some useful information for the client. 29 | func Info(server *app.App, version string) func(w http.ResponseWriter, req *http.Request) { 30 | return func(w http.ResponseWriter, req *http.Request) { 31 | info := &Infos{} 32 | info.Version = version 33 | info.Proxy.SSL.Enabled = server.Config.Proxy.SSL.Enabled 34 | info.Proxy.SSL.Listener = server.Config.Proxy.SSL.Listener 35 | info.Proxy.HTTP.Enabled = server.Config.Proxy.HTTP.Enabled 36 | info.Proxy.HTTP.Listener = server.Config.Proxy.HTTP.Listener 37 | info.Proxy.DNS.Enabled = server.Config.Proxy.DNS.Enabled 38 | info.Proxy.DNS.Listener = server.Config.Proxy.DNS.Listener 39 | server.Render.JSON(w, http.StatusOK, info) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /handlers/proxy.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "crypto/tls" 5 | "net" 6 | "net/http" 7 | "net/http/httputil" 8 | "net/url" 9 | "strconv" 10 | "strings" 11 | 12 | "github.com/miekg/dns" 13 | "github.com/tomsteele/shellsquid/app" 14 | "github.com/tomsteele/shellsquid/models" 15 | ) 16 | 17 | func hostname(host string) string { 18 | parts := strings.SplitN(host, ":", 2) 19 | return parts[0] 20 | } 21 | 22 | // ProxyDNS returns a handler for a proxy DNS server. 23 | func ProxyDNS(server *app.App) func(w dns.ResponseWriter, req *dns.Msg) { 24 | return func(w dns.ResponseWriter, req *dns.Msg) { 25 | if len(req.Question) == 0 { 26 | dns.HandleFailed(w, req) 27 | return 28 | } 29 | name := req.Question[0].Name 30 | record, err := models.FindRecordBySubOfFQDN(server.DB, name) 31 | if err != nil || record.ID == "" { 32 | dns.HandleFailed(w, req) 33 | return 34 | } 35 | if record.Blacklist { 36 | dns.HandleFailed(w, req) 37 | return 38 | } 39 | transport := "udp" 40 | if _, ok := w.RemoteAddr().(*net.TCPAddr); ok { 41 | transport = "tcp" 42 | } 43 | c := &dns.Client{Net: transport} 44 | resp, _, err := c.Exchange(req, record.HandlerHost+":"+strconv.Itoa(record.HandlerPort)) 45 | if err != nil { 46 | dns.HandleFailed(w, req) 47 | return 48 | } 49 | if err := w.WriteMsg(resp); err != nil { 50 | dns.HandleFailed(w, req) 51 | return 52 | } 53 | } 54 | } 55 | 56 | // Proxy returns a handler to proxy HTTP(S) requests. 57 | func Proxy(server *app.App, isHTTPS bool) func(w http.ResponseWriter, req *http.Request) { 58 | return func(w http.ResponseWriter, req *http.Request) { 59 | record, err := models.FindRecordByFQDN(server.DB, hostname(req.Host)) 60 | if err != nil || record.ID == "" { 61 | server.Render.Data(w, http.StatusNotFound, nil) 62 | return 63 | } 64 | if record.Blacklist { 65 | server.Render.Data(w, http.StatusNotFound, nil) 66 | return 67 | } 68 | u, err := url.Parse(record.HandlerProtocol + "://" + record.HandlerHost + ":" + strconv.Itoa(record.HandlerPort)) 69 | if err != nil { 70 | server.Render.Data(w, http.StatusNotFound, nil) 71 | return 72 | } 73 | proxy := httputil.NewSingleHostReverseProxy(u) 74 | if isHTTPS { 75 | proxy.Transport = &http.Transport{ 76 | TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 77 | } 78 | } 79 | proxy.ServeHTTP(w, req) 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /handlers/record.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | "strconv" 7 | "time" 8 | 9 | "github.com/gorilla/context" 10 | "github.com/gorilla/mux" 11 | "github.com/jinzhu/copier" 12 | "github.com/mholt/binding" 13 | "github.com/tomsteele/shellsquid/app" 14 | "github.com/tomsteele/shellsquid/models" 15 | ) 16 | 17 | func isSameAsListener(listener string, req *models.RecordRequest) bool { 18 | return listener == req.HandlerHost+":"+strconv.Itoa(req.HandlerPort) 19 | } 20 | 21 | // CreateRecord handles a request to create a new record. 22 | func CreateRecord(server *app.App) func(w http.ResponseWriter, req *http.Request) { 23 | return func(w http.ResponseWriter, req *http.Request) { 24 | user := &models.User{} 25 | user = context.Get(req, "user").(*models.User) 26 | recordReq := &models.RecordRequest{} 27 | if err := binding.Bind(req, recordReq); err.Handle(w) { 28 | return 29 | } 30 | if isSameAsListener(server.Config.Proxy.HTTP.Listener, recordReq) { 31 | server.Render.JSON(w, http.StatusBadRequest, map[string]string{"error": "Handler Host and Handler Port must not be the same as HTTP Listener"}) 32 | return 33 | } 34 | if isSameAsListener(server.Config.Proxy.SSL.Listener, recordReq) { 35 | server.Render.JSON(w, http.StatusBadRequest, map[string]string{"error": "Handler Host and Handler Port must not be the same as SSL Listener"}) 36 | return 37 | } 38 | existing, err := models.FindRecordByFQDN(server.DB, recordReq.FQDN) 39 | if err != nil { 40 | server.Render.JSON(w, http.StatusInternalServerError, map[string]string{"error": "there was an error saving the record to the database"}) 41 | log.Println(err) 42 | return 43 | } 44 | if existing.ID != "" { 45 | server.Render.JSON(w, http.StatusBadRequest, map[string]string{"error": "fqdn must be unique across the application"}) 46 | return 47 | } 48 | now := time.Now().Unix() 49 | record := &models.Record{ 50 | CreatedAt: now, 51 | UpdatedAt: now, 52 | } 53 | record.Owner.Email = user.Email 54 | record.Owner.ID = user.ID 55 | if err := copier.Copy(record, recordReq); err != nil { 56 | server.Render.JSON(w, http.StatusInternalServerError, map[string]string{"error": "there was an error saving the record to the database"}) 57 | return 58 | } 59 | 60 | if err := server.DB.Save(record); err != nil { 61 | server.Render.JSON(w, http.StatusInternalServerError, map[string]string{"error": "there was an error saving the record to the database"}) 62 | return 63 | } 64 | 65 | server.Render.JSON(w, http.StatusCreated, record) 66 | } 67 | } 68 | 69 | // IndexRecord handles a request to return a list of all records. 70 | func IndexRecord(server *app.App) func(w http.ResponseWriter, req *http.Request) { 71 | return func(w http.ResponseWriter, req *http.Request) { 72 | 73 | records := []models.Record{} 74 | if err := server.DB.All(&records); err != nil { 75 | server.Render.JSON(w, http.StatusInternalServerError, map[string]string{"error": "there was an error getting records from the database"}) 76 | return 77 | } 78 | server.Render.JSON(w, http.StatusOK, records) 79 | } 80 | } 81 | 82 | // ShowRecord handles a request to return a single record provided by the mux parameter id. 83 | func ShowRecord(server *app.App) func(w http.ResponseWriter, req *http.Request) { 84 | return func(w http.ResponseWriter, req *http.Request) { 85 | vars := mux.Vars(req) 86 | id := vars["id"] 87 | record := &models.Record{ID: id} 88 | if ok, err := server.DB.Exists(record); err != nil || !ok { 89 | server.Render.JSON(w, http.StatusNotFound, nil) 90 | return 91 | } 92 | if err := server.DB.Get(record); err != nil { 93 | server.Render.JSON(w, http.StatusInternalServerError, map[string]string{"error": "there was an error getting record from the database"}) 94 | log.Println(err) 95 | return 96 | } 97 | server.Render.JSON(w, http.StatusOK, record) 98 | } 99 | } 100 | 101 | // DeleteRecord handles a request to delete a single record provided the mux parameter id. 102 | func DeleteRecord(server *app.App) func(w http.ResponseWriter, req *http.Request) { 103 | return func(w http.ResponseWriter, req *http.Request) { 104 | vars := mux.Vars(req) 105 | id := vars["id"] 106 | record := &models.Record{ID: id} 107 | if ok, err := server.DB.Exists(record); err != nil || !ok { 108 | server.Render.JSON(w, http.StatusNotFound, nil) 109 | return 110 | } 111 | if err := server.DB.Delete(record); err != nil { 112 | server.Render.JSON(w, http.StatusInternalServerError, map[string]string{"error": "there was an error deleting record from the database"}) 113 | log.Println(err) 114 | return 115 | } 116 | server.Render.JSON(w, http.StatusNoContent, nil) 117 | } 118 | } 119 | 120 | // UpdateRecord handles a request to update a single record provided the mux parameter id. 121 | func UpdateRecord(server *app.App) func(w http.ResponseWriter, req *http.Request) { 122 | return func(w http.ResponseWriter, req *http.Request) { 123 | vars := mux.Vars(req) 124 | id := vars["id"] 125 | record := &models.Record{ID: id} 126 | if ok, err := server.DB.Exists(record); err != nil || !ok { 127 | server.Render.JSON(w, http.StatusNotFound, nil) 128 | return 129 | } 130 | 131 | updateReq := &models.UpdateRecordRequest{} 132 | if err := binding.Bind(req, updateReq); err.Handle(w) { 133 | return 134 | } 135 | 136 | if err := server.DB.Get(record); err != nil { 137 | server.Render.JSON(w, http.StatusInternalServerError, map[string]string{"error": "there was an error getting record from the database"}) 138 | log.Println(err) 139 | return 140 | } 141 | 142 | if updateReq.FQDN != record.FQDN { 143 | existing, err := models.FindRecordByFQDN(server.DB, updateReq.FQDN) 144 | if err != nil { 145 | server.Render.JSON(w, http.StatusInternalServerError, map[string]string{"error": "there was an error saving the record to the database"}) 146 | log.Println(err) 147 | return 148 | } 149 | if existing.ID != "" { 150 | server.Render.JSON(w, http.StatusBadRequest, map[string]string{"error": "fqdn must be unique across the application"}) 151 | return 152 | } 153 | } 154 | 155 | if updateReq.Owner.ID != record.ID { 156 | if ok, err := server.DB.Exists(&models.User{ID: updateReq.Owner.ID}); err != nil || !ok { 157 | server.Render.JSON(w, http.StatusBadRequest, map[string]string{"error": "owner does not exist"}) 158 | return 159 | } 160 | } 161 | 162 | if err := copier.Copy(record, updateReq); err != nil { 163 | server.Render.JSON(w, http.StatusInternalServerError, map[string]string{"error": "there was an error updating the record"}) 164 | return 165 | } 166 | record.UpdatedAt = time.Now().Unix() 167 | if err := server.DB.Save(record); err != nil { 168 | server.Render.JSON(w, http.StatusInternalServerError, map[string]string{"error": "there was an error updating the record"}) 169 | log.Println(err) 170 | return 171 | } 172 | server.Render.JSON(w, http.StatusOK, record) 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /handlers/token.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | 7 | "github.com/dgrijalva/jwt-go" 8 | "github.com/mholt/binding" 9 | "github.com/tomsteele/shellsquid/app" 10 | "github.com/tomsteele/shellsquid/models" 11 | "golang.org/x/crypto/bcrypt" 12 | ) 13 | 14 | // UserToken returns an HTTP handler to generate a token for a user. 15 | func UserToken(server *app.App) func(w http.ResponseWriter, req *http.Request) { 16 | return func(w http.ResponseWriter, req *http.Request) { 17 | userTokenReq := &models.UserTokenRequest{} 18 | if err := binding.Bind(req, userTokenReq); err.Handle(w) { 19 | return 20 | } 21 | user, err := models.FindUserByEmail(server.DB, userTokenReq.Email) 22 | if err != nil { 23 | log.Println(err) 24 | server.Render.JSON(w, http.StatusInternalServerError, map[string]string{"error": "error getting user from database"}) 25 | return 26 | } 27 | if user.ID == "" { 28 | server.Render.JSON(w, http.StatusNotFound, map[string]string{"error": "invalid username or password"}) 29 | return 30 | } 31 | if err := bcrypt.CompareHashAndPassword([]byte(user.Hash), []byte(userTokenReq.Password)); err != nil { 32 | server.Render.JSON(w, http.StatusNotFound, map[string]string{"error": "invalid username or password"}) 33 | return 34 | } 35 | token := jwt.New(jwt.GetSigningMethod("HS256")) 36 | token.Claims["id"] = user.ID 37 | tokenString, err := token.SignedString(server.JWTSecret) 38 | if err != nil { 39 | log.Println(err) 40 | server.Render.JSON(w, http.StatusInternalServerError, map[string]string{"error": "error signing token"}) 41 | return 42 | } 43 | server.Render.JSON(w, http.StatusCreated, map[string]string{"token": tokenString}) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /handlers/user.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | 7 | "github.com/gorilla/mux" 8 | "github.com/mholt/binding" 9 | "github.com/tomsteele/shellsquid/app" 10 | "github.com/tomsteele/shellsquid/models" 11 | "golang.org/x/crypto/bcrypt" 12 | ) 13 | 14 | // CreateUser is a http handler function to creation a new user. 15 | func CreateUser(server *app.App) func(w http.ResponseWriter, req *http.Request) { 16 | return func(w http.ResponseWriter, req *http.Request) { 17 | userReq := &models.UserRequest{} 18 | if err := binding.Bind(req, userReq); err.Handle(w) { 19 | return 20 | } 21 | existing, err := models.FindUserByEmail(server.DB, userReq.Email) 22 | if err != nil { 23 | server.Render.JSON(w, http.StatusInternalServerError, map[string]string{"error": "there was an error saving the user to the database"}) 24 | log.Println(err) 25 | return 26 | } 27 | if existing.ID != "" { 28 | server.Render.JSON(w, http.StatusBadRequest, map[string]string{"error": "user email must be unique across the application"}) 29 | return 30 | } 31 | user, err := models.NewUser(userReq.Email, []byte(userReq.Password)) 32 | if err != nil { 33 | server.Render.JSON(w, http.StatusInternalServerError, map[string]string{"error": "there was an error saving the user to the database"}) 34 | log.Println(err) 35 | return 36 | } 37 | if err := server.DB.Save(user); err != nil { 38 | server.Render.JSON(w, http.StatusInternalServerError, map[string]string{"error": "there was an error saving the user to the database"}) 39 | log.Println(err) 40 | return 41 | } 42 | user.Hash = "" 43 | server.Render.JSON(w, http.StatusCreated, user) 44 | } 45 | } 46 | 47 | // IndexUser returns a list of all users. 48 | func IndexUser(server *app.App) func(w http.ResponseWriter, req *http.Request) { 49 | return func(w http.ResponseWriter, req *http.Request) { 50 | users := []models.User{} 51 | if err := server.DB.All(&users); err != nil { 52 | server.Render.JSON(w, http.StatusInternalServerError, map[string]string{"error": "there was an error getting users from the database"}) 53 | log.Println(err) 54 | return 55 | } 56 | for _, u := range users { 57 | u.Hash = "" 58 | } 59 | server.Render.JSON(w, http.StatusOK, users) 60 | } 61 | } 62 | 63 | // ShowUser returns a single user provided by an id mux parameter. 64 | func ShowUser(server *app.App) func(w http.ResponseWriter, req *http.Request) { 65 | return func(w http.ResponseWriter, req *http.Request) { 66 | vars := mux.Vars(req) 67 | id := vars["id"] 68 | user := &models.User{ID: id} 69 | if ok, err := server.DB.Exists(user); err != nil || !ok { 70 | server.Render.JSON(w, http.StatusNotFound, nil) 71 | return 72 | } 73 | if err := server.DB.Get(user); err != nil { 74 | server.Render.JSON(w, http.StatusInternalServerError, map[string]string{"error": "there was an error getting user from the database"}) 75 | log.Println(err) 76 | return 77 | } 78 | user.Hash = "" 79 | server.Render.JSON(w, http.StatusOK, user) 80 | } 81 | } 82 | 83 | // DeleteUser deletes a single user provided by an id mux parameter. 84 | func DeleteUser(server *app.App) func(w http.ResponseWriter, req *http.Request) { 85 | return func(w http.ResponseWriter, req *http.Request) { 86 | vars := mux.Vars(req) 87 | id := vars["id"] 88 | user := &models.User{ID: id} 89 | if ok, err := server.DB.Exists(user); err != nil || !ok { 90 | server.Render.JSON(w, http.StatusNotFound, nil) 91 | return 92 | } 93 | if foundRecords, err := models.FindRecordsForOwner(server.DB, id); err != nil || len(foundRecords) > 0 { 94 | server.Render.JSON(w, http.StatusBadRequest, map[string]string{"error": "this user has records owned by them, remove or reassign before deleting"}) 95 | return 96 | } 97 | if err := server.DB.Delete(user); err != nil { 98 | server.Render.JSON(w, http.StatusInternalServerError, map[string]string{"error": "there was an error deleting the user from the database"}) 99 | log.Println(err) 100 | return 101 | } 102 | server.Render.JSON(w, http.StatusNoContent, nil) 103 | } 104 | } 105 | 106 | // UpdateUser updates selected fields of a user provided by an id mux parameter. 107 | func UpdateUser(server *app.App) func(w http.ResponseWriter, req *http.Request) { 108 | return func(w http.ResponseWriter, req *http.Request) { 109 | vars := mux.Vars(req) 110 | id := vars["id"] 111 | user := &models.User{ID: id} 112 | if ok, err := server.DB.Exists(user); err != nil || !ok { 113 | server.Render.JSON(w, http.StatusNotFound, nil) 114 | return 115 | } 116 | updateReq := &models.UserUpdateRequest{} 117 | if err := binding.Bind(req, updateReq); err.Handle(w) { 118 | return 119 | } 120 | hash, err := bcrypt.GenerateFromPassword([]byte(updateReq.Password), 12) 121 | if err != nil { 122 | server.Render.JSON(w, http.StatusInternalServerError, map[string]string{"error": "there was an error updating the user"}) 123 | log.Println(err) 124 | return 125 | } 126 | if err := server.DB.Update(user, map[string]interface{}{"Hash": string(hash)}); err != nil { 127 | server.Render.JSON(w, http.StatusInternalServerError, map[string]string{"error": "there was an error updating the user"}) 128 | log.Println(err) 129 | return 130 | } 131 | user.Hash = "" 132 | server.Render.JSON(w, http.StatusOK, user) 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | 7 | "github.com/codegangsta/negroni" 8 | "github.com/gorilla/mux" 9 | "github.com/jmcvetta/randutil" 10 | "github.com/miekg/dns" 11 | "github.com/nlf/boltons" 12 | "github.com/tomsteele/shellsquid/app" 13 | "github.com/tomsteele/shellsquid/config" 14 | "github.com/tomsteele/shellsquid/handlers" 15 | "github.com/tomsteele/shellsquid/middleware" 16 | "github.com/tomsteele/shellsquid/models" 17 | "github.com/unrolled/render" 18 | ) 19 | 20 | const version = "2.2.0" 21 | 22 | func main() { 23 | conf, err := config.New("./config.json") 24 | if err != nil { 25 | log.Fatalf("Error parsing confuration file: %s", err.Error()) 26 | } 27 | if conf.JWTKey == "" { 28 | log.Fatalf("jwt_secret in config.json is not set, please set this to a random value") 29 | } 30 | 31 | db, err := boltons.Open(conf.BoltDBFile, 0600, nil) 32 | if err != nil { 33 | log.Fatalf("Error opening db: %s", err.Error()) 34 | } 35 | defer db.Close() 36 | 37 | keys, err := db.Keys(models.User{}) 38 | if err != nil { 39 | log.Fatalf("Error getting keys from db: %s", err.Error()) 40 | } 41 | if len(keys) == 0 { 42 | log.Println("No users found creating admin@localhost user with random password") 43 | random, err := randutil.AlphaString(10) 44 | if err != nil { 45 | log.Fatalf("Error generating password: %s", err.Error()) 46 | } 47 | firstUser, err := models.NewUser("admin@localhost", []byte(random)) 48 | if err != nil { 49 | } 50 | if err := db.Save(firstUser); err != nil { 51 | log.Fatalf("Error saving first user to db: %s", err.Error()) 52 | } 53 | log.Printf("admin@localhost password set to %s", random) 54 | } 55 | 56 | serverApp := &app.App{ 57 | DB: db, 58 | JWTSecret: []byte(conf.JWTKey), 59 | Render: render.New(), 60 | Config: conf, 61 | } 62 | 63 | if conf.Proxy.SSL.Enabled { 64 | sslMux := http.NewServeMux() 65 | sslMux.HandleFunc("/", handlers.Proxy(serverApp, true)) 66 | sslRecovery := negroni.NewRecovery() 67 | sslRecovery.PrintStack = false 68 | sslProxy := negroni.New(sslRecovery) 69 | sslProxy.UseHandler(sslMux) 70 | go func() { 71 | log.Fatal(http.ListenAndServeTLS(conf.Proxy.SSL.Listener, conf.Proxy.SSL.Cert, conf.Proxy.SSL.Key, sslProxy)) 72 | }() 73 | } 74 | 75 | if conf.Proxy.HTTP.Enabled { 76 | httpMux := http.NewServeMux() 77 | httpMux.HandleFunc("/", handlers.Proxy(serverApp, false)) 78 | httpRecovery := negroni.NewRecovery() 79 | httpRecovery.PrintStack = false 80 | httpProxy := negroni.New(httpRecovery) 81 | httpProxy.UseHandler(httpMux) 82 | go func() { 83 | log.Fatal(http.ListenAndServe(conf.Proxy.HTTP.Listener, httpProxy)) 84 | }() 85 | } 86 | 87 | if conf.Proxy.DNS.Enabled { 88 | tcpDNServer := &dns.Server{Addr: conf.Proxy.DNS.Listener, Net: "udp"} 89 | udpDNServer := &dns.Server{Addr: conf.Proxy.DNS.Listener, Net: "tcp"} 90 | 91 | dns.HandleFunc(".", handlers.ProxyDNS(serverApp)) 92 | 93 | go func() { 94 | log.Fatal(tcpDNServer.ListenAndServe()) 95 | }() 96 | 97 | go func() { 98 | log.Fatal(udpDNServer.ListenAndServe()) 99 | }() 100 | } 101 | 102 | r := mux.NewRouter() 103 | api := mux.NewRouter() 104 | r.HandleFunc("/api/token", handlers.UserToken(serverApp)).Methods("POST") 105 | 106 | api.HandleFunc("/api/users", handlers.CreateUser(serverApp)).Methods("POST") 107 | api.HandleFunc("/api/users", handlers.IndexUser(serverApp)).Methods("GET") 108 | api.HandleFunc("/api/users/{id}", handlers.ShowUser(serverApp)).Methods("GET") 109 | api.HandleFunc("/api/users/{id}", handlers.DeleteUser(serverApp)).Methods("DELETE") 110 | api.HandleFunc("/api/users/{id}", handlers.UpdateUser(serverApp)).Methods("PUT") 111 | api.HandleFunc("/api/records", handlers.CreateRecord(serverApp)).Methods("POST") 112 | api.HandleFunc("/api/records", handlers.IndexRecord(serverApp)).Methods("GET") 113 | api.HandleFunc("/api/records/{id}", handlers.ShowRecord(serverApp)).Methods("GET") 114 | api.HandleFunc("/api/records/{id}", handlers.DeleteRecord(serverApp)).Methods("DELETE") 115 | api.HandleFunc("/api/records/{id}", handlers.UpdateRecord(serverApp)).Methods("PUT") 116 | api.HandleFunc("/api/info", handlers.Info(serverApp, version)).Methods("GET") 117 | 118 | r.PathPrefix("/api").Handler(negroni.New( 119 | negroni.HandlerFunc(middleware.JWTAuth(serverApp)), 120 | negroni.HandlerFunc(middleware.SetUserContext(serverApp)), 121 | negroni.Wrap(api), 122 | )) 123 | 124 | server := negroni.New( 125 | negroni.NewLogger(), 126 | negroni.NewStatic(http.Dir("static")), 127 | negroni.NewRecovery(), 128 | ) 129 | 130 | server.UseHandler(r) 131 | log.Fatal(http.ListenAndServeTLS(conf.Admin.Listener, conf.Admin.Cert, conf.Admin.Key, server)) 132 | 133 | } 134 | -------------------------------------------------------------------------------- /middleware/middleware.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/auth0/go-jwt-middleware" 7 | "github.com/dgrijalva/jwt-go" 8 | "github.com/gorilla/context" 9 | "github.com/tomsteele/shellsquid/app" 10 | "github.com/tomsteele/shellsquid/models" 11 | ) 12 | 13 | // SetUserContext takes a JWT token from the mux context and looks up the user by id. The user 14 | // is then set into the same context. 15 | func SetUserContext(server *app.App) func(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) { 16 | return func(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) { 17 | token := context.Get(req, "user").(*jwt.Token) 18 | id := token.Claims["id"].(string) 19 | user := &models.User{ID: id} 20 | if ok, err := server.DB.Exists(user); err != nil || !ok { 21 | server.Render.JSON(w, http.StatusUnauthorized, nil) 22 | return 23 | } 24 | if err := server.DB.Get(user); err != nil { 25 | server.Render.JSON(w, http.StatusUnauthorized, nil) 26 | return 27 | } 28 | context.Set(req, "user", user) 29 | next(w, req) 30 | } 31 | } 32 | 33 | // JWTAuth parses a JWT token from an authorization header. 34 | func JWTAuth(server *app.App) func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { 35 | j := jwtmiddleware.New(jwtmiddleware.Options{ 36 | ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) { 37 | return server.JWTSecret, nil 38 | }, 39 | }) 40 | return j.HandlerWithNext 41 | } 42 | -------------------------------------------------------------------------------- /models/record.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "net/http" 5 | "regexp" 6 | 7 | "github.com/mholt/binding" 8 | "github.com/nlf/boltons" 9 | ) 10 | 11 | // Record is a single proxy record used for routing. 12 | type Record struct { 13 | ID string `json:"id"` 14 | Owner struct { 15 | ID string `json:"id"` 16 | Email string `json:"email"` 17 | } `json:"owner"` 18 | FQDN string `json:"fqdn"` 19 | HandlerHost string `json:"handler_host"` 20 | HandlerPort int `json:"handler_port"` 21 | HandlerProtocol string `json:"handler_protocol"` 22 | UpdatedAt int64 `json:"updated_at"` 23 | CreatedAt int64 `json:"created_at"` 24 | Blacklist bool `json:"blacklist"` 25 | } 26 | 27 | // FindRecordsForOwner returns a list of all records for a given owner by their id. 28 | func FindRecordsForOwner(db *boltons.DB, ID string) ([]Record, error) { 29 | records := []Record{} 30 | foundRecords := []Record{} 31 | if err := db.All(&records); err != nil { 32 | return foundRecords, err 33 | } 34 | for _, r := range records { 35 | if r.Owner.ID == ID { 36 | foundRecords = append(foundRecords, r) 37 | } 38 | } 39 | return foundRecords, nil 40 | } 41 | 42 | // FindRecordByFQDN returns a single record for the provided fqdn. 43 | func FindRecordByFQDN(db *boltons.DB, fqdn string) (*Record, error) { 44 | record := Record{} 45 | records := []Record{} 46 | if err := db.All(&records); err != nil { 47 | return &record, err 48 | } 49 | for _, r := range records { 50 | if r.FQDN == fqdn { 51 | return &r, nil 52 | } 53 | } 54 | return &record, nil 55 | } 56 | 57 | // FindRecordBySubOfFQDN is used for DNS requests and tries to find 58 | // the record whos FQDN matches name. 59 | func FindRecordBySubOfFQDN(db *boltons.DB, name string) (*Record, error) { 60 | record := Record{} 61 | records := []Record{} 62 | if err := db.All(&records); err != nil { 63 | return &record, err 64 | } 65 | for _, r := range records { 66 | if ok, err := regexp.MatchString(".*\\."+regexp.QuoteMeta(r.FQDN)+"\\.", name); ok && err == nil { 67 | return &r, nil 68 | } 69 | } 70 | return &record, nil 71 | } 72 | 73 | // RecordRequest is used for JSON binding during a request to create a new record. 74 | type RecordRequest struct { 75 | FQDN string `json:"fqdn"` 76 | HandlerHost string `json:"handler_host"` 77 | HandlerPort int `json:"handler_port"` 78 | HandlerProtocol string `json:"handler_protocol"` 79 | } 80 | 81 | // FieldMap implements binding.FieldMap 82 | func (r *RecordRequest) FieldMap(req *http.Request) binding.FieldMap { 83 | return binding.FieldMap{} 84 | } 85 | 86 | // Validate validates a request payload for a new record. 87 | func (r *RecordRequest) Validate(req *http.Request, errs binding.Errors) binding.Errors { 88 | if r.FQDN == "" { 89 | errs = append(errs, binding.Error{ 90 | FieldNames: []string{"fqdn"}, 91 | Message: "fqdn must be a valid hostname", 92 | }) 93 | } 94 | if ok, err := regexp.Match(`^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$`, []byte(r.HandlerHost)); !ok || err != nil || r.HandlerHost == "" { 95 | errs = append(errs, binding.Error{ 96 | FieldNames: []string{"handler_host"}, 97 | Message: "handler_host must be a valid IP address", 98 | }) 99 | } 100 | if r.HandlerPort < 0 || r.HandlerPort > 65535 { 101 | errs = append(errs, binding.Error{ 102 | FieldNames: []string{"handler_port"}, 103 | Message: "handler_port must be a valid TCP port", 104 | }) 105 | } 106 | if r.HandlerProtocol != "http" && r.HandlerProtocol != "https" && r.HandlerProtocol != "dns" { 107 | errs = append(errs, binding.Error{ 108 | FieldNames: []string{"handler_protocol"}, 109 | Message: "handler_protocol must be either http, https, or dns", 110 | }) 111 | } 112 | return errs 113 | } 114 | 115 | // UpdateRecordRequest is used to perform JSON binding when updating a record. 116 | type UpdateRecordRequest struct { 117 | FQDN string `json:"fqdn"` 118 | HandlerHost string `json:"handler_host"` 119 | HandlerPort int `json:"handler_port"` 120 | HandlerProtocol string `json:"handler_protocol"` 121 | Blacklist bool `json:"blacklist"` 122 | Owner struct { 123 | ID string `json:"id"` 124 | Email string `json:"email"` 125 | } `json:"owner"` 126 | } 127 | 128 | // FieldMap implements binding.FieldMap 129 | func (r *UpdateRecordRequest) FieldMap(req *http.Request) binding.FieldMap { 130 | return binding.FieldMap{} 131 | } 132 | 133 | // Validate validates a request payload to update a record. 134 | func (r *UpdateRecordRequest) Validate(req *http.Request, errs binding.Errors) binding.Errors { 135 | if r.FQDN == "" { 136 | errs = append(errs, binding.Error{ 137 | FieldNames: []string{"fqdn"}, 138 | Message: "fqdn must be a valid hostname", 139 | }) 140 | } 141 | if r.HandlerHost == "" { 142 | errs = append(errs, binding.Error{ 143 | FieldNames: []string{"handler_host"}, 144 | Message: "handler_host must be a valid IP address", 145 | }) 146 | } 147 | if r.HandlerPort < 0 || r.HandlerPort > 65535 { 148 | errs = append(errs, binding.Error{ 149 | FieldNames: []string{"handler_port"}, 150 | Message: "handler_port must be a valid TCP port", 151 | }) 152 | } 153 | if r.HandlerProtocol != "http" && r.HandlerProtocol != "https" && r.HandlerProtocol != "dns" { 154 | errs = append(errs, binding.Error{ 155 | FieldNames: []string{"handler_protocol"}, 156 | Message: "handler_protocol must be either http, https, or dns", 157 | }) 158 | } 159 | if r.Owner.ID == "" { 160 | errs = append(errs, binding.Error{ 161 | FieldNames: []string{"owner.id"}, 162 | Message: "owner.id is required", 163 | }) 164 | } 165 | if r.Owner.Email == "" { 166 | errs = append(errs, binding.Error{ 167 | FieldNames: []string{"email"}, 168 | Message: "owner.email is required", 169 | }) 170 | } 171 | return errs 172 | } 173 | -------------------------------------------------------------------------------- /models/user.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "net/http" 5 | "time" 6 | 7 | "github.com/mholt/binding" 8 | "github.com/nlf/boltons" 9 | "golang.org/x/crypto/bcrypt" 10 | ) 11 | 12 | // User is a single user of the application. 13 | type User struct { 14 | ID string `json:"id"` 15 | Hash string `json:"hash"` 16 | Email string `json:"email"` 17 | CreatedAt int64 `json:"created_at"` 18 | UpdatedAt int64 `json:"updated_at"` 19 | } 20 | 21 | // NewUser creates and returns a new user object provided a username and password. 22 | func NewUser(email string, password []byte) (*User, error) { 23 | now := time.Now().Unix() 24 | user := &User{ 25 | Email: email, 26 | CreatedAt: now, 27 | UpdatedAt: now, 28 | } 29 | hash, err := bcrypt.GenerateFromPassword(password, 12) 30 | if err != nil { 31 | return user, err 32 | } 33 | user.Hash = string(hash) 34 | return user, nil 35 | } 36 | 37 | // FindUserByEmail is a convenience function to locate a users record by a given email address. 38 | func FindUserByEmail(db *boltons.DB, email string) (*User, error) { 39 | user := User{} 40 | users := []User{} 41 | if err := db.All(&users); err != nil { 42 | return &user, err 43 | } 44 | for _, u := range users { 45 | if u.Email == email { 46 | return &u, nil 47 | } 48 | } 49 | return &user, nil 50 | } 51 | 52 | // UserRequest is used for JSON binding when creating a new user. 53 | type UserRequest struct { 54 | Email string `json:"email"` 55 | Password string `json:"password"` 56 | } 57 | 58 | // FieldMap implements binding.FieldMap 59 | func (u *UserRequest) FieldMap(req *http.Request) binding.FieldMap { 60 | return binding.FieldMap{} 61 | } 62 | 63 | // Validate validates a request payload to create a new user. 64 | func (u *UserRequest) Validate(req *http.Request, errs binding.Errors) binding.Errors { 65 | if u.Email == "" { 66 | errs = append(errs, binding.Error{ 67 | FieldNames: []string{"email"}, 68 | Message: "email is required", 69 | }) 70 | } 71 | if u.Password == "" { 72 | errs = append(errs, binding.Error{ 73 | FieldNames: []string{"password"}, 74 | Message: "password is required", 75 | }) 76 | } 77 | return errs 78 | } 79 | 80 | // UserTokenRequest is used when doing a login to generate a new JWT token for the given user. 81 | type UserTokenRequest struct { 82 | Email string `json:"email"` 83 | Password string `json:"password"` 84 | } 85 | 86 | // FieldMap implements binding.FieldMap 87 | func (u *UserTokenRequest) FieldMap(req *http.Request) binding.FieldMap { 88 | return binding.FieldMap{} 89 | } 90 | 91 | // Validate validates a request payload to generate a token for a user. 92 | func (u *UserTokenRequest) Validate(req *http.Request, errs binding.Errors) binding.Errors { 93 | if u.Email == "" { 94 | errs = append(errs, binding.Error{ 95 | FieldNames: []string{"email"}, 96 | Message: "email is required", 97 | }) 98 | } 99 | if u.Password == "" { 100 | errs = append(errs, binding.Error{ 101 | FieldNames: []string{"password"}, 102 | Message: "password is required", 103 | }) 104 | } 105 | return errs 106 | } 107 | 108 | // UserUpdateRequest is used to perform JSON binding when updating a user. 109 | type UserUpdateRequest struct { 110 | Password string `json:"password"` 111 | } 112 | 113 | // FieldMap implements binding.FieldMap 114 | func (u *UserUpdateRequest) FieldMap(req *http.Request) binding.FieldMap { 115 | return binding.FieldMap{} 116 | } 117 | 118 | // Validate validates a request payload to update a user. 119 | func (u *UserUpdateRequest) Validate(req *http.Request, errs binding.Errors) binding.Errors { 120 | if u.Password == "" { 121 | errs = append(errs, binding.Error{ 122 | FieldNames: []string{"password"}, 123 | Message: "password is required", 124 | }) 125 | } 126 | return errs 127 | } 128 | -------------------------------------------------------------------------------- /release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | for OS in "linux" "darwin" "freebsd"; do 4 | for ARCH in "amd64"; do 5 | GOOS=$OS CGO_ENABLED=0 GOARCH=$ARCH godep go build 6 | FOLDER=shellsquid2.1.0$OS-$ARCH 7 | ARCHIVE=$FOLDER.tar.gz 8 | mkdir -p $FOLDER/static 9 | cp LICENSE $FOLDER 10 | cp config.json $FOLDER 11 | if [ $OS = "windows" ] ; then 12 | cp shellsquid.exe $FOLDER 13 | rm shellsquid.exe 14 | else 15 | cp shellsquid $FOLDER 16 | rm shellsquid 17 | fi 18 | tar -czf $ARCHIVE $FOLDER 19 | rm -rf $FOLDER 20 | echo $ARCHIVE 21 | done 22 | done 23 | --------------------------------------------------------------------------------