<commit_before>package pkglib

import (
	"crypto/sha1"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"strings"

	"gopkg.in/yaml.v2"

	"github.com/linuxkit/linuxkit/src/cmd/linuxkit/moby"
	"github.com/linuxkit/linuxkit/src/cmd/linuxkit/util"
)

// Contains fields settable in the build.yml
type pkgInfo struct {
	Image        string            `yaml:"image"`
	Org          string            `yaml:"org"`
	Arches       []string          `yaml:"arches"`
	ExtraSources []string          `yaml:"extra-sources"`
	GitRepo      string            `yaml:"gitrepo"` // ??
	Network      bool              `yaml:"network"`
	DisableCache bool              `yaml:"disable-cache"`
	Config       *moby.ImageConfig `yaml:"config"`
	Depends      struct {
		DockerImages struct {
			TargetDir string   `yaml:"target-dir"`
			Target    string   `yaml:"target"`
			FromFile  string   `yaml:"from-file"`
			List      []string `yaml:"list"`
		} `yaml:"docker-images"`
	} `yaml:"depends"`
}

// Specifies the source directory for a package and their destination in the build context.
type pkgSource struct {
	src string
	dst string
}

// Pkg encapsulates information about a package's source
type Pkg struct {
	// These correspond to pkgInfo fields
	image         string
	org           string
	arches        []string
	sources       []pkgSource
	gitRepo       string
	network       bool
	trust         bool
	cache         bool
	config        *moby.ImageConfig
	dockerDepends dockerDepends

	// Internal state
	path       string
	hash       string
	dirty      bool
	commitHash string
	git        *git
}

// NewFromCLI creates a Pkg from a set of CLI arguments. Calls fs.Parse()
func NewFromCLI(fs *flag.FlagSet, args ...string) (Pkg, error) {
	// Defaults
	pi := pkgInfo{
		Org:          "linuxkit",
		Arches:       []string{"amd64", "arm64", "s390x"},
		GitRepo:      "https://github.com/linuxkit/linuxkit",
		Network:      false,
		DisableCache: false,
	}

	// TODO(ijc) look for "$(git rev-parse --show-toplevel)/.build-defaults.yml"?

	// Ideally want to look at every directory from root to `pkg`
	// for this file but might be tricky to arrange ordering-wise.

	// These override fields in pi below, bools are in both forms to allow user overrides in either direction
	argDisableCache := fs.Bool("disable-cache", pi.DisableCache, "Disable build cache")
	argEnableCache := fs.Bool("enable-cache", !pi.DisableCache, "Enable build cache")
	argNoNetwork := fs.Bool("nonetwork", !pi.Network, "Disallow network use during build")
	argNetwork := fs.Bool("network", pi.Network, "Allow network use during build")

	argOrg := fs.String("org", pi.Org, "Override the hub org")

	// Other arguments
	var buildYML, hash, hashCommit, hashPath string
	var dirty, devMode bool
	fs.StringVar(&buildYML, "build-yml", "build.yml", "Override the name of the yml file")
	fs.StringVar(&hash, "hash", "", "Override the image hash (default is to query git for the package's tree-sh)")
	fs.StringVar(&hashCommit, "hash-commit", "HEAD", "Override the git commit to use for the hash")
	fs.StringVar(&hashPath, "hash-path", "", "Override the directory to use for the image hash, must be a parent of the package dir (default is to use the package dir)")
	fs.BoolVar(&dirty, "force-dirty", false, "Force the pkg to be considered dirty")
	fs.BoolVar(&devMode, "dev", false, "Force org and hash to $USER and \"dev\" respectively")

	fs.Parse(args)

	if fs.NArg() < 1 {
		return Pkg{}, fmt.Errorf("A pkg directory is required")
	}
	if fs.NArg() > 1 {
		return Pkg{}, fmt.Errorf("Unknown extra arguments given: %s", fs.Args()[1:])
	}

	pkg := fs.Arg(0)
	pkgPath, err := filepath.Abs(pkg)
	if err != nil {
		return Pkg{}, err
	}

	if hashPath == "" {
		hashPath = pkgPath
	} else {
		hashPath, err = filepath.Abs(hashPath)
		if err != nil {
			return Pkg{}, err
		}

		if !strings.HasPrefix(pkgPath, hashPath) {
			return Pkg{}, fmt.Errorf("Hash path is not a prefix of the package path")
		}

		// TODO(ijc) pkgPath and hashPath really ought to be in the same git tree too...
	}

	b, err := ioutil.ReadFile(filepath.Join(pkgPath, buildYML))
	if err != nil {
		return Pkg{}, err
	}
	if err := yaml.Unmarshal(b, &pi); err != nil {
		return Pkg{}, err
	}

	if pi.Image == "" {
		return Pkg{}, fmt.Errorf("Image field is required")
	}

	dockerDepends, err := newDockerDepends(pkgPath, &pi)
	if err != nil {
		return Pkg{}, err
	}

	if devMode {
		// If --org is also used then this will be overwritten
		// by argOrg when we iterate over the provided options
		// in the fs.Visit block below.
		pi.Org = os.Getenv("USER")
		if hash == "" {
			hash = "dev"
		}
	}

	// Go's flag package provides no way to see if a flag was set
	// apart from Visit which iterates over only those which were
	// set.
	fs.Visit(func(f *flag.Flag) {
		switch f.Name {
		case "disable-cache":
			pi.DisableCache = *argDisableCache
		case "enable-cache":
			pi.DisableCache = !*argEnableCache
		case "network":
			pi.Network = *argNetwork
		case "nonetwork":
			pi.Network = !*argNoNetwork
		case "org":
			pi.Org = *argOrg
		}
	})

	var srcHashes string
	sources := []pkgSource{{src: pkgPath, dst: "/"}}

	for _, source := range pi.ExtraSources {
		tmp := strings.Split(source, ":")
		if len(tmp) != 2 {
			return Pkg{}, fmt.Errorf("Bad source format in %s", source)
		}
		srcPath := filepath.Clean(tmp[0]) // Should work with windows paths
		dstPath := path.Clean(tmp[1])     // 'path' here because this should be a Unix path

		if !filepath.IsAbs(srcPath) {
			srcPath = filepath.Join(pkgPath, srcPath)
		}

		g, err := newGit(srcPath)
		if err != nil {
			return Pkg{}, err
		}
		if g == nil {
			return Pkg{}, fmt.Errorf("Source %s not in a git repository", srcPath)
		}
		h, err := g.treeHash(srcPath, hashCommit)
		if err != nil {
			return Pkg{}, err
		}

		srcHashes += h
		sources = append(sources, pkgSource{src: srcPath, dst: dstPath})
	}

	git, err := newGit(pkgPath)
	if err != nil {
		return Pkg{}, err
	}

	if git != nil {
		gitDirty, err := git.isDirty(hashPath, hashCommit)
		if err != nil {
			return Pkg{}, err
		}

		dirty = dirty || gitDirty

		if hash == "" {
			if hash, err = git.treeHash(hashPath, hashCommit); err != nil {
				return Pkg{}, err
			}

			if srcHashes != "" {
				hash += srcHashes
				hash = fmt.Sprintf("%x", sha1.Sum([]byte(hash)))
			}

			if dirty {
				hash += "-dirty"
			}
		}
	}

	return Pkg{
		image:         pi.Image,
		org:           pi.Org,
		hash:          hash,
		commitHash:    hashCommit,
		arches:        pi.Arches,
		sources:       sources,
		gitRepo:       pi.GitRepo,
		network:       pi.Network,
		cache:         !pi.DisableCache,
		config:        pi.Config,
		dockerDepends: dockerDepends,
		dirty:         dirty,
		path:          pkgPath,
		git:           git,
	}, nil
}

// Hash returns the hash of the package
func (p Pkg) Hash() string {
	return p.hash
}

// ReleaseTag returns the tag to use for a particular release of the package
func (p Pkg) ReleaseTag(release string) (string, error) {
	if release == "" {
		return "", fmt.Errorf("A release tag is required")
	}
	if p.dirty {
		return "", fmt.Errorf("Cannot release a dirty package")
	}
	tag := p.org + "/" + p.image + ":" + release
	return tag, nil
}

// Tag returns the tag to use for the package
func (p Pkg) Tag() string {
	t := p.hash
	if t == "" {
		t = "latest"
	}
	return p.org + "/" + p.image + ":" + t
}

func (p Pkg) FullTag() string {
	return util.ReferenceExpand(p.Tag())
}

// TrustEnabled returns true if trust is enabled
func (p Pkg) TrustEnabled() bool {
	return p.trust
}

// Arches which arches this can be built for
func (p Pkg) Arches() []string {
	return p.arches
}

func (p Pkg) archSupported(want string) bool {
	for _, supp := range p.arches {
		if supp == want {
			return true
		}
	}
	return false
}

func (p Pkg) cleanForBuild() error {
	if p.commitHash != "HEAD" {
		return fmt.Errorf("Cannot build from commit hash != HEAD")
	}
	return nil
}

// Expands path from relative to abs against base, ensuring the result is within base, but is not base itself. Field is the fieldname, to be used for constructing the error.
func makeAbsSubpath(field, base, path string) (string, error) {
	if path == "" {
		return "", nil
	}

	if filepath.IsAbs(path) {
		return "", fmt.Errorf("%s must be relative to package directory", field)
	}

	p, err := filepath.Abs(filepath.Join(base, path))
	if err != nil {
		return "", err
	}

	if p == base {
		return "", fmt.Errorf("%s must not be exactly the package directory", field)
	}

	if !filepath.HasPrefix(p, base) {
		return "", fmt.Errorf("%s must be within package directory", field)
	}

	return p, nil
}
<commit_msg>pkglib: Add missing comment to FullTag<commit_after>package pkglib

import (
	"crypto/sha1"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"strings"

	"gopkg.in/yaml.v2"

	"github.com/linuxkit/linuxkit/src/cmd/linuxkit/moby"
	"github.com/linuxkit/linuxkit/src/cmd/linuxkit/util"
)

// Contains fields settable in the build.yml
type pkgInfo struct {
	Image        string            `yaml:"image"`
	Org          string            `yaml:"org"`
	Arches       []string          `yaml:"arches"`
	ExtraSources []string          `yaml:"extra-sources"`
	GitRepo      string            `yaml:"gitrepo"` // ??
	Network      bool              `yaml:"network"`
	DisableCache bool              `yaml:"disable-cache"`
	Config       *moby.ImageConfig `yaml:"config"`
	Depends      struct {
		DockerImages struct {
			TargetDir string   `yaml:"target-dir"`
			Target    string   `yaml:"target"`
			FromFile  string   `yaml:"from-file"`
			List      []string `yaml:"list"`
		} `yaml:"docker-images"`
	} `yaml:"depends"`
}

// Specifies the source directory for a package and their destination in the build context.
type pkgSource struct {
	src string
	dst string
}

// Pkg encapsulates information about a package's source
type Pkg struct {
	// These correspond to pkgInfo fields
	image         string
	org           string
	arches        []string
	sources       []pkgSource
	gitRepo       string
	network       bool
	trust         bool
	cache         bool
	config        *moby.ImageConfig
	dockerDepends dockerDepends

	// Internal state
	path       string
	hash       string
	dirty      bool
	commitHash string
	git        *git
}

// NewFromCLI creates a Pkg from a set of CLI arguments. Calls fs.Parse()
func NewFromCLI(fs *flag.FlagSet, args ...string) (Pkg, error) {
	// Defaults
	pi := pkgInfo{
		Org:          "linuxkit",
		Arches:       []string{"amd64", "arm64", "s390x"},
		GitRepo:      "https://github.com/linuxkit/linuxkit",
		Network:      false,
		DisableCache: false,
	}

	// TODO(ijc) look for "$(git rev-parse --show-toplevel)/.build-defaults.yml"?

	// Ideally want to look at every directory from root to `pkg`
	// for this file but might be tricky to arrange ordering-wise.

	// These override fields in pi below, bools are in both forms to allow user overrides in either direction
	argDisableCache := fs.Bool("disable-cache", pi.DisableCache, "Disable build cache")
	argEnableCache := fs.Bool("enable-cache", !pi.DisableCache, "Enable build cache")
	argNoNetwork := fs.Bool("nonetwork", !pi.Network, "Disallow network use during build")
	argNetwork := fs.Bool("network", pi.Network, "Allow network use during build")

	argOrg := fs.String("org", pi.Org, "Override the hub org")

	// Other arguments
	var buildYML, hash, hashCommit, hashPath string
	var dirty, devMode bool
	fs.StringVar(&buildYML, "build-yml", "build.yml", "Override the name of the yml file")
	fs.StringVar(&hash, "hash", "", "Override the image hash (default is to query git for the package's tree-sh)")
	fs.StringVar(&hashCommit, "hash-commit", "HEAD", "Override the git commit to use for the hash")
	fs.StringVar(&hashPath, "hash-path", "", "Override the directory to use for the image hash, must be a parent of the package dir (default is to use the package dir)")
	fs.BoolVar(&dirty, "force-dirty", false, "Force the pkg to be considered dirty")
	fs.BoolVar(&devMode, "dev", false, "Force org and hash to $USER and \"dev\" respectively")

	fs.Parse(args)

	if fs.NArg() < 1 {
		return Pkg{}, fmt.Errorf("A pkg directory is required")
	}
	if fs.NArg() > 1 {
		return Pkg{}, fmt.Errorf("Unknown extra arguments given: %s", fs.Args()[1:])
	}

	pkg := fs.Arg(0)
	pkgPath, err := filepath.Abs(pkg)
	if err != nil {
		return Pkg{}, err
	}

	if hashPath == "" {
		hashPath = pkgPath
	} else {
		hashPath, err = filepath.Abs(hashPath)
		if err != nil {
			return Pkg{}, err
		}

		if !strings.HasPrefix(pkgPath, hashPath) {
			return Pkg{}, fmt.Errorf("Hash path is not a prefix of the package path")
		}

		// TODO(ijc) pkgPath and hashPath really ought to be in the same git tree too...
	}

	b, err := ioutil.ReadFile(filepath.Join(pkgPath, buildYML))
	if err != nil {
		return Pkg{}, err
	}
	if err := yaml.Unmarshal(b, &pi); err != nil {
		return Pkg{}, err
	}

	if pi.Image == "" {
		return Pkg{}, fmt.Errorf("Image field is required")
	}

	dockerDepends, err := newDockerDepends(pkgPath, &pi)
	if err != nil {
		return Pkg{}, err
	}

	if devMode {
		// If --org is also used then this will be overwritten
		// by argOrg when we iterate over the provided options
		// in the fs.Visit block below.
		pi.Org = os.Getenv("USER")
		if hash == "" {
			hash = "dev"
		}
	}

	// Go's flag package provides no way to see if a flag was set
	// apart from Visit which iterates over only those which were
	// set.
	fs.Visit(func(f *flag.Flag) {
		switch f.Name {
		case "disable-cache":
			pi.DisableCache = *argDisableCache
		case "enable-cache":
			pi.DisableCache = !*argEnableCache
		case "network":
			pi.Network = *argNetwork
		case "nonetwork":
			pi.Network = !*argNoNetwork
		case "org":
			pi.Org = *argOrg
		}
	})

	var srcHashes string
	sources := []pkgSource{{src: pkgPath, dst: "/"}}

	for _, source := range pi.ExtraSources {
		tmp := strings.Split(source, ":")
		if len(tmp) != 2 {
			return Pkg{}, fmt.Errorf("Bad source format in %s", source)
		}
		srcPath := filepath.Clean(tmp[0]) // Should work with windows paths
		dstPath := path.Clean(tmp[1])     // 'path' here because this should be a Unix path

		if !filepath.IsAbs(srcPath) {
			srcPath = filepath.Join(pkgPath, srcPath)
		}

		g, err := newGit(srcPath)
		if err != nil {
			return Pkg{}, err
		}
		if g == nil {
			return Pkg{}, fmt.Errorf("Source %s not in a git repository", srcPath)
		}
		h, err := g.treeHash(srcPath, hashCommit)
		if err != nil {
			return Pkg{}, err
		}

		srcHashes += h
		sources = append(sources, pkgSource{src: srcPath, dst: dstPath})
	}

	git, err := newGit(pkgPath)
	if err != nil {
		return Pkg{}, err
	}

	if git != nil {
		gitDirty, err := git.isDirty(hashPath, hashCommit)
		if err != nil {
			return Pkg{}, err
		}

		dirty = dirty || gitDirty

		if hash == "" {
			if hash, err = git.treeHash(hashPath, hashCommit); err != nil {
				return Pkg{}, err
			}

			if srcHashes != "" {
				hash += srcHashes
				hash = fmt.Sprintf("%x", sha1.Sum([]byte(hash)))
			}

			if dirty {
				hash += "-dirty"
			}
		}
	}

	return Pkg{
		image:         pi.Image,
		org:           pi.Org,
		hash:          hash,
		commitHash:    hashCommit,
		arches:        pi.Arches,
		sources:       sources,
		gitRepo:       pi.GitRepo,
		network:       pi.Network,
		cache:         !pi.DisableCache,
		config:        pi.Config,
		dockerDepends: dockerDepends,
		dirty:         dirty,
		path:          pkgPath,
		git:           git,
	}, nil
}

// Hash returns the hash of the package
func (p Pkg) Hash() string {
	return p.hash
}

// ReleaseTag returns the tag to use for a particular release of the package
func (p Pkg) ReleaseTag(release string) (string, error) {
	if release == "" {
		return "", fmt.Errorf("A release tag is required")
	}
	if p.dirty {
		return "", fmt.Errorf("Cannot release a dirty package")
	}
	tag := p.org + "/" + p.image + ":" + release
	return tag, nil
}

// Tag returns the tag to use for the package
func (p Pkg) Tag() string {
	t := p.hash
	if t == "" {
		t = "latest"
	}
	return p.org + "/" + p.image + ":" + t
}

// FullTag returns a reference expanded tag
func (p Pkg) FullTag() string {
	return util.ReferenceExpand(p.Tag())
}

// TrustEnabled returns true if trust is enabled
func (p Pkg) TrustEnabled() bool {
	return p.trust
}

// Arches which arches this can be built for
func (p Pkg) Arches() []string {
	return p.arches
}

func (p Pkg) archSupported(want string) bool {
	for _, supp := range p.arches {
		if supp == want {
			return true
		}
	}
	return false
}

func (p Pkg) cleanForBuild() error {
	if p.commitHash != "HEAD" {
		return fmt.Errorf("Cannot build from commit hash != HEAD")
	}
	return nil
}

// Expands path from relative to abs against base, ensuring the result is within base, but is not base itself. Field is the fieldname, to be used for constructing the error.
func makeAbsSubpath(field, base, path string) (string, error) {
	if path == "" {
		return "", nil
	}

	if filepath.IsAbs(path) {
		return "", fmt.Errorf("%s must be relative to package directory", field)
	}

	p, err := filepath.Abs(filepath.Join(base, path))
	if err != nil {
		return "", err
	}

	if p == base {
		return "", fmt.Errorf("%s must not be exactly the package directory", field)
	}

	if !filepath.HasPrefix(p, base) {
		return "", fmt.Errorf("%s must be within package directory", field)
	}

	return p, nil
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"math/rand"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"os/signal"
	"path/filepath"
	"sync"
	"text/tabwriter"
	"time"

	"github.com/codegangsta/cli"
	"github.com/itsabot/abot/core"
	"github.com/itsabot/abot/core/log"
	"github.com/itsabot/abot/shared/datatypes"
)

var conf *core.PluginJSON

func main() {
	rand.Seed(time.Now().UnixNano())
	log.SetDebug(os.Getenv("ABOT_DEBUG") == "true")

	var err error
	conf, err = core.LoadConf()
	if err != nil {
		log.Fatal(err)
	}
	err = core.LoadEnvVars()
	if err != nil {
		log.Fatal(err)
	}

	app := cli.NewApp()
	app.Name = conf.Name
	app.Usage = conf.Description
	app.Version = conf.Version
	app.Commands = []cli.Command{
		{
			Name:    "server",
			Aliases: []string{"s"},
			Usage:   "run server",
			Action: func(c *cli.Context) {
				var err error
				if err = startServer(); err != nil {
					l := log.New("")
					l.SetFlags(0)
					l.Fatalf("could not start server\n%s", err)
				}
			},
		},
		{
			Name:    "plugin",
			Aliases: []string{"p"},
			Usage:   "manage and install plugins from plugins.json",
			Subcommands: []cli.Command{
				{
					Name:  "install",
					Usage: "download and install plugins listed in plugins.json",
					Action: func(c *cli.Context) {
						installPlugins()
					},
				},
				{
					Name:    "search",
					Aliases: []string{"s"},
					Usage:   "search plugins indexed on itsabot.org",
					Action: func(c *cli.Context) {
						l := log.New("")
						l.SetFlags(0)
						args := c.Args()
						if len(args) == 0 || len(args) > 2 {
							l.Fatal(errors.New(`usage: abot plugin search "{term}"`))
						}
						if err := searchPlugins(args.First()); err != nil {
							l.Fatalf("could not start console\n%s", err)
						}
					},
				},
				{
					Name:    "update",
					Aliases: []string{"u", "upgrade"},
					Usage:   "update and install plugins listed in plugins.json",
					Action: func(c *cli.Context) {
						updatePlugins()
					},
				},
			},
		},
		{
			Name:    "console",
			Aliases: []string{"c"},
			Usage:   "communicate with a running abot server",
			Action: func(c *cli.Context) {
				if err := startConsole(c); err != nil {
					l := log.New("")
					l.SetFlags(0)
					l.Fatalf("could not start console\n%s", err)
				}
			},
		},
	}
	app.Action = func(c *cli.Context) {
		cli.ShowAppHelp(c)
	}
	if err := app.Run(os.Args); err != nil {
		log.Fatal(err)
	}
}

// startServer initializes any clients that are needed, sets up routes, and
// boots plugins.
func startServer() error {
	hr, err := core.NewServer()
	if err != nil {
		return err
	}
	log.Info("started", conf.Name)
	if err = http.ListenAndServe(":"+os.Getenv("PORT"), hr); err != nil {
		return err
	}
	return nil
}

func searchPlugins(query string) error {
	byt, err := searchItsAbot(query)
	if err != nil {
		return err
	}
	if err = outputPluginResults(os.Stdout, byt); err != nil {
		return err
	}
	return nil
}

func outputPluginResults(w io.Writer, byt []byte) error {
	var results []struct {
		ID            uint64
		Name          string
		Username      string
		Description   string
		Path          string
		Readme        string
		DownloadCount uint64
		Similarity    float64
	}
	if err := json.Unmarshal(byt, &results); err != nil {
		return err
	}
	writer := tabwriter.Writer{}
	writer.Init(w, 0, 8, 1, '\t', 0)
	_, err := writer.Write([]byte("NAME\tDESCRIPTION\tUSERNAME\tDOWNLOADS\n"))
	if err != nil {
		return err
	}
	for _, result := range results {
		d := result.Description
		if len(result.Description) >= 30 {
			d = d[:27] + "..."
		}
		_, err = writer.Write([]byte(fmt.Sprintf("%s\t%s\t%s\t%d\n",
			result.Name, d, result.Username, result.DownloadCount)))
		if err != nil {
			return err
		}
	}
	return writer.Flush()
}

func searchItsAbot(q string) ([]byte, error) {
	u := fmt.Sprintf("https://www.itsabot.org/api/search.json?q=%s",
		url.QueryEscape(q))
	client := http.Client{Timeout: 10 * time.Second}
	res, err := client.Get(u)
	if err != nil {
		return nil, err
	}
	defer func() {
		if err := res.Body.Close(); err != nil {
			return
		}
	}()
	return ioutil.ReadAll(res.Body)
}

func startConsole(c *cli.Context) error {
	args := c.Args()
	if len(args) == 0 || len(args) >= 3 {
		return errors.New("usage: abot console {abotAddress} {userPhone}")
	}
	var addr, phone string
	if len(args) == 1 {
		addr = "localhost:" + os.Getenv("PORT")
		phone = args[0]
	} else if len(args) == 2 {
		addr = args[0]
		phone = args[1]
	}

	// Capture ^C interrupt to add a newline
	sig := make(chan os.Signal, 1)
	signal.Notify(sig, os.Interrupt)
	go func() {
		for range sig {
			fmt.Printf("\n")
			os.Exit(0)
		}
	}()

	body := struct {
		CMD        string
		FlexID     string
		FlexIDType dt.FlexIDType
	}{
		FlexID:     phone,
		FlexIDType: 2,
	}
	base := "http://" + addr
	scanner := bufio.NewScanner(os.Stdin)

	// Test connection
	req, err := http.NewRequest("GET", base, nil)
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	if err = resp.Body.Close(); err != nil {
		return err
	}
	fmt.Print("> ")

	// Handle each user input
	for scanner.Scan() {
		body.CMD = scanner.Text()
		byt, err := json.Marshal(body)
		if err != nil {
			return err
		}
		req, err := http.NewRequest("POST", base, bytes.NewBuffer(byt))
		if err != nil {
			return err
		}
		client := &http.Client{}
		resp, err := client.Do(req)
		if err != nil {
			return err
		}
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return err
		}
		if err = resp.Body.Close(); err != nil {
			return err
		}
		fmt.Println(string(body))
		fmt.Print("> ")
	}
	if err := scanner.Err(); err != nil {
		return err
	}
	return nil
}

func installPlugins() {
	l := log.New("")
	l.SetFlags(0)
	l.SetDebug(os.Getenv("ABOT_DEBUG") == "true")

	plugins := buildPluginFile(l)

	// Fetch all plugins
	l.Info("Fetching", len(plugins.Dependencies), "plugins...")
	outC, err := exec.
		Command("/bin/sh", "-c", "go get ./...").
		CombinedOutput()
	if err != nil {
		l.Info(string(outC))
		l.Fatal(err)
	}

	// Sync each of them to get dependencies
	var wg sync.WaitGroup
	wg.Add(len(plugins.Dependencies))
	rand.Seed(time.Now().UTC().UnixNano())
	for url, version := range plugins.Dependencies {
		go func(url, version string) {
			// Check out specific commit
			var outB []byte
			if version != "*" {
				l.Debug("checking out", url, "at", version)
				p := filepath.Join(os.Getenv("GOPATH"), "src",
					url)
				c := fmt.Sprintf("git -C %s checkout %s", p, version)
				outB, err = exec.
					Command("/bin/sh", "-c", c).
					CombinedOutput()
				if err != nil {
					l.Debug(string(outB))
					l.Fatal(err)
				}
			}

			// Anonymously increment the plugin's download count
			// at itsabot.org
			l.Debug("incrementing download count", url)
			p := struct{ URL string }{URL: url}
			outB, err = json.Marshal(p)
			if err != nil {
				l.Info("failed to build itsabot.org JSON.", err)
				wg.Done()
				return
			}
			var u string
			if len(os.Getenv("ITSABOT_URL")) > 0 {
				u = os.Getenv("ITSABOT_URL") + "/api/plugins.json"
			} else {
				u = "https://www.itsabot.org/api/plugins.json"
			}
			resp, errB := http.Post(u, "application/json",
				bytes.NewBuffer(outB))
			if errB != nil {
				l.Info("failed to update itsabot.org.", errB)
				wg.Done()
				return
			}
			defer func() {
				if errB = resp.Body.Close(); errB != nil {
					l.Fatal(errB)
				}
			}()
			if resp.StatusCode != 200 {
				l.Infof("WARN: %d - %s\n", resp.StatusCode,
					resp.Status)
			}
			wg.Done()
		}(url, version)
	}
	wg.Wait()

	// Ensure dependencies are still there with the latest checked out
	// versions, and install the plugins
	l.Info("Installing plugins...")
	outC, err = exec.
		Command("/bin/sh", "-c", "go get ./...").
		CombinedOutput()
	if err != nil {
		l.Info(string(outC))
		l.Fatal(err)
	}

	updateGlockfileAndInstall(l)
	l.Info("Success!")
}

func updatePlugins() {
	l := log.New("")
	l.SetFlags(0)
	l.SetDebug(os.Getenv("ABOT_DEBUG") == "true")

	plugins := buildPluginFile(l)

	l.Info("Updating plugins...")
	for path, version := range plugins.Dependencies {
		if version != "*" {
			continue
		}
		l.Infof("Updating %s...\n", path)
		outC, err := exec.
			Command("/bin/sh", "-c", "go get -u "+path).
			CombinedOutput()
		if err != nil {
			l.Info(string(outC))
			l.Fatal(err)
		}
	}

	updateGlockfileAndInstall(l)
	l.Info("Success!")
}

func updateGlockfileAndInstall(l *log.Logger) {
	outC, err := exec.
		Command("/bin/sh", "-c", `pwd | sed "s|$GOPATH/src/||"`).
		CombinedOutput()
	if err != nil {
		l.Info(string(outC))
		l.Fatal(err)
	}

	// Update plugin dependency versions in GLOCKFILE
	p := string(outC)
	outC, err = exec.
		Command("/bin/sh", "-c", "glock save "+p).
		CombinedOutput()
	if err != nil {
		l.Info(string(outC))
		l.Fatal(err)
	}

	outC, err = exec.
		Command("/bin/sh", "-c", "go install").
		CombinedOutput()
	if err != nil {
		l.Info(string(outC))
		l.Fatal(err)
	}
}

func buildPluginFile(l *log.Logger) *core.PluginJSON {
	plugins, err := core.LoadConf()
	if err != nil {
		l.Fatal(err)
	}

	// Create plugin.go file, truncate if exists
	fi, err := os.Create("plugins.go")
	if err != nil {
		l.Fatal(err)
	}
	defer func() {
		if err = fi.Close(); err != nil {
			l.Fatal(err)
		}
	}()

	// Insert _ imports
	s := "// This file is generated by `abot plugin install`. Do not edit.\n\n"
	s += "package main\n\nimport (\n"
	for url := range plugins.Dependencies {
		s += fmt.Sprintf("\t_ \"%s\"\n", url)
	}
	s += ")"
	_, err = fi.WriteString(s)
	if err != nil {
		l.Fatal(err)
	}

	return plugins
}
<commit_msg>Allow https protocol in abot console<commit_after>package main

import (
	"bufio"
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"math/rand"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"os/signal"
	"path/filepath"
	"sync"
	"text/tabwriter"
	"time"

	"github.com/codegangsta/cli"
	"github.com/itsabot/abot/core"
	"github.com/itsabot/abot/core/log"
	"github.com/itsabot/abot/shared/datatypes"
)

var conf *core.PluginJSON

func main() {
	rand.Seed(time.Now().UnixNano())
	log.SetDebug(os.Getenv("ABOT_DEBUG") == "true")

	var err error
	conf, err = core.LoadConf()
	if err != nil {
		log.Fatal(err)
	}
	err = core.LoadEnvVars()
	if err != nil {
		log.Fatal(err)
	}

	app := cli.NewApp()
	app.Name = conf.Name
	app.Usage = conf.Description
	app.Version = conf.Version
	app.Commands = []cli.Command{
		{
			Name:    "server",
			Aliases: []string{"s"},
			Usage:   "run server",
			Action: func(c *cli.Context) {
				var err error
				if err = startServer(); err != nil {
					l := log.New("")
					l.SetFlags(0)
					l.Fatalf("could not start server\n%s", err)
				}
			},
		},
		{
			Name:    "plugin",
			Aliases: []string{"p"},
			Usage:   "manage and install plugins from plugins.json",
			Subcommands: []cli.Command{
				{
					Name:  "install",
					Usage: "download and install plugins listed in plugins.json",
					Action: func(c *cli.Context) {
						installPlugins()
					},
				},
				{
					Name:    "search",
					Aliases: []string{"s"},
					Usage:   "search plugins indexed on itsabot.org",
					Action: func(c *cli.Context) {
						l := log.New("")
						l.SetFlags(0)
						args := c.Args()
						if len(args) == 0 || len(args) > 2 {
							l.Fatal(errors.New(`usage: abot plugin search "{term}"`))
						}
						if err := searchPlugins(args.First()); err != nil {
							l.Fatalf("could not start console\n%s", err)
						}
					},
				},
				{
					Name:    "update",
					Aliases: []string{"u", "upgrade"},
					Usage:   "update and install plugins listed in plugins.json",
					Action: func(c *cli.Context) {
						updatePlugins()
					},
				},
			},
		},
		{
			Name:    "console",
			Aliases: []string{"c"},
			Usage:   "communicate with a running abot server",
			Action: func(c *cli.Context) {
				if err := startConsole(c); err != nil {
					l := log.New("")
					l.SetFlags(0)
					l.Fatalf("could not start console\n%s", err)
				}
			},
		},
	}
	app.Action = func(c *cli.Context) {
		cli.ShowAppHelp(c)
	}
	if err := app.Run(os.Args); err != nil {
		log.Fatal(err)
	}
}

// startServer initializes any clients that are needed, sets up routes, and
// boots plugins.
func startServer() error {
	hr, err := core.NewServer()
	if err != nil {
		return err
	}
	log.Info("started", conf.Name)
	if err = http.ListenAndServe(":"+os.Getenv("PORT"), hr); err != nil {
		return err
	}
	return nil
}

func searchPlugins(query string) error {
	byt, err := searchItsAbot(query)
	if err != nil {
		return err
	}
	if err = outputPluginResults(os.Stdout, byt); err != nil {
		return err
	}
	return nil
}

func outputPluginResults(w io.Writer, byt []byte) error {
	var results []struct {
		ID            uint64
		Name          string
		Username      string
		Description   string
		Path          string
		Readme        string
		DownloadCount uint64
		Similarity    float64
	}
	if err := json.Unmarshal(byt, &results); err != nil {
		return err
	}
	writer := tabwriter.Writer{}
	writer.Init(w, 0, 8, 1, '\t', 0)
	_, err := writer.Write([]byte("NAME\tDESCRIPTION\tUSERNAME\tDOWNLOADS\n"))
	if err != nil {
		return err
	}
	for _, result := range results {
		d := result.Description
		if len(result.Description) >= 30 {
			d = d[:27] + "..."
		}
		_, err = writer.Write([]byte(fmt.Sprintf("%s\t%s\t%s\t%d\n",
			result.Name, d, result.Username, result.DownloadCount)))
		if err != nil {
			return err
		}
	}
	return writer.Flush()
}

func searchItsAbot(q string) ([]byte, error) {
	u := fmt.Sprintf("https://www.itsabot.org/api/search.json?q=%s",
		url.QueryEscape(q))
	client := http.Client{Timeout: 10 * time.Second}
	res, err := client.Get(u)
	if err != nil {
		return nil, err
	}
	defer func() {
		if err := res.Body.Close(); err != nil {
			return
		}
	}()
	return ioutil.ReadAll(res.Body)
}

func startConsole(c *cli.Context) error {
	args := c.Args()
	if len(args) == 0 || len(args) >= 3 {
		return errors.New("usage: abot console {abotAddress} {userPhone}")
	}
	var addr, phone string
	if len(args) == 1 {
		addr = "http://localhost:" + os.Getenv("PORT")
		phone = args[0]
	} else if len(args) == 2 {
		addr = args[0]
		phone = args[1]
	}

	// Capture ^C interrupt to add a newline
	sig := make(chan os.Signal, 1)
	signal.Notify(sig, os.Interrupt)
	go func() {
		for range sig {
			fmt.Printf("\n")
			os.Exit(0)
		}
	}()

	body := struct {
		CMD        string
		FlexID     string
		FlexIDType dt.FlexIDType
	}{
		FlexID:     phone,
		FlexIDType: 2,
	}
	scanner := bufio.NewScanner(os.Stdin)

	// Test connection
	req, err := http.NewRequest("GET", addr, nil)
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	if err = resp.Body.Close(); err != nil {
		return err
	}
	fmt.Print("> ")

	// Handle each user input
	for scanner.Scan() {
		body.CMD = scanner.Text()
		byt, err := json.Marshal(body)
		if err != nil {
			return err
		}
		req, err := http.NewRequest("POST", addr, bytes.NewBuffer(byt))
		if err != nil {
			return err
		}
		client := &http.Client{}
		resp, err := client.Do(req)
		if err != nil {
			return err
		}
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return err
		}
		if err = resp.Body.Close(); err != nil {
			return err
		}
		fmt.Println(string(body))
		fmt.Print("> ")
	}
	if err := scanner.Err(); err != nil {
		return err
	}
	return nil
}

func installPlugins() {
	l := log.New("")
	l.SetFlags(0)
	l.SetDebug(os.Getenv("ABOT_DEBUG") == "true")

	plugins := buildPluginFile(l)

	// Fetch all plugins
	l.Info("Fetching", len(plugins.Dependencies), "plugins...")
	outC, err := exec.
		Command("/bin/sh", "-c", "go get ./...").
		CombinedOutput()
	if err != nil {
		l.Info(string(outC))
		l.Fatal(err)
	}

	// Sync each of them to get dependencies
	var wg sync.WaitGroup
	wg.Add(len(plugins.Dependencies))
	rand.Seed(time.Now().UTC().UnixNano())
	for url, version := range plugins.Dependencies {
		go func(url, version string) {
			// Check out specific commit
			var outB []byte
			if version != "*" {
				l.Debug("checking out", url, "at", version)
				p := filepath.Join(os.Getenv("GOPATH"), "src",
					url)
				c := fmt.Sprintf("git -C %s checkout %s", p, version)
				outB, err = exec.
					Command("/bin/sh", "-c", c).
					CombinedOutput()
				if err != nil {
					l.Debug(string(outB))
					l.Fatal(err)
				}
			}

			// Anonymously increment the plugin's download count
			// at itsabot.org
			l.Debug("incrementing download count", url)
			p := struct{ URL string }{URL: url}
			outB, err = json.Marshal(p)
			if err != nil {
				l.Info("failed to build itsabot.org JSON.", err)
				wg.Done()
				return
			}
			var u string
			if len(os.Getenv("ITSABOT_URL")) > 0 {
				u = os.Getenv("ITSABOT_URL") + "/api/plugins.json"
			} else {
				u = "https://www.itsabot.org/api/plugins.json"
			}
			resp, errB := http.Post(u, "application/json",
				bytes.NewBuffer(outB))
			if errB != nil {
				l.Info("failed to update itsabot.org.", errB)
				wg.Done()
				return
			}
			defer func() {
				if errB = resp.Body.Close(); errB != nil {
					l.Fatal(errB)
				}
			}()
			if resp.StatusCode != 200 {
				l.Infof("WARN: %d - %s\n", resp.StatusCode,
					resp.Status)
			}
			wg.Done()
		}(url, version)
	}
	wg.Wait()

	// Ensure dependencies are still there with the latest checked out
	// versions, and install the plugins
	l.Info("Installing plugins...")
	outC, err = exec.
		Command("/bin/sh", "-c", "go get ./...").
		CombinedOutput()
	if err != nil {
		l.Info(string(outC))
		l.Fatal(err)
	}

	updateGlockfileAndInstall(l)
	l.Info("Success!")
}

func updatePlugins() {
	l := log.New("")
	l.SetFlags(0)
	l.SetDebug(os.Getenv("ABOT_DEBUG") == "true")

	plugins := buildPluginFile(l)

	l.Info("Updating plugins...")
	for path, version := range plugins.Dependencies {
		if version != "*" {
			continue
		}
		l.Infof("Updating %s...\n", path)
		outC, err := exec.
			Command("/bin/sh", "-c", "go get -u "+path).
			CombinedOutput()
		if err != nil {
			l.Info(string(outC))
			l.Fatal(err)
		}
	}

	updateGlockfileAndInstall(l)
	l.Info("Success!")
}

func updateGlockfileAndInstall(l *log.Logger) {
	outC, err := exec.
		Command("/bin/sh", "-c", `pwd | sed "s|$GOPATH/src/||"`).
		CombinedOutput()
	if err != nil {
		l.Info(string(outC))
		l.Fatal(err)
	}

	// Update plugin dependency versions in GLOCKFILE
	p := string(outC)
	outC, err = exec.
		Command("/bin/sh", "-c", "glock save "+p).
		CombinedOutput()
	if err != nil {
		l.Info(string(outC))
		l.Fatal(err)
	}

	outC, err = exec.
		Command("/bin/sh", "-c", "go install").
		CombinedOutput()
	if err != nil {
		l.Info(string(outC))
		l.Fatal(err)
	}
}

func buildPluginFile(l *log.Logger) *core.PluginJSON {
	plugins, err := core.LoadConf()
	if err != nil {
		l.Fatal(err)
	}

	// Create plugin.go file, truncate if exists
	fi, err := os.Create("plugins.go")
	if err != nil {
		l.Fatal(err)
	}
	defer func() {
		if err = fi.Close(); err != nil {
			l.Fatal(err)
		}
	}()

	// Insert _ imports
	s := "// This file is generated by `abot plugin install`. Do not edit.\n\n"
	s += "package main\n\nimport (\n"
	for url := range plugins.Dependencies {
		s += fmt.Sprintf("\t_ \"%s\"\n", url)
	}
	s += ")"
	_, err = fi.WriteString(s)
	if err != nil {
		l.Fatal(err)
	}

	return plugins
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"github.com/fadion/aria/interpreter"
	"github.com/fadion/aria/lexer"
	"github.com/fadion/aria/parser"
	"github.com/fadion/aria/reader"
	"github.com/fadion/aria/reporter"
	"github.com/fatih/color"
	"github.com/urfave/cli"
	"io/ioutil"
	"os"
)

func main() {
	app := cli.NewApp()
	app.Name = "aria"
	app.Usage = "an expressive, noiseless, interpreted toy language"
	app.Authors = []cli.Author{{
		Name:  "Fadion Dashi",
		Email: "jonidashi@gmail.com",
	}}
	app.Version = "0.1.0"

	app.Commands = []cli.Command{
		{
			Name:  "run",
			Usage: "Run an Aria source file",
			Action: func(c *cli.Context) error {
				if len(c.Args()) != 1 {
					color.Red("Run expects a source file as argument.")
				}

				file := c.Args()[0]
				source, err := ioutil.ReadFile(file)
				if err != nil {
					color.Red("Couldn't read '%s'", file)
					return nil
				}

				lex := lexer.New(reader.New(source))
				if reporter.HasErrors() {
					printErrors()
					return nil
				}

				parse := parser.New(lex)
				program := parse.Parse()
				if reporter.HasErrors() {
					printErrors()
					return nil
				}

				runner := interpreter.New()
				runner.Interpret(program, interpreter.NewScope())
				if reporter.HasErrors() {
					printErrors()
					return nil
				}

				return nil
			},
		},
		{
			Name:  "repl",
			Usage: "Start the interactive repl",
			Action: func(c *cli.Context) error {
				input := bufio.NewReader(os.Stdin)
				color.Yellow(`    _   ___ ___   _
   /_\ | _ \_ _| /_\
  / _ \|   /| | / _ \
 /_/ \_\_|_\___/_/ \_\
 `)
				color.White("Close by pressing CTRL+C")
				fmt.Println()

				scope := interpreter.NewScope()

				for {
					color.Set(color.FgWhite)
					fmt.Print(">> ")
					color.Unset()

					source, _ := input.ReadBytes('\n')
					lex := lexer.New(reader.New(source))
					if reporter.HasErrors() {
						printErrors()
						continue
					}

					parse := parser.New(lex)
					program := parse.Parse()
					if reporter.HasErrors() {
						printErrors()
						continue
					}

					runner := interpreter.New()
					object := runner.Interpret(program, scope)
					if reporter.HasErrors() {
						printErrors()
						continue
					}

					if object != nil {
						fmt.Println(object.Inspect())
					}
				}
			},
		},
	}

	app.CommandNotFound = func(ctx *cli.Context, command string) {
		fmt.Fprintf(ctx.App.Writer, "Command %q doesn't exist.\n", command)
	}

	app.Run(os.Args)
}

func printErrors() {
	color.White("Oops, found some errors:")
	for _, v := range reporter.GetErrors() {
		color.Red(v)
	}
	reporter.ClearErrors()
}
<commit_msg>Update to version 0.2.0<commit_after>package main

import (
	"bufio"
	"fmt"
	"github.com/fadion/aria/interpreter"
	"github.com/fadion/aria/lexer"
	"github.com/fadion/aria/parser"
	"github.com/fadion/aria/reader"
	"github.com/fadion/aria/reporter"
	"github.com/fatih/color"
	"github.com/urfave/cli"
	"io/ioutil"
	"os"
)

func main() {
	app := cli.NewApp()
	app.Name = "aria"
	app.Usage = "an expressive, noiseless, interpreted toy language"
	app.Authors = []cli.Author{{
		Name:  "Fadion Dashi",
		Email: "jonidashi@gmail.com",
	}}
	app.Version = "0.2.0"

	app.Commands = []cli.Command{
		{
			Name:  "run",
			Usage: "Run an Aria source file",
			Action: func(c *cli.Context) error {
				if len(c.Args()) != 1 {
					color.Red("Run expects a source file as argument.")
				}

				file := c.Args()[0]
				source, err := ioutil.ReadFile(file)
				if err != nil {
					color.Red("Couldn't read '%s'", file)
					return nil
				}

				lex := lexer.New(reader.New(source))
				if reporter.HasErrors() {
					printErrors()
					return nil
				}

				parse := parser.New(lex)
				program := parse.Parse()
				if reporter.HasErrors() {
					printErrors()
					return nil
				}

				runner := interpreter.New()
				runner.Interpret(program, interpreter.NewScope())
				if reporter.HasErrors() {
					printErrors()
					return nil
				}

				return nil
			},
		},
		{
			Name:  "repl",
			Usage: "Start the interactive repl",
			Action: func(c *cli.Context) error {
				input := bufio.NewReader(os.Stdin)
				color.Yellow(`    _   ___ ___   _
   /_\ | _ \_ _| /_\
  / _ \|   /| | / _ \
 /_/ \_\_|_\___/_/ \_\
 `)
				color.White("Close by pressing CTRL+C")
				fmt.Println()

				scope := interpreter.NewScope()

				for {
					color.Set(color.FgWhite)
					fmt.Print(">> ")
					color.Unset()

					source, _ := input.ReadBytes('\n')
					lex := lexer.New(reader.New(source))
					if reporter.HasErrors() {
						printErrors()
						continue
					}

					parse := parser.New(lex)
					program := parse.Parse()
					if reporter.HasErrors() {
						printErrors()
						continue
					}

					runner := interpreter.New()
					object := runner.Interpret(program, scope)
					if reporter.HasErrors() {
						printErrors()
						continue
					}

					if object != nil {
						fmt.Println(object.Inspect())
					}
				}
			},
		},
	}

	app.CommandNotFound = func(ctx *cli.Context, command string) {
		fmt.Fprintf(ctx.App.Writer, "Command %q doesn't exist.\n", command)
	}

	app.Run(os.Args)
}

func printErrors() {
	color.White("Oops, found some errors:")
	for _, v := range reporter.GetErrors() {
		color.Red(v)
	}
	reporter.ClearErrors()
}
<|endoftext|>


<commit_before>package kit

import (
	"fmt"
	"os"
	"time"

	jwt "github.com/dgrijalva/jwt-go"
)

var (
	jwtSigningMethod = jwt.SigningMethodHS256
	jwtSecret        = "JWT_SECRET"
)

const (
	JWT_KEY = "JWT_SECRET"
)

func init() {
	if s := os.Getenv(JWT_KEY); s != "" {
		jwtSecret = s
	}
}
func NewToken(m map[string]interface{}) (string, error) {
	claims := jwt.MapClaims{
		"iss": "account",
		"aud": "epayjan",
		"nbf": time.Now().Unix(),
		"exp": time.Now().Add(time.Hour * 24 * 3).Unix(),
	}
	for k, v := range m {
		claims[k] = v
	}
	return jwt.NewWithClaims(jwtSigningMethod, claims).SignedString([]byte(jwtSecret))
}

func Renew(token string) (string, error) {
	claim, err := Extract(token)
	if err != nil {
		return "", err
	}
	claim["nbf"] = time.Now().Unix()
	claim["exp"] = time.Now().Add(time.Hour * 24 * 3).Unix()
	return jwt.NewWithClaims(jwtSigningMethod, claim).SignedString([]byte(jwtSecret))
}

func EditPayload(token string, m map[string]interface{}) (string, error) {
	claimInfo, err := Extract(token)
	if err != nil {
		return "", err
	}

	for k, v := range m {
		claimInfo[k] = v
	}

	return jwt.NewWithClaims(jwtSigningMethod, claimInfo).SignedString([]byte(jwtSecret))
}

func Extract(token string) (jwt.MapClaims, error) {
	if token == "" {
		return nil, fmt.Errorf("Required authorization token not found")
	}

	parsedToken, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) { return []byte(jwtSecret), nil })
	if err != nil {
		return nil, fmt.Errorf("Error parsing token: %v", err)
	}

	if jwtSigningMethod != nil && jwtSigningMethod.Alg() != parsedToken.Header["alg"] {
		return nil, fmt.Errorf("Expected %s signing method but token specified %s",
			jwtSigningMethod.Alg(),
			parsedToken.Header["alg"])
	}

	if !parsedToken.Valid {
		return nil, fmt.Errorf("Token is invalid")
	}

	claimInfo, ok := parsedToken.Claims.(jwt.MapClaims)
	if !ok {
		return nil, fmt.Errorf("invalid token")
	}
	return claimInfo, nil
}
<commit_msg>no reason<commit_after>package kit

import (
	"fmt"
	"os"
	"time"

	jwt "github.com/dgrijalva/jwt-go"
)

var (
	jwtSigningMethod = jwt.SigningMethodHS256
	jwtSecret        = "JWT_SECRET"
)

const (
	JWT_KEY = "JWT_SECRET"
)

func init() {
	if s := os.Getenv(JWT_KEY); s != "" {
		jwtSecret = s
	}
}
func NewToken(m map[string]interface{}) (string, error) {
	claims := jwt.MapClaims{
		"iss": "account",
		"aud": "kitauth",
		"nbf": time.Now().Unix(),
		"exp": time.Now().Add(time.Hour * 24 * 3).Unix(),
	}
	for k, v := range m {
		claims[k] = v
	}
	return jwt.NewWithClaims(jwtSigningMethod, claims).SignedString([]byte(jwtSecret))
}

func Renew(token string) (string, error) {
	claim, err := Extract(token)
	if err != nil {
		return "", err
	}
	claim["nbf"] = time.Now().Unix()
	claim["exp"] = time.Now().Add(time.Hour * 24 * 3).Unix()
	return jwt.NewWithClaims(jwtSigningMethod, claim).SignedString([]byte(jwtSecret))
}

func EditPayload(token string, m map[string]interface{}) (string, error) {
	claimInfo, err := Extract(token)
	if err != nil {
		return "", err
	}

	for k, v := range m {
		claimInfo[k] = v
	}

	return jwt.NewWithClaims(jwtSigningMethod, claimInfo).SignedString([]byte(jwtSecret))
}

func Extract(token string) (jwt.MapClaims, error) {
	if token == "" {
		return nil, fmt.Errorf("Required authorization token not found")
	}

	parsedToken, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) { return []byte(jwtSecret), nil })
	if err != nil {
		return nil, fmt.Errorf("Error parsing token: %v", err)
	}

	if jwtSigningMethod != nil && jwtSigningMethod.Alg() != parsedToken.Header["alg"] {
		return nil, fmt.Errorf("Expected %s signing method but token specified %s",
			jwtSigningMethod.Alg(),
			parsedToken.Header["alg"])
	}

	if !parsedToken.Valid {
		return nil, fmt.Errorf("Token is invalid")
	}

	claimInfo, ok := parsedToken.Claims.(jwt.MapClaims)
	if !ok {
		return nil, fmt.Errorf("invalid token")
	}
	return claimInfo, nil
}
<|endoftext|>


<commit_before>// Package login2 provides sign in and sign up by oauth2 and email and password.
// Inspired in omniauth and devise gem
//
package login2

import (
	"encoding/json"
	"net/http"
	"os"
	"strconv"

	"code.google.com/p/go.crypto/bcrypt"
	"code.google.com/p/goauth2/oauth"
	"github.com/gorilla/mux"
	"github.com/gorilla/sessions"
)

var store = sessions.NewCookieStore([]byte(os.Getenv("SESSION_SECRET")))

// Provider is a oauth2 provider, like facebook or google
// Name is provider name, it's like a key, will can be use it after,
// the package only use it as a index.
// Key is oauth2 key
// Secret is oauth2 secret key
// RedirectURL is a url will config on provider
// TokenURL is a URL to get the token on provider
// AuthURL is a URL to auth user on provider
// UserInfoURL is a URL to get User Information on provider
// Scope is whats the scope your app wants
type Provider struct {
	Name        string
	Key         string
	Secret      string
	RedirectURL string
	TokenURL    string
	AuthURL     string
	UserInfoURL string
	Scope       string
}

// Internal auth config
type builderConfig struct {
	Auth        *oauth.Config
	UserInfoURL string
}

// URLS

type URLS struct {
	Redirect string
	SignIn   string
	SignUp   string
}

type Builder struct {
	Providers           map[string]*builderConfig
	UserSetupFn         func(provider string, user *User, rawResponde *http.Response)
	UserExistsFn        func(email string) bool
	UserCreateFn        func(email string, password string, request *http.Request) (int64, error)
	UserIdByEmail       func(email string) (int64, error)
	UserPasswordByEmail func(email string) (string, error)
	URLS                URLS
}

type User struct {
	ID     int64
	Email  string
	Link   string
	Name   string
	Gender string
	Locale string
}

func NewBuilder(userProviders []*Provider) *Builder {
	builder := new(Builder)
	builder.Providers = make(map[string]*builderConfig, 0)

	for _, p := range userProviders {
		config := &oauth.Config{
			ClientId:     p.Key,
			ClientSecret: p.Secret,
			RedirectURL:  p.RedirectURL,
			Scope:        p.Scope,
			AuthURL:      p.AuthURL,
			TokenURL:     p.TokenURL,
			TokenCache:   oauth.CacheFile("cache-" + p.Name + ".json"),
		}

		provider := new(builderConfig)
		provider.Auth = config
		provider.UserInfoURL = p.UserInfoURL

		builder.Providers[p.Name] = provider
	}

	return builder
}

func (b *Builder) Router(r *mux.Router) {
	for provider, _ := range b.Providers {
		r.HandleFunc("/auth/"+provider, b.OAuthAuthorize(provider)).Methods("GET")
	}

	r.HandleFunc("/auth/callback/{provider}", b.OAuthLogin()).Methods("GET")
	r.HandleFunc("/users/sign_in", b.SignIn()).Methods("POST")
	r.HandleFunc("/users/sign_up", b.SignUp()).Methods("POST")

}

// HTTP server

// OAuthAuthorize Send user to Authorize on provider
func (b *Builder) OAuthAuthorize(provider string) func(http.ResponseWriter, *http.Request) {
	config := b.Providers[provider]

	return func(w http.ResponseWriter, r *http.Request) {
		url := config.Auth.AuthCodeURL("")
		http.Redirect(w, r, url, http.StatusFound)
	}
}

func (b *Builder) OAuthLogin() func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, request *http.Request) {
		vars := mux.Vars(request)
		provider := vars["provider"]

		user := b.OAuthCallback(provider, request)

		b.login(request, w, strconv.FormatInt(user.ID, 10))
	}
}

// OAuthCallback receive code from provider and get user information on provider
func (b *Builder) OAuthCallback(provider string, r *http.Request) User {
	config := b.Providers[provider]
	code := r.FormValue("code")
	t := &oauth.Transport{Config: config.Auth}
	t.Exchange(code)
	responseAuth, _ := t.Client().Get(config.UserInfoURL)
	defer responseAuth.Body.Close()

	var user User
	decoder := json.NewDecoder(responseAuth.Body)
	err := decoder.Decode(&user)
	if err != nil {
		panic(err)
	}

	b.UserSetupFn(provider, &user, responseAuth)
	return user
}

// SignUp Hanlder create and login user on database and redirecto to RedirectURL
func (b *Builder) SignUp() func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, request *http.Request) {
		email := request.FormValue("email")
		password := request.FormValue("password")
		hpassword := generatePassword(password)

		userID, err := b.UserCreateFn(email, hpassword, request)
		if err != nil {
			http.Redirect(w, request, b.URLS.SignIn, 302)
		} else {
			b.login(request, w, strconv.FormatInt(userID, 10))
		}
	}
}

func (b *Builder) SignIn() func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		email := r.FormValue("email")
		password := r.FormValue("password")
		userPassword, err := b.UserPasswordByEmail(email)

		if err != nil {
			http.Redirect(w, r, b.URLS.Redirect, 302)
		}

		err = checkPassword(userPassword, password)
		if err != nil {
			http.Redirect(w, r, b.URLS.Redirect, 302)
		} else {
			userId, _ := b.UserIdByEmail(email)
			b.login(r, w, strconv.FormatInt(userId, 10))
		}
	}
}

func (b *Builder) Protected(fn func(string, http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		userID := b.CurrentUser(r)
		if userID != "" {
			fn(userID, w, r)
		} else {
			http.Redirect(w, r, b.URLS.SignIn, 302)
		}
	}
}

// helper

func (b *Builder) login(r *http.Request, w http.ResponseWriter, userId string) {
	session, _ := store.Get(r, "_session")
	session.Values["user_id"] = userId
	session.Save(r, w)

	http.Redirect(w, r, b.URLS.Redirect, 302)
}

func (b *Builder) CurrentUser(r *http.Request) string {
	session, _ := store.Get(r, "_session")
	userId := session.Values["user_id"]
	id, _ := userId.(string)
	return id
}

func generatePassword(password string) string {
	h, _ := bcrypt.GenerateFromPassword([]byte(password), 0)
	return string(h[:])
}

func checkPassword(hashedPassword, password string) error {
	return bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password))
}
<commit_msg>updated setup callback to fix oauth login<commit_after>// Package login2 provides sign in and sign up by oauth2 and email and password.
// Inspired in omniauth and devise gem
//
package login2

import (
	"encoding/json"
	"net/http"
	"os"
	"strconv"

	"code.google.com/p/go.crypto/bcrypt"
	"code.google.com/p/goauth2/oauth"
	"github.com/gorilla/mux"
	"github.com/gorilla/sessions"
)

var store = sessions.NewCookieStore([]byte(os.Getenv("SESSION_SECRET")))

// Provider is a oauth2 provider, like facebook or google
// Name is provider name, it's like a key, will can be use it after,
// the package only use it as a index.
// Key is oauth2 key
// Secret is oauth2 secret key
// RedirectURL is a url will config on provider
// TokenURL is a URL to get the token on provider
// AuthURL is a URL to auth user on provider
// UserInfoURL is a URL to get User Information on provider
// Scope is whats the scope your app wants
type Provider struct {
	Name        string
	Key         string
	Secret      string
	RedirectURL string
	TokenURL    string
	AuthURL     string
	UserInfoURL string
	Scope       string
}

// Internal auth config
type builderConfig struct {
	Auth        *oauth.Config
	UserInfoURL string
}

// URLS

type URLS struct {
	Redirect string
	SignIn   string
	SignUp   string
}

type Builder struct {
	Providers           map[string]*builderConfig
	UserSetupFn         func(provider string, user *User, rawResponde *http.Response) (int64, error)
	UserExistsFn        func(email string) bool
	UserCreateFn        func(email string, password string, request *http.Request) (int64, error)
	UserIdByEmail       func(email string) (int64, error)
	UserPasswordByEmail func(email string) (string, error)
	URLS                URLS
}

type User struct {
	Id     string
	Email  string
	Link   string
	Name   string
	Gender string
	Locale string
}

func NewBuilder(userProviders []*Provider) *Builder {
	builder := new(Builder)
	builder.Providers = make(map[string]*builderConfig, 0)

	for _, p := range userProviders {
		config := &oauth.Config{
			ClientId:     p.Key,
			ClientSecret: p.Secret,
			RedirectURL:  p.RedirectURL,
			Scope:        p.Scope,
			AuthURL:      p.AuthURL,
			TokenURL:     p.TokenURL,
			TokenCache:   oauth.CacheFile("cache-" + p.Name + ".json"),
		}

		provider := new(builderConfig)
		provider.Auth = config
		provider.UserInfoURL = p.UserInfoURL

		builder.Providers[p.Name] = provider
	}

	return builder
}

func (b *Builder) Router(r *mux.Router) {
	for provider, _ := range b.Providers {
		r.HandleFunc("/auth/"+provider, b.OAuthAuthorize(provider)).Methods("GET")
	}

	r.HandleFunc("/auth/callback/{provider}", b.OAuthLogin()).Methods("GET")
	r.HandleFunc("/users/sign_in", b.SignIn()).Methods("POST")
	r.HandleFunc("/users/sign_up", b.SignUp()).Methods("POST")

}

// HTTP server

// OAuthAuthorize Send user to Authorize on provider
func (b *Builder) OAuthAuthorize(provider string) func(http.ResponseWriter, *http.Request) {
	config := b.Providers[provider]

	return func(w http.ResponseWriter, r *http.Request) {
		url := config.Auth.AuthCodeURL("")
		http.Redirect(w, r, url, http.StatusFound)
	}
}

func (b *Builder) OAuthLogin() func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, request *http.Request) {
		vars := mux.Vars(request)
		provider := vars["provider"]

		userId, err := b.OAuthCallback(provider, request)

		if err != nil {
			http.Redirect(w, request, b.URLS.SignIn, 302)
		} else {
			b.login(request, w, strconv.FormatInt(userId, 10))
		}
	}
}

// OAuthCallback receive code from provider and get user information on provider
func (b *Builder) OAuthCallback(provider string, r *http.Request) (int64, error) {
	config := b.Providers[provider]
	code := r.FormValue("code")
	t := &oauth.Transport{Config: config.Auth}
	t.Exchange(code)
	responseAuth, _ := t.Client().Get(config.UserInfoURL)
	defer responseAuth.Body.Close()

	var user User
	decoder := json.NewDecoder(responseAuth.Body)
	err := decoder.Decode(&user)
	if err != nil {
		panic(err)
	}

	return b.UserSetupFn(provider, &user, responseAuth)
}

// SignUp Hanlder create and login user on database and redirecto to RedirectURL
func (b *Builder) SignUp() func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, request *http.Request) {
		email := request.FormValue("email")
		password := request.FormValue("password")
		hpassword := generatePassword(password)

		userID, err := b.UserCreateFn(email, hpassword, request)
		if err != nil {
			http.Redirect(w, request, b.URLS.SignIn, 302)
		} else {
			b.login(request, w, strconv.FormatInt(userID, 10))
		}
	}
}

func (b *Builder) SignIn() func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		email := r.FormValue("email")
		password := r.FormValue("password")
		userPassword, err := b.UserPasswordByEmail(email)

		if err != nil {
			http.Redirect(w, r, b.URLS.Redirect, 302)
		}

		err = checkPassword(userPassword, password)
		if err != nil {
			http.Redirect(w, r, b.URLS.Redirect, 302)
		} else {
			userId, _ := b.UserIdByEmail(email)
			b.login(r, w, strconv.FormatInt(userId, 10))
		}
	}
}

func (b *Builder) Protected(fn func(string, http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		userID := b.CurrentUser(r)
		if userID != "" {
			fn(userID, w, r)
		} else {
			http.Redirect(w, r, b.URLS.SignIn, 302)
		}
	}
}

// helper

func (b *Builder) login(r *http.Request, w http.ResponseWriter, userId string) {
	session, _ := store.Get(r, "_session")
	session.Values["user_id"] = userId
	session.Save(r, w)

	http.Redirect(w, r, b.URLS.Redirect, 302)
}

func (b *Builder) CurrentUser(r *http.Request) string {
	session, _ := store.Get(r, "_session")
	userId := session.Values["user_id"]
	id, _ := userId.(string)
	return id
}

func generatePassword(password string) string {
	h, _ := bcrypt.GenerateFromPassword([]byte(password), 0)
	return string(h[:])
}

func checkPassword(hashedPassword, password string) error {
	return bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password))
}
<|endoftext|>


<commit_before>package server

const (
	Read  = 4
	Write = 2
)

type Auth interface {
	AllowAnonymous() bool
	CheckPasswd(string, string) bool
	GetPerms(string, string) int
	HasPerm(string, string, int) bool
}

type AnonymousAuth struct {
}

func (AnonymousAuth) AllowAnonymous() bool {
	return true
}

func (AnonymousAuth) CheckPasswd(string, string) bool {
	return true
}

func (AnonymousAuth) GetPerms(string, string) int {
	return Read + Write
}
func (AnonymousAuth) HasPerm(string, string, int) bool {
	return true
}
<commit_msg>change Auth interface<commit_after>package server

const (
	Read  = 4
	Write = 2
)

type Auth interface {
	AllowAnonymous(bool)
	DefaultPerm(int)
	CheckPasswd(string, string) bool
	GetPerms(string, string) int
}

type AnonymousAuth struct {
}

func (AnonymousAuth) AllowAnonymous(bool) {
}

func (AnonymousAuth) DefaultPerm(perm int) {
}

func (AnonymousAuth) CheckPasswd(string, string) bool {
	return true
}

func (AnonymousAuth) GetPerms(string, string) int {
	return Read + Write
}
<|endoftext|>


<commit_before>package main

import (
    "git.lukas.moe/sn0w/Karen/logger"
    "github.com/sn0w/discordgo"
    "time"
)

var BETA_GUILDS = [...]string{
    "259831440064118784", // FADED's Sandbox        (Me)
    "180818466847064065", // Karen's Sandbox        (Me)
    "172041631258640384", // P0WERPLANT             (Me)
    "161637499939192832", // Coding Lounge          (Devsome)
    "225168913808228352", // Emily's Space          (Kaaz)
    "267186654312136704", // Shinda Sekai Sensen    (黒ゲロロロ)
    "244110097599430667", // S E K A I              (Senpai /「 ステ 」Abuse)
    "268279577598492672", // ZAKINET                (Senpai /「 ステ 」Abuse)
    "266326434505687041", // Bot Test               (quoththeraven)
    "267658193407049728", // Bot Creation           (quoththeraven)
    "106029722458136576", // Shadow Realm           (WhereIsMyAim)
    "268143270520029187", // Joel's Beasts          (Joel)
    "271346578189582339", // Universe Internet Ltd. (Inside24)
    "270353850085408780", // Turdy Republic         (Moopdedoop)
    "275720670045011968", // Omurice                (Katsurice)
}

// Automatically leaves guilds that are not registered beta testers
func autoLeaver(session *discordgo.Session) {
    for {
        for _, guild := range session.State.Guilds {
            match := false

            for _, betaGuild := range BETA_GUILDS {
                if guild.ID == betaGuild {
                    match = true
                    break
                }
            }

            if !match {
                logger.WARNING.L("beta", "Leaving guild " + guild.ID + " (" + guild.Name + ") because it didn't apply for the beta")
                session.GuildLeave(guild.ID)
            }
        }

        time.Sleep(10 * time.Second)
    }
}
<commit_msg>Remove obsolete server from whitelist<commit_after>package main

import (
    "git.lukas.moe/sn0w/Karen/logger"
    "github.com/sn0w/discordgo"
    "time"
)

var BETA_GUILDS = [...]string{
    "180818466847064065", // FADED's Sandbox        (Me)
    "172041631258640384", // P0WERPLANT             (Me)
    "161637499939192832", // Coding Lounge          (Devsome)
    "225168913808228352", // Emily's Space          (Kaaz)
    "267186654312136704", // Shinda Sekai Sensen    (黒ゲロロロ)
    "244110097599430667", // S E K A I              (Senpai /「 ステ 」Abuse)
    "268279577598492672", // ZAKINET                (Senpai /「 ステ 」Abuse)
    "266326434505687041", // Bot Test               (quoththeraven)
    "267658193407049728", // Bot Creation           (quoththeraven)
    "106029722458136576", // Shadow Realm           (WhereIsMyAim)
    "268143270520029187", // Joel's Beasts          (Joel)
    "271346578189582339", // Universe Internet Ltd. (Inside24)
    "270353850085408780", // Turdy Republic         (Moopdedoop)
    "275720670045011968", // Omurice                (Katsurice)
}

// Automatically leaves guilds that are not registered beta testers
func autoLeaver(session *discordgo.Session) {
    for {
        for _, guild := range session.State.Guilds {
            match := false

            for _, betaGuild := range BETA_GUILDS {
                if guild.ID == betaGuild {
                    match = true
                    break
                }
            }

            if !match {
                logger.WARNING.L("beta", "Leaving guild " + guild.ID + " (" + guild.Name + ") because it didn't apply for the beta")
                session.GuildLeave(guild.ID)
            }
        }

        time.Sleep(10 * time.Second)
    }
}
<|endoftext|>


<commit_before>package cuckoo

import (
	"bytes"
	"sync/atomic"
	"time"
	"unsafe"
)

// offset64 is the fnv1a 64-bit offset
var offset64 uint64 = 14695981039346656037

// prime64 is the fnv1a 64-bit prime
var prime64 uint64 = 1099511628211

var intoffs []uint = []uint{0, 8, 16, 24}

// bin returns the nth hash of the given key
func (m *cmap) bin(n int, key keyt) int {
	s := offset64
	for _, c := range key {
		s ^= uint64(c)
		s *= prime64
	}
	for _, i := range intoffs {
		s ^= uint64(n >> i)
		s *= prime64
	}
	return int(s % uint64(len(m.bins)))
}

// kbins returns all hashes of the given key.
// as m.hashes increases, this function will return more hashes.
func (m *cmap) kbins(key keyt) []int {
	nb := uint64(len(m.bins))
	nh := int(m.hashes)
	bins := make([]int, nh)

	// only hash the key once
	s := offset64
	for _, c := range key {
		s ^= uint64(c)
		s *= prime64
	}

	for i := 0; i < nh; i++ {
		// compute key for this i
		s_ := s
		for _, o := range intoffs {
			s_ ^= uint64(i >> o)
			s_ *= prime64
		}
		bins[i] = int(s_ % nb)
	}
	return bins
}

// cbin is a single Cuckoo map bin holding up to ASSOCIATIVITY values.
// each bin has a lock that must be used for *writes*.
// values should never be accessed directly, but rather through v()
type cbin struct {
	vals [ASSOCIATIVITY]unsafe.Pointer
	mx   SpinLock
}

// v returns a pointer to the current key data for a given slot (if any).
// this function may return nil if no key data is set for the given slot.
// this function is safe in the face of concurrent updates, assuming writers
// use setv().
func (b *cbin) v(i int) *cval {
	v := atomic.LoadPointer(&b.vals[i])
	return (*cval)(v)
}

// vpresent returns true if the given slot contains unexpired key data
func (b *cbin) vpresent(i int, now time.Time) bool {
	v := b.v(i)
	return v != nil && v.present(now)
}

// setv will atomically update the key data for the given slot
func (b *cbin) setv(i int, v *cval) {
	atomic.StorePointer(&b.vals[i], unsafe.Pointer(v))
}

// subin atomically replaces the first free slot in this bin with the given key
// data
func (b *cbin) subin(v *cval, now time.Time) {
	for i := 0; i < ASSOCIATIVITY; i++ {
		if !b.vpresent(i, now) {
			b.setv(i, v)
			return
		}
	}
}

// kill will immediately and atomically invalidate the given slot's key data
func (b *cbin) kill(i int) {
	b.setv(i, nil)
}

// available returns true if this bin has a slot that is currently unoccupied
// or expired
func (b *cbin) available(now time.Time) bool {
	for i := 0; i < ASSOCIATIVITY; i++ {
		if !b.vpresent(i, now) {
			return true
		}
	}
	return false
}

// add will atomically replace the first available slot in this bin with the
// given key data. this function may return an error if there are no free
// slots.
func (b *cbin) add(val *cval, upd Memop, now time.Time) (ret MemopRes) {
	b.mx.Lock()
	defer b.mx.Unlock()

	ret.T = SERVER_ERROR
	if b.available(now) {
		val.val, ret = upd(val.val, false)
		if ret.T == STORED {
			b.subin(val, now)
		}
		return
	}
	return
}

// has returns the slot holding the key data for the given key in this bin.
// if no slot has the relevant key data, -1 is returned.
func (b *cbin) has(key keyt, now time.Time) int {
	for i := 0; i < ASSOCIATIVITY; i++ {
		v := b.v(i)
		if v != nil && v.present(now) && bytes.Equal(v.key, key) {
			return i
		}
	}
	return -1
}
<commit_msg>Avoid alloc in v()<commit_after>package cuckoo

import (
	"bytes"
	"sync/atomic"
	"time"
	"unsafe"
)

// offset64 is the fnv1a 64-bit offset
var offset64 uint64 = 14695981039346656037

// prime64 is the fnv1a 64-bit prime
var prime64 uint64 = 1099511628211

var intoffs []uint = []uint{0, 8, 16, 24}

// bin returns the nth hash of the given key
func (m *cmap) bin(n int, key keyt) int {
	s := offset64
	for _, c := range key {
		s ^= uint64(c)
		s *= prime64
	}
	for _, i := range intoffs {
		s ^= uint64(n >> i)
		s *= prime64
	}
	return int(s % uint64(len(m.bins)))
}

// kbins returns all hashes of the given key.
// as m.hashes increases, this function will return more hashes.
func (m *cmap) kbins(key keyt) []int {
	nb := uint64(len(m.bins))
	nh := int(m.hashes)
	bins := make([]int, nh)

	// only hash the key once
	s := offset64
	for _, c := range key {
		s ^= uint64(c)
		s *= prime64
	}

	for i := 0; i < nh; i++ {
		// compute key for this i
		s_ := s
		for _, o := range intoffs {
			s_ ^= uint64(i >> o)
			s_ *= prime64
		}
		bins[i] = int(s_ % nb)
	}
	return bins
}

// cbin is a single Cuckoo map bin holding up to ASSOCIATIVITY values.
// each bin has a lock that must be used for *writes*.
// values should never be accessed directly, but rather through v()
type cbin struct {
	vals [ASSOCIATIVITY]unsafe.Pointer
	mx   SpinLock
}

// v returns a pointer to the current key data for a given slot (if any).
// this function may return nil if no key data is set for the given slot.
// this function is safe in the face of concurrent updates, assuming writers
// use setv().
func (b *cbin) v(i int) *cval {
	return (*cval)(atomic.LoadPointer(&b.vals[i]))
}

// vpresent returns true if the given slot contains unexpired key data
func (b *cbin) vpresent(i int, now time.Time) bool {
	v := b.v(i)
	return v != nil && v.present(now)
}

// setv will atomically update the key data for the given slot
func (b *cbin) setv(i int, v *cval) {
	atomic.StorePointer(&b.vals[i], unsafe.Pointer(v))
}

// subin atomically replaces the first free slot in this bin with the given key
// data
func (b *cbin) subin(v *cval, now time.Time) {
	for i := 0; i < ASSOCIATIVITY; i++ {
		if !b.vpresent(i, now) {
			b.setv(i, v)
			return
		}
	}
}

// kill will immediately and atomically invalidate the given slot's key data
func (b *cbin) kill(i int) {
	b.setv(i, nil)
}

// available returns true if this bin has a slot that is currently unoccupied
// or expired
func (b *cbin) available(now time.Time) bool {
	for i := 0; i < ASSOCIATIVITY; i++ {
		if !b.vpresent(i, now) {
			return true
		}
	}
	return false
}

// add will atomically replace the first available slot in this bin with the
// given key data. this function may return an error if there are no free
// slots.
func (b *cbin) add(val *cval, upd Memop, now time.Time) (ret MemopRes) {
	b.mx.Lock()
	defer b.mx.Unlock()

	ret.T = SERVER_ERROR
	if b.available(now) {
		val.val, ret = upd(val.val, false)
		if ret.T == STORED {
			b.subin(val, now)
		}
		return
	}
	return
}

// has returns the slot holding the key data for the given key in this bin.
// if no slot has the relevant key data, -1 is returned.
func (b *cbin) has(key keyt, now time.Time) int {
	for i := 0; i < ASSOCIATIVITY; i++ {
		v := b.v(i)
		if v != nil && v.present(now) && bytes.Equal(v.key, key) {
			return i
		}
	}
	return -1
}
<|endoftext|>


<commit_before>package luddite

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"mime"
	"net/http"
	"reflect"
	"time"

	"github.com/gorilla/schema"
)

const (
	ContentTypeMultipartFormData = "multipart/form-data"
	ContentTypeWwwFormUrlencoded = "application/x-www-form-urlencoded"
	ContentTypeJson              = "application/json"
	ContentTypeOctetStream       = "application/octet-stream"
	ContentTypeXml               = "application/xml"
	ContentTypeHtml              = "text/html"

	maxFormDataMemoryUsage = 10 * 1024 * 1024
)

var formDecoder = schema.NewDecoder()

func init() {
	t := time.Time{}
	formDecoder.RegisterConverter(t, ConvertTime)
}

func ConvertTime(value string) reflect.Value {
	if t, err := time.Parse(time.RFC3339, value); err == nil {
		return reflect.ValueOf(t)
	}
	return reflect.Value{}
}

func ReadRequest(req *http.Request, v interface{}) error {
	ct := req.Header.Get(HeaderContentType)
	switch mt, _, _ := mime.ParseMediaType(ct); mt {
	case ContentTypeMultipartFormData:
		if err := req.ParseMultipartForm(maxFormDataMemoryUsage); err != nil {
			return NewError(nil, EcodeDeserializationFailed, err)
		}
		if err := formDecoder.Decode(v, req.PostForm); err != nil {
			return NewError(nil, EcodeDeserializationFailed, err)
		}
		return nil
	case ContentTypeWwwFormUrlencoded:
		if err := req.ParseForm(); err != nil {
			return NewError(nil, EcodeDeserializationFailed, err)
		}
		if err := formDecoder.Decode(v, req.PostForm); err != nil {
			return NewError(nil, EcodeDeserializationFailed, err)
		}
		return nil
	case ContentTypeJson:
		decoder := json.NewDecoder(req.Body)
		err := decoder.Decode(v)
		if err != nil {
			return NewError(nil, EcodeDeserializationFailed, err)
		}
		return nil
	case ContentTypeXml:
		decoder := xml.NewDecoder(req.Body)
		err := decoder.Decode(v)
		if err != nil {
			return NewError(nil, EcodeDeserializationFailed, err)
		}
		return nil
	default:
		return NewError(nil, EcodeUnsupportedMediaType, ct)
	}
}

func WriteResponse(rw http.ResponseWriter, status int, v interface{}) (err error) {
	var b []byte
	if v != nil {
		if _, ok := v.(error); ok {
			v = NewError(nil, EcodeInternal, v)
		}
		switch rw.Header().Get(HeaderContentType) {
		case ContentTypeJson:
			b, err = json.Marshal(v)
			if err != nil {
				rw.WriteHeader(http.StatusInternalServerError)
				b, err = json.Marshal(NewError(nil, EcodeSerializationFailed, err))
				if err != nil {
					rw.Write(b)
				}
				return
			}
		case ContentTypeXml:
			b, err = xml.Marshal(v)
			if err != nil {
				rw.WriteHeader(http.StatusInternalServerError)
				b, err = xml.Marshal(NewError(nil, EcodeSerializationFailed, err))
				if err != nil {
					rw.Write(b)
				}
				return
			}
		case ContentTypeHtml:
			switch v.(type) {
			case []byte:
				b = v.([]byte)
			case string:
				b = []byte(v.(string))
			default:
				b, err = json.Marshal(v)
				if err != nil {
					rw.WriteHeader(http.StatusInternalServerError)
					b, err = json.Marshal(NewError(nil, EcodeSerializationFailed, err))
					if err != nil {
						rw.Write(b)
					}
					return
				}
				esc := new(bytes.Buffer)
				json.HTMLEscape(esc, b)
				b = esc.Bytes()
			}
		case ContentTypeOctetStream:
			switch v.(type) {
			case []byte:
				b = v.([]byte)
			case string:
				b = []byte(v.(string))
			default:
				rw.WriteHeader(http.StatusInternalServerError)
				return
			}
		}
	}
	rw.WriteHeader(status)
	if b != nil {
		_, err = rw.Write(b)
	}
	return
}
<commit_msg>Reverse portion of ddfd58779a<commit_after>package luddite

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"mime"
	"net/http"
	"reflect"
	"time"

	"github.com/gorilla/schema"
)

const (
	ContentTypeMultipartFormData = "multipart/form-data"
	ContentTypeWwwFormUrlencoded = "application/x-www-form-urlencoded"
	ContentTypeJson              = "application/json"
	ContentTypeOctetStream       = "application/octet-stream"
	ContentTypeXml               = "application/xml"
	ContentTypeHtml              = "text/html"

	maxFormDataMemoryUsage = 10 * 1024 * 1024
)

var formDecoder = schema.NewDecoder()

func init() {
	t := time.Time{}
	formDecoder.RegisterConverter(t, ConvertTime)
}

func ConvertTime(value string) reflect.Value {
	if t, err := time.Parse(time.RFC3339, value); err == nil {
		return reflect.ValueOf(t)
	}
	return reflect.Value{}
}

func ReadRequest(req *http.Request, v interface{}) error {
	ct := req.Header.Get(HeaderContentType)
	switch mt, _, _ := mime.ParseMediaType(ct); mt {
	case ContentTypeMultipartFormData:
		if err := req.ParseMultipartForm(maxFormDataMemoryUsage); err != nil {
			return NewError(nil, EcodeDeserializationFailed, err)
		}
		if err := formDecoder.Decode(v, req.PostForm); err != nil {
			return NewError(nil, EcodeDeserializationFailed, err)
		}
		return nil
	case ContentTypeWwwFormUrlencoded:
		if err := req.ParseForm(); err != nil {
			return NewError(nil, EcodeDeserializationFailed, err)
		}
		if err := formDecoder.Decode(v, req.PostForm); err != nil {
			return NewError(nil, EcodeDeserializationFailed, err)
		}
		return nil
	case ContentTypeJson:
		decoder := json.NewDecoder(req.Body)
		err := decoder.Decode(v)
		if err != nil {
			return NewError(nil, EcodeDeserializationFailed, err)
		}
		return nil
	case ContentTypeXml:
		decoder := xml.NewDecoder(req.Body)
		err := decoder.Decode(v)
		if err != nil {
			return NewError(nil, EcodeDeserializationFailed, err)
		}
		return nil
	default:
		return NewError(nil, EcodeUnsupportedMediaType, ct)
	}
}

func WriteResponse(rw http.ResponseWriter, status int, v interface{}) (err error) {
	var b []byte
	if v != nil {
		switch v.(type) {
		case *Error:
		case error:
			v = NewError(nil, EcodeInternal, v)
		}
		switch rw.Header().Get(HeaderContentType) {
		case ContentTypeJson:
			b, err = json.Marshal(v)
			if err != nil {
				rw.WriteHeader(http.StatusInternalServerError)
				b, err = json.Marshal(NewError(nil, EcodeSerializationFailed, err))
				if err != nil {
					rw.Write(b)
				}
				return
			}
		case ContentTypeXml:
			b, err = xml.Marshal(v)
			if err != nil {
				rw.WriteHeader(http.StatusInternalServerError)
				b, err = xml.Marshal(NewError(nil, EcodeSerializationFailed, err))
				if err != nil {
					rw.Write(b)
				}
				return
			}
		case ContentTypeHtml:
			switch v.(type) {
			case []byte:
				b = v.([]byte)
			case string:
				b = []byte(v.(string))
			default:
				b, err = json.Marshal(v)
				if err != nil {
					rw.WriteHeader(http.StatusInternalServerError)
					b, err = json.Marshal(NewError(nil, EcodeSerializationFailed, err))
					if err != nil {
						rw.Write(b)
					}
					return
				}
				esc := new(bytes.Buffer)
				json.HTMLEscape(esc, b)
				b = esc.Bytes()
			}
		case ContentTypeOctetStream:
			switch v.(type) {
			case []byte:
				b = v.([]byte)
			case string:
				b = []byte(v.(string))
			default:
				rw.WriteHeader(http.StatusInternalServerError)
				return
			}
		}
	}
	rw.WriteHeader(status)
	if b != nil {
		_, err = rw.Write(b)
	}
	return
}
<|endoftext|>


<commit_before>package jsval_test

import "github.com/lestrrat/go-jsval"

func JSValFoo() *jsval.JSVal {
	V := jsval.New()
	V.SetRoot(
		jsval.Object().
			AdditionalProperties(
				jsval.NilConstraint,
			).
			AddProp(
				`$schema`,
				jsval.String().Format("uri"),
			).
			AddProp(
				`additionalItems`,
				jsval.Any().
					Add(
						jsval.Boolean(),
					).
					Add(
						jsval.Reference(V).RefersTo(`#`),
					),
			).
			AddProp(
				`additionalProperties`,
				jsval.Any().
					Add(
						jsval.Boolean(),
					).
					Add(
						jsval.Reference(V).RefersTo(`#`),
					),
			).
			AddProp(
				`allOf`,
				jsval.Reference(V).RefersTo(`#/definitions/schemaArray`),
			).
			AddProp(
				`anyOf`,
				jsval.Reference(V).RefersTo(`#/definitions/schemaArray`),
			).
			AddProp(
				`default`,
				jsval.NilConstraint,
			).
			AddProp(
				`definitions`,
				jsval.Object().
					AdditionalProperties(
						jsval.Reference(V).RefersTo(`#`),
					),
			).
			AddProp(
				`dependencies`,
				jsval.Object().
					AdditionalProperties(
						jsval.Any().
							Add(
								jsval.Reference(V).RefersTo(`#`),
							).
							Add(
								jsval.Reference(V).RefersTo(`#/definitions/stringArray`),
							),
					),
			).
			AddProp(
				`description`,
				jsval.String(),
			).
			AddProp(
				`enum`,
				jsval.Array().MinItems(1).MaxItems(0).UniqueItems(),
			).
			AddProp(
				`exclusiveMaximum`,
				jsval.Boolean(),
			).
			AddProp(
				`exclusiveMinimum`,
				jsval.Boolean(),
			).
			AddProp(
				`id`,
				jsval.String().Format("uri"),
			).
			AddProp(
				`items`,
				jsval.Any().
					Add(
						jsval.Reference(V).RefersTo(`#`),
					).
					Add(
						jsval.Reference(V).RefersTo(`#/definitions/schemaArray`),
					),
			).
			AddProp(
				`maxItems`,
				jsval.Reference(V).RefersTo(`#/definitions/positiveInteger`),
			).
			AddProp(
				`maxLength`,
				jsval.Reference(V).RefersTo(`#/definitions/positiveInteger`),
			).
			AddProp(
				`maxProperties`,
				jsval.Reference(V).RefersTo(`#/definitions/positiveInteger`),
			).
			AddProp(
				`maximum`,
				jsval.Number(),
			).
			AddProp(
				`minItems`,
				jsval.Reference(V).RefersTo(`#/definitions/positiveIntegerDefault0`),
			).
			AddProp(
				`minLength`,
				jsval.Reference(V).RefersTo(`#/definitions/positiveIntegerDefault0`),
			).
			AddProp(
				`minProperties`,
				jsval.Reference(V).RefersTo(`#/definitions/positiveIntegerDefault0`),
			).
			AddProp(
				`minimum`,
				jsval.Number(),
			).
			AddProp(
				`multipleOf`,
				jsval.Number().Minimum(0.000000).ExclusiveMinimum(true),
			).
			AddProp(
				`not`,
				jsval.Reference(V).RefersTo(`#`),
			).
			AddProp(
				`oneOf`,
				jsval.Reference(V).RefersTo(`#/definitions/schemaArray`),
			).
			AddProp(
				`pattern`,
				jsval.String().Format("regex"),
			).
			AddProp(
				`patternProperties`,
				jsval.Object().
					AdditionalProperties(
						jsval.Reference(V).RefersTo(`#`),
					),
			).
			AddProp(
				`properties`,
				jsval.Object().
					AdditionalProperties(
						jsval.Reference(V).RefersTo(`#`),
					),
			).
			AddProp(
				`required`,
				jsval.Reference(V).RefersTo(`#/definitions/stringArray`),
			).
			AddProp(
				`title`,
				jsval.String(),
			).
			AddProp(
				`type`,
				jsval.Any().
					Add(
						jsval.Reference(V).RefersTo(`#/definitions/simpleTypes`),
					).
					Add(
						jsval.Array().MinItems(1).MaxItems(0).UniqueItems(),
					),
			).
			AddProp(
				`uniqueItems`,
				jsval.Boolean(),
			),
	)

	V.SetReference(
		`#`,
		V.Root(),
	)
	V.SetReference(
		`#/definitions/positiveInteger`,
		jsval.Integer().Minimum(0),
	)
	V.SetReference(
		`#/definitions/positiveIntegerDefault0`,
		jsval.All().
			Add(
				jsval.Reference(V).RefersTo(`#/definitions/positiveInteger`),
			).
			Add(
				jsval.NilConstraint,
			),
	)
	V.SetReference(
		`#/definitions/schemaArray`,
		jsval.Array().MinItems(1).MaxItems(0),
	)
	V.SetReference(
		`#/definitions/simpleTypes`,
		jsval.String().Enum([]interface{}{"array", "boolean", "integer", "null", "number", "object", "string"}),
	)
	V.SetReference(
		`#/definitions/stringArray`,
		jsval.Array().MinItems(1).MaxItems(0).UniqueItems(),
	)
	return V
}
<commit_msg>apply defaults<commit_after>package jsval_test

import "github.com/lestrrat/go-jsval"

func JSValFoo() *jsval.JSVal {
	V := jsval.New()
	V.SetRoot(
		jsval.Object().
			AdditionalProperties(
				jsval.NilConstraint,
			).
			AddProp(
				`$schema`,
				jsval.String().Format("uri"),
			).
			AddProp(
				`additionalItems`,
				jsval.Any().
					Add(
						jsval.Boolean(),
					).
					Add(
						jsval.Reference(V).RefersTo(`#`),
					),
			).
			AddProp(
				`additionalProperties`,
				jsval.Any().
					Add(
						jsval.Boolean(),
					).
					Add(
						jsval.Reference(V).RefersTo(`#`),
					),
			).
			AddProp(
				`allOf`,
				jsval.Reference(V).RefersTo(`#/definitions/schemaArray`),
			).
			AddProp(
				`anyOf`,
				jsval.Reference(V).RefersTo(`#/definitions/schemaArray`),
			).
			AddProp(
				`default`,
				jsval.NilConstraint,
			).
			AddProp(
				`definitions`,
				jsval.Object().
					AdditionalProperties(
						jsval.Reference(V).RefersTo(`#`),
					),
			).
			AddProp(
				`dependencies`,
				jsval.Object().
					AdditionalProperties(
						jsval.Any().
							Add(
								jsval.Reference(V).RefersTo(`#`),
							).
							Add(
								jsval.Reference(V).RefersTo(`#/definitions/stringArray`),
							),
					),
			).
			AddProp(
				`description`,
				jsval.String(),
			).
			AddProp(
				`enum`,
				jsval.Array().MinItems(1).MaxItems(0).UniqueItems(),
			).
			AddProp(
				`exclusiveMaximum`,
				jsval.Boolean().Default(false),
			).
			AddProp(
				`exclusiveMinimum`,
				jsval.Boolean().Default(false),
			).
			AddProp(
				`id`,
				jsval.String().Format("uri"),
			).
			AddProp(
				`items`,
				jsval.Any().
					Add(
						jsval.Reference(V).RefersTo(`#`),
					).
					Add(
						jsval.Reference(V).RefersTo(`#/definitions/schemaArray`),
					),
			).
			AddProp(
				`maxItems`,
				jsval.Reference(V).RefersTo(`#/definitions/positiveInteger`),
			).
			AddProp(
				`maxLength`,
				jsval.Reference(V).RefersTo(`#/definitions/positiveInteger`),
			).
			AddProp(
				`maxProperties`,
				jsval.Reference(V).RefersTo(`#/definitions/positiveInteger`),
			).
			AddProp(
				`maximum`,
				jsval.Number(),
			).
			AddProp(
				`minItems`,
				jsval.Reference(V).RefersTo(`#/definitions/positiveIntegerDefault0`),
			).
			AddProp(
				`minLength`,
				jsval.Reference(V).RefersTo(`#/definitions/positiveIntegerDefault0`),
			).
			AddProp(
				`minProperties`,
				jsval.Reference(V).RefersTo(`#/definitions/positiveIntegerDefault0`),
			).
			AddProp(
				`minimum`,
				jsval.Number(),
			).
			AddProp(
				`multipleOf`,
				jsval.Number().Minimum(0.000000).ExclusiveMinimum(true),
			).
			AddProp(
				`not`,
				jsval.Reference(V).RefersTo(`#`),
			).
			AddProp(
				`oneOf`,
				jsval.Reference(V).RefersTo(`#/definitions/schemaArray`),
			).
			AddProp(
				`pattern`,
				jsval.String().Format("regex"),
			).
			AddProp(
				`patternProperties`,
				jsval.Object().
					AdditionalProperties(
						jsval.Reference(V).RefersTo(`#`),
					),
			).
			AddProp(
				`properties`,
				jsval.Object().
					AdditionalProperties(
						jsval.Reference(V).RefersTo(`#`),
					),
			).
			AddProp(
				`required`,
				jsval.Reference(V).RefersTo(`#/definitions/stringArray`),
			).
			AddProp(
				`title`,
				jsval.String(),
			).
			AddProp(
				`type`,
				jsval.Any().
					Add(
						jsval.Reference(V).RefersTo(`#/definitions/simpleTypes`),
					).
					Add(
						jsval.Array().MinItems(1).MaxItems(0).UniqueItems(),
					),
			).
			AddProp(
				`uniqueItems`,
				jsval.Boolean().Default(false),
			),
	)

	V.SetReference(
		`#`,
		V.Root(),
	)
	V.SetReference(
		`#/definitions/positiveInteger`,
		jsval.Integer().Minimum(0),
	)
	V.SetReference(
		`#/definitions/positiveIntegerDefault0`,
		jsval.All().
			Add(
				jsval.Reference(V).RefersTo(`#/definitions/positiveInteger`),
			).
			Add(
				jsval.NilConstraint,
			),
	)
	V.SetReference(
		`#/definitions/schemaArray`,
		jsval.Array().MinItems(1).MaxItems(0),
	)
	V.SetReference(
		`#/definitions/simpleTypes`,
		jsval.String().Enum([]interface{}{"array", "boolean", "integer", "null", "number", "object", "string"},),
	)
	V.SetReference(
		`#/definitions/stringArray`,
		jsval.Array().MinItems(1).MaxItems(0).UniqueItems(),
	)
	return V
}
<|endoftext|>


<commit_before>package generator

import (
	"io"
	"reflect"
	"testing"

	"github.com/golang/protobuf/proto"
	plugin "github.com/golang/protobuf/protoc-gen-go/plugin"
)

func TestGenerator_GenerateAllFiles(t *testing.T) {
	type fields struct {
		w io.Writer
	}
	tests := []struct {
		name   string
		fields fields
		want   *plugin.CodeGeneratorResponse
	}{
		{
			name: "simple",
			fields: fields{
				w: nil,
			},
			want: &plugin.CodeGeneratorResponse{
				File: []*plugin.CodeGeneratorResponse_File{
					{
						Name:    proto.String("foo"),
						Content: proto.String("bar"),
					},
				},
			},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			g := &Generator{
				w: tt.fields.w,
			}
			if got := g.GenerateAllFiles(); !reflect.DeepEqual(got, tt.want) {
				t.Errorf("Generator.GenerateAllFiles() = %v, want %v", got, tt.want)
			}
		})
	}
}
<commit_msg>Fix test name to 'helloworld'<commit_after>package generator

import (
	"io"
	"reflect"
	"testing"

	"github.com/golang/protobuf/proto"
	plugin "github.com/golang/protobuf/protoc-gen-go/plugin"
)

func TestGenerator_GenerateAllFiles(t *testing.T) {
	type fields struct {
		w io.Writer
	}
	tests := []struct {
		name   string
		fields fields
		want   *plugin.CodeGeneratorResponse
	}{
		{
			name: "helloworld",
			fields: fields{
				w: nil,
			},
			want: &plugin.CodeGeneratorResponse{
				File: []*plugin.CodeGeneratorResponse_File{
					{
						Name:    proto.String("foo"),
						Content: proto.String("bar"),
					},
				},
			},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			g := &Generator{
				w: tt.fields.w,
			}
			if got := g.GenerateAllFiles(); !reflect.DeepEqual(got, tt.want) {
				t.Errorf("Generator.GenerateAllFiles() = %v, want %v", got, tt.want)
			}
		})
	}
}
<|endoftext|>