<commit_before>// Copyright 2014 ISRG.  All rights reserved
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package core

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"math/big"
)

// MaxUsed defines the maximum number of Nonces we're willing to hold in
// memory.
const MaxUsed = 65536

// NonceService generates, cancels, and tracks Nonces.
type NonceService struct {
	latest   int64
	earliest int64
	used     map[int64]bool
	gcm      cipher.AEAD
	maxUsed  int
}

// NewNonceService constructs a NonceService with defaults
func NewNonceService() (NonceService, error) {
	key := make([]byte, 16)
	if _, err := rand.Read(key); err != nil {
		return NonceService{}, err
	}

	// It is safe to ignore these errors because they only happen
	// on key size and block size mismatches.
	c, _ := aes.NewCipher(key)
	gcm, _ := cipher.NewGCM(c)

	return NonceService{
		earliest: 0,
		latest:   0,
		used:     make(map[int64]bool, MaxUsed),
		gcm:      gcm,
		maxUsed:  MaxUsed,
	}, nil
}

func (ns NonceService) encrypt(counter int64) (string, error) {
	// Generate a nonce with upper 4 bytes zero
	nonce := make([]byte, 12)
	for i := 0; i < 4; i++ {
		nonce[i] = 0
	}
	if _, err := rand.Read(nonce[4:]); err != nil {
		return "", err
	}

	// Encode counter to plaintext
	pt := make([]byte, 8)
	ctr := big.NewInt(counter)
	pad := 8 - len(ctr.Bytes())
	copy(pt[pad:], ctr.Bytes())

	// Encrypt
	ret := make([]byte, 32)
	ct := ns.gcm.Seal(nil, nonce, pt, nil)
	copy(ret, nonce[4:])
	copy(ret[8:], ct)
	return B64enc(ret), nil
}

func (ns NonceService) decrypt(nonce string) (int64, error) {
	decoded, err := B64dec(nonce)
	if err != nil {
		return 0, err
	}

	n := make([]byte, 12)
	for i := 0; i < 4; i++ {
		n[i] = 0
	}
	copy(n[4:], decoded[:8])

	pt, err := ns.gcm.Open(nil, n, decoded[8:], nil)
	if err != nil {
		return 0, err
	}

	ctr := big.NewInt(0)
	ctr.SetBytes(pt)
	return ctr.Int64(), nil
}

// Nonce provides a new Nonce.
func (ns *NonceService) Nonce() (string, error) {
	ns.latest++
	return ns.encrypt(ns.latest)
}

func (ns *NonceService) minUsed() int64 {
	min := ns.latest
	for t := range ns.used {
		if t < min {
			min = t
		}
	}
	return min
}

// Valid determines whether the provided Nonce string is valid, returning
// true if so.
func (ns *NonceService) Valid(nonce string) bool {
	c, err := ns.decrypt(nonce)
	if err != nil {
		return false
	}

	if c > ns.latest {
		return false
	}

	if c <= ns.earliest {
		return false
	}

	if ns.used[c] {
		return false
	}

	ns.used[c] = true
	if len(ns.used) > ns.maxUsed {
		ns.earliest = ns.minUsed()
		delete(ns.used, ns.earliest)
	}

	return true
}
<commit_msg>Fix some races in nonce.go<commit_after>// Copyright 2014 ISRG.  All rights reserved
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package core

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"math/big"
	"sync"
)

// MaxUsed defines the maximum number of Nonces we're willing to hold in
// memory.
const MaxUsed = 65536

// NonceService generates, cancels, and tracks Nonces.
type NonceService struct {
	mu       sync.Mutex
	latest   int64
	earliest int64
	used     map[int64]bool
	gcm      cipher.AEAD
	maxUsed  int
}

// NewNonceService constructs a NonceService with defaults
func NewNonceService() (NonceService, error) {
	key := make([]byte, 16)
	if _, err := rand.Read(key); err != nil {
		return NonceService{}, err
	}

	c, err := aes.NewCipher(key)
	if err != nil {
		panic("Failure in NewCipher")
	}
	gcm, _ := cipher.NewGCM(c)
	if err != nil {
		panic("Failure in NewGCM")
	}

	return NonceService{
		earliest: 0,
		latest:   0,
		used:     make(map[int64]bool, MaxUsed),
		gcm:      gcm,
		maxUsed:  MaxUsed,
	}, nil
}

func (ns NonceService) encrypt(counter int64) (string, error) {
	// Generate a nonce with upper 4 bytes zero
	nonce := make([]byte, 12)
	for i := 0; i < 4; i++ {
		nonce[i] = 0
	}
	if _, err := rand.Read(nonce[4:]); err != nil {
		return "", err
	}

	// Encode counter to plaintext
	pt := make([]byte, 8)
	ctr := big.NewInt(counter)
	pad := 8 - len(ctr.Bytes())
	copy(pt[pad:], ctr.Bytes())

	// Encrypt
	ret := make([]byte, 32)
	ct := ns.gcm.Seal(nil, nonce, pt, nil)
	copy(ret, nonce[4:])
	copy(ret[8:], ct)
	return B64enc(ret), nil
}

func (ns NonceService) decrypt(nonce string) (int64, error) {
	decoded, err := B64dec(nonce)
	if err != nil {
		return 0, err
	}

	n := make([]byte, 12)
	for i := 0; i < 4; i++ {
		n[i] = 0
	}
	copy(n[4:], decoded[:8])

	pt, err := ns.gcm.Open(nil, n, decoded[8:], nil)
	if err != nil {
		return 0, err
	}

	ctr := big.NewInt(0)
	ctr.SetBytes(pt)
	return ctr.Int64(), nil
}

// Nonce provides a new Nonce.
func (ns *NonceService) Nonce() (string, error) {
	ns.mu.Lock()
	ns.latest++
	latest := ns.latest
	ns.mu.Unlock()
	return ns.encrypt(latest)
}

// minUsed returns the lowest key in the used map. Requires that a lock be held
// by caller.
func (ns *NonceService) minUsed() int64 {
	min := ns.latest
	for t := range ns.used {
		if t < min {
			min = t
		}
	}
	return min
}

// Valid determines whether the provided Nonce string is valid, returning
// true if so.
func (ns *NonceService) Valid(nonce string) bool {
	c, err := ns.decrypt(nonce)
	if err != nil {
		return false
	}

	ns.mu.Lock()
	defer ns.mu.Unlock()
	if c > ns.latest {
		return false
	}

	if c <= ns.earliest {
		return false
	}

	if ns.used[c] {
		return false
	}

	ns.used[c] = true
	if len(ns.used) > ns.maxUsed {
		ns.earliest = ns.minUsed()
		delete(ns.used, ns.earliest)
	}

	return true
}
<|endoftext|>


<commit_before>package user

import (
	"errors"
	"github.com/globocom/gandalf/db"
	"github.com/globocom/gandalf/key"
	"github.com/globocom/tsuru/fs"
	"labix.org/v2/mgo/bson"
	"regexp"
)

type User struct {
	Name string `bson:"_id"`
	Keys []string
}

func New(name string, keys []string) (*User, error) {
	u := &User{Name: name, Keys: keys}
	if v, err := u.isValid(); !v {
		return u, err
	}
	// extract to method
	fSystem := filesystem()
	for _, k := range keys {
		key.Add(k, fSystem)
	}
	return u, db.Session.User().Insert(&u)
}

func (u *User) isValid() (isValid bool, err error) {
	m, err := regexp.Match(`\s|[^aA-zZ0-9\.@]|(^$)`, []byte(u.Name))
	if err != nil {
		panic(err)
	}
	if m {
		return false, errors.New("Validation Error: user name is not valid")
	}
	return true, nil
}

func (u *User) AddKeys(keys []string) error {
	// the key is saved in the database without any the needed formats (like command and no-pty)
	u.Keys = append(u.Keys, keys...)
	err := db.Session.User().Update(bson.M{"_id": u.Name}, u)
	if err != nil {
		return err
	}
	return u.writeKeys(keys)
}

func (u *User) writeKeys(keys []string) error {
	for _, k := range keys {
		err := key.Add(k, filesystem())
		if err != nil {
			return err
		}
	}
	return nil
}

func Remove(u *User) error {
	//extract
	fSystem := filesystem()
	for _, k := range u.Keys {
		err := key.Remove(k, fSystem)
		if err != nil {
			return err
		}
	}
	return db.Session.User().RemoveId(u.Name)
}

var fsystem fs.Fs

func filesystem() fs.Fs {
	if fsystem == nil {
		return fs.OsFs{}
	}
	return fsystem
}
<commit_msg>key: using writeKeys methodin New function<commit_after>package user

import (
	"errors"
	"github.com/globocom/gandalf/db"
	"github.com/globocom/gandalf/key"
	"github.com/globocom/tsuru/fs"
	"labix.org/v2/mgo/bson"
	"regexp"
)

type User struct {
	Name string `bson:"_id"`
	Keys []string
}

func New(name string, keys []string) (*User, error) {
	u := &User{Name: name, Keys: keys}
	if v, err := u.isValid(); !v {
		return u, err
	}
	if err := db.Session.User().Insert(&u); err != nil {
		return u, err
	}
	return u, u.writeKeys(keys)
}

func (u *User) isValid() (isValid bool, err error) {
	m, err := regexp.Match(`\s|[^aA-zZ0-9\.@]|(^$)`, []byte(u.Name))
	if err != nil {
		panic(err)
	}
	if m {
		return false, errors.New("Validation Error: user name is not valid")
	}
	return true, nil
}

func (u *User) AddKeys(keys []string) error {
	// the key is saved in the database without any the needed formats (like command and no-pty)
	u.Keys = append(u.Keys, keys...)
	err := db.Session.User().Update(bson.M{"_id": u.Name}, u)
	if err != nil {
		return err
	}
	return u.writeKeys(keys)
}

func (u *User) writeKeys(keys []string) error {
	for _, k := range keys {
		err := key.Add(k, filesystem())
		if err != nil {
			return err
		}
	}
	return nil
}

func Remove(u *User) error {
	//extract
	fSystem := filesystem()
	for _, k := range u.Keys {
		err := key.Remove(k, fSystem)
		if err != nil {
			return err
		}
	}
	return db.Session.User().RemoveId(u.Name)
}

var fsystem fs.Fs

func filesystem() fs.Fs {
	if fsystem == nil {
		return fs.OsFs{}
	}
	return fsystem
}
<|endoftext|>


<commit_before>package util

import (
	"encoding/xml"
	"fmt"
	"go/build"
	"io"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/Masterminds/vcs"
)

// ResolveCurrent selects whether the package should only the dependencies for
// the current OS/ARCH instead of all possible permutations.
// This is not concurrently safe which is ok for the current application. If
// other needs arise it may need to be re-written.
var ResolveCurrent = false

func init() {
	// Precompile the regular expressions used to check VCS locations.
	for _, v := range vcsList {
		v.regex = regexp.MustCompile(v.pattern)
	}
}

func toSlash(v string) string {
	v = strings.Replace(v, "\\", "/", -1)
	if os.PathSeparator != '\\' && os.PathSeparator != '/' {
		v = strings.Replace(v, string(os.PathSeparator), "/", -1)
	}
	return v
}

// GetRootFromPackage retrives the top level package from a name.
//
// From a package name find the root repo. For example,
// the package github.com/Masterminds/cookoo/io has a root repo
// at github.com/Masterminds/cookoo
func GetRootFromPackage(pkg string) string {
	pkg = toSlash(pkg)
	for _, v := range vcsList {
		m := v.regex.FindStringSubmatch(pkg)
		if m == nil {
			continue
		}

		if m[1] != "" {
			return m[1]
		}
	}

	// There are cases where a package uses the special go get magic for
	// redirects. If we've not discovered the location already try that.
	pkg = getRootFromGoGet(pkg)

	return pkg
}

// Pages like https://golang.org/x/net provide an html document with
// meta tags containing a location to work with. The go tool uses
// a meta tag with the name go-import which is what we use here.
// godoc.org also has one call go-source that we do not need to use.
// The value of go-import is in the form "prefix vcs repo". The prefix
// should match the vcsURL and the repo is a location that can be
// checked out. Note, to get the html document you you need to add
// ?go-get=1 to the url.
func getRootFromGoGet(pkg string) string {

	p, found := checkRemotePackageCache(pkg)
	if found {
		return p
	}

	vcsURL := "https://" + pkg
	u, err := url.Parse(vcsURL)
	if err != nil {
		return pkg
	}
	if u.RawQuery == "" {
		u.RawQuery = "go-get=1"
	} else {
		u.RawQuery = u.RawQuery + "&go-get=1"
	}
	checkURL := u.String()
	resp, err := http.Get(checkURL)
	if err != nil {
		addToRemotePackageCache(pkg, pkg)
		return pkg
	}
	defer resp.Body.Close()

	nu, err := parseImportFromBody(u, resp.Body)
	if err != nil {
		addToRemotePackageCache(pkg, pkg)
		return pkg
	} else if nu == "" {
		addToRemotePackageCache(pkg, pkg)
		return pkg
	}

	addToRemotePackageCache(pkg, nu)
	return nu
}

// The caching is not concurrency safe but should be made to be that way.
// This implementation is far too much of a hack... rewrite needed.
var remotePackageCache = make(map[string]string)

func checkRemotePackageCache(pkg string) (string, bool) {
	for k, v := range remotePackageCache {
		if pkg == k {
			return v, true
		}
	}

	return pkg, false
}

func addToRemotePackageCache(pkg, v string) {
	remotePackageCache[pkg] = v
}

func parseImportFromBody(ur *url.URL, r io.ReadCloser) (u string, err error) {
	d := xml.NewDecoder(r)
	d.CharsetReader = charsetReader
	d.Strict = false
	var t xml.Token
	for {
		t, err = d.Token()
		if err != nil {
			if err == io.EOF {
				// If we hit the end of the markup and don't have anything
				// we return an error.
				err = vcs.ErrCannotDetectVCS
			}
			return
		}
		if e, ok := t.(xml.StartElement); ok && strings.EqualFold(e.Name.Local, "body") {
			return
		}
		if e, ok := t.(xml.EndElement); ok && strings.EqualFold(e.Name.Local, "head") {
			return
		}
		e, ok := t.(xml.StartElement)
		if !ok || !strings.EqualFold(e.Name.Local, "meta") {
			continue
		}
		if attrValue(e.Attr, "name") != "go-import" {
			continue
		}
		if f := strings.Fields(attrValue(e.Attr, "content")); len(f) == 3 {

			// If the prefix supplied by the remote system isn't a prefix to the
			// url we're fetching return continue looking for more go-imports.
			// This will work for exact matches and prefixes. For example,
			// golang.org/x/net as a prefix will match for golang.org/x/net and
			// golang.org/x/net/context.
			vcsURL := ur.Host + ur.Path
			if !strings.HasPrefix(vcsURL, f[0]) {
				continue
			} else {
				u = f[0]
				return
			}

		}
	}
}

func charsetReader(charset string, input io.Reader) (io.Reader, error) {
	switch strings.ToLower(charset) {
	case "ascii":
		return input, nil
	default:
		return nil, fmt.Errorf("can't decode XML document using charset %q", charset)
	}
}

func attrValue(attrs []xml.Attr, name string) string {
	for _, a := range attrs {
		if strings.EqualFold(a.Name.Local, name) {
			return a.Value
		}
	}
	return ""
}

type vcsInfo struct {
	host    string
	pattern string
	regex   *regexp.Regexp
}

var vcsList = []*vcsInfo{
	{
		host:    "github.com",
		pattern: `^(?P<rootpkg>github\.com/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`,
	},
	{
		host:    "bitbucket.org",
		pattern: `^(?P<rootpkg>bitbucket\.org/([A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`,
	},
	{
		host:    "launchpad.net",
		pattern: `^(?P<rootpkg>launchpad\.net/(([A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)?|~[A-Za-z0-9_.\-]+/(\+junk|[A-Za-z0-9_.\-]+)/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`,
	},
	{
		host:    "git.launchpad.net",
		pattern: `^(?P<rootpkg>git\.launchpad\.net/(([A-Za-z0-9_.\-]+)|~[A-Za-z0-9_.\-]+/(\+git|[A-Za-z0-9_.\-]+)/[A-Za-z0-9_.\-]+))$`,
	},
	{
		host:    "hub.jazz.net",
		pattern: `^(?P<rootpkg>hub\.jazz\.net/git/[a-z0-9]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`,
	},
	{
		host:    "go.googlesource.com",
		pattern: `^(?P<rootpkg>go\.googlesource\.com/[A-Za-z0-9_.\-]+/?)$`,
	},
	// TODO: Once Google Code becomes fully deprecated this can be removed.
	{
		host:    "code.google.com",
		pattern: `^(?P<rootpkg>code\.google\.com/[pr]/([a-z0-9\-]+)(\.([a-z0-9\-]+))?)(/[A-Za-z0-9_.\-]+)*$`,
	},
	// Alternative Google setup for SVN. This is the previous structure but it still works... until Google Code goes away.
	{
		pattern: `^(?P<rootpkg>[a-z0-9_\-.]+\.googlecode\.com/svn(/.*)?)$`,
	},
	// Alternative Google setup. This is the previous structure but it still works... until Google Code goes away.
	{
		pattern: `^(?P<rootpkg>[a-z0-9_\-.]+\.googlecode\.com/(git|hg))(/.*)?$`,
	},
	// If none of the previous detect the type they will fall to this looking for the type in a generic sense
	// by the extension to the path.
	{
		pattern: `^(?P<rootpkg>(?P<repo>([a-z0-9.\-]+\.)+[a-z0-9.\-]+(:[0-9]+)?/[A-Za-z0-9_.\-/]*?)\.(bzr|git|hg|svn))(/[A-Za-z0-9_.\-]+)*$`,
	},
}

// BuildCtxt is a convenience wrapper for not having to import go/build
// anywhere else
type BuildCtxt struct {
	build.Context
}

// PackageName attempts to determine the name of the base package.
//
// If resolution fails, this will return "main".
func (b *BuildCtxt) PackageName(base string) string {
	cwd, err := os.Getwd()
	if err != nil {
		return "main"
	}

	pkg, err := b.Import(base, cwd, 0)
	if err != nil {
		// There may not be any top level Go source files but the project may
		// still be within the GOPATH.
		if strings.HasPrefix(base, b.GOPATH) {
			p := strings.TrimPrefix(base, filepath.Join(b.GOPATH, "src"))
			return strings.Trim(p, string(os.PathSeparator))
		}
	}

	return pkg.ImportPath
}

// GetBuildContext returns a build context from go/build. When the $GOROOT
// variable is not set in the users environment it sets the context's root
// path to the path returned by 'go env GOROOT'.
//
// TODO: This should be moved to the `dependency` package.
func GetBuildContext() (*BuildCtxt, error) {
	buildContext := &BuildCtxt{build.Default}

	// If we aren't resolving for the current system set to look at all
	// build modes.
	if !ResolveCurrent {
		// This tells the context scanning to skip filtering on +build flags or
		// file names.
		buildContext.UseAllFiles = true
	}

	if goRoot := os.Getenv("GOROOT"); len(goRoot) == 0 {
		goExecutable := os.Getenv("GLIDE_GO_EXECUTABLE")
		if len(goExecutable) <= 0 {
			goExecutable = "go"
		}
		out, err := exec.Command(goExecutable, "env", "GOROOT").Output()
		if goRoot = strings.TrimSpace(string(out)); len(goRoot) == 0 || err != nil {
			return nil, fmt.Errorf("Please set the $GOROOT environment " +
				"variable to use this command\n")
		}
		buildContext.GOROOT = goRoot
	}
	return buildContext, nil
}

// NormalizeName takes a package name and normalizes it to the top level package.
//
// For example, golang.org/x/crypto/ssh becomes golang.org/x/crypto. 'ssh' is
// returned as extra data.
//
// FIXME: Is this deprecated?
func NormalizeName(name string) (string, string) {
	// Fastpath check if a name in the GOROOT. There is an issue when a pkg
	// is in the GOROOT and GetRootFromPackage tries to look it up because it
	// expects remote names.
	b, err := GetBuildContext()
	if err == nil {
		p := filepath.Join(b.GOROOT, "src", name)
		if _, err := os.Stat(p); err == nil {
			return toSlash(name), ""
		}
	}

	name = toSlash(name)
	root := GetRootFromPackage(name)
	extra := strings.TrimPrefix(name, root)
	if len(extra) > 0 && extra != "/" {
		extra = strings.TrimPrefix(extra, "/")
	} else {
		// If extra is / (which is what it would be here) we want to return ""
		extra = ""
	}

	return root, extra
}
<commit_msg>Only replace backslashes from toSlash.<commit_after>package util

import (
	"encoding/xml"
	"fmt"
	"go/build"
	"io"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/Masterminds/vcs"
)

// ResolveCurrent selects whether the package should only the dependencies for
// the current OS/ARCH instead of all possible permutations.
// This is not concurrently safe which is ok for the current application. If
// other needs arise it may need to be re-written.
var ResolveCurrent = false

func init() {
	// Precompile the regular expressions used to check VCS locations.
	for _, v := range vcsList {
		v.regex = regexp.MustCompile(v.pattern)
	}
}

func toSlash(v string) string {
	return strings.Replace(v, "\\", "/", -1)
}

// GetRootFromPackage retrives the top level package from a name.
//
// From a package name find the root repo. For example,
// the package github.com/Masterminds/cookoo/io has a root repo
// at github.com/Masterminds/cookoo
func GetRootFromPackage(pkg string) string {
	pkg = toSlash(pkg)
	for _, v := range vcsList {
		m := v.regex.FindStringSubmatch(pkg)
		if m == nil {
			continue
		}

		if m[1] != "" {
			return m[1]
		}
	}

	// There are cases where a package uses the special go get magic for
	// redirects. If we've not discovered the location already try that.
	pkg = getRootFromGoGet(pkg)

	return pkg
}

// Pages like https://golang.org/x/net provide an html document with
// meta tags containing a location to work with. The go tool uses
// a meta tag with the name go-import which is what we use here.
// godoc.org also has one call go-source that we do not need to use.
// The value of go-import is in the form "prefix vcs repo". The prefix
// should match the vcsURL and the repo is a location that can be
// checked out. Note, to get the html document you you need to add
// ?go-get=1 to the url.
func getRootFromGoGet(pkg string) string {

	p, found := checkRemotePackageCache(pkg)
	if found {
		return p
	}

	vcsURL := "https://" + pkg
	u, err := url.Parse(vcsURL)
	if err != nil {
		return pkg
	}
	if u.RawQuery == "" {
		u.RawQuery = "go-get=1"
	} else {
		u.RawQuery = u.RawQuery + "&go-get=1"
	}
	checkURL := u.String()
	resp, err := http.Get(checkURL)
	if err != nil {
		addToRemotePackageCache(pkg, pkg)
		return pkg
	}
	defer resp.Body.Close()

	nu, err := parseImportFromBody(u, resp.Body)
	if err != nil {
		addToRemotePackageCache(pkg, pkg)
		return pkg
	} else if nu == "" {
		addToRemotePackageCache(pkg, pkg)
		return pkg
	}

	addToRemotePackageCache(pkg, nu)
	return nu
}

// The caching is not concurrency safe but should be made to be that way.
// This implementation is far too much of a hack... rewrite needed.
var remotePackageCache = make(map[string]string)

func checkRemotePackageCache(pkg string) (string, bool) {
	for k, v := range remotePackageCache {
		if pkg == k {
			return v, true
		}
	}

	return pkg, false
}

func addToRemotePackageCache(pkg, v string) {
	remotePackageCache[pkg] = v
}

func parseImportFromBody(ur *url.URL, r io.ReadCloser) (u string, err error) {
	d := xml.NewDecoder(r)
	d.CharsetReader = charsetReader
	d.Strict = false
	var t xml.Token
	for {
		t, err = d.Token()
		if err != nil {
			if err == io.EOF {
				// If we hit the end of the markup and don't have anything
				// we return an error.
				err = vcs.ErrCannotDetectVCS
			}
			return
		}
		if e, ok := t.(xml.StartElement); ok && strings.EqualFold(e.Name.Local, "body") {
			return
		}
		if e, ok := t.(xml.EndElement); ok && strings.EqualFold(e.Name.Local, "head") {
			return
		}
		e, ok := t.(xml.StartElement)
		if !ok || !strings.EqualFold(e.Name.Local, "meta") {
			continue
		}
		if attrValue(e.Attr, "name") != "go-import" {
			continue
		}
		if f := strings.Fields(attrValue(e.Attr, "content")); len(f) == 3 {

			// If the prefix supplied by the remote system isn't a prefix to the
			// url we're fetching return continue looking for more go-imports.
			// This will work for exact matches and prefixes. For example,
			// golang.org/x/net as a prefix will match for golang.org/x/net and
			// golang.org/x/net/context.
			vcsURL := ur.Host + ur.Path
			if !strings.HasPrefix(vcsURL, f[0]) {
				continue
			} else {
				u = f[0]
				return
			}

		}
	}
}

func charsetReader(charset string, input io.Reader) (io.Reader, error) {
	switch strings.ToLower(charset) {
	case "ascii":
		return input, nil
	default:
		return nil, fmt.Errorf("can't decode XML document using charset %q", charset)
	}
}

func attrValue(attrs []xml.Attr, name string) string {
	for _, a := range attrs {
		if strings.EqualFold(a.Name.Local, name) {
			return a.Value
		}
	}
	return ""
}

type vcsInfo struct {
	host    string
	pattern string
	regex   *regexp.Regexp
}

var vcsList = []*vcsInfo{
	{
		host:    "github.com",
		pattern: `^(?P<rootpkg>github\.com/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`,
	},
	{
		host:    "bitbucket.org",
		pattern: `^(?P<rootpkg>bitbucket\.org/([A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`,
	},
	{
		host:    "launchpad.net",
		pattern: `^(?P<rootpkg>launchpad\.net/(([A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)?|~[A-Za-z0-9_.\-]+/(\+junk|[A-Za-z0-9_.\-]+)/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`,
	},
	{
		host:    "git.launchpad.net",
		pattern: `^(?P<rootpkg>git\.launchpad\.net/(([A-Za-z0-9_.\-]+)|~[A-Za-z0-9_.\-]+/(\+git|[A-Za-z0-9_.\-]+)/[A-Za-z0-9_.\-]+))$`,
	},
	{
		host:    "hub.jazz.net",
		pattern: `^(?P<rootpkg>hub\.jazz\.net/git/[a-z0-9]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`,
	},
	{
		host:    "go.googlesource.com",
		pattern: `^(?P<rootpkg>go\.googlesource\.com/[A-Za-z0-9_.\-]+/?)$`,
	},
	// TODO: Once Google Code becomes fully deprecated this can be removed.
	{
		host:    "code.google.com",
		pattern: `^(?P<rootpkg>code\.google\.com/[pr]/([a-z0-9\-]+)(\.([a-z0-9\-]+))?)(/[A-Za-z0-9_.\-]+)*$`,
	},
	// Alternative Google setup for SVN. This is the previous structure but it still works... until Google Code goes away.
	{
		pattern: `^(?P<rootpkg>[a-z0-9_\-.]+\.googlecode\.com/svn(/.*)?)$`,
	},
	// Alternative Google setup. This is the previous structure but it still works... until Google Code goes away.
	{
		pattern: `^(?P<rootpkg>[a-z0-9_\-.]+\.googlecode\.com/(git|hg))(/.*)?$`,
	},
	// If none of the previous detect the type they will fall to this looking for the type in a generic sense
	// by the extension to the path.
	{
		pattern: `^(?P<rootpkg>(?P<repo>([a-z0-9.\-]+\.)+[a-z0-9.\-]+(:[0-9]+)?/[A-Za-z0-9_.\-/]*?)\.(bzr|git|hg|svn))(/[A-Za-z0-9_.\-]+)*$`,
	},
}

// BuildCtxt is a convenience wrapper for not having to import go/build
// anywhere else
type BuildCtxt struct {
	build.Context
}

// PackageName attempts to determine the name of the base package.
//
// If resolution fails, this will return "main".
func (b *BuildCtxt) PackageName(base string) string {
	cwd, err := os.Getwd()
	if err != nil {
		return "main"
	}

	pkg, err := b.Import(base, cwd, 0)
	if err != nil {
		// There may not be any top level Go source files but the project may
		// still be within the GOPATH.
		if strings.HasPrefix(base, b.GOPATH) {
			p := strings.TrimPrefix(base, filepath.Join(b.GOPATH, "src"))
			return strings.Trim(p, string(os.PathSeparator))
		}
	}

	return pkg.ImportPath
}

// GetBuildContext returns a build context from go/build. When the $GOROOT
// variable is not set in the users environment it sets the context's root
// path to the path returned by 'go env GOROOT'.
//
// TODO: This should be moved to the `dependency` package.
func GetBuildContext() (*BuildCtxt, error) {
	buildContext := &BuildCtxt{build.Default}

	// If we aren't resolving for the current system set to look at all
	// build modes.
	if !ResolveCurrent {
		// This tells the context scanning to skip filtering on +build flags or
		// file names.
		buildContext.UseAllFiles = true
	}

	if goRoot := os.Getenv("GOROOT"); len(goRoot) == 0 {
		goExecutable := os.Getenv("GLIDE_GO_EXECUTABLE")
		if len(goExecutable) <= 0 {
			goExecutable = "go"
		}
		out, err := exec.Command(goExecutable, "env", "GOROOT").Output()
		if goRoot = strings.TrimSpace(string(out)); len(goRoot) == 0 || err != nil {
			return nil, fmt.Errorf("Please set the $GOROOT environment " +
				"variable to use this command\n")
		}
		buildContext.GOROOT = goRoot
	}
	return buildContext, nil
}

// NormalizeName takes a package name and normalizes it to the top level package.
//
// For example, golang.org/x/crypto/ssh becomes golang.org/x/crypto. 'ssh' is
// returned as extra data.
//
// FIXME: Is this deprecated?
func NormalizeName(name string) (string, string) {
	// Fastpath check if a name in the GOROOT. There is an issue when a pkg
	// is in the GOROOT and GetRootFromPackage tries to look it up because it
	// expects remote names.
	b, err := GetBuildContext()
	if err == nil {
		p := filepath.Join(b.GOROOT, "src", name)
		if _, err := os.Stat(p); err == nil {
			return toSlash(name), ""
		}
	}

	name = toSlash(name)
	root := GetRootFromPackage(name)
	extra := strings.TrimPrefix(name, root)
	if len(extra) > 0 && extra != "/" {
		extra = strings.TrimPrefix(extra, "/")
	} else {
		// If extra is / (which is what it would be here) we want to return ""
		extra = ""
	}

	return root, extra
}
<|endoftext|>


<commit_before>package shp

import (
	"archive/zip"
	"fmt"
	"io"
	"path"
	"strings"
)

// ZipReader provides an interface for reading Shapefiles that are compressed in a ZIP archive.
type ZipReader struct {
	sr SequentialReader
	z  *zip.ReadCloser
}

// openFromZIP is convenience function for opening the file called name that is
// compressed in z for reading.
func openFromZIP(z *zip.ReadCloser, name string) (io.ReadCloser, error) {
	for _, f := range z.File {
		if f.Name == name {
			return f.Open()

		}
	}
	return nil, fmt.Errorf("No such file in archive: %s", name)
}

func countAndFirstShape(z *zip.ReadCloser) (int, string) {
	count := 0
	firstShape := ""
	for _, f := range z.File {
		if strings.HasSuffix(f.Name, ".shp") {
			count++
			if firstShape == "" {
				firstShape = f.Name
			}
		}
	}
	return count, firstShape
}

// OpenZip opens a ZIP file that contains a single shapefile.
func OpenZip(zipFilePath string) (*ZipReader, error) {
	z, err := zip.OpenReader(zipFilePath)
	if err != nil {
		return nil, err
	}
	zr := &ZipReader{
		z: z,
	}
	count, first := countAndFirstShape(z)
	if count == 0 {
		return nil, fmt.Errorf("archive does not contain a .shp file")
	}
	if count > 1 {
		return nil, fmt.Errorf("archive does contain multiple .shp files")
	}
	prefix := strings.TrimSuffix(first, path.Ext(first))

	shp, err := openFromZIP(zr.z, prefix+".shp")
	if err != nil {
		return nil, err
	}
	// dbf is optional, so no error checking here
	dbf, _ := openFromZIP(zr.z, prefix+".dbf")
	zr.sr = SequentialReaderFromExt(shp, dbf)
	return zr, nil
}

// OpenZipWithName opens a shape file that is contained in a ZIP achive. The
// parameter name name of the shape file.
// It must be a relative path: it must not start with a drive
// letter (e.g. C:) or leading slash, and only forward slashes
// are allowed.
func OpenZipWithName(zipFilePath string, name string) (*ZipReader, error) {
	z, err := zip.OpenReader(zipFilePath)
	if err != nil {
		return nil, err
	}
	zr := &ZipReader{
		z: z,
	}

	shp, err := openFromZIP(zr.z, name)
	if err != nil {
		return nil, err
	}
	// dbf is optional, so no error checking here
	prefix := strings.TrimSuffix(name, path.Ext(name))
	dbf, _ := openFromZIP(zr.z, prefix+".dbf")
	zr.sr = SequentialReaderFromExt(shp, dbf)
	return zr, nil
}

// Close closes the ZipReader and frees the allocated resources.
func (zr *ZipReader) Close() error {
	s := ""
	err := zr.sr.Close()
	if err != nil {
		s += err.Error() + ". "
	}
	err = zr.z.Close()
	if err != nil {
		s += err.Error() + ". "
	}
	if s != "" {
		return fmt.Errorf(s)
	}
	return nil
}

// Next reads the next shape in the shapefile and the next row in the DBF. Call
// Shape() and Attribute() to access the values.
func (zr *ZipReader) Next() bool {
	return zr.sr.Next()
}

// Shape returns the shape that was last read as well as the current index.
func (zr *ZipReader) Shape() (int, Shape) {
	return zr.sr.Shape()
}

// Attribute returns the n-th field of the last row that was read. If there
// were any errors before, the empty string is returned.
func (zr *ZipReader) Attribute(n int) string {
	return zr.sr.Attribute(n)
}

// Fields returns a slice of Fields that are present in the
// DBF table.
func (zr *ZipReader) Fields() []Field {
	return zr.sr.Fields()
}

// Err returns the last non-EOF error that was encountered by this ZipReader.
func (zr *ZipReader) Err() error {
	return zr.sr.Err()
}
<commit_msg>Rename OpenZipWithName to OpenShapeFromZip, improve comment<commit_after>package shp

import (
	"archive/zip"
	"fmt"
	"io"
	"path"
	"strings"
)

// ZipReader provides an interface for reading Shapefiles that are compressed in a ZIP archive.
type ZipReader struct {
	sr SequentialReader
	z  *zip.ReadCloser
}

// openFromZIP is convenience function for opening the file called name that is
// compressed in z for reading.
func openFromZIP(z *zip.ReadCloser, name string) (io.ReadCloser, error) {
	for _, f := range z.File {
		if f.Name == name {
			return f.Open()

		}
	}
	return nil, fmt.Errorf("No such file in archive: %s", name)
}

func countAndFirstShape(z *zip.ReadCloser) (int, string) {
	count := 0
	firstShape := ""
	for _, f := range z.File {
		if strings.HasSuffix(f.Name, ".shp") {
			count++
			if firstShape == "" {
				firstShape = f.Name
			}
		}
	}
	return count, firstShape
}

// OpenZip opens a ZIP file that contains a single shapefile.
func OpenZip(zipFilePath string) (*ZipReader, error) {
	z, err := zip.OpenReader(zipFilePath)
	if err != nil {
		return nil, err
	}
	zr := &ZipReader{
		z: z,
	}
	count, first := countAndFirstShape(z)
	if count == 0 {
		return nil, fmt.Errorf("archive does not contain a .shp file")
	}
	if count > 1 {
		return nil, fmt.Errorf("archive does contain multiple .shp files")
	}
	prefix := strings.TrimSuffix(first, path.Ext(first))

	shp, err := openFromZIP(zr.z, prefix+".shp")
	if err != nil {
		return nil, err
	}
	// dbf is optional, so no error checking here
	dbf, _ := openFromZIP(zr.z, prefix+".dbf")
	zr.sr = SequentialReaderFromExt(shp, dbf)
	return zr, nil
}

// OpenShapeFromZip opens a shape file that is contained in a ZIP achive. The
// parameter name is name of the shape file.
// The name of the shapefile must be a relative path: it must not start with a
// drive letter (e.g. C:) or leading slash, and only forward slashes are
// allowed. These rules are the same as in
// https://golang.org/pkg/archive/zip/#FileHeader.
func OpenShapeFromZip(zipFilePath string, name string) (*ZipReader, error) {
	z, err := zip.OpenReader(zipFilePath)
	if err != nil {
		return nil, err
	}
	zr := &ZipReader{
		z: z,
	}

	shp, err := openFromZIP(zr.z, name)
	if err != nil {
		return nil, err
	}
	// dbf is optional, so no error checking here
	prefix := strings.TrimSuffix(name, path.Ext(name))
	dbf, _ := openFromZIP(zr.z, prefix+".dbf")
	zr.sr = SequentialReaderFromExt(shp, dbf)
	return zr, nil
}

// Close closes the ZipReader and frees the allocated resources.
func (zr *ZipReader) Close() error {
	s := ""
	err := zr.sr.Close()
	if err != nil {
		s += err.Error() + ". "
	}
	err = zr.z.Close()
	if err != nil {
		s += err.Error() + ". "
	}
	if s != "" {
		return fmt.Errorf(s)
	}
	return nil
}

// Next reads the next shape in the shapefile and the next row in the DBF. Call
// Shape() and Attribute() to access the values.
func (zr *ZipReader) Next() bool {
	return zr.sr.Next()
}

// Shape returns the shape that was last read as well as the current index.
func (zr *ZipReader) Shape() (int, Shape) {
	return zr.sr.Shape()
}

// Attribute returns the n-th field of the last row that was read. If there
// were any errors before, the empty string is returned.
func (zr *ZipReader) Attribute(n int) string {
	return zr.sr.Attribute(n)
}

// Fields returns a slice of Fields that are present in the
// DBF table.
func (zr *ZipReader) Fields() []Field {
	return zr.sr.Fields()
}

// Err returns the last non-EOF error that was encountered by this ZipReader.
func (zr *ZipReader) Err() error {
	return zr.sr.Err()
}
<|endoftext|>


<commit_before>package watchdog

import (
	. "gopkg.in/check.v1"
	"time"
)

func (s *WatchdogSuite) TestSuccess(c *C) {
	attempts := 0
	m := NewMockRetry(func() bool {
		attempts += 1
		return attempts >= 20
	})

	w := NewWatcher(m, NewZeroBackOff())
	w.Watch()
	<-w.Success

	c.Assert(attempts, Equals, 20)
}

func (s *WatchdogSuite) TestWatcherRespectsBackOff(c *C) {
	attempts := 0
	m := NewMockRetry(func() bool {
		attempts += 1
		return attempts >= 4
	})

	w := NewWatcher(m, NewConstantBackOff(time.Millisecond*200))
	w.Watch()

	select {
	case <-time.After(time.Millisecond * 500):
	case <-w.Success:
		c.Fatalf("Success happened too quickly.")
	}
}

func (s *WatchdogSuite) TestStop(c *C) {
	attempts := 0
	m := NewMockRetry(func() bool {
		attempts += 1
		return false
	})

	w := NewWatcher(m, NewZeroBackOff())
	w.Watch()

	<-time.After(50 * time.Millisecond)
	a1 := attempts

	<-time.After(50 * time.Millisecond)
	w.Stop()

	a2 := attempts
	<-time.After(50 * time.Millisecond)
	a3 := attempts

	c.Assert(a1, Not(Equals), a2)
	c.Assert(a2, Equals, a3)
}

func (s *WatchdogSuite) TestShouldRetry(c *C) {
	attempts := 0
	m := NewMockRetry(func() bool {
		attempts += 1
		return (attempts % 20) == 0
	})

	w := NewWatcher(m, NewZeroBackOff())
	w.Watch()
	<-w.Success
	c.Assert(attempts, Equals, 20)

	w.ShouldRetry <- true
	<-w.Success
	c.Assert(attempts, Equals, 40)

	w.ShouldRetry <- true
	<-w.Success
	c.Assert(attempts, Equals, 60)
}

func (s *WatchdogSuite) TestShouldRetryIgnored(c *C) {
	attempts := 0
	m := NewMockRetry(func() bool {
		attempts += 1
		return false
	})

	resets := 0
	b := NewMockBackOff(func() {
		resets += 1
	}, func() time.Duration {
		return 0 * time.Millisecond
	})

	w := NewWatcher(m, b)
	w.Watch()

	a1 := attempts
	<-time.After(50 * time.Millisecond)
	w.ShouldRetry <- true

	a2 := attempts
	<-time.After(50 * time.Millisecond)
	w.ShouldRetry <- true

	a3 := attempts
	<-time.After(50 * time.Millisecond)
	w.ShouldRetry <- true

	w.Stop()
	c.Assert(resets, Equals, 1)
	c.Assert(a1, Not(Equals), a2)
	c.Assert(a2, Not(Equals), a3)
}

func (s *WatchdogSuite) TestShouldRetryResetsBackOff(c *C) {
	attempts1 := 0
	m := NewMockRetry(func() bool {
		attempts1 += 1
		return (attempts1 % 20) == 0
	})

	attempts2 := 0
	b := NewMockBackOff(func() {
		attempts2 = 0
	}, func() time.Duration {
		attempts2 += 1
		return 0 * time.Millisecond
	})

	w := NewWatcher(m, b)
	w.Watch()
	<-w.Success
	c.Assert(attempts1, Equals, 20)
	c.Assert(attempts2, Equals, 19)

	w.ShouldRetry <- true
	<-w.Success
	c.Assert(attempts1, Equals, 40)
	c.Assert(attempts2, Equals, 19)
}
<commit_msg>Add test (for coverage).<commit_after>package watchdog

import (
	. "gopkg.in/check.v1"
	"time"
)

func (s *WatchdogSuite) TestSuccess(c *C) {
	attempts := 0
	m := NewMockRetry(func() bool {
		attempts += 1
		return attempts >= 20
	})

	w := NewWatcher(m, NewZeroBackOff())
	w.Watch()
	<-w.Success

	c.Assert(attempts, Equals, 20)
}

func (s *WatchdogSuite) TestWatcherRespectsBackOff(c *C) {
	attempts := 0
	m := NewMockRetry(func() bool {
		attempts += 1
		return attempts >= 4
	})

	w := NewWatcher(m, NewConstantBackOff(time.Millisecond*200))
	w.Watch()

	select {
	case <-time.After(time.Millisecond * 500):
	case <-w.Success:
		c.Fatalf("Success happened too quickly.")
	}
}

func (s *WatchdogSuite) TestStop(c *C) {
	attempts := 0
	m := NewMockRetry(func() bool {
		attempts += 1
		return false
	})

	w := NewWatcher(m, NewZeroBackOff())
	w.Watch()

	<-time.After(50 * time.Millisecond)
	a1 := attempts

	<-time.After(50 * time.Millisecond)
	w.Stop()

	a2 := attempts
	<-time.After(50 * time.Millisecond)
	a3 := attempts

	c.Assert(a1, Not(Equals), a2)
	c.Assert(a2, Equals, a3)
}

func (s *WatchdogSuite) TestStopAfterSuccess(c *C) {
	attempts := 0
	m := NewMockRetry(func() bool {
		attempts += 1
		return true
	})

	w := NewWatcher(m, NewZeroBackOff())
	w.Watch()
	<-w.Success
	w.Stop()

	select {
	case w.ShouldRetry <- true:
		c.Fatalf("Watcher should not have accepted retry request.")
	default:
	}
}

func (s *WatchdogSuite) TestShouldRetry(c *C) {
	attempts := 0
	m := NewMockRetry(func() bool {
		attempts += 1
		return (attempts % 20) == 0
	})

	w := NewWatcher(m, NewZeroBackOff())
	w.Watch()
	<-w.Success
	c.Assert(attempts, Equals, 20)

	w.ShouldRetry <- true
	<-w.Success
	c.Assert(attempts, Equals, 40)

	w.ShouldRetry <- true
	<-w.Success
	c.Assert(attempts, Equals, 60)
}

func (s *WatchdogSuite) TestShouldRetryIgnored(c *C) {
	attempts := 0
	m := NewMockRetry(func() bool {
		attempts += 1
		return false
	})

	resets := 0
	b := NewMockBackOff(func() {
		resets += 1
	}, func() time.Duration {
		return 0 * time.Millisecond
	})

	w := NewWatcher(m, b)
	w.Watch()

	a1 := attempts
	<-time.After(50 * time.Millisecond)
	w.ShouldRetry <- true

	a2 := attempts
	<-time.After(50 * time.Millisecond)
	w.ShouldRetry <- true

	a3 := attempts
	<-time.After(50 * time.Millisecond)
	w.ShouldRetry <- true

	w.Stop()
	c.Assert(resets, Equals, 1)
	c.Assert(a1, Not(Equals), a2)
	c.Assert(a2, Not(Equals), a3)
}

func (s *WatchdogSuite) TestShouldRetryResetsBackOff(c *C) {
	attempts1 := 0
	m := NewMockRetry(func() bool {
		attempts1 += 1
		return (attempts1 % 20) == 0
	})

	attempts2 := 0
	b := NewMockBackOff(func() {
		attempts2 = 0
	}, func() time.Duration {
		attempts2 += 1
		return 0 * time.Millisecond
	})

	w := NewWatcher(m, b)
	w.Watch()
	<-w.Success
	c.Assert(attempts1, Equals, 20)
	c.Assert(attempts2, Equals, 19)

	w.ShouldRetry <- true
	<-w.Success
	c.Assert(attempts1, Equals, 40)
	c.Assert(attempts2, Equals, 19)
}
<|endoftext|>


<commit_before>package aws

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"io"
	"net/http"
	"net/url"
	"os"
	"path"
	"sort"
	"strings"
	"time"
)

const (
	ISO8601BasicFormat      = "20060102T150405Z"
	ISO8601BasicFormatShort = "20060102"
)

var (
	unreserved = make([]bool, 128)
)

func init() {
	// RFC3986
	u := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890-_.~"
	for _, c := range u {
		unreserved[c] = true
	}
}

// Tests if a character requires encoding in a URI.
//
func charRequiresEncoding(c byte) bool {
	return c > 127 || !unreserved[c]
}

// Tests if a character requires encoding in a URI.
//
func stringRequiresEncoding(s string) bool {
	for _, c := range []byte(s) {
		if charRequiresEncoding(c) {
			return true
		}
	}
	return false
}

// URI encode a string.  Characters that are not in `unreserved` are
// replaced with their hex encoding preceded by a '%' character.
//
// Note:
//  * Based on https://launchpad.net/goamz
//
func uriEncodeString(s string) string {

	// If `s` does not require encoding, we're done.
	if !stringRequiresEncoding(s) {
		return s
	}

	// Encode `s`.  `e` is initialized to 3x the size of `s`
	// because that is the max possible length of the hex
	// encoded copy of `s`, assuming each character needed to
	// be encoded.
	e := make([]byte, len(s)*3)
	ei := 0
	const hex = "0123456789ABCDEF"
	for _, c := range []byte(s) {

		if charRequiresEncoding(c) {

			// This character requires encoding.
			e[ei] = '%'
			e[ei+1] = hex[c>>4]
			e[ei+2] = hex[c&0xF]
			ei += 3

		} else {

			// This character does not require encoding.
			e[ei] = c
			ei += 1
		}
	}
	return string(e[:ei])
}

// Return a new copy of the input byte array that is
// hex encoded.
//
func toHex(x []byte) []byte {
	z := make([]byte, 2*len(x))
	hex.Encode(z, x)
	return z
}

// Get secret and access ID keys (in that order) from enviroment variables
// AWS_SECRET_KEY and AWS_ACCESS_KEY.
func KeysFromEnviroment() (string, string) {
	return os.Getenv("AWS_SECRET_KEY"), os.Getenv("AWS_ACCESS_KEY")
}

// Signature contains the access ID key, UTC date in YYYYMMDD format, region,
// service name, and the signing key.
type Signature struct {
	AccessID   string
	Date       string
	Region     *Region
	Service    string
	SigningKey [sha256.Size]byte
	NewKeys    func() (string, string) // function to get keys if date changes
}

// NewSignature creates a new signature from the secret key, access key,
// region, and service with the date set to UTC now.
func NewSignature(secret, access string, r *Region, service string) *Signature {
	var s Signature

	s.AccessID = access
	s.Date = time.Now().UTC().Format(ISO8601BasicFormatShort)
	s.Region = r
	s.Service = service
	s.generateSigningKey(secret)

	return &s
}

// AWS signature Version 4 requires that you sign your message using a key that
// is derived from your secret access key rather than using the secret access key
// directly.  See  http://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html.
//
// Note:
//  * This is a separate function so that test suite can set a custom date.
//
func (s *Signature) generateSigningKey(secret string) {

	// Get an HMAC digest of the date using a key that
	// is our AWS secret prepended with the string "AWS4".
	h := hmac.New(sha256.New, []byte("AWS4"+secret))
	h.Write([]byte(s.Date))

	// Get an HMAC digest of the region name using a key that
	// is the HMAC digest computed in the previous step.
	h = hmac.New(sha256.New, h.Sum(nil))
	h.Write([]byte(s.Region.Name))

	// Repeat for service name.
	h = hmac.New(sha256.New, h.Sum(nil))
	h.Write([]byte(s.Service))

	// Repeat for the string "aws4_request".
	h = hmac.New(sha256.New, h.Sum(nil))
	h.Write([]byte("aws4_request"))

	// Copy this HMAC into the s.SigningKey byte array.
	h.Sum(s.SigningKey[:0])
}

// Sign uses signature s to sign the HTTP request. It sets the Authorization
// header and sets / overwrites the Date header for now.
// If the signature was created on a different UTC day the signing will be
// invalid.
// If a hash of the body is provided it is used and the body of the request is
// left alone. If no hash is provided one is created from the ReadSeeker, this
// reads the entire body and then resets it to the beginning. If there is no
// body then neither a ReadSeeker or hash is required.
//
// Possible errors are an invalid URL query parameters (url.EscapeError) or if
// the date header isn't in time.RFC1123 format (*time.ParseError).
func (s *Signature) Sign(r *http.Request, rs io.ReadSeeker, hash []byte) error {
	// TODO check if header already has hash instead of parameter
	// TODO check all error cases first

	if today := time.Now().UTC().Format(ISO8601BasicFormatShort); s.NewKeys != nil && s.Date != today {
		access, secret := s.NewKeys()
		s.AccessID = access
		s.Date = today
		s.generateSigningKey(secret)
	}

	credential := s.Date + "/" + s.Region.Name + "/" + s.Service + "/aws4_request"

	// create canonical request
	var crb bytes.Buffer // canonical request buffer

	// 1
	crb.WriteString(r.Method)
	crb.WriteByte('\n')

	// 2
	var cp bytes.Buffer // canonical path
	parts := strings.Split(path.Clean(r.URL.Path)[1:], "/")
	for i := range parts {
		cp.WriteByte('/')
		cp.WriteString(uriEncodeString(parts[i]))
	}
	crb.Write(cp.Bytes())
	crb.WriteByte('\n')

	// 3
	query, err := url.ParseQuery(r.URL.RawQuery)
	if err != nil {
		return err
	}
	keys := make([]string, 0, len(query))
	for i := range query {
		keys = append(keys, i)
	}
	sort.Strings(keys)
	var cqs bytes.Buffer // canonical query string
	for i := range keys {
		if i > 0 {
			cqs.WriteByte('&')
		}
		parameters := query[keys[i]]
		sort.Strings(parameters)
		for j := range parameters {
			if j > 0 {
				cqs.WriteByte('&')
			}
			cqs.WriteString(uriEncodeString(keys[i]))
			cqs.WriteByte('=')
			cqs.WriteString(uriEncodeString(parameters[j]))
		}
	}
	if cqs.Len() > 0 {
		crb.Write(cqs.Bytes())
	}
	crb.WriteByte('\n')

	// 4
	// TODO check for date and add if required
	headers := make([]string, 0, len(r.Header)+1)
	headersMap := make(map[string]string)
	for i := range r.Header {
		header := strings.ToLower(i)
		headers = append(headers, header)
		headersMap[header] = i
	}
	headers = append(headers, "host")
	sort.Strings(headers)
	for i := range headers {
		crb.WriteString(headers[i])
		crb.WriteByte(':')
		var value string
		if headers[i] == "host" {
			value = r.Host
		} else {
			values := r.Header[headersMap[headers[i]]]
			sort.Strings(values)
			value = strings.Join(values, ",")
		}
		crb.WriteString(value)
		crb.WriteByte('\n')
	}
	crb.WriteByte('\n')

	// 5
	crb.WriteString(strings.Join(headers, ";"))
	crb.WriteByte('\n')

	// 6
	hasher := sha256.New()
	var hashed [sha256.Size]byte
	if hash == nil {
		if rs != nil {
			io.Copy(hasher, rs)
			rs.Seek(0, 0)
		}
		crb.Write(toHex(hasher.Sum(hashed[:0])))
		hasher.Reset()
	} else {
		crb.Write(toHex(hash))
	}

	// create string to sign
	var sts bytes.Buffer

	// 1
	sts.WriteString("AWS4-HMAC-SHA256\n")

	// 2
	// TODO parsing dates just to pass test suite, implement such that the date
	// is just overwritten if it exists
	var dateTime time.Time
	dates, ok := r.Header["Date"]
	if !ok || len(dates) < 1 {
		dateTime = time.Now().UTC() // TODO could be different day than signature
		r.Header.Set("Date", dateTime.Format(time.RFC3339))
	} else {
		dateTime, err = time.Parse(time.RFC1123, dates[0])
		if err != nil {
			return err
		}
	}
	sts.WriteString(dateTime.Format(ISO8601BasicFormat))
	sts.WriteByte('\n')

	// 3
	sts.WriteString(credential)
	sts.WriteByte('\n')

	// 4
	hasher.Write(crb.Bytes())
	sts.Write(toHex(hasher.Sum(hashed[:0])))

	// sign string and write to authorization header
	var authz bytes.Buffer
	authz.WriteString("AWS4-HMAC-SHA256 Credential=")
	authz.WriteString(s.AccessID)
	authz.WriteByte('/')
	authz.WriteString(credential)
	authz.WriteString(", SignedHeaders=")
	for i := range headers {
		if i > 0 {
			authz.WriteByte(';')
		}
		authz.WriteString(headers[i])
	}
	authz.WriteString(", Signature=")
	h := hmac.New(sha256.New, s.SigningKey[:])
	h.Write(sts.Bytes())
	authz.Write(toHex(h.Sum(hashed[:0])))

	r.Header.Add("Authorization", authz.String())

	return nil
}
<commit_msg>Add documentation for canonical request construction.<commit_after>package aws

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"io"
	"net/http"
	"net/url"
	"os"
	"path"
	"sort"
	"strings"
	"time"
)

const (
	ISO8601BasicFormat      = "20060102T150405Z"
	ISO8601BasicFormatShort = "20060102"
)

var (
	unreserved = make([]bool, 128)
)

func init() {
	// RFC3986
	u := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890-_.~"
	for _, c := range u {
		unreserved[c] = true
	}
}

// Tests if a character requires encoding in a URI.
//
func charRequiresEncoding(c byte) bool {
	return c > 127 || !unreserved[c]
}

// Tests if a character requires encoding in a URI.
//
func stringRequiresEncoding(s string) bool {
	for _, c := range []byte(s) {
		if charRequiresEncoding(c) {
			return true
		}
	}
	return false
}

// URI encode a string.  Characters that are not in `unreserved` are
// replaced with their hex encoding preceded by a '%' character.
//
// Note:
//  * Based on https://launchpad.net/goamz
//
func uriEncodeString(s string) string {

	// If `s` does not require encoding, we're done.
	if !stringRequiresEncoding(s) {
		return s
	}

	// Encode `s`.  `e` is initialized to 3x the size of `s`
	// because that is the max possible length of the hex
	// encoded copy of `s`, assuming each character needed to
	// be encoded.
	e := make([]byte, len(s)*3)
	ei := 0
	const hex = "0123456789ABCDEF"
	for _, c := range []byte(s) {

		if charRequiresEncoding(c) {

			// This character requires encoding.
			e[ei] = '%'
			e[ei+1] = hex[c>>4]
			e[ei+2] = hex[c&0xF]
			ei += 3

		} else {

			// This character does not require encoding.
			e[ei] = c
			ei += 1
		}
	}
	return string(e[:ei])
}

// Return a new copy of the input byte array that is
// hex encoded.
//
func toHex(x []byte) []byte {
	z := make([]byte, 2*len(x))
	hex.Encode(z, x)
	return z
}

// Get secret and access ID keys (in that order) from enviroment variables
// AWS_SECRET_KEY and AWS_ACCESS_KEY.
func KeysFromEnviroment() (string, string) {
	return os.Getenv("AWS_SECRET_KEY"), os.Getenv("AWS_ACCESS_KEY")
}

// Signature contains the access ID key, UTC date in YYYYMMDD format, region,
// service name, and the signing key.
type Signature struct {
	AccessID   string
	Date       string
	Region     *Region
	Service    string
	SigningKey [sha256.Size]byte
	NewKeys    func() (string, string) // function to get keys if date changes
}

// NewSignature creates a new signature from the secret key, access key,
// region, and service with the date set to UTC now.
func NewSignature(secret, access string, r *Region, service string) *Signature {
	var s Signature

	s.AccessID = access
	s.Date = time.Now().UTC().Format(ISO8601BasicFormatShort)
	s.Region = r
	s.Service = service
	s.generateSigningKey(secret)

	return &s
}

// AWS signature Version 4 requires that you sign your message using a key that
// is derived from your secret access key rather than using the secret access key
// directly.  See  http://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html.
//
// Note:
//  * This is a separate function so that test suite can set a custom date.
//
func (s *Signature) generateSigningKey(secret string) {

	// Get an HMAC digest of the date using a key that
	// is our AWS secret prepended with the string "AWS4".
	h := hmac.New(sha256.New, []byte("AWS4"+secret))
	h.Write([]byte(s.Date))

	// Get an HMAC digest of the region name using a key that
	// is the HMAC digest computed in the previous step.
	h = hmac.New(sha256.New, h.Sum(nil))
	h.Write([]byte(s.Region.Name))

	// Repeat for service name.
	h = hmac.New(sha256.New, h.Sum(nil))
	h.Write([]byte(s.Service))

	// Repeat for the string "aws4_request".
	h = hmac.New(sha256.New, h.Sum(nil))
	h.Write([]byte("aws4_request"))

	// Copy this HMAC into the s.SigningKey byte array.
	h.Sum(s.SigningKey[:0])
}

// Sign uses signature s to sign the HTTP request. It sets the Authorization
// header and sets / overwrites the Date header for now.
// If the signature was created on a different UTC day the signing will be
// invalid.
// If a hash of the body is provided it is used and the body of the request is
// left alone. If no hash is provided one is created from the ReadSeeker, this
// reads the entire body and then resets it to the beginning. If there is no
// body then neither a ReadSeeker or hash is required.
//
// Possible errors are an invalid URL query parameters (url.EscapeError) or if
// the date header isn't in time.RFC1123 format (*time.ParseError).
func (s *Signature) Sign(r *http.Request, rs io.ReadSeeker, hash []byte) error {
	// TODO check if header already has hash instead of parameter
	// TODO check all error cases first

	if today := time.Now().UTC().Format(ISO8601BasicFormatShort); s.NewKeys != nil && s.Date != today {
		access, secret := s.NewKeys()
		s.AccessID = access
		s.Date = today
		s.generateSigningKey(secret)
	}

	credential := s.Date + "/" + s.Region.Name + "/" + s.Service + "/aws4_request"

	// Create the canonical request, which is the string we must sign
	// with our derived key. See
	// http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
	//
	var crb bytes.Buffer // canonical request buffer

	// 1 - Start with the HTTP request method (GET, PUT, POST, etc.).
	//
	crb.WriteString(r.Method)
	crb.WriteByte('\n')

	// 2 - Add the CanonicalURI parameter. This is the URI-encoded version
	// of the absolute path component of the URI—everything from the HTTP host
	// header to the question mark character ('?') that begins the query string
	// parameters.
	//
	var cp bytes.Buffer // canonical path
	parts := strings.Split(path.Clean(r.URL.Path)[1:], "/")
	for i := range parts {
		cp.WriteByte('/')
		cp.WriteString(uriEncodeString(parts[i]))
	}
	crb.Write(cp.Bytes())
	crb.WriteByte('\n')

	// 3 - Add the CanonicalQueryString parameter. If the request does not
	// include a query string, set the value of CanonicalQueryString to an empty string.
	//
	query, err := url.ParseQuery(r.URL.RawQuery)
	if err != nil {
		return err
	}
	keys := make([]string, 0, len(query))
	for i := range query {
		keys = append(keys, i)
	}
	sort.Strings(keys)
	var cqs bytes.Buffer // canonical query string
	for i := range keys {
		if i > 0 {
			cqs.WriteByte('&')
		}
		parameters := query[keys[i]]
		sort.Strings(parameters)
		for j := range parameters {
			if j > 0 {
				cqs.WriteByte('&')
			}
			cqs.WriteString(uriEncodeString(keys[i]))
			cqs.WriteByte('=')
			cqs.WriteString(uriEncodeString(parameters[j]))
		}
	}
	if cqs.Len() > 0 {
		crb.Write(cqs.Bytes())
	}
	crb.WriteByte('\n')

	// 4 - Add the CanonicalHeaders parameter, which is a list of all
	// the HTTP headers for the request. You must include a valid host
	// header. Any other required headers are described by the service
	// you're using.
	//
	// TODO:
	//   * check for date and add if required
	//
	headers := make([]string, 0, len(r.Header)+1)
	headersMap := make(map[string]string)
	for i := range r.Header {
		header := strings.ToLower(i)
		headers = append(headers, header)
		headersMap[header] = i
	}
	headers = append(headers, "host")
	sort.Strings(headers)
	for i := range headers {
		crb.WriteString(headers[i])
		crb.WriteByte(':')
		var value string
		if headers[i] == "host" {
			value = r.Host
		} else {
			values := r.Header[headersMap[headers[i]]]
			sort.Strings(values)
			value = strings.Join(values, ",")
		}
		crb.WriteString(value)
		crb.WriteByte('\n')
	}
	crb.WriteByte('\n')

	// 5 - Add the SignedHeaders parameter, which is the list of HTTP
	// headers that you included in the canonical headers. You must include
	// a list of signed headers because extra headers are often added to the
	// request by the transport layers. The list of signed headers enables
	// AWS to determine which headers are part of your original request.
	//
	crb.WriteString(strings.Join(headers, ";"))
	crb.WriteByte('\n')

	// 6 - Add the payload, which you derive from the body of the HTTP
	// or HTTPS request.
	//
	hasher := sha256.New()
	var hashed [sha256.Size]byte
	if hash == nil {
		if rs != nil {
			io.Copy(hasher, rs)
			rs.Seek(0, 0)
		}
		crb.Write(toHex(hasher.Sum(hashed[:0])))
		hasher.Reset()
	} else {
		crb.Write(toHex(hash))
	}

	// create string to sign
	var sts bytes.Buffer

	// 1
	sts.WriteString("AWS4-HMAC-SHA256\n")

	// 2
	// TODO parsing dates just to pass test suite, implement such that the date
	// is just overwritten if it exists
	var dateTime time.Time
	dates, ok := r.Header["Date"]
	if !ok || len(dates) < 1 {
		dateTime = time.Now().UTC() // TODO could be different day than signature
		r.Header.Set("Date", dateTime.Format(time.RFC3339))
	} else {
		dateTime, err = time.Parse(time.RFC1123, dates[0])
		if err != nil {
			return err
		}
	}
	sts.WriteString(dateTime.Format(ISO8601BasicFormat))
	sts.WriteByte('\n')

	// 3
	sts.WriteString(credential)
	sts.WriteByte('\n')

	// 4
	hasher.Write(crb.Bytes())
	sts.Write(toHex(hasher.Sum(hashed[:0])))

	// sign string and write to authorization header
	var authz bytes.Buffer
	authz.WriteString("AWS4-HMAC-SHA256 Credential=")
	authz.WriteString(s.AccessID)
	authz.WriteByte('/')
	authz.WriteString(credential)
	authz.WriteString(", SignedHeaders=")
	for i := range headers {
		if i > 0 {
			authz.WriteByte(';')
		}
		authz.WriteString(headers[i])
	}
	authz.WriteString(", Signature=")
	h := hmac.New(sha256.New, s.SigningKey[:])
	h.Write(sts.Bytes())
	authz.Write(toHex(h.Sum(hashed[:0])))

	r.Header.Add("Authorization", authz.String())

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	// "encoding/json"
	"github.com/taskcluster/httpbackoff"
	"io/ioutil"
	"time"
)

// for when running in aws
func queryUserData() (*UserData, error) {
	// TODO: currently assuming UserData is json, need to work out with jhford how this will work with provisioner
	// http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html#instancedata-user-data-retrieval
	// call http://169.254.169.254/latest/user-data with httpbackoff
	resp, _, err := httpbackoff.Get("http://169.254.169.254/latest/user-data")
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	userData := new(UserData)
	// decoder := json.NewDecoder(resp.Body)
	// err = decoder.Decode(userData)
	return userData, err
}

func queryInstanceName() (string, error) {
	// http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html#instancedata-data-retrieval
	// call http://169.254.169.254/latest/meta-data/instance-id with httpbackoff
	resp, _, err := httpbackoff.Get("http://169.254.169.254/latest/meta-data/instance-id")
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()
	content, err := ioutil.ReadAll(resp.Body)
	return string(content), err
}

type UserData struct {
	Raw                    string
	Capacity               int
	WorkerType             string
	ProvisionerId          string
	Region                 string
	InstanceType           string
	TaskclusterAccessToken string
	TaskclusterClientId    string
	LaunchSpecGenerated    time.Time
}

func updateConfigWithAmazonSettings(configFile string, provisioner string) error {
	// error indicates whether file existed or not, so can be ignored.
	// loadConfig already returns default config if file doesn't exist
	config, _ := loadConfig(configFile)

	userData, err := queryUserData()
	if err != nil {
		return err
	}
	instanceName, err := queryInstanceName()
	if err != nil {
		return err
	}
	config.ProvisionerId = provisioner
	config.TaskclusterAccessToken = userData.TaskclusterAccessToken
	config.TaskclusterClientId = userData.TaskclusterClientId
	config.WorkerGroup = userData.Region
	config.WorkerId = instanceName
	config.WorkerType = userData.WorkerType
	return nil
}
<commit_msg>Work in progress...<commit_after>package main

import (
	// "encoding/json"
	"fmt"
	"github.com/taskcluster/httpbackoff"
	"io/ioutil"
	"time"
)

// for when running in aws
func queryUserData() (*UserData, error) {
	// TODO: currently assuming UserData is json, need to work out with jhford how this will work with provisioner
	// http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html#instancedata-user-data-retrieval
	// call http://169.254.169.254/latest/user-data with httpbackoff
	resp, _, err := httpbackoff.Get("http://169.254.169.254/latest/user-data")
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	userData := new(UserData)
	// decoder := json.NewDecoder(resp.Body)
	// err = decoder.Decode(userData)
	return userData, err
}

func queryInstanceName() (string, error) {
	// http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html#instancedata-data-retrieval
	// call http://169.254.169.254/latest/meta-data/instance-id with httpbackoff
	resp, _, err := httpbackoff.Get("http://169.254.169.254/latest/meta-data/instance-id")
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()
	content, err := ioutil.ReadAll(resp.Body)
	fmt.Println("Instance name: " + string(content))
	return string(content), err
}

type UserData struct {
	Raw                    string
	Capacity               int
	WorkerType             string
	ProvisionerId          string
	Region                 string
	InstanceType           string
	TaskclusterAccessToken string
	TaskclusterClientId    string
	LaunchSpecGenerated    time.Time
}

func updateConfigWithAmazonSettings(configFile string, provisioner string) error {
	// error indicates whether file existed or not, so can be ignored.
	// loadConfig already returns default config if file doesn't exist
	config, _ := loadConfig(configFile)

	userData, err := queryUserData()
	if err != nil {
		return err
	}
	instanceName, err := queryInstanceName()
	if err != nil {
		return err
	}
	config.ProvisionerId = provisioner
	config.TaskclusterAccessToken = userData.TaskclusterAccessToken
	config.TaskclusterClientId = userData.TaskclusterClientId
	config.WorkerGroup = userData.Region
	config.WorkerId = instanceName
	config.WorkerType = userData.WorkerType
	return nil
}
<|endoftext|>


<commit_before>// Copyright ©2012 Dan Kortschak <dan.kortschak@adelaide.edu.au>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

package boom

import ()

type BAMFile struct {
	*samFile
}

func OpenBAM(filename string) (b *BAMFile, err error) {
	sf, err := samOpen(filename, "rb", nil)
	if err != nil {
		return
	}
	return &BAMFile{sf}, nil
}

var bWModes = [2]string{"wb", "wbu"}

func CreateBAM(filename string, ref Header, comp bool) (b *BAMFile, err error) {
	var mode string
	if comp {
		mode = bWModes[0]
	} else {
		mode = bWModes[1]
	}
	sf, err := samOpen(filename, mode, ref.bamHeader)
	if err != nil {
		return
	}
	return &BAMFile{sf}, nil
}

func (self *BAMFile) Close() error {
	return self.samClose()
}

func (self *BAMFile) Read() (r *Record, n int, err error) {
	n, br, err := self.samRead()
	r = &Record{bamRecord: br}
	return
}

func (self *BAMFile) Write(r *Record) (n int, err error) {
	return self.samWrite(r.bamRecord)
}

func (self *BAMFile) ReferenceNames() []string {
	return self.header().targetNames()
}

func (self *BAMFile) ReferenceLengths() []uint32 {
	return self.header().targetLengths()
}

func (self *BAMFile) Text() string {
	return self.header().text()
}
<commit_msg>Bugfix - typo pointer not base type<commit_after>// Copyright ©2012 Dan Kortschak <dan.kortschak@adelaide.edu.au>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

package boom

import ()

type BAMFile struct {
	*samFile
}

func OpenBAM(filename string) (b *BAMFile, err error) {
	sf, err := samOpen(filename, "rb", nil)
	if err != nil {
		return
	}
	return &BAMFile{sf}, nil
}

var bWModes = [2]string{"wb", "wbu"}

func CreateBAM(filename string, ref *Header, comp bool) (b *BAMFile, err error) {
	var mode string
	if comp {
		mode = bWModes[0]
	} else {
		mode = bWModes[1]
	}
	sf, err := samOpen(filename, mode, ref.bamHeader)
	if err != nil {
		return
	}
	return &BAMFile{sf}, nil
}

func (self *BAMFile) Close() error {
	return self.samClose()
}

func (self *BAMFile) Read() (r *Record, n int, err error) {
	n, br, err := self.samRead()
	r = &Record{bamRecord: br}
	return
}

func (self *BAMFile) Write(r *Record) (n int, err error) {
	return self.samWrite(r.bamRecord)
}

func (self *BAMFile) ReferenceNames() []string {
	return self.header().targetNames()
}

func (self *BAMFile) ReferenceLengths() []uint32 {
	return self.header().targetLengths()
}

func (self *BAMFile) Text() string {
	return self.header().text()
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"

	irc "github.com/fluffle/goirc/client"
)

var config *Config

// Config holds all the configuration data
type Config struct {
	IRCHost      string `json:"ircHost"`
	IRCChannel   string `json:"ircChannel"`
	IRCName      string `json:"ircName"`
	IRCPassword  string `json:"ircPassword"`
	SlackWebhook string `json:"slackWebhook"`
	SlackChannel string `json:"slackChannel"`
}

// SlackMsg represents a message sent to Slack over a webhook
type SlackMsg struct {
	User    string  `json:"username"`
	Text    string  `json:"text"`
	Channel *string `json:"channel"`
}

func init() {
	config = &Config{}
	data, err := ioutil.ReadFile("config.json")
	if err != nil {
		log.Fatalf("Error reading configuration: %v", err)
	}
	err = json.Unmarshal(data, config)
	if err != nil {
		log.Fatalf("Error parsing configuration: %v", err)
	}
}

func main() {
	c := irc.SimpleClient("netlibot", "netlibot")
	c.EnableStateTracking()
	c.HandleFunc("connected",
		func(conn *irc.Conn, line *irc.Line) { conn.Join("#netlify") })

	quit := make(chan bool)
	c.HandleFunc("disconnected",
		func(conn *irc.Conn, line *irc.Line) { quit <- true })

	c.HandleFunc("PRIVMSG",
		func(conn *irc.Conn, line *irc.Line) {

			msg := &SlackMsg{
				User:    line.Nick,
				Text:    line.Text(),
				Channel: &config.SlackChannel,
			}
			b, err := json.Marshal(msg)
			if err != nil {
				log.Printf("Error encoding json for message: %v %v\n", line, err)
			} else {
				buf := bytes.NewReader(b)
				http.Post(config.SlackWebhook, "application/json", buf)
			}

			fmt.Printf("Got public msg: %v\n", line)
		})

	for {
		// connect to server
		if err := c.ConnectTo("irc.freenode.net"); err != nil {
			fmt.Printf("Connection error: %s\n", err)
			return
		}

		// wait on quit channel
		<-quit
	}
}
<commit_msg>identify with NickServ on connect<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"

	irc "github.com/fluffle/goirc/client"
)

var config *Config

// Config holds all the configuration data
type Config struct {
	IRCHost      string `json:"ircHost"`
	IRCChannel   string `json:"ircChannel"`
	IRCName      string `json:"ircName"`
	IRCPassword  string `json:"ircPassword"`
	SlackWebhook string `json:"slackWebhook"`
	SlackChannel string `json:"slackChannel"`
}

// SlackMsg represents a message sent to Slack over a webhook
type SlackMsg struct {
	User    string  `json:"username"`
	Text    string  `json:"text"`
	Channel *string `json:"channel"`
}

func init() {
	config = &Config{}
	data, err := ioutil.ReadFile("config.json")
	if err != nil {
		log.Fatalf("Error reading configuration: %v", err)
	}
	err = json.Unmarshal(data, config)
	if err != nil {
		log.Fatalf("Error parsing configuration: %v", err)
	}
}

func onConnect(conn *irc.Conn, line *irc.Line) {
	conn.Join("#netlify")
	if config.IRCPassword != "" {
		conn.Privmsg("NickServ", "identify "+config.IRCPassword)
	}
}

func main() {
	c := irc.SimpleClient("netlibot", "netlibot")
	c.EnableStateTracking()
	c.HandleFunc("connected", onConnect)

	quit := make(chan bool)
	c.HandleFunc("disconnected",
		func(conn *irc.Conn, line *irc.Line) { quit <- true })

	c.HandleFunc("PRIVMSG",
		func(conn *irc.Conn, line *irc.Line) {

			msg := &SlackMsg{
				User:    line.Nick,
				Text:    line.Text(),
				Channel: &config.SlackChannel,
			}
			b, err := json.Marshal(msg)
			if err != nil {
				log.Printf("Error encoding json for message: %v %v\n", line, err)
			} else {
				buf := bytes.NewReader(b)
				http.Post(config.SlackWebhook, "application/json", buf)
			}

			fmt.Printf("Got public msg: %v\n", line)
		})

	for {
		// connect to server
		if err := c.ConnectTo("irc.freenode.net"); err != nil {
			fmt.Printf("Connection error: %s\n", err)
			return
		}

		// wait on quit channel
		<-quit
	}
}
<|endoftext|>


<commit_before>// Package Wbzr provides tool to create a wooble in a given language and to package
// (wrap) some woobles.
package wbzr

import (
	"bytes"
	"io/ioutil"
	"text/template"

	"github.com/woobleio/wooblizer/wbzr/engine"
)

// ScriptLang are constants for implemented script languages.
type ScriptLang int

const (
	JSES5 ScriptLang = iota
)

type Wbzr struct {
	DomainsSec []string
	Scripts    []engine.Script

	lang     ScriptLang
	skeleton string
}

// New takes a script language which is used to inject and output a file.
func New(sl ScriptLang) *Wbzr {
	var skeleton string
	switch sl {
	case JSES5:
		skeleton = wbJses5
	default:
		panic("Language not supported")
	}

	return &Wbzr{
		nil,
		make([]engine.Script, 0),
		sl,
		skeleton,
	}
}

// Get returns an injected source.
func (wb *Wbzr) Get(name string) (engine.Script, error) {
	for _, sc := range wb.Scripts {
		if sc.GetName() == name {
			return sc, nil
		}
	}
	return nil, ErrUniqueName
}

// Inject injects a source code to be wooblized. It takes a name which must be
// unique. Src can be empty, it'll create a default object
func (wb *Wbzr) Inject(src string, name string) (engine.Script, error) {
	if _, err := wb.Get(name); err == nil {
		return nil, ErrUniqueName
	}
	var sc engine.Script
	var err error

	switch wb.lang {
	case JSES5:
		sc, err = engine.NewJSES5(src, name)
	}

	if err != nil {
		return nil, err
	}

	wb.Scripts = append(wb.Scripts, sc)
	return sc, nil
}

// InjectFile injects a source from a file.
func (wb *Wbzr) InjectFile(path string, name string) (engine.Script, error) {
	c, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}

	return wb.Inject(string(c[:]), name)
}

// Secure set some domains to protect the script and make it works only for specific domains
func (wb *Wbzr) Secure(domains ...string) {
	wb.DomainsSec = domains
}

func (wb *Wbzr) SecureAndWrap(domains ...string) (*bytes.Buffer, error) {
	wb.Secure(domains...)
	return wb.Wrap()
}

// Wrap packages some woobles (all the woobles injected in the Wbzr)
// and build a file which contains the wooble library.
func (wb *Wbzr) Wrap() (*bytes.Buffer, error) {
	for _, sc := range wb.Scripts {
		if _, err := sc.Build(); err != nil {
			return nil, err
		}
	}

	tmpl := template.Must(template.New("WbJSES5").Parse(wbJses5))

	var out bytes.Buffer
	if err := tmpl.Execute(&out, wb); err != nil {
		return nil, err
	}

	return &out, nil
}

var wbJses5 = `
function Wb(id) {
	{{if .DomainsSec}}
	var ah = [{{range $i, $o := .DomainsSec}}"{{$o}}"{{if not $i}},{{end}}{{end}}];
  var xx = ah.indexOf(window.location.hostname);
  if(ah.indexOf(window.location.hostname) == -1) {
  	console.log("Wooble error : domain restricted");
    return;
  }
	{{end}}

	if(window === this) {
  	return new Wb(id);
  }

  var cs = {
  	{{range $i, $o := .Scripts}}"{{$o.GetName}}":{{"{"}}{{$o.GetSource}}{{"}"}}{{if not $i}},{{end}}{{end}}
  }

  var c = cs[id];
  if(typeof c == 'undefined') {
  	console.log("Wooble error : creation", id, "not found");
    return undefined;
  }

  this.init = function (target) {
    if(document.querySelector(target) == null) {
    	console.log("Wooble error : Element", target, "not found in the document");
      return;
    }

    if("_buildDoc" in c) c._buildDoc(target);
    if("_buildStyle" in c) c._buildStyle();
    if("_init" in c) c._init();

		return c;
  }

  this.get = function() {
  	return c;
  }

  return this;
}
`
<commit_msg>Adds JSES5 template for object<commit_after>// Package Wbzr provides tool to create a wooble in a given language and to package
// (wrap) some woobles.
package wbzr

import (
	"bytes"
	"io/ioutil"
	"text/template"

	"github.com/woobleio/wooblizer/wbzr/engine"
)

// ScriptLang are constants for implemented script languages.
type ScriptLang int

const (
	JSES5 ScriptLang = iota
)

type Wbzr struct {
	DomainsSec []string
	Scripts    []engine.Script

	lang     ScriptLang
	skeleton string
}

// New takes a script language which is used to inject and output a file.
func New(sl ScriptLang) *Wbzr {
	var skeleton string
	switch sl {
	case JSES5:
		skeleton = wbJses5
	default:
		panic("Language not supported")
	}

	return &Wbzr{
		nil,
		make([]engine.Script, 0),
		sl,
		skeleton,
	}
}

// Get returns an injected source.
func (wb *Wbzr) Get(name string) (engine.Script, error) {
	for _, sc := range wb.Scripts {
		if sc.GetName() == name {
			return sc, nil
		}
	}
	return nil, ErrUniqueName
}

// Inject injects a source code to be wooblized. It takes a name which must be
// unique. Src can be empty, it'll create a default object
func (wb *Wbzr) Inject(src string, name string) (engine.Script, error) {
	if _, err := wb.Get(name); err == nil {
		return nil, ErrUniqueName
	}
	var sc engine.Script
	var err error

	switch wb.lang {
	case JSES5:
		sc, err = engine.NewJSES5(src, name)
	}

	if err != nil {
		return nil, err
	}

	wb.Scripts = append(wb.Scripts, sc)
	return sc, nil
}

// InjectFile injects a source from a file.
func (wb *Wbzr) InjectFile(path string, name string) (engine.Script, error) {
	c, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}

	return wb.Inject(string(c[:]), name)
}

// Secure set some domains to protect the script and make it works only for specific domains
func (wb *Wbzr) Secure(domains ...string) {
	wb.DomainsSec = domains
}

func (wb *Wbzr) SecureAndWrap(domains ...string) (*bytes.Buffer, error) {
	wb.Secure(domains...)
	return wb.Wrap()
}

// Wrap packages some woobles (all the woobles injected in the Wbzr)
// and build a file which contains the wooble library.
func (wb *Wbzr) Wrap() (*bytes.Buffer, error) {
	for _, sc := range wb.Scripts {
		if _, err := sc.Build(); err != nil {
			return nil, err
		}
	}

	tmpl := template.Must(template.New("WbJSES5").Parse(wbJses5))

	var out bytes.Buffer
	if err := tmpl.Execute(&out, wb); err != nil {
		return nil, err
	}

	return &out, nil
}

// WooblyJSES5 is a Wooble creation template for JSES5
var WooblyJSES5 = `woobly = {
	doc: document,
  attribute: "a value (optionnal)",
  _init: function() {
    // Creation code at runtime
  },
  method: function(a, b) {
    // a method (optionnal)
  }
}`

var wbJses5 = `
function Wb(id) {
	{{if .DomainsSec}}
	var ah = [{{range $i, $o := .DomainsSec}}"{{$o}}"{{if not $i}},{{end}}{{end}}];
  var xx = ah.indexOf(window.location.hostname);
  if(ah.indexOf(window.location.hostname) == -1) {
  	console.log("Wooble error : domain restricted");
    return;
  }
	{{end}}

	if(window === this) {
  	return new Wb(id);
  }

  var cs = {
  	{{range $i, $o := .Scripts}}"{{$o.GetName}}":{{"{"}}{{$o.GetSource}}{{"}"}}{{if not $i}},{{end}}{{end}}
  }

  var c = cs[id];
  if(typeof c == 'undefined') {
  	console.log("Wooble error : creation", id, "not found");
    return undefined;
  }

  this.init = function (target) {
    if(document.querySelector(target) == null) {
    	console.log("Wooble error : Element", target, "not found in the document");
      return;
    }

    if("_buildDoc" in c) c._buildDoc(target);
    if("_buildStyle" in c) c._buildStyle();
    if("_init" in c) c._init();

		return c;
  }

  this.get = function() {
  	return c;
  }

  return this;
}
`
<|endoftext|>


<commit_before>// Copyright 2021 The Prometheus Authors
// This code is partly borrowed from Caddy:
//    Copyright 2015 Matthew Holt and The Caddy Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package web

import (
	weakrand "math/rand"
	"sync"
	"time"
)

var cacheSize = 100

func init() {
	weakrand.Seed(time.Now().UnixNano())
}

type cache struct {
	cache map[string]bool
	mtx   sync.Mutex
}

// newCache returns a cache that contains a mapping of plaintext passwords
// to their hashes (with random eviction). This can greatly improve the
// performance of traffic-heavy servers that use secure password hashing
// algorithms, with the downside that plaintext passwords will be stored in
// memory for a longer time (this should not be a problem as long as your
// machine is not compromised, at which point all bets are off, since basicauth
// necessitates plaintext passwords being received over the wire anyway).
func newCache(size int) *cache {
	return &cache{
		cache: make(map[string]bool, size),
	}
}

func (c *cache) get(key string) (bool, bool) {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	v, ok := c.cache[key]
	return v, ok
}

func (c *cache) set(key string, value bool) {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	c.makeRoom()
	c.cache[key] = value
}

func (c *cache) makeRoom() {
	if len(c.cache) < cacheSize {
		return
	}
	// We delete more than just 1 entry so that we don't have
	// to do this on every request; assuming the capacity of
	// the cache is on a long tail, we can save a lot of CPU
	// time by doing a whole bunch of deletions now and then
	// we won't have to do them again for a while.
	numToDelete := len(c.cache) / 10
	if numToDelete < 1 {
		numToDelete = 1
	}
	for deleted := 0; deleted <= numToDelete; deleted++ {
		// Go maps are "nondeterministic" not actually random,
		// so although we could just chop off the "front" of the
		// map with less code, this is a heavily skewed eviction
		// strategy; generating random numbers is cheap and
		// ensures a much better distribution.
		rnd := weakrand.Intn(len(c.cache))
		i := 0
		for key := range c.cache {
			if i == rnd {
				delete(c.cache, key)
				break
			}
			i++
		}
	}
}
<commit_msg>Limit basicauth cache size<commit_after>// Copyright 2021 The Prometheus Authors
// This code is partly borrowed from Caddy:
//    Copyright 2015 Matthew Holt and The Caddy Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package web

import (
	weakrand "math/rand"
	"sync"
	"time"
)

var cacheSize = 100

func init() {
	weakrand.Seed(time.Now().UnixNano())
}

type cache struct {
	cache map[string]bool
	mtx   sync.Mutex
}

// newCache returns a cache that contains a mapping of plaintext passwords
// to their hashes (with random eviction). This can greatly improve the
// performance of traffic-heavy servers that use secure password hashing
// algorithms, with the downside that plaintext passwords will be stored in
// memory for a longer time (this should not be a problem as long as your
// machine is not compromised, at which point all bets are off, since basicauth
// necessitates plaintext passwords being received over the wire anyway).
func newCache(size int) *cache {
	if size > cacheSize/10 {
		size = cacheSize / 10
	}
	return &cache{
		cache: make(map[string]bool, size),
	}
}

func (c *cache) get(key string) (bool, bool) {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	v, ok := c.cache[key]
	return v, ok
}

func (c *cache) set(key string, value bool) {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	c.makeRoom()
	c.cache[key] = value
}

func (c *cache) makeRoom() {
	if len(c.cache) < cacheSize {
		return
	}
	// We delete more than just 1 entry so that we don't have
	// to do this on every request; assuming the capacity of
	// the cache is on a long tail, we can save a lot of CPU
	// time by doing a whole bunch of deletions now and then
	// we won't have to do them again for a while.
	numToDelete := len(c.cache) / 10
	if numToDelete < 1 {
		numToDelete = 1
	}
	for deleted := 0; deleted <= numToDelete; deleted++ {
		// Go maps are "nondeterministic" not actually random,
		// so although we could just chop off the "front" of the
		// map with less code, this is a heavily skewed eviction
		// strategy; generating random numbers is cheap and
		// ensures a much better distribution.
		rnd := weakrand.Intn(len(c.cache))
		i := 0
		for key := range c.cache {
			if i == rnd {
				delete(c.cache, key)
				break
			}
			i++
		}
	}
}
<|endoftext|>


<commit_before>package thumbnailer

// #include <string.h>
import "C"
import (
	"io"
	"sync"
	"unsafe"
)

// Initial minimum size of pooled buffer
const MinBufSize = 10 << 10

var bufPool = sync.Pool{
	New: func() interface{} {
		return make([]byte, 0, MinBufSize)
	},
}

// Retrieve a buffer from the memory pool or allocate a new one.
// Use this to reduce large allocations in your side of the application.
//
// Return the buffer to the pool using ReturnBuffer() when it is no longer being
// used.
func GetBuffer() []byte {
	return bufPool.Get().([]byte)
}

// Like GetBuffer() but the capacity of the returned buffer will be at least
// `capacity`. This can greatly reduce reallocation, if you already have a hint
// of the end size of the buffer.
func GetBufferCap(capacity int) []byte {
	if capacity < MinBufSize {
		capacity = MinBufSize
	}
	b := GetBuffer()
	if cap(b) < capacity {
		ReturnBuffer(b)
		b = make([]byte, 0, capacity)
	}
	return b
}

// Reads data from r until EOF and appends it to the buffer, growing the buffer
// as needed. The return value n is the number of bytes read. Any error except
// io.EOF encountered during the read is also returned. If the buffer becomes
// too large, ReadFrom will panic with ErrTooLarge.
//
// Unlike similar functions in the standard library this function uses the
// internal memory pool for reducing reallocations and decreasing heap sizes
// during heavy thumbnailing workloads.
//
// Return the buffer to the pool using ReturnBuffer() when it is no longer being
// used.
func ReadFrom(r io.Reader) ([]byte, error) {
	buf := GetBuffer()
	for {
		// Make for more room and return old buffer to the pool for reuse
		if cap(buf)-len(buf) < 512 {
			new := make([]byte, len(buf), cap(buf)*2)
			copy(new, buf)
			ReturnBuffer(buf)
			buf = new
		}

		n, err := r.Read(buf[len(buf):cap(buf)])
		buf = buf[:len(buf)+n]
		switch err {
		case nil:
		case io.EOF:
			return buf, nil
		default:
			ReturnBuffer(buf)
			return nil, err
		}
	}
}

// Return or put a buffer into the pool.
// It is recommended not to put buffers with capacity smaller than MinBufSize
// into the pool.
// The buffer must not be used after this call.
func ReturnBuffer(buf []byte) {
	bufPool.Put(buf[:0])
}

// Copy a C buffer into a Go buffer from the pool
func copyCBuffer(data unsafe.Pointer, size C.int) []byte {
	buf := GetBufferCap(int(size))
	buf = buf[0:int(size)]
	C.memcpy(unsafe.Pointer(&buf[0]), data, C.size_t(size))
	return buf
}
<commit_msg>Add fucntion for reading into a preallocated buffer<commit_after>package thumbnailer

// #include <string.h>
import "C"
import (
	"io"
	"sync"
	"unsafe"
)

// Initial minimum size of pooled buffer
const MinBufSize = 10 << 10

var bufPool = sync.Pool{
	New: func() interface{} {
		return make([]byte, 0, MinBufSize)
	},
}

// Retrieve a buffer from the memory pool or allocate a new one.
// Use this to reduce large allocations in your side of the application.
//
// Return the buffer to the pool using ReturnBuffer() when it is no longer being
// used.
func GetBuffer() []byte {
	return bufPool.Get().([]byte)
}

// Like GetBuffer() but the capacity of the returned buffer will be at least
// `capacity`. This can greatly reduce reallocation, if you already have a hint
// of the end size of the buffer.
func GetBufferCap(capacity int) []byte {
	if capacity < MinBufSize {
		capacity = MinBufSize
	}
	b := GetBuffer()
	if cap(b) < capacity {
		ReturnBuffer(b)
		b = make([]byte, 0, capacity)
	}
	return b
}

// Reads data from r until EOF and appends it to the buffer, growing the buffer
// as needed. The return value n is the number of bytes read. Any error except
// io.EOF encountered during the read is also returned. If the buffer becomes
// too large, ReadFrom will panic with ErrTooLarge.
//
// Unlike similar functions in the standard library this function uses the
// internal memory pool for reducing reallocations and decreasing heap sizes
// during heavy thumbnailing workloads.
//
// Return the buffer to the pool using ReturnBuffer() when it is no longer being
// used.
func ReadFrom(r io.Reader) ([]byte, error) {
	return ReadInto(GetBuffer(), r)
}

// Like ReadFrom() but the suplied buffer is used for reading. The supplied
// buffer should not be used after this call.
func ReadInto(buf []byte, r io.Reader) ([]byte, error) {
	for {
		// Make for more room and return old buffer to the pool for reuse
		if cap(buf)-len(buf) < 512 {
			new := make([]byte, len(buf), cap(buf)*2)
			copy(new, buf)
			ReturnBuffer(buf)
			buf = new
		}

		n, err := r.Read(buf[len(buf):cap(buf)])
		buf = buf[:len(buf)+n]
		switch err {
		case nil:
		case io.EOF:
			return buf, nil
		default:
			ReturnBuffer(buf)
			return nil, err
		}
	}
}

// Return or put a buffer into the pool.
// It is recommended not to put buffers with capacity smaller than MinBufSize
// into the pool.
// The buffer must not be used after this call.
func ReturnBuffer(buf []byte) {
	bufPool.Put(buf[:0])
}

// Copy a C buffer into a Go buffer from the pool
func copyCBuffer(data unsafe.Pointer, size C.int) []byte {
	buf := GetBufferCap(int(size))
	buf = buf[0:int(size)]
	C.memcpy(unsafe.Pointer(&buf[0]), data, C.size_t(size))
	return buf
}
<|endoftext|>


<commit_before>//
//  Created by Robert A. Baruch on 03/14/2015
//  Copyright (c) 2015 Robert A. Baruch, All rights reserved.
//

package main

import (
	"errors"
	"fmt"
	"html/template"
	"log"
	"net/http"

	"github.com/gin-gonic/gin"
)

const ()

type DemoPages struct {
	pages map[string]DemoPage
}

type DemoPage struct {
	urlString string
	callback  gin.HandlerFunc
	template  string
	context   interface{}
}

type Movies struct {
	Title string `json:"title"`
}

var (
	nullFunc = func(c *gin.Context) {
		c.String(http.StatusOK, "default func - stub - replace with actual function")
	}
)

func main() {

	var dp DemoPages
	var foo map[string]int = map[string]int{"foo": 1, "bar": 2}
	var bar map[string]string = map[string]string{"foo": "Alpha", "bar": "Beta"}
	var grill map[string]string = map[string]string{"foo": "Omega", "bar": "Alpha"}

	dp.pages = map[string]DemoPage{
		"fred":  DemoPage{"/fred", FredFunc, "fred.tmpl", foo},
		"tom":   DemoPage{"/tom", TomFunc, "tom.tmpl", grill},
		"sally": DemoPage{"/sally", SallyFunc, "sally.tmpl", bar},
		"core":  DemoPage{"/feeds/api/rob", coreFunc, "core.tmpl", nil},
	}

	// Use Gin-Gonic for our web framework
	router := gin.Default()
	router.Use(dp.Params())

	// Register a template for each page in the pages table
	var html = template.New("temps")

	// Escape the {{ }} braces used by Polymer and Golang Templates
	html.Delims("{[", "]}")

	// Load all of the templates defined in the pages map
	template.Must(html.ParseFiles(buildTmpArray("./templates", dp.pages)...))
	router.SetHTMLTemplate(html)

	// Serve static content
	router.Static("/static", "./static")

	// Add a default GET for /
	router.GET("/", func(c *gin.Context) {
		c.HTML(http.StatusOK, "index.tmpl", nil)
	})

	// for each element in the pages map, add a GET route and corresponding handler
	for _, p := range dp.pages {
		router.GET(p.urlString, p.callback)
	}

	router.Run(":8080")
}

// GET callbacks: Fred
func FredFunc(c *gin.Context) {

	dp, err := GetDPContext(c)

	log.Printf("preparing %s\n", dp.pages["fred"].urlString)
	log.Printf("context = %v\n", dp.pages["fred"].context)

	ctx := (dp.pages["fred"].context).(map[string]int)

	if err != nil {
		log.Printf("failed to get server context\n")
	} else {
		obj := gin.H{"title": dp.pages["fred"].urlString,
			"foo": ctx["foo"],
		}
		c.HTML(http.StatusOK, "fred.tmpl", obj)
	}

}

// GET callbacks; Tom
func TomFunc(c *gin.Context) {

	dp, err := GetDPContext(c)

	ctx := (dp.pages["tom"].context).(map[string]string)

	if err != nil {
		log.Printf("failed to get server context\n")
	} else {
		obj := gin.H{"title": dp.pages["tom"].urlString,
			"foo": ctx["foo"],
		}
		c.HTML(http.StatusOK, "tom.tmpl", obj)
	}

}

// GET callbacks; Sally
func SallyFunc(c *gin.Context) {

	dp, err := GetDPContext(c)

	ctx := (dp.pages["sally"].context).(map[string]string)

	if err != nil {
		log.Printf("failed to get server context\n")
	} else {
		obj := gin.H{"title": dp.pages["sally"].urlString,
			"foo": ctx["foo"],
		}
		c.HTML(http.StatusOK, "sally.tmpl", obj)
	}

}

// GET callbacks; core
func coreFunc(c *gin.Context) {

	// dp, err := GetDPContext(c)
	var core []Movies = []Movies{
		Movies{"yo bro"},
		Movies{"sambo"},
		Movies{"huh"},
	}

	c.JSON(http.StatusOK, core)

}

// Middleware handler for global Context
func (dp *DemoPages) Params() gin.HandlerFunc {
	return func(c *gin.Context) {
		_, err := c.Get("dp")
		if err != nil {
			log.Printf("Setting context\n")
			c.Set("dp", dp)
		}
		c.Next()
	}
}

// Function to retrieve global Context
func GetDPContext(c *gin.Context) (*DemoPages, error) {
	dp, err := c.Get("dp")
	if err != nil {
		log.Printf("failed to find server parameter context")
		return nil, errors.New("failed to find parameter context")
	}

	return dp.(*DemoPages), nil
}

// return an array of templates to pass to ParseFiles
func buildTmpArray(tdir string, p map[string]DemoPage) []string {
	var temps []string = []string{}

	for _, page := range p {
		pe := fmt.Sprintf("%s/%s", tdir, page.template)
		temps = append(temps, pe)
	}

	return temps
}
<commit_msg>added url param procesing<commit_after>//
//  Created by Robert A. Baruch on 03/14/2015
//  Copyright (c) 2015 Robert A. Baruch, All rights reserved.
//

package main

import (
	"errors"
	"fmt"
	"html/template"
	"log"
	"net/http"

	"github.com/gin-gonic/gin"
)

const ()

type DemoPages struct {
	pages map[string]DemoPage
}

type DemoPage struct {
	urlString string
	callback  gin.HandlerFunc
	template  string
	context   interface{}
}

type Movies struct {
	Title string `json:"title"`
}

var (
	nullFunc = func(c *gin.Context) {
		c.String(http.StatusOK, "default func - stub - replace with actual function")
	}
)

func main() {

	var dp DemoPages
	var foo map[string]int = map[string]int{"foo": 1, "bar": 2}
	var bar map[string]string = map[string]string{"foo": "Alpha", "bar": "Beta"}
	var grill map[string]string = map[string]string{"foo": "Omega", "bar": "Alpha"}

	dp.pages = map[string]DemoPage{
		"fred":  DemoPage{"/fred", FredFunc, "fred.tmpl", foo},
		"tom":   DemoPage{"/tom", TomFunc, "tom.tmpl", grill},
		"sally": DemoPage{"/sally", SallyFunc, "sally.tmpl", bar},
		"core":  DemoPage{"/feeds/api/rob", coreFunc, "core.tmpl", nil},
	}

	// Use Gin-Gonic for our web framework
	router := gin.Default()
	router.Use(dp.Params())

	// Register a template for each page in the pages table
	var html = template.New("temps")

	// Escape the {{ }} braces used by Polymer and Golang Templates
	html.Delims("{[", "]}")

	// Load all of the templates defined in the pages map
	template.Must(html.ParseFiles(buildTmpArray("./templates", dp.pages)...))
	router.SetHTMLTemplate(html)

	// Serve static content
	router.Static("/static", "./static")

	// Add a default GET for /
	router.GET("/", func(c *gin.Context) {
		c.HTML(http.StatusOK, "index.tmpl", nil)
	})

	// for each element in the pages map, add a GET route and corresponding handler
	for _, p := range dp.pages {
		router.GET(p.urlString, p.callback)
	}

	router.Run(":8080")
}

// GET callbacks: Fred
func FredFunc(c *gin.Context) {

	dp, err := GetDPContext(c)

	log.Printf("preparing %s\n", dp.pages["fred"].urlString)
	log.Printf("context = %v\n", dp.pages["fred"].context)

	ctx := (dp.pages["fred"].context).(map[string]int)

	if err != nil {
		log.Printf("failed to get server context\n")
	} else {
		obj := gin.H{"title": dp.pages["fred"].urlString,
			"foo": ctx["foo"],
		}
		c.HTML(http.StatusOK, "fred.tmpl", obj)
	}

}

// GET callbacks; Tom
func TomFunc(c *gin.Context) {

	dp, err := GetDPContext(c)

	ctx := (dp.pages["tom"].context).(map[string]string)

	if err != nil {
		log.Printf("failed to get server context\n")
	} else {
		obj := gin.H{"title": dp.pages["tom"].urlString,
			"foo": ctx["foo"],
		}
		c.HTML(http.StatusOK, "tom.tmpl", obj)
	}

}

// GET callbacks; Sally
func SallyFunc(c *gin.Context) {

	dp, err := GetDPContext(c)

	ctx := (dp.pages["sally"].context).(map[string]string)

	if err != nil {
		log.Printf("failed to get server context\n")
	} else {
		obj := gin.H{"title": dp.pages["sally"].urlString,
			"foo": ctx["foo"],
		}
		c.HTML(http.StatusOK, "sally.tmpl", obj)
	}

}

// GET callbacks; core
func coreFunc(c *gin.Context) {

	// dp, err := GetDPContext(c)
	p1 := c.Request.URL.Query().Get("alt")
	p2 := c.Request.URL.Query().Get("q")

	fmt.Printf("P1 = [%s] P2 = [%s]\n", p1, p2)

	var core []Movies = []Movies{
		Movies{"yo bro"},
		Movies{"sambo"},
		Movies{"huh"},
	}

	c.JSON(http.StatusOK, core)

}

// Middleware handler for global Context
func (dp *DemoPages) Params() gin.HandlerFunc {
	return func(c *gin.Context) {
		_, err := c.Get("dp")
		if err != nil {
			log.Printf("Setting context\n")
			c.Set("dp", dp)
		}
		c.Next()
	}
}

// Function to retrieve global Context
func GetDPContext(c *gin.Context) (*DemoPages, error) {
	dp, err := c.Get("dp")
	if err != nil {
		log.Printf("failed to find server parameter context")
		return nil, errors.New("failed to find parameter context")
	}

	return dp.(*DemoPages), nil
}

// return an array of templates to pass to ParseFiles
func buildTmpArray(tdir string, p map[string]DemoPage) []string {
	var temps []string = []string{}

	for _, page := range p {
		pe := fmt.Sprintf("%s/%s", tdir, page.template)
		temps = append(temps, pe)
	}

	return temps
}
<|endoftext|>