<commit_before>package immortal

import (
	"bufio"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"os/user"
	"path/filepath"
	"sort"
	"strings"

	"github.com/immortal/natcasesort"
	"gopkg.in/yaml.v2"
)

// Parser interface
type Parser interface {
	Parse(fs *flag.FlagSet) (*Flags, error)
	isDir(path string) bool
	isFile(path string) bool
	parseYml(file string) (*Config, error)
	checkWrkdir(dir string) error
	parseEnvdir(dir string) (map[string]string, error)
	checkUser(username string) (*user.User, error)
}

// Parse implements parser
type Parse struct {
	Flags
	UserLookup func(username string) (*user.User, error)
}

// Parse parse the command line flags
func (p *Parse) Parse(fs *flag.FlagSet) (*Flags, error) {
	fs.BoolVar(&p.Flags.Ctrl, "ctrl", false, "Create supervise directory")
	fs.BoolVar(&p.Flags.Version, "v", false, "Print version")
	fs.StringVar(&p.Flags.Configfile, "c", "", "`run.yml` configuration file")
	fs.StringVar(&p.Flags.Wrkdir, "d", "", "Change to `dir` before starting the command")
	fs.StringVar(&p.Flags.Envdir, "e", "", "Set environment variables specified by files in the `dir`")
	fs.StringVar(&p.Flags.FollowPid, "f", "", "Follow PID in `pidfile`")
	fs.StringVar(&p.Flags.Logfile, "l", "", "Write stdout/stderr to `logfile`")
	fs.StringVar(&p.Flags.Logger, "logger", "", "A `command` to pipe stdout/stderr to stdin")
	fs.StringVar(&p.Flags.ParentPid, "P", "", "Path to write the supervisor `pidfile`")
	fs.StringVar(&p.Flags.ChildPid, "p", "", "Path to write the child `pidfile`")
	fs.IntVar(&p.Flags.Seconds, "s", 0, "`seconds` to wait before starting")
	fs.StringVar(&p.Flags.User, "u", "", "Execute command on behalf `user`")

	err := fs.Parse(os.Args[1:])
	if err != nil {
		return nil, err
	}
	return &p.Flags, nil
}

func (p *Parse) isDir(path string) bool {
	f, err := os.Stat(path)
	if err != nil {
		return false
	}
	if m := f.Mode(); m.IsDir() && m&400 != 0 {
		return true
	}
	return false
}

func (p *Parse) isFile(path string) bool {
	f, err := os.Stat(path)
	if err != nil {
		return false
	}
	if m := f.Mode(); !m.IsDir() && m.IsRegular() && m&400 != 0 {
		return true
	}
	return false
}

func (p *Parse) parseYml(file string) (*Config, error) {
	f, err := ioutil.ReadFile(file)
	if err != nil {
		return nil, err
	}
	var cfg Config
	if err := yaml.Unmarshal(f, &cfg); err != nil {
		return nil, fmt.Errorf("Unable to parse YAML file %q %s", file, err)
	}
	return &cfg, nil
}

func (p *Parse) checkWrkdir(dir string) (err error) {
	if !p.isDir(dir) {
		err = fmt.Errorf("-d %q does not exist or has wrong permissions, use (\"%s -h\") for help.", dir, os.Args[0])
	}
	return
}

func (p *Parse) parseEnvdir(dir string) (map[string]string, error) {
	if !p.isDir(dir) {
		return nil, fmt.Errorf("-e %q does not exist or has wrong permissions, use (\"%s -h\") for help.", dir, os.Args[0])
	}
	files, err := ioutil.ReadDir(dir)
	if err != nil {
		return nil, err
	}
	env := make(map[string]string)
	for _, f := range files {
		if f.Mode().IsRegular() {
			lines := 0
			ff, err := os.Open(filepath.Join(dir, f.Name()))
			if err != nil {
				continue
			}
			defer ff.Close()
			s := bufio.NewScanner(ff)
			for s.Scan() {
				if lines >= 1 {
					break
				}
				env[f.Name()] = s.Text()
				lines++
			}
		}
	}
	return env, nil
}

func (p *Parse) checkUser(u string) (usr *user.User, err error) {
	usr, err = p.UserLookup(u)
	if err != nil {
		if _, ok := err.(user.UnknownUserError); ok {
			err = fmt.Errorf("User %q does not exist.", u)
		} else if err != nil {
			err = fmt.Errorf("Error looking up user: %q", u)
		}
		return
	}
	return
}

// Usage prints to standard error a usage message
func (p *Parse) Usage(fs *flag.FlagSet) func() {
	return func() {
		fmt.Fprintf(os.Stderr, "Usage: %s [-v -ctrl] [-d dir] [-e dir] [-f pidfile] [-l logfile] [-logger logger] [-p child_pidfile] [-P supervisor_pidfile] [-u user] command\n\n   command\n        The command with arguments if any, to supervise\n\n", os.Args[0])
		var flags []string
		fs.VisitAll(func(f *flag.Flag) {
			flags = append(flags, f.Name)
		})
		sort.Sort(natcasesort.Sort(flags))
		for _, v := range flags {
			f := fs.Lookup(v)
			s := fmt.Sprintf("  -%s", f.Name)
			name, usage := flag.UnquoteUsage(f)
			if len(name) > 0 {
				s += " " + name
			}
			if len(s) <= 4 {
				s += "\t"
			} else {
				s += "\n    \t"
			}
			s += usage
			fmt.Fprintf(os.Stderr, "%s\n", s)
		}
	}
}

// ParseArgs parse command arguments
func ParseArgs(p Parser, fs *flag.FlagSet) (cfg *Config, err error) {
	flags, err := p.Parse(fs)
	if err != nil {
		return
	}

	// if -v
	if flags.Version {
		return
	}

	// if -c
	if flags.Configfile != "" {
		if !p.isFile(flags.Configfile) {
			err = fmt.Errorf("Cannot read file: %q, use (\"%s -h\") for help.", flags.Configfile, os.Args[0])
			return
		}
		cfg, err = p.parseYml(flags.Configfile)
		if err != nil {
			return
		}
		if cfg.Cmd == "" {
			err = fmt.Errorf("Missing command, use (\"%s -h\") for help.", os.Args[0])
			return
		}
		cfg.command = strings.Fields(cfg.Cmd)
		if cfg.Cwd != "" {
			if err = p.checkWrkdir(cfg.Cwd); err != nil {
				return
			}
		}
		if cfg.User != "" {
			if cfg.user, err = p.checkUser(cfg.User); err != nil {
				return
			}
		}
		return
	}

	// if no args
	if len(fs.Args()) < 1 {
		err = fmt.Errorf("Missing command, use (\"%s -h\") for help.", os.Args[0])
		return
	}

	// create new cfg if not using run.yml
	cfg = new(Config)
	cfg.command = fs.Args()

	// if -ctrl
	if flags.Ctrl {
		cfg.ctrl = true
	}

	// if -d
	if flags.Wrkdir != "" {
		if err = p.checkWrkdir(flags.Wrkdir); err != nil {
			return
		}
		cfg.Cwd = flags.Wrkdir
	}

	// if -e
	if flags.Envdir != "" {
		if cfg.Env, err = p.parseEnvdir(flags.Envdir); err != nil {
			return
		}
	}

	// if -f
	if flags.FollowPid != "" {
		cfg.Follow = flags.FollowPid
	}

	// if -l
	if flags.Logfile != "" {
		cfg.File = flags.Logfile
	}

	// if -logger
	if flags.Logger != "" {
		cfg.Logger = flags.Logger
	}

	// if -P
	if flags.ParentPid != "" {
		cfg.Parent = flags.ParentPid
	}

	// if -p
	if flags.ChildPid != "" {
		cfg.Child = flags.ChildPid
	}

	// if -s
	if flags.Seconds > 0 {
		cfg.Wait = flags.Seconds
	}

	// if -u
	if flags.User != "" {
		if cfg.user, err = p.checkUser(flags.User); err != nil {
			return
		}
	}
	return
}
<commit_msg>if no run.yml log size 1<commit_after>package immortal

import (
	"bufio"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"os/user"
	"path/filepath"
	"sort"
	"strings"

	"github.com/immortal/natcasesort"
	"gopkg.in/yaml.v2"
)

// Parser interface
type Parser interface {
	Parse(fs *flag.FlagSet) (*Flags, error)
	isDir(path string) bool
	isFile(path string) bool
	parseYml(file string) (*Config, error)
	checkWrkdir(dir string) error
	parseEnvdir(dir string) (map[string]string, error)
	checkUser(username string) (*user.User, error)
}

// Parse implements parser
type Parse struct {
	Flags
	UserLookup func(username string) (*user.User, error)
}

// Parse parse the command line flags
func (p *Parse) Parse(fs *flag.FlagSet) (*Flags, error) {
	fs.BoolVar(&p.Flags.Ctrl, "ctrl", false, "Create supervise directory")
	fs.BoolVar(&p.Flags.Version, "v", false, "Print version")
	fs.StringVar(&p.Flags.Configfile, "c", "", "`run.yml` configuration file")
	fs.StringVar(&p.Flags.Wrkdir, "d", "", "Change to `dir` before starting the command")
	fs.StringVar(&p.Flags.Envdir, "e", "", "Set environment variables specified by files in the `dir`")
	fs.StringVar(&p.Flags.FollowPid, "f", "", "Follow PID in `pidfile`")
	fs.StringVar(&p.Flags.Logfile, "l", "", "Write stdout/stderr to `logfile`")
	fs.StringVar(&p.Flags.Logger, "logger", "", "A `command` to pipe stdout/stderr to stdin")
	fs.StringVar(&p.Flags.ParentPid, "P", "", "Path to write the supervisor `pidfile`")
	fs.StringVar(&p.Flags.ChildPid, "p", "", "Path to write the child `pidfile`")
	fs.IntVar(&p.Flags.Seconds, "s", 0, "`seconds` to wait before starting")
	fs.StringVar(&p.Flags.User, "u", "", "Execute command on behalf `user`")

	err := fs.Parse(os.Args[1:])
	if err != nil {
		return nil, err
	}
	return &p.Flags, nil
}

func (p *Parse) isDir(path string) bool {
	f, err := os.Stat(path)
	if err != nil {
		return false
	}
	if m := f.Mode(); m.IsDir() && m&400 != 0 {
		return true
	}
	return false
}

func (p *Parse) isFile(path string) bool {
	f, err := os.Stat(path)
	if err != nil {
		return false
	}
	if m := f.Mode(); !m.IsDir() && m.IsRegular() && m&400 != 0 {
		return true
	}
	return false
}

func (p *Parse) parseYml(file string) (*Config, error) {
	f, err := ioutil.ReadFile(file)
	if err != nil {
		return nil, err
	}
	var cfg Config
	if err := yaml.Unmarshal(f, &cfg); err != nil {
		return nil, fmt.Errorf("Unable to parse YAML file %q %s", file, err)
	}
	return &cfg, nil
}

func (p *Parse) checkWrkdir(dir string) (err error) {
	if !p.isDir(dir) {
		err = fmt.Errorf("-d %q does not exist or has wrong permissions, use (\"%s -h\") for help.", dir, os.Args[0])
	}
	return
}

func (p *Parse) parseEnvdir(dir string) (map[string]string, error) {
	if !p.isDir(dir) {
		return nil, fmt.Errorf("-e %q does not exist or has wrong permissions, use (\"%s -h\") for help.", dir, os.Args[0])
	}
	files, err := ioutil.ReadDir(dir)
	if err != nil {
		return nil, err
	}
	env := make(map[string]string)
	for _, f := range files {
		if f.Mode().IsRegular() {
			lines := 0
			ff, err := os.Open(filepath.Join(dir, f.Name()))
			if err != nil {
				continue
			}
			defer ff.Close()
			s := bufio.NewScanner(ff)
			for s.Scan() {
				if lines >= 1 {
					break
				}
				env[f.Name()] = s.Text()
				lines++
			}
		}
	}
	return env, nil
}

func (p *Parse) checkUser(u string) (usr *user.User, err error) {
	usr, err = p.UserLookup(u)
	if err != nil {
		if _, ok := err.(user.UnknownUserError); ok {
			err = fmt.Errorf("User %q does not exist.", u)
		} else if err != nil {
			err = fmt.Errorf("Error looking up user: %q", u)
		}
		return
	}
	return
}

// Usage prints to standard error a usage message
func (p *Parse) Usage(fs *flag.FlagSet) func() {
	return func() {
		fmt.Fprintf(os.Stderr, "Usage: %s [-v -ctrl] [-d dir] [-e dir] [-f pidfile] [-l logfile] [-logger logger] [-p child_pidfile] [-P supervisor_pidfile] [-u user] command\n\n   command\n        The command with arguments if any, to supervise\n\n", os.Args[0])
		var flags []string
		fs.VisitAll(func(f *flag.Flag) {
			flags = append(flags, f.Name)
		})
		sort.Sort(natcasesort.Sort(flags))
		for _, v := range flags {
			f := fs.Lookup(v)
			s := fmt.Sprintf("  -%s", f.Name)
			name, usage := flag.UnquoteUsage(f)
			if len(name) > 0 {
				s += " " + name
			}
			if len(s) <= 4 {
				s += "\t"
			} else {
				s += "\n    \t"
			}
			s += usage
			fmt.Fprintf(os.Stderr, "%s\n", s)
		}
	}
}

// ParseArgs parse command arguments
func ParseArgs(p Parser, fs *flag.FlagSet) (cfg *Config, err error) {
	flags, err := p.Parse(fs)
	if err != nil {
		return
	}

	// if -v
	if flags.Version {
		return
	}

	// if -c
	if flags.Configfile != "" {
		if !p.isFile(flags.Configfile) {
			err = fmt.Errorf("Cannot read file: %q, use (\"%s -h\") for help.", flags.Configfile, os.Args[0])
			return
		}
		cfg, err = p.parseYml(flags.Configfile)
		if err != nil {
			return
		}
		if cfg.Cmd == "" {
			err = fmt.Errorf("Missing command, use (\"%s -h\") for help.", os.Args[0])
			return
		}
		cfg.command = strings.Fields(cfg.Cmd)
		if cfg.Cwd != "" {
			if err = p.checkWrkdir(cfg.Cwd); err != nil {
				return
			}
		}
		if cfg.User != "" {
			if cfg.user, err = p.checkUser(cfg.User); err != nil {
				return
			}
		}
		return
	}

	// if no args
	if len(fs.Args()) < 1 {
		err = fmt.Errorf("Missing command, use (\"%s -h\") for help.", os.Args[0])
		return
	}

	// create new cfg if not using run.yml
	cfg = new(Config)
	cfg.command = fs.Args()
	cfg.Log.Size = 1

	// if -ctrl
	if flags.Ctrl {
		cfg.ctrl = true
	}

	// if -d
	if flags.Wrkdir != "" {
		if err = p.checkWrkdir(flags.Wrkdir); err != nil {
			return
		}
		cfg.Cwd = flags.Wrkdir
	}

	// if -e
	if flags.Envdir != "" {
		if cfg.Env, err = p.parseEnvdir(flags.Envdir); err != nil {
			return
		}
	}

	// if -f
	if flags.FollowPid != "" {
		cfg.Follow = flags.FollowPid
	}

	// if -l
	if flags.Logfile != "" {
		cfg.File = flags.Logfile
	}

	// if -logger
	if flags.Logger != "" {
		cfg.Logger = flags.Logger
	}

	// if -P
	if flags.ParentPid != "" {
		cfg.Parent = flags.ParentPid
	}

	// if -p
	if flags.ChildPid != "" {
		cfg.Child = flags.ChildPid
	}

	// if -s
	if flags.Seconds > 0 {
		cfg.Wait = flags.Seconds
	}

	// if -u
	if flags.User != "" {
		if cfg.user, err = p.checkUser(flags.User); err != nil {
			return
		}
	}
	return
}
<|endoftext|>


<commit_before>/*
 Copyright 2016 Padduck, LLC

 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 server

import (
	"encoding/json"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"github.com/itsjamie/gin-cors"
	"github.com/pufferpanel/pufferd/httphandlers"
	"github.com/pufferpanel/pufferd/logging"
	"github.com/pufferpanel/pufferd/programs"
	"github.com/pufferpanel/pufferd/utils"
	"github.com/pkg/errors"
	"strings"
	"strconv"
)

var wsupgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
}

func RegisterRoutes(e *gin.Engine) {
	l := e.Group("/server")
	{
		e.Handle("CONNECT", "/:id/console", func(c *gin.Context) {
			c.Header("Access-Control-Allow-Origin", "*")
			c.Header("Access-Control-Allow-Credentials", "false")
		})
		l.Use(httphandlers.OAuth2Handler)
		l.PUT("/:id", CreateServer)
		l.DELETE("/:id", DeleteServer)
		l.POST("/:id", EditServer)
		l.GET("/:id/start", StartServer)
		l.GET("/:id/stop", StopServer)
		l.POST("/:id/install", InstallServer)
		l.GET("/:id/file/*filename", GetFile)
		l.PUT("/:id/file/*filename", PutFile)
		l.POST("/:id/console", PostConsole)
		l.GET("/:id/stats", GetStats)
		l.POST("/:id/reload", ReloadServer)
		l.GET("/:id/console", cors.Middleware(cors.Config{
			Origins:     "*",
			Credentials: true,
		}), GetConsole)
		l.GET("/:id/logs", GetLogs)
	}
	e.GET("/network", httphandlers.OAuth2Handler, NetworkServer)
}

func StartServer(c *gin.Context) {
	valid, existing := handleInitialCallServer(c, "server.start", true)

	if !valid {
		c.Status(404)
		return
	}

	existing.Start()
}

func StopServer(c *gin.Context) {
	valid, existing := handleInitialCallServer(c, "server.stop", true)
	wait := c.Param("wait")
	if wait == "" || (wait != "true" && wait != "false") {
		wait = "true"
	}

	if !valid {
		return
	}

	err := existing.Stop()
	if err != nil {
		c.Error(err)
	}

	if wait == "true" {
		err = existing.GetEnvironment().WaitForMainProcess()
		if err != nil {
			c.Error(err)
		}
	}
}

func CreateServer(c *gin.Context) {
	serverId := c.Param("id")
	handleInitialCallServer(c, "server.create", false)

	existing := programs.GetFromCache(serverId)

	if existing != nil {
		c.AbortWithStatus(409)
		return
	}

	data := make(map[string]interface{}, 0)
	err := json.NewDecoder(c.Request.Body).Decode(&data)

	if err != nil {
		logging.Error("Error decoding JSON body", err)
		c.AbortWithError(400, err)
		return
	}

	serverType := data["type"].(string)

	if !programs.Create(serverId, serverType, data) {
		c.AbortWithStatus(500)
	}
}

func DeleteServer(c *gin.Context) {
	valid, existing := handleInitialCallServer(c, "server.delete", true)

	if !valid {
		return
	}

	programs.Delete(existing.Id())
	c.Status(204)
}

func InstallServer(c *gin.Context) {
	valid, existing := handleInitialCallServer(c, "server.install", true)

	if !valid {
		return
	}

	c.Status(200)
	go func() {
		existing.Install()
	}()
}

func EditServer(c *gin.Context) {
	valid, existing := handleInitialCallServer(c, "server.edit", true)

	if !valid {
		return
	}

	data := make(map[string]interface{}, 0)
	json.NewDecoder(c.Request.Body).Decode(&data)

	c.Status(200)
	existing.Edit(data)
}

func GetFile(c *gin.Context) {

	valid, server := handleInitialCallServer(c, "server.file.get", true)

	if !valid {
		return
	}

	targetPath := c.Param("filename")

	targetFile := utils.JoinPath(server.GetEnvironment().GetRootDirectory(), targetPath)

	if !utils.EnsureAccess(targetFile, server.GetEnvironment().GetRootDirectory()) {
		return
	}

	info, err := os.Stat(targetFile)

	if os.IsNotExist(err) {
		c.Status(404)
		return
	}

	if info.IsDir() {

		type FileDesc struct {
			Name      string    `json:"name"`
			Modified  time.Time `json:"modifyTime"`
			Size      int64     `json:"size,omitempty"`
			File      bool      `json:"isFile"`
			Extension string    `json:"extension,omitempty"`
		}

		files, _ := ioutil.ReadDir(targetFile)
		fileNames := make([]interface{}, 0)
		if targetFile != "." {
			newFile := &FileDesc{
				Name:      "..",
				File:      false,
			}
			fileNames = append(fileNames, newFile)
		}
		for _, file := range files {
			newFile := &FileDesc{
				Name:      file.Name(),
				File:      !file.IsDir(),
			}

			if newFile.File {
				newFile.Size = file.Size()
				newFile.Modified = file.ModTime()
				newFile.Extension = filepath.Ext(file.Name())
			}

			fileNames = append(fileNames, newFile)
		}
		c.JSON(200, fileNames)
	} else {
		_, err := os.Open(targetFile)
		if err != nil {
			if err == os.ErrNotExist {
				c.AbortWithStatus(404)
			} else {
				c.AbortWithStatus(500)
			}
		}
		c.File(targetFile)
	}
}

func PutFile(c *gin.Context) {
	valid, server := handleInitialCallServer(c, "server.file.put", true)

	if !valid {
		return
	}

	targetPath := c.Param("filename")

	if targetPath == "" {
		c.Status(404)
		return
	}

	targetFile := utils.JoinPath(server.GetEnvironment().GetRootDirectory(), targetPath)

	if !utils.EnsureAccess(targetFile, server.GetEnvironment().GetRootDirectory()) {
		return
	}

	file, err := os.Create(targetFile)

	if err != nil {
		logging.Error("Error writing file", err)
		return
	}

	_, err = io.Copy(file, c.Request.Body)

	if err != nil {
		logging.Error("Error writing file", err)
	}
}

func PostConsole(c *gin.Context) {
	valid, program := handleInitialCallServer(c, "server.console.send", true)
	if !valid {
		return
	}
	d, _ := ioutil.ReadAll(c.Request.Body)
	cmd := string(d)
	err := program.Execute(cmd)
	if err != nil {
		c.Error(err)
	} else {
		c.Status(200)
	}
}

func GetConsole(c *gin.Context) {
	valid, program := handleInitialCallServer(c, "server.console", true)
	if !valid {
		return
	}
	conn, err := wsupgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		logging.Error("Error creating websocket", err)
		c.AbortWithError(500, err)
		return
	}
	console, _ := program.GetEnvironment().GetConsole()
	for _, v := range console {
		conn.WriteMessage(websocket.TextMessage, []byte(v))
	}
	program.GetEnvironment().AddListener(conn)
}

func GetStats(c *gin.Context) {
	valid, server := handleInitialCallServer(c, "server.stats", true)

	if !valid {
		return
	}

	results, err := server.GetEnvironment().GetStats()
	if err != nil {
		result := make(map[string]interface{})
		result["error"] = err.Error()
		c.JSON(200, result)
	} else {
		c.JSON(200, results)
	}
}

func ReloadServer(c *gin.Context) {
	valid, existing := handleInitialCallServer(c, "server.reload", true)

	if !valid {
		c.Status(404)
		return
	}

	programs.Reload(existing.Id())
}

func NetworkServer(c *gin.Context) {

	scopes, _ := c.Get("scopes")
	valid := false
	for _, v := range scopes.([]string) {
		if v == "server.network"{
			valid = true
		}
	}
	if !valid {
		c.AbortWithStatus(401)
		return
	}

	servers := c.DefaultQuery("ids", "")
	if servers == "" {
		c.AbortWithError(400, errors.New("Server ids required"))
		return
	}
	serverIds := strings.Split(servers, ",")
	result := make(map[string]string)
	for _, v := range serverIds {
		program, _ := programs.Get(v)
		if program == nil {
			continue
		}
		result[program.Id()] = program.GetNetwork()
	}
	c.JSON(200, result)
}

func GetLogs (c *gin.Context) {
	valid, program := handleInitialCallServer(c, "server.console", true)
	if !valid {
		return
	}

	time := c.DefaultQuery("time", "0")

	castedTime, ok := strconv.ParseInt(time, 10, 64)

	if ok != nil {
		c.AbortWithError(400, errors.New("Time provided is not a valid UNIX time"))
		return
	}

	console, epoch := program.GetEnvironment().GetConsoleFrom(castedTime)
	msg := ""
	for _, k := range console {
		msg += k + "\n"
	}
	result := make(map[string]interface{})
	result["epoch"] = epoch
	result["logs"] = msg;
	c.JSON(200, result)
}

func handleInitialCallServer(c *gin.Context, perm string, requireServer bool) (valid bool, program programs.Program) {
	valid = false

	serverId := c.Param("id")
	canAccessId, _ := c.Get("server_id")

	accessId := canAccessId.(string)

	if accessId != serverId && accessId != "*" {
		c.AbortWithStatus(401)
		return
	}

	if accessId == "*" {
		program, _ = programs.Get(serverId)
	} else {
		program, _ = programs.Get(accessId)
	}

	if requireServer && program == nil {
		c.AbortWithStatus(404)
		valid = false
		return
	}

	scopes, _ := c.Get("scopes")

	for _, v := range scopes.([]string) {
		if v == perm {
			valid = true
		}
	}

	valid = true

	return
}
<commit_msg>Alter api to return unix time, add delete<commit_after>/*
 Copyright 2016 Padduck, LLC

 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 server

import (
	"encoding/json"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"

	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"github.com/itsjamie/gin-cors"
	"github.com/pufferpanel/pufferd/httphandlers"
	"github.com/pufferpanel/pufferd/logging"
	"github.com/pufferpanel/pufferd/programs"
	"github.com/pufferpanel/pufferd/utils"
	"github.com/pkg/errors"
	"strings"
	"strconv"
)

var wsupgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
}

func RegisterRoutes(e *gin.Engine) {
	l := e.Group("/server")
	{
		e.Handle("CONNECT", "/:id/console", func(c *gin.Context) {
			c.Header("Access-Control-Allow-Origin", "*")
			c.Header("Access-Control-Allow-Credentials", "false")
		})
		l.Use(httphandlers.OAuth2Handler)
		l.PUT("/:id", CreateServer)
		l.DELETE("/:id", DeleteServer)
		l.POST("/:id", EditServer)
		l.GET("/:id/start", StartServer)
		l.GET("/:id/stop", StopServer)
		l.POST("/:id/install", InstallServer)
		l.GET("/:id/file/*filename", GetFile)
		l.PUT("/:id/file/*filename", PutFile)
		l.DELETE("/:id/file/*filename", DeleteFile)
		l.POST("/:id/console", PostConsole)
		l.GET("/:id/stats", GetStats)
		l.POST("/:id/reload", ReloadServer)
		l.GET("/:id/console", cors.Middleware(cors.Config{
			Origins:     "*",
			Credentials: true,
		}), GetConsole)
		l.GET("/:id/logs", GetLogs)
	}
	e.GET("/network", httphandlers.OAuth2Handler, NetworkServer)
}

func StartServer(c *gin.Context) {
	valid, existing := handleInitialCallServer(c, "server.start", true)

	if !valid {
		c.Status(404)
		return
	}

	existing.Start()
}

func StopServer(c *gin.Context) {
	valid, existing := handleInitialCallServer(c, "server.stop", true)
	wait := c.Param("wait")
	if wait == "" || (wait != "true" && wait != "false") {
		wait = "true"
	}

	if !valid {
		return
	}

	err := existing.Stop()
	if err != nil {
		c.Error(err)
	}

	if wait == "true" {
		err = existing.GetEnvironment().WaitForMainProcess()
		if err != nil {
			c.Error(err)
		}
	}
}

func CreateServer(c *gin.Context) {
	serverId := c.Param("id")
	handleInitialCallServer(c, "server.create", false)

	existing := programs.GetFromCache(serverId)

	if existing != nil {
		c.AbortWithStatus(409)
		return
	}

	data := make(map[string]interface{}, 0)
	err := json.NewDecoder(c.Request.Body).Decode(&data)

	if err != nil {
		logging.Error("Error decoding JSON body", err)
		c.AbortWithError(400, err)
		return
	}

	serverType := data["type"].(string)

	if !programs.Create(serverId, serverType, data) {
		c.AbortWithStatus(500)
	}
}

func DeleteServer(c *gin.Context) {
	valid, existing := handleInitialCallServer(c, "server.delete", true)

	if !valid {
		return
	}

	programs.Delete(existing.Id())
	c.Status(204)
}

func InstallServer(c *gin.Context) {
	valid, existing := handleInitialCallServer(c, "server.install", true)

	if !valid {
		return
	}

	c.Status(200)
	go func() {
		existing.Install()
	}()
}

func EditServer(c *gin.Context) {
	valid, existing := handleInitialCallServer(c, "server.edit", true)

	if !valid {
		return
	}

	data := make(map[string]interface{}, 0)
	json.NewDecoder(c.Request.Body).Decode(&data)

	c.Status(200)
	existing.Edit(data)
}

func GetFile(c *gin.Context) {

	valid, server := handleInitialCallServer(c, "server.file.get", true)

	if !valid {
		return
	}

	targetPath := c.Param("filename")

	targetFile := utils.JoinPath(server.GetEnvironment().GetRootDirectory(), targetPath)

	if !utils.EnsureAccess(targetFile, server.GetEnvironment().GetRootDirectory()) {
		return
	}

	info, err := os.Stat(targetFile)

	if os.IsNotExist(err) {
		c.Status(404)
		return
	}

	if info.IsDir() {

		type FileDesc struct {
			Name      string    `json:"name"`
			Modified  int64     `json:"modifyTime"`
			Size      int64     `json:"size,omitempty"`
			File      bool      `json:"isFile"`
			Extension string    `json:"extension,omitempty"`
		}

		files, _ := ioutil.ReadDir(targetFile)
		fileNames := make([]interface{}, 0)
		if targetFile != "." {
			newFile := &FileDesc{
				Name:      "..",
				File:      false,
			}
			fileNames = append(fileNames, newFile)
		}
		for _, file := range files {
			newFile := &FileDesc{
				Name:      file.Name(),
				File:      !file.IsDir(),
			}

			if newFile.File {
				newFile.Size = file.Size()
				newFile.Modified = file.ModTime().Unix()
				newFile.Extension = filepath.Ext(file.Name())
			}

			fileNames = append(fileNames, newFile)
		}
		c.JSON(200, fileNames)
	} else {
		_, err := os.Open(targetFile)
		if err != nil {
			if err == os.ErrNotExist {
				c.AbortWithStatus(404)
			} else {
				c.AbortWithStatus(500)
			}
		}
		c.File(targetFile)
	}
}

func PutFile(c *gin.Context) {
	valid, server := handleInitialCallServer(c, "server.file.put", true)

	if !valid {
		return
	}

	targetPath := c.Param("filename")

	if targetPath == "" {
		c.Status(404)
		return
	}

	targetFile := utils.JoinPath(server.GetEnvironment().GetRootDirectory(), targetPath)

	if !utils.EnsureAccess(targetFile, server.GetEnvironment().GetRootDirectory()) {
		return
	}

	file, err := os.Create(targetFile)

	if err != nil {
		logging.Error("Error writing file", err)
		return
	}

	_, err = io.Copy(file, c.Request.Body)

	if err != nil {
		logging.Error("Error writing file", err)
	}
}

func DeleteFile (c *gin.Context) {
	valid, server := handleInitialCallServer(c, "server.file.delete", true)

	if !valid {
		return
	}

	targetPath := c.Param("filename")

	targetFile := utils.JoinPath(server.GetEnvironment().GetRootDirectory(), targetPath)

	if !utils.EnsureAccess(targetFile, server.GetEnvironment().GetRootDirectory()) {
		return
	}

	err := os.Remove(targetFile)
	if err != nil {
		c.Status(500)
		logging.Error("Failed to delete file", err)
	} else {
		c.Status(204)
	}
}

func PostConsole(c *gin.Context) {
	valid, program := handleInitialCallServer(c, "server.console.send", true)
	if !valid {
		return
	}
	d, _ := ioutil.ReadAll(c.Request.Body)
	cmd := string(d)
	err := program.Execute(cmd)
	if err != nil {
		c.Error(err)
	} else {
		c.Status(200)
	}
}

func GetConsole(c *gin.Context) {
	valid, program := handleInitialCallServer(c, "server.console", true)
	if !valid {
		return
	}
	conn, err := wsupgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		logging.Error("Error creating websocket", err)
		c.AbortWithError(500, err)
		return
	}
	console, _ := program.GetEnvironment().GetConsole()
	for _, v := range console {
		conn.WriteMessage(websocket.TextMessage, []byte(v))
	}
	program.GetEnvironment().AddListener(conn)
}

func GetStats(c *gin.Context) {
	valid, server := handleInitialCallServer(c, "server.stats", true)

	if !valid {
		return
	}

	results, err := server.GetEnvironment().GetStats()
	if err != nil {
		result := make(map[string]interface{})
		result["error"] = err.Error()
		c.JSON(200, result)
	} else {
		c.JSON(200, results)
	}
}

func ReloadServer(c *gin.Context) {
	valid, existing := handleInitialCallServer(c, "server.reload", true)

	if !valid {
		c.Status(404)
		return
	}

	programs.Reload(existing.Id())
}

func NetworkServer(c *gin.Context) {

	scopes, _ := c.Get("scopes")
	valid := false
	for _, v := range scopes.([]string) {
		if v == "server.network"{
			valid = true
		}
	}
	if !valid {
		c.AbortWithStatus(401)
		return
	}

	servers := c.DefaultQuery("ids", "")
	if servers == "" {
		c.AbortWithError(400, errors.New("Server ids required"))
		return
	}
	serverIds := strings.Split(servers, ",")
	result := make(map[string]string)
	for _, v := range serverIds {
		program, _ := programs.Get(v)
		if program == nil {
			continue
		}
		result[program.Id()] = program.GetNetwork()
	}
	c.JSON(200, result)
}

func GetLogs (c *gin.Context) {
	valid, program := handleInitialCallServer(c, "server.console", true)
	if !valid {
		return
	}

	time := c.DefaultQuery("time", "0")

	castedTime, ok := strconv.ParseInt(time, 10, 64)

	if ok != nil {
		c.AbortWithError(400, errors.New("Time provided is not a valid UNIX time"))
		return
	}

	console, epoch := program.GetEnvironment().GetConsoleFrom(castedTime)
	msg := ""
	for _, k := range console {
		msg += k + "\n"
	}
	result := make(map[string]interface{})
	result["epoch"] = epoch
	result["logs"] = msg;
	c.JSON(200, result)
}

func handleInitialCallServer(c *gin.Context, perm string, requireServer bool) (valid bool, program programs.Program) {
	valid = false

	serverId := c.Param("id")
	canAccessId, _ := c.Get("server_id")

	accessId := canAccessId.(string)

	if accessId != serverId && accessId != "*" {
		c.AbortWithStatus(401)
		return
	}

	if accessId == "*" {
		program, _ = programs.Get(serverId)
	} else {
		program, _ = programs.Get(accessId)
	}

	if requireServer && program == nil {
		c.AbortWithStatus(404)
		valid = false
		return
	}

	scopes, _ := c.Get("scopes")

	for _, v := range scopes.([]string) {
		if v == perm {
			valid = true
		}
	}

	valid = true

	return
}
<|endoftext|>


<commit_before>package zipext

import (
	"archive/zip"
	"fmt"

	"os"
	"path/filepath"
	"reflect"
	"strings"
	"testing"

	"github.com/enr/go-commons/lang"
)

func TestCreateFlatWin(t *testing.T) {
	testdataDir, _ := filepath.Abs("testdata")
	contents := filepath.FromSlash(fmt.Sprintf("%s/files", testdataDir))
	outputDir, _ := filepath.Abs("output")
	zipPath := filepath.FromSlash(fmt.Sprintf("%s/TestCreate_win_01.zip", outputDir))

	// clean paths
	deleteFile(zipPath, t)
	createDir(outputDir, t)

	var b string
	// check which/how many files will be putted in the zip
	testfiles := make([]string, 1)
	filepath.Walk(contents, func(path string, info os.FileInfo, err error) error {
		if info.Mode().IsRegular() {
			b = strings.Replace(filepath.FromSlash(path), contents, "", 1)
			c := strings.TrimLeft(filepath.ToSlash(b), "/")
			testfiles = append(testfiles, c)
		}
		return nil
	})

	// create the zip
	err := CreateFlat(contents, zipPath)
	if err != nil {
		t.Errorf("error in Create(%s,%s): %s %s", contents, zipPath, reflect.TypeOf(err), err.Error())
	}

	// walk the created zip file and register contents
	zipfiles := make([]string, 1)
	Walk(zipPath, func(f *zip.File, err error) error {
		zipfiles = append(zipfiles, f.Name)
		return nil
	})

	// verify that zip contents are the expected files
	testfilesNum := len(testfiles)
	zipfilesNum := len(zipfiles)
	if testfilesNum != zipfilesNum {
		t.Errorf("expected len zipfiles %d but found %d", testfilesNum, zipfilesNum)
	}
	for _, tf := range testfiles {
		if !lang.SliceContainsString(zipfiles, tf) {
			t.Errorf(`expected "%s" not found in zip`, tf)
		}
	}
}
<commit_msg>win test<commit_after>// +build windows

package zipext

import (
	"archive/zip"
	"fmt"

	"os"
	"path/filepath"
	"reflect"
	"strings"
	"testing"

	"github.com/enr/go-commons/lang"
)

func TestCreateFlatWin(t *testing.T) {
	testdataDir, _ := filepath.Abs("testdata")
	contents := filepath.FromSlash(fmt.Sprintf("%s/files", testdataDir))
	outputDir, _ := filepath.Abs("output")
	zipPath := filepath.FromSlash(fmt.Sprintf("%s/TestCreate_win_01.zip", outputDir))

	// clean paths
	deleteFile(zipPath, t)
	createDir(outputDir, t)

	var b string
	// check which/how many files will be putted in the zip
	testfiles := make([]string, 1)
	filepath.Walk(contents, func(path string, info os.FileInfo, err error) error {
		if info.Mode().IsRegular() {
			b = strings.Replace(filepath.FromSlash(path), contents, "", 1)
			c := strings.TrimLeft(filepath.ToSlash(b), "/")
			testfiles = append(testfiles, c)
		}
		return nil
	})

	// create the zip
	err := CreateFlat(contents, zipPath)
	if err != nil {
		t.Errorf("error in Create(%s,%s): %s %s", contents, zipPath, reflect.TypeOf(err), err.Error())
	}

	// walk the created zip file and register contents
	zipfiles := make([]string, 1)
	Walk(zipPath, func(f *zip.File, err error) error {
		zipfiles = append(zipfiles, f.Name)
		return nil
	})

	// verify that zip contents are the expected files
	testfilesNum := len(testfiles)
	zipfilesNum := len(zipfiles)
	if testfilesNum != zipfilesNum {
		t.Errorf("expected len zipfiles %d but found %d", testfilesNum, zipfilesNum)
	}
	for _, tf := range testfiles {
		if !lang.SliceContainsString(zipfiles, tf) {
			t.Errorf(`expected "%s" not found in zip`, tf)
		}
	}
}
<|endoftext|>


<commit_before>package parser

import (
	"fmt"
	"io"
	"log"
	"net"
	"net/mail"
	"strconv"
	"text/scanner"
	"unicode"
)

type Lexer struct {
	scanner.Scanner
	result Checker
}

func NewLexer(src io.Reader) *Lexer {
	var lex Lexer
	lex.Init(src)
	lex.Mode &^= scanner.ScanInts | scanner.ScanFloats | scanner.ScanChars | scanner.ScanRawStrings | scanner.ScanComments | scanner.SkipComments
	lex.IsIdentRune = isIdentRune
	return &lex
}

func isIdentRune(ch rune, i int) bool {
	return ch == '_' || ch == '.' || ch == '@' || unicode.IsLetter(ch) || unicode.IsDigit(ch)
}

func (l *Lexer) Lex(lval *yySymType) int {
	token := int(l.Scan())
	s := l.TokenText()

	log.Printf("token text: %s\n", s)

	if net.ParseIP(s) != nil {
		token = IPADDR
	}

	_, err := mail.ParseAddress(s)
	if err == nil {
		token = EMAIL
	}

	if s == "{" {
		token = LB
	} else if s == "}" {
		token = RB
	} else if s == "global_defs" {
		token = GLOBALDEFS
	} else if s == "notification_email" {
		token = NOTIFICATION_EMAIL
	} else if s == "notification_email_from" {
		token = NOTIFICATION_EMAIL_FROM
	} else if s == "smtp_server" {
		token = SMTP_SERVER
	} else if s == "smtp_connect_timeout" {
		token = SMTP_CONNECT_TIMEOUT
	} else if s == "router_id" {
		token = ROUTER_ID
	} else if s == "vrrp_instance" {
		token = VRRP_INSTANCE
	} else if s == "interface" {
		token = INTERFACE
	} else if s == "virtual_router_id" {
		token = VIRTUAL_ROUTER_ID
	}

	// Is Integer?
	if val, err := strconv.Atoi(s); err == nil {
		token = NUMBER
		if val >= 0 {
			return POSITIVE_INT
		}
	}

	if token == scanner.Ident {
		token = STRING
	}
	return token
}

func (l *Lexer) Error(e string) {
	fmt.Printf("Error Line %d, Pos %d\n", l.Line, l.Column)
	panic(e)
}

<commit_msg>Replace if elseif into symbol tables<commit_after>package parser

import (
	"fmt"
	"io"
	"log"
	"net"
	"net/mail"
	"strconv"
	"text/scanner"
	"unicode"
)

var SYMBOL_TABLES = map[string]int{
	"{": LB,
	"}": RB,
	"global_defs": GLOBALDEFS,
	"notification_email":NOTIFICATION_EMAIL,
	"notification_email_from": NOTIFICATION_EMAIL_FROM,
	"smtp_server": SMTP_SERVER,
	"smtp_connect_timeout": SMTP_CONNECT_TIMEOUT,
	"router_id": ROUTER_ID,
	"vrrp_instance": VRRP_INSTANCE,
	"interface": INTERFACE,
	"virtual_router_id": VIRTUAL_ROUTER_ID,
}

type Lexer struct {
	scanner.Scanner
	result Checker
}

func NewLexer(src io.Reader) *Lexer {
	var lex Lexer
	lex.Init(src)
	lex.Mode &^= scanner.ScanInts | scanner.ScanFloats | scanner.ScanChars | scanner.ScanRawStrings | scanner.ScanComments | scanner.SkipComments
	lex.IsIdentRune = isIdentRune
	return &lex
}

func isIdentRune(ch rune, i int) bool {
	return ch == '_' || ch == '.' || ch == '@' || unicode.IsLetter(ch) || unicode.IsDigit(ch)
}

func (l *Lexer) Lex(lval *yySymType) int {
	token := int(l.Scan())
	s := l.TokenText()

	log.Printf("token text: %s\n", s)

	if net.ParseIP(s) != nil {
		token = IPADDR
	}

	_, err := mail.ParseAddress(s)
	if err == nil {
		token = EMAIL
	}

	if _, ok := SYMBOL_TABLES[s]; ok {
		token = SYMBOL_TABLES[s]
	}

	// Is Integer?
	if val, err := strconv.Atoi(s); err == nil {
		token = NUMBER
		if val >= 0 {
			return POSITIVE_INT
		}
	}

	if token == scanner.Ident {
		token = STRING
	}
	return token
}

func (l *Lexer) Error(e string) {
	fmt.Printf("Error Line %d, Pos %d\n", l.Line, l.Column)
	panic(e)
}

<|endoftext|>


<commit_before>// Copyright 2015 The Numgrad Authors. All rights reserved.
// See the LICENSE file for rights to use this source code.

package parser

import "fmt"

//go:generate stringer -type=Token

// Token is a numgrad lexical token.
type Token int

const (
	Unknown Token = iota
	Comment

	// Constants

	Identifier // funcName
	Int        // 1001
	Float      // 10.01
	Imaginary  // 10.01i
	String     // "a string"

	// Expression Operators

	Add          // +
	Sub          // -
	Mul          // *
	Div          // /
	Rem          // %
	Pow          // ^
	And          // &&
	Or           // ||
	Equal        // ==
	Less         // <
	Greater      // >
	Assign       // =
	Not          // !
	NotEqual     // !=
	LessEqual    // <=
	GreaterEqual // >=

	// Statement Operators

	Inc       // ++
	Dec       // --
	AddAssign // +=
	SubAssign // -=
	MulAssign // *=
	DivAssign // /=
	RemAssign // %=
	PowAssign // ^=
	Define    // :=

	LeftParen    // (
	LeftBracket  // [
	LeftBrace    // {
	RightParen   // )
	RightBracket // ]
	RightBrace   // }
	Comma        // ,
	Period       // .
	Semicolon    // ;
	Colon        // :

	// Keywords

	Package
	Import

	Func
	Return

	Switch
	Case
	Default
	Fallthrough

	Const

	If
	Else

	For
	Range
	Continue
	Break
	Goto

	Go

	Frame
	Map
	Struct
	Type
)

var tokens = map[string]Token{
	"Unknown":      Unknown,
	"Comment":      Comment,
	"Identifier":   Identifier,
	"Int":          Int,
	"Float":        Float,
	"Imaginary":    Imaginary,
	"string":       String,
	"Add":          Add,
	"Sub":          Sub,
	"Mul":          Mul,
	"Div":          Div,
	"Rem":          Rem,
	"Pow":          Pow,
	"And":          And,
	"Or":           Or,
	"Equal":        Equal,
	"Less":         Less,
	"Greater":      Greater,
	"Assign":       Assign,
	"Not":          Not,
	"NotEqual":     NotEqual,
	"LessEqual":    LessEqual,
	"GreaterEqual": GreaterEqual,
	"Inc":          Inc,
	"Dec":          Dec,
	"AddAssign":    AddAssign,
	"SubAssign":    SubAssign,
	"MulAssign":    MulAssign,
	"DivAssign":    DivAssign,
	"RemAssign":    RemAssign,
	"PowAssign":    PowAssign,
	"Define":       Define,
	"LeftParen":    LeftParen,
	"LeftBracket":  LeftBracket,
	"LeftBrace":    LeftBrace,
	"RightParen":   RightParen,
	"RightBracket": RightBracket,
	"RightBrace":   RightBrace,
	"Comma":        Comma,
	"Period":       Period,
	"Semicolon":    Semicolon,
	"Colon":        Colon,
	"package":      Package,
	"import":       Import,
	"func":         Func,
	"return":       Return,
	"switch":       Switch,
	"case":         Case,
	"default":      Default,
	"fallthrough":  Fallthrough,
	"const":        Const,
	"if":           If,
	"else":         Else,
	"for":          For,
	"range":        Range,
	"continue":     Continue,
	"break":        Break,
	"goto":         Goto,
	"go":           Go,
	"frame":        Frame,
	"map":          Map,
	"struct":       Struct,
	"type":         Type,
}

var tokenStrings = make(map[Token]string, len(tokens))

func init() {
	for s, t := range tokens {
		tokenStrings[t] = s
	}
}

func (t Token) String() string {
	if s := tokenStrings[t]; s != "" {
		return s
	}
	return fmt.Sprintf("parser.Token(%d)", t)
}
<commit_msg>token precedence<commit_after>// Copyright 2015 The Numgrad Authors. All rights reserved.
// See the LICENSE file for rights to use this source code.

package parser

import "fmt"

// Token is a numgrad lexical token.
type Token int

const (
	Unknown Token = iota
	Comment

	// Constants

	Identifier // funcName
	Int        // 1001
	Float      // 10.01
	Imaginary  // 10.01i
	String     // "a string"

	// Expression Operators

	Add          // +
	Sub          // -
	Mul          // *
	Div          // /
	Rem          // %
	Pow          // ^
	Ref          // &
	LogicalAnd   // &&
	LogicalOr    // ||
	Equal        // ==
	Less         // <
	Greater      // >
	Assign       // =
	Not          // !
	NotEqual     // !=
	LessEqual    // <=
	GreaterEqual // >=

	// Statement Operators

	Inc       // ++
	Dec       // --
	AddAssign // +=
	SubAssign // -=
	MulAssign // *=
	DivAssign // /=
	RemAssign // %=
	PowAssign // ^=
	Define    // :=

	LeftParen    // (
	LeftBracket  // [
	LeftBrace    // {
	RightParen   // )
	RightBracket // ]
	RightBrace   // }
	Comma        // ,
	Period       // .
	Semicolon    // ;
	Colon        // :

	// Keywords

	Package
	Import

	Func
	Return

	Switch
	Case
	Default
	Fallthrough

	Const

	If
	Else

	For
	Range
	Continue
	Break
	Goto

	Go

	Frame
	Map
	Struct
	Type
)

var tokens = map[string]Token{
	"Unknown":      Unknown,
	"Comment":      Comment,
	"Identifier":   Identifier,
	"Int":          Int,
	"Float":        Float,
	"Imaginary":    Imaginary,
	"string":       String,
	"Add":          Add,
	"Sub":          Sub,
	"Mul":          Mul,
	"Div":          Div,
	"Rem":          Rem,
	"Pow":          Pow,
	"LogicalAnd":   LogicalAnd,
	"LogicalOr":    LogicalOr,
	"Equal":        Equal,
	"Less":         Less,
	"Greater":      Greater,
	"Assign":       Assign,
	"Not":          Not,
	"NotEqual":     NotEqual,
	"LessEqual":    LessEqual,
	"GreaterEqual": GreaterEqual,
	"Inc":          Inc,
	"Dec":          Dec,
	"AddAssign":    AddAssign,
	"SubAssign":    SubAssign,
	"MulAssign":    MulAssign,
	"DivAssign":    DivAssign,
	"RemAssign":    RemAssign,
	"PowAssign":    PowAssign,
	"Define":       Define,
	"LeftParen":    LeftParen,
	"LeftBracket":  LeftBracket,
	"LeftBrace":    LeftBrace,
	"RightParen":   RightParen,
	"RightBracket": RightBracket,
	"RightBrace":   RightBrace,
	"Comma":        Comma,
	"Period":       Period,
	"Semicolon":    Semicolon,
	"Colon":        Colon,
	"package":      Package,
	"import":       Import,
	"func":         Func,
	"return":       Return,
	"switch":       Switch,
	"case":         Case,
	"default":      Default,
	"fallthrough":  Fallthrough,
	"const":        Const,
	"if":           If,
	"else":         Else,
	"for":          For,
	"range":        Range,
	"continue":     Continue,
	"break":        Break,
	"goto":         Goto,
	"go":           Go,
	"frame":        Frame,
	"map":          Map,
	"struct":       Struct,
	"type":         Type,
}

var tokenStrings = make(map[Token]string, len(tokens))

func init() {
	for s, t := range tokens {
		tokenStrings[t] = s
	}
}

func (t Token) String() string {
	if s := tokenStrings[t]; s != "" {
		return s
	}
	return fmt.Sprintf("parser.Token(%d)", t)
}

func (t Token) Precedence() int {
	switch t {
	case LogicalOr:
		return 1
	case LogicalAnd:
		return 2
	case Equal, NotEqual, Less, LessEqual, Greater, GreaterEqual:
		return 3
	case Add, Sub:
		return 4
	case Mul, Div, Rem:
		return 5
	}
	return 0
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"github.com/kr/fs"
	"github.com/ogier/pflag"
	"os"
	"runtime"
	"strconv"
	"strings"
)

func getSearchSources() []string {
	home := os.Getenv("HOME")

	// OS X
	if runtime.GOOS == "darwin" {
		var sources []string

		sources = append(sources, "/etc/paths")

		walker := fs.Walk("/etc/paths.d")
		for walker.Step() {
			if err := walker.Err(); err != nil {
				fmt.Fprintln(os.Stderr, err)
				continue
			}

			if walker.Path() != "/etc/paths.d" {
				sources = append(sources, walker.Path())
			}
		}

		sources = append(sources, home+"/.bash_profile")

		return sources
	}

	// Ubuntu
	bashrc := home + "/.bashrc"
	bashprofile := home + "/.bash_profile"
	profile := home + "/.profile"
	env := "/etc/environment"

	return []string{bashrc, bashprofile, profile, env}
}

func appendSource(path string, pathChan chan string) {
	pathSetBy := path + " set by: "

	for _, source := range getSearchSources() {
		f, err := os.Open(source)
		if err != nil {
			// Allow execution to continue as some files are optional.
			//panic(err)
		}
		defer f.Close()

		scanner := bufio.NewScanner(f)
		for i := 1; scanner.Scan(); i++ {
			if runtime.GOOS == "darwin" {
				if strings.Contains(scanner.Text(), path) {
					p := pathSetBy + source + " (line " + strconv.Itoa(i) + ")"
					pathChan <- p
					return
				}
			} else {
				if strings.Contains(scanner.Text(), "PATH=") {
					if strings.Contains(scanner.Text(), path) {
						p := pathSetBy + source + " (line " + strconv.Itoa(i) + ")"
						pathChan <- p
						return
					}
				}
			}
		}
	}

	pathChan <- pathSetBy + "unknown"
	return
}

func returnPathList(detailedList bool) []string {
	pathList := strings.Split(os.Getenv("PATH"), ":")
	if !detailedList {
		return pathList
	}

	pathChan := make(chan string, len(pathList))
	for _, path := range pathList {
		go appendSource(path, pathChan)
	}

	var appendedPathList []string
	for i := 0; i < len(pathList); i++ {
		appendedPathList = append(appendedPathList, <-pathChan)
	}

	return appendedPathList
}

func main() {
	const listUsage = "use a long listing format"
	useList := pflag.BoolP("list", "l", false, listUsage)

	const detailedUsage = "use a (detailed) long listing format"
	detailedList := pflag.BoolP("detailed-list", "d", false, detailedUsage)

	pflag.Parse()

	if !(*useList || *detailedList) {
		fmt.Println(os.Getenv("PATH"))
		return
	}

	for _, p := range returnPathList(*detailedList) {
		fmt.Println(p)
	}
}
<commit_msg>Added comments.<commit_after>// pather is a command-line tool to make working with Unix paths easier.
package main

import (
	"bufio"
	"fmt"
	"github.com/kr/fs"
	"github.com/ogier/pflag"
	"os"
	"runtime"
	"strconv"
	"strings"
)

// GetSearchSources will return a list of search locations that typically set
// path elements. The list depends on the user's OS.
func getSearchSources() []string {
	home := os.Getenv("HOME")

	// OS X
	if runtime.GOOS == "darwin" {
		var sources []string

		sources = append(sources, "/etc/paths")

		walker := fs.Walk("/etc/paths.d")
		for walker.Step() {
			if err := walker.Err(); err != nil {
				fmt.Fprintln(os.Stderr, err)
				continue
			}

			// We want to exclude the top-level paths.d
			if walker.Path() != "/etc/paths.d" {
				sources = append(sources, walker.Path())
			}
		}

		sources = append(sources, home+"/.bash_profile")

		return sources
	}

	// Ubuntu
	bashrc := home + "/.bashrc"
	bashprofile := home + "/.bash_profile"
	profile := home + "/.profile"
	env := "/etc/environment"

	return []string{bashrc, bashprofile, profile, env}
}

// appendSource will search through a list of possible locations, provided by
// getSearchSources(), where the path may have been set and append that data to
// the path string. If it can't be located, "unknown" will be returned.
func appendSource(path string, pathChan chan string) {
	pathSetBy := path + " set by: "

	for _, source := range getSearchSources() {
		f, err := os.Open(source)
		if err != nil {
			// Allow execution to continue as some files are optional.
			//panic(err)
		}
		defer f.Close()

		scanner := bufio.NewScanner(f)
		for i := 1; scanner.Scan(); i++ {
			if runtime.GOOS == "darwin" {
				if strings.Contains(scanner.Text(), path) {
					p := pathSetBy + source + " (line " + strconv.Itoa(i) + ")"
					pathChan <- p
					return
				}
			} else {
				if strings.Contains(scanner.Text(), "PATH=") {
					if strings.Contains(scanner.Text(), path) {
						p := pathSetBy + source + " (line " + strconv.Itoa(i) + ")"
						pathChan <- p
						return
					}
				}
			}
		}
	}

	pathChan <- pathSetBy + "unknown"
	return
}

// returnPathList returns a slice of path strings with or without extra details.
// The strings should be printed to stdout.
func returnPathList(detailedList bool) []string {
	pathList := strings.Split(os.Getenv("PATH"), ":")
	if !detailedList {
		return pathList
	}

	pathChan := make(chan string, len(pathList))
	for _, path := range pathList {
		go appendSource(path, pathChan)
	}

	var appendedPathList []string
	for i := 0; i < len(pathList); i++ {
		appendedPathList = append(appendedPathList, <-pathChan)
	}

	return appendedPathList
}

func main() {
	const listUsage = "use a long listing format"
	useList := pflag.BoolP("list", "l", false, listUsage)

	const detailedUsage = "use a (detailed) long listing format"
	detailedList := pflag.BoolP("detailed-list", "d", false, detailedUsage)

	pflag.Parse()

	if !(*useList || *detailedList) {
		fmt.Println(os.Getenv("PATH"))
		return
	}

	for _, p := range returnPathList(*detailedList) {
		fmt.Println(p)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"

	log "github.com/Sirupsen/logrus"
	"github.com/google/go-github/github"
	"github.com/mattbaird/elastigo/core"
)

const (
	LabelsAttribute = "labels"
)

type Storage int

const (
	StoreSnapshot Storage = iota
	StoreCurrentState
	StoreLiveEvent
)

type blobStore struct {
	Client *github.Client
	Config *Config
}

func (b *blobStore) Index(storage Storage, repo *Repository, blob *Blob, id string) error {
	// Apply the transformation.
	if trans, ok := b.Config.Transformations[blob.Type()]; ok {
		b, err := trans.ApplyBlob(blob)
		if err != nil {
			return fmt.Errorf("applying transformation to event %q: %v", blob.Type(), err)
		}
		blob = b
	}

	switch storage {
	// Live is an index containing the webhook events. In this particular case,
	// we use the delivery id as the document index.
	//
	// When storing a live event, we always update the next two indices.
	case StoreLiveEvent:
		log.Debugf("store live event to %s/%s/%s", repo.LiveIndex(), blob.Type(), id)
		if _, err := core.Index(repo.LiveIndex(), blob.Type(), id, nil, blob.Data); err != nil {
			return fmt.Errorf("store live event %s data: %v", id, err)
		}
		id, blob = blob.Snapshot()
		fallthrough
	// Current state is an index containing the last version of items at a
	// given moment in time, and is updated at a frequency configured by the
	// user.
	//
	// When storing a current state, we always update the next index.
	case StoreCurrentState:
		if _, ok := GithubSnapshotedEvents[blob.Type()]; ok {
			log.Debugf("store current state to %s/%s/%s", repo.CurrentStateIndex(), blob.Type(), id)
			if _, err := core.Index(repo.CurrentStateIndex(), blob.Type(), id, nil, blob.Data); err != nil {
				return fmt.Errorf("store current state %s data: %v", id, err)
			}
		}
		fallthrough
	// Snapshot is an index containing the last version of all items, opened or
	// closed.
	case StoreSnapshot:
		if _, ok := GithubSnapshotedEvents[blob.Type()]; ok {
			log.Debugf("store snapshot to %s/%s/%s", repo.SnapshotIndex(), blob.Type(), id)
			log.Debugf("%#v\n", blob.Data)
			if _, err := core.Index(repo.SnapshotIndex(), blob.Type(), id, nil, blob.Data); err != nil {
				return fmt.Errorf("store snapshot %s data: %v", id, err)
			}
		}
	}
	return nil
}

func (b *blobStore) PrepareForStorage(repo *Repository, o *Blob) error {
	if o.Type() == EvtPullRequest && !o.HasAttribute(LabelsAttribute) {
		number := o.Data.Get("number").MustInt()
		log.Debugf("fetching labels for %s #%d", repo.PrettyName(), number)
		l, _, err := b.Client.Issues.ListLabelsByIssue(repo.User, repo.Repo, number, &github.ListOptions{})
		if err != nil {
			return fmt.Errorf("retrieve labels for issue %s: %v", number, err)
		}
		o.Push(LabelsAttribute, l)
	}
	return nil
}
<commit_msg>Remove debug print<commit_after>package main

import (
	"fmt"

	log "github.com/Sirupsen/logrus"
	"github.com/google/go-github/github"
	"github.com/mattbaird/elastigo/core"
)

const (
	LabelsAttribute = "labels"
)

type Storage int

const (
	StoreSnapshot Storage = iota
	StoreCurrentState
	StoreLiveEvent
)

func NewBlobStore(client *github.Client, config *Config) *blobStore {
	return &blobStore{
		Client: client,
		Config: config,
	}
}

type blobStore struct {
	Client *github.Client
	Config *Config
}

func (b *blobStore) Index(storage Storage, repo *Repository, blob *Blob, id string) error {
	// Apply the transformation.
	if trans, ok := b.Config.Transformations[blob.Type()]; ok {
		b, err := trans.ApplyBlob(blob)
		if err != nil {
			return fmt.Errorf("applying transformation to event %q: %v", blob.Type(), err)
		}
		blob = b
	}

	switch storage {
	// Live is an index containing the webhook events. In this particular case,
	// we use the delivery id as the document index.
	//
	// When storing a live event, we always update the next two indices.
	case StoreLiveEvent:
		log.Debugf("store live event to %s/%s/%s", repo.LiveIndex(), blob.Type(), id)
		if _, err := core.Index(repo.LiveIndex(), blob.Type(), id, nil, blob.Data); err != nil {
			return fmt.Errorf("store live event %s data: %v", id, err)
		}
		// Before falling through, replace the blob with the snapshot data from
		// the event, if any.
		if snapshotId, snapshotBlob := blob.Snapshot(); snapshotBlob != nil {
			id, blob = snapshotId, snapshotBlob
		}
		fallthrough
	// Current state is an index containing the last version of items at a
	// given moment in time, and is updated at a frequency configured by the
	// user.
	//
	// When storing a current state, we always update the next index.
	case StoreCurrentState:
		if _, ok := GithubSnapshotedEvents[blob.Type()]; ok {
			log.Debugf("store current state to %s/%s/%s", repo.CurrentStateIndex(), blob.Type(), id)
			if _, err := core.Index(repo.CurrentStateIndex(), blob.Type(), id, nil, blob.Data); err != nil {
				return fmt.Errorf("store current state %s data: %v", id, err)
			}
		}
		fallthrough
	// Snapshot is an index containing the last version of all items, opened or
	// closed.
	case StoreSnapshot:
		if _, ok := GithubSnapshotedEvents[blob.Type()]; ok {
			log.Debugf("store snapshot to %s/%s/%s", repo.SnapshotIndex(), blob.Type(), id)
			if _, err := core.Index(repo.SnapshotIndex(), blob.Type(), id, nil, blob.Data); err != nil {
				return fmt.Errorf("store snapshot %s data: %v", id, err)
			}
		}
	}
	return nil
}

func (b *blobStore) PrepareForStorage(repo *Repository, o *Blob) error {
	if o.Type() == EvtPullRequest && !o.HasAttribute(LabelsAttribute) {
		number := o.Data.Get("number").MustInt()
		log.Debugf("fetching labels for %s #%d", repo.PrettyName(), number)
		l, _, err := b.Client.Issues.ListLabelsByIssue(repo.User, repo.Repo, number, &github.ListOptions{})
		if err != nil {
			return fmt.Errorf("retrieve labels for issue %s: %v", number, err)
		}
		o.Push(LabelsAttribute, l)
	}
	return nil
}
<|endoftext|>


<commit_before>package toolbox

//ByteWriterAt  represents a bytes writer at
type ByteWriterAt struct {
	Buffer   []byte
	position int
}

//WriteAt returns number of written bytes or error
func (w *ByteWriterAt) WriteAt(p []byte, offset int64) (n int, err error) {
	if int(offset) == w.position {
		w.Buffer = append(w.Buffer, p...)
		w.position += len(p)
		return len(p), nil
	} else if w.position < int(offset) {
		var diff = (int(offset) - w.position)
		var fillingBytes = make([]byte, diff)
		w.position += len(fillingBytes)
		w.Buffer = append(w.Buffer, fillingBytes...)
		return w.WriteAt(p, offset)
	} else {
		for i := 0; i < len(p); i++ {
			var index = int(offset) + i
			if index < len(w.Buffer) {
				w.Buffer[int(offset)+i] = p[i]
			} else {
				w.Buffer = append(w.Buffer, p[i:]...)
				break
			}
		}
		return len(p), nil
	}
}

//NewWriterAt returns a new instance of byte writer at
func NewByteWriterAt() *ByteWriterAt {
	return &ByteWriterAt{
		Buffer: make([]byte, 0),
	}
}
<commit_msg>patched concurrent writess<commit_after>package toolbox

import (
	"sync"
)

//ByteWriterAt  represents a bytes writer at
type ByteWriterAt struct {
	mutex *sync.Mutex
	Buffer   []byte
	position int
}

//WriteAt returns number of written bytes or error
func (w *ByteWriterAt) WriteAt(p []byte, offset int64) (n int, err error) {
	w.mutex.Lock()

	if int(offset) == w.position {
		w.Buffer = append(w.Buffer, p...)
		w.position += len(p)
		w.mutex.Unlock()
		return len(p), nil
	} else if w.position < int(offset) {
		var diff = (int(offset) - w.position)
		var fillingBytes = make([]byte, diff)
		w.position += len(fillingBytes)
		w.Buffer = append(w.Buffer, fillingBytes...)
		w.mutex.Unlock()
		return w.WriteAt(p, offset)
	} else {
		for i := 0; i < len(p); i++ {
			var index = int(offset) + i
			if index < len(w.Buffer) {
				w.Buffer[int(offset)+i] = p[i]
			} else {
				w.Buffer = append(w.Buffer, p[i:]...)
				break
			}
		}
		w.mutex.Unlock()
		return len(p), nil
	}
}

//NewWriterAt returns a new instance of byte writer at
func NewByteWriterAt() *ByteWriterAt {
	return &ByteWriterAt{
		mutex:&sync.Mutex{},
		Buffer: make([]byte, 0),
	}
}
<|endoftext|>


<commit_before>package wx

import (
	"bytes"
	"crypto/tls"
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"net/http"
)

// constants for response.
const (
	Success = "SUCCESS"
)

// Config contains all configuration info.
type Config struct {
	AppID     string
	AppKey    string
	MchID     string
	NotifyURL string
	TradeType string
	SandBox   bool
}

// Client handles all transactions.
type Client struct {
	config    Config
	tlsClient http.Client
}

// NewClient returns a *Client ready to use.
func NewClient(cfg Config) *Client {
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: false},
	}
	client := http.Client{Transport: tr}
	return &Client{
		config:    cfg,
		tlsClient: client,
	}
}

// UnifiedOrder creates new order from Weixin.
func (c *Client) UnifiedOrder(totalFee int, desc, orderID, clientIP string) (*UnifiedOrderRsp, error) {
	req := unifiedOrderReq{
		AppID:          c.config.AppID,
		MchID:          c.config.MchID,
		NonceStr:       generateNonceStr(),
		Body:           desc,
		Attach:         "optional",
		OutTradeNo:     orderID,
		TotalFee:       fmt.Sprintf("%d", totalFee),
		SpbillCreateIP: clientIP,
		NotifyURL:      c.config.NotifyURL,
		TradeType:      c.config.TradeType,
	}

	reqMap, err := toMap(req)
	if err != nil {
		return nil, err
	}

	reqMap["sign"] = signature(reqMap, c.config.AppKey)
	xmlStr := toXMLStr(reqMap)

	uri := req.URI()
	if c.config.SandBox {
		uri = req.SandBoxURI()
	}

	data, err := c.doHTTPRequest(uri, xmlStr)
	if err != nil {
		return nil, err
	}

	rsp := &UnifiedOrderRsp{}
	if err = xml.NewDecoder(bytes.NewReader(data)).Decode(rsp); err != nil {
		return nil, err
	}

	rspMap, err := toMap(rsp)
	if err != nil {
		return nil, err
	}

	rspSign := signature(rspMap, c.config.AppKey)
	if rspSign != rspMap["sign"] {
		return nil, fmt.Errorf("signature failed, expected %s, got %s, response %#v, rsp map %v", rspSign, rspMap["sign"], rsp, rspMap)
	}

	if rsp.ReturnCode != Success {
		return nil, fmt.Errorf("return code %s, return msg %s", rsp.ReturnCode, rsp.ReturnMsg)
	}

	if rsp.ResultCode != Success {
		return nil, fmt.Errorf("err code %s, err code desc %s", rsp.ErrCode, rsp.ErrCodeDesc)
	}

	return rsp, nil
}

// ToPayment returns Payment from prePayID.
func (c *Client) ToPayment(prePayID string) Payment {
	nonceStr := generateNonceStr()
	timestampStr := generateTimestampStr()
	params := map[string]string{
		"appid":     c.config.AppID,
		"partnerid": c.config.MchID,
		"prepayid":  prePayID,
		"noncestr":  nonceStr,
		"timestamp": timestampStr,
		"package":   "Sign=WXPay",
	}

	return Payment{
		AppID:     c.config.AppID,
		PartnerID: c.config.MchID,
		PrepayID:  prePayID,
		NonceStr:  nonceStr,
		Timestamp: timestampStr,
		Package:   "Sign=WXPay",
		Sign:      signature(params, c.config.AppKey),
	}
}

// QueryOrder queries order info from Weixin.
func (c *Client) QueryOrder(transID string) (*QueryOrderRsp, error) {
	req := queryOrderReq{
		AppID:         c.config.AppID,
		MchID:         c.config.MchID,
		TransactionID: transID,
		NonceStr:      generateNonceStr(),
	}

	reqMap, err := toMap(req)
	if err != nil {
		return nil, err
	}

	reqMap["sign"] = signature(reqMap, c.config.AppKey)
	xmlStr := toXMLStr(reqMap)

	uri := req.URI()
	if c.config.SandBox {
		uri = req.SandBoxURI()
	}

	data, err := c.doHTTPRequest(uri, xmlStr)
	if err != nil {
		return nil, err
	}

	rsp := &QueryOrderRsp{}
	if err = xml.NewDecoder(bytes.NewReader(data)).Decode(rsp); err != nil {
		return nil, err
	}

	if rsp.ReturnCode != Success {
		return nil, fmt.Errorf("return code %s, return msg %s", rsp.ReturnCode, rsp.ReturnMsg)
	}

	rspMap, err := toMap(rsp)
	if err != nil {
		return nil, err
	}

	rspSign := signature(rspMap, c.config.AppKey)
	if rspSign != rspMap["sign"] {
		return nil, fmt.Errorf("signature failed, expected %s, got %s", rspSign, rspMap["sign"])
	}

	if rsp.ResultCode != Success {
		return nil, fmt.Errorf("err code %s, err code desc %s", rsp.ErrCode, rsp.ErrCodeDesc)
	}

	return rsp, nil
}

// AsyncNotification retrieves the asynchronous notification from Weixin.
func (c *Client) AsyncNotification(req *http.Request) (*AsyncNotificationResult, error) {
	defer req.Body.Close()
	result := &AsyncNotificationResult{}
	if err := xml.NewDecoder(req.Body).Decode(result); err != nil {
		return nil, err
	}

	if result.ReturnCode != Success {
		return nil, fmt.Errorf("return code %s, return msg %s", result.ReturnCode, result.ReturnMsg)
	}

	rspMap, err := toMap(result)
	if err != nil {
		return nil, err
	}

	rspSign := signature(rspMap, c.config.AppKey)
	if rspSign != rspMap["sign"] {
		return nil, fmt.Errorf("signature failed, expected %s, got %s", rspSign, rspMap["sign"])
	}

	if result.ResultCode != Success {
		return nil, fmt.Errorf("err code %s, err code desc %s", result.ErrCode, result.ErrCodeDesc)
	}

	return result, nil
}

// AnswerAsyncNotify returns a xml in string answering Weixin asynchronous notification.
func (c *Client) AnswerAsyncNotify(returnCode, returnMsg string) string {
	retMap := map[string]string{
		"return_code": returnCode,
		"return_msg":  returnMsg,
	}
	return toXMLStr(retMap)
}

// GetSandBoxSignKey gets sandox sign key from Weixin.
func (c *Client) GetSandBoxSignKey() (*GetSandBoxSignKeyRsp, error) {
	req := getSandBoxSignKeyReq{
		MchID:    c.config.MchID,
		NonceStr: generateNonceStr(),
	}

	reqMap, err := toMap(req)
	if err != nil {
		return nil, err
	}

	reqMap["sign"] = signature(reqMap, c.config.AppKey)
	xmlStr := toXMLStr(reqMap)

	data, err := c.doHTTPRequest(req.SandBoxURI(), xmlStr)
	if err != nil {
		return nil, err
	}

	rsp := &GetSandBoxSignKeyRsp{}
	if err = xml.NewDecoder(bytes.NewReader(data)).Decode(rsp); err != nil {
		return nil, err
	}

	if rsp.ReturnCode != Success {
		return nil, fmt.Errorf("return code %s, return msg %s", rsp.ReturnCode, rsp.ReturnMsg)
	}

	return rsp, nil
}

// AsyncNotificationResult is the result return from Weixin.
type AsyncNotificationResult struct {
	ReturnCode     string `xml:"return_code"`
	ReturnMsg      string `xml:"return_msg"`
	AppID          string `xml:"appid"`
	MchID          string `xml:"mch_id"`
	NonceStr       string `xml:"nonce_str"`
	Sign           string `xml:"sign"`
	ResultCode     string `xml:"result_code"`
	ErrCode        string `xml:"err_code"`
	ErrCodeDesc    string `xml:"err_code_des"`
	DeviceInfo     string `xml:"device_info"`
	OpenID         string `xml:"open_id"`
	IsSubscribe    string `xml:"is_subscribe"`
	TradeType      string `xml:"trade_type"`
	BankType       string `xml:"bank_type"`
	TotalFee       string `xml:"total_fee"`
	FeeType        string `xml:"fee_type"`
	CashFee        string `xml:"cash_fee"`
	CashFeeType    string `xml:"cash_fee_type"`
	CouponFee      string `xml:"coupon_fee"`
	CouponCount    string `xml:"coupon_count"`
	TransactionID  string `xml:"transaction_id"`
	OutTradeNo     string `xml:"out_trade_no"`
	Attach         string `xml:"attach"`
	TimeEnd        string `xml:"time_end"`
	TradeStateDesc string `xml:"trade_state_desc"`
}

func (c *Client) doHTTPRequest(uri string, xmlStr string) ([]byte, error) {
	req, err := http.NewRequest(http.MethodPost, uri, bytes.NewReader([]byte(xmlStr)))
	if err != nil {
		return nil, err
	}
	req.Header.Add("Content-type", "application/x-www-form-urlencoded;charset=UTF-8")

	rsp, err := c.tlsClient.Do(req)
	if err != nil {
		return nil, err
	}
	defer rsp.Body.Close()

	data, err := ioutil.ReadAll(rsp.Body)
	if err != nil {
		return nil, err
	}

	return data, nil
}
<commit_msg>check code before check signature<commit_after>package wx

import (
	"bytes"
	"crypto/tls"
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"net/http"
)

// constants for response.
const (
	Success = "SUCCESS"
)

// Config contains all configuration info.
type Config struct {
	AppID     string
	AppKey    string
	MchID     string
	NotifyURL string
	TradeType string
	SandBox   bool
}

// Client handles all transactions.
type Client struct {
	config    Config
	tlsClient http.Client
}

// NewClient returns a *Client ready to use.
func NewClient(cfg Config) *Client {
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: false},
	}
	client := http.Client{Transport: tr}
	return &Client{
		config:    cfg,
		tlsClient: client,
	}
}

// UnifiedOrder creates new order from Weixin.
func (c *Client) UnifiedOrder(totalFee int, desc, orderID, clientIP string) (*UnifiedOrderRsp, error) {
	req := unifiedOrderReq{
		AppID:          c.config.AppID,
		MchID:          c.config.MchID,
		NonceStr:       generateNonceStr(),
		Body:           desc,
		Attach:         "optional",
		OutTradeNo:     orderID,
		TotalFee:       fmt.Sprintf("%d", totalFee),
		SpbillCreateIP: clientIP,
		NotifyURL:      c.config.NotifyURL,
		TradeType:      c.config.TradeType,
	}

	reqMap, err := toMap(req)
	if err != nil {
		return nil, err
	}

	reqMap["sign"] = signature(reqMap, c.config.AppKey)
	xmlStr := toXMLStr(reqMap)

	uri := req.URI()
	if c.config.SandBox {
		uri = req.SandBoxURI()
	}

	data, err := c.doHTTPRequest(uri, xmlStr)
	if err != nil {
		return nil, err
	}

	rsp := &UnifiedOrderRsp{}
	if err = xml.NewDecoder(bytes.NewReader(data)).Decode(rsp); err != nil {
		return nil, err
	}

	if rsp.ReturnCode != Success {
		return nil, fmt.Errorf("return code %s, return msg %s", rsp.ReturnCode, rsp.ReturnMsg)
	}

	if rsp.ResultCode != Success {
		return nil, fmt.Errorf("err code %s, err code desc %s", rsp.ErrCode, rsp.ErrCodeDesc)
	}

	rspMap, err := toMap(rsp)
	if err != nil {
		return nil, err
	}
	rspSign := signature(rspMap, c.config.AppKey)
	if rspSign != rspMap["sign"] {
		return nil, fmt.Errorf("signature failed, expected %s, got %s", rspSign, rspMap["sign"])
	}

	return rsp, nil
}

// ToPayment returns Payment from prePayID.
func (c *Client) ToPayment(prePayID string) Payment {
	nonceStr := generateNonceStr()
	timestampStr := generateTimestampStr()
	params := map[string]string{
		"appid":     c.config.AppID,
		"partnerid": c.config.MchID,
		"prepayid":  prePayID,
		"noncestr":  nonceStr,
		"timestamp": timestampStr,
		"package":   "Sign=WXPay",
	}

	return Payment{
		AppID:     c.config.AppID,
		PartnerID: c.config.MchID,
		PrepayID:  prePayID,
		NonceStr:  nonceStr,
		Timestamp: timestampStr,
		Package:   "Sign=WXPay",
		Sign:      signature(params, c.config.AppKey),
	}
}

// QueryOrder queries order info from Weixin.
func (c *Client) QueryOrder(transID string) (*QueryOrderRsp, error) {
	req := queryOrderReq{
		AppID:         c.config.AppID,
		MchID:         c.config.MchID,
		TransactionID: transID,
		NonceStr:      generateNonceStr(),
	}

	reqMap, err := toMap(req)
	if err != nil {
		return nil, err
	}

	reqMap["sign"] = signature(reqMap, c.config.AppKey)
	xmlStr := toXMLStr(reqMap)

	uri := req.URI()
	if c.config.SandBox {
		uri = req.SandBoxURI()
	}

	data, err := c.doHTTPRequest(uri, xmlStr)
	if err != nil {
		return nil, err
	}

	rsp := &QueryOrderRsp{}
	if err = xml.NewDecoder(bytes.NewReader(data)).Decode(rsp); err != nil {
		return nil, err
	}

	if rsp.ReturnCode != Success {
		return nil, fmt.Errorf("return code %s, return msg %s", rsp.ReturnCode, rsp.ReturnMsg)
	}

	if rsp.ResultCode != Success {
		return nil, fmt.Errorf("err code %s, err code desc %s", rsp.ErrCode, rsp.ErrCodeDesc)
	}

	rspMap, err := toMap(rsp)
	if err != nil {
		return nil, err
	}

	rspSign := signature(rspMap, c.config.AppKey)
	if rspSign != rspMap["sign"] {
		return nil, fmt.Errorf("signature failed, expected %s, got %s", rspSign, rspMap["sign"])
	}

	return rsp, nil
}

// AsyncNotification retrieves the asynchronous notification from Weixin.
func (c *Client) AsyncNotification(req *http.Request) (*AsyncNotificationResult, error) {
	defer req.Body.Close()
	result := &AsyncNotificationResult{}
	if err := xml.NewDecoder(req.Body).Decode(result); err != nil {
		return nil, err
	}

	if result.ReturnCode != Success {
		return nil, fmt.Errorf("return code %s, return msg %s", result.ReturnCode, result.ReturnMsg)
	}

	rspMap, err := toMap(result)
	if err != nil {
		return nil, err
	}

	rspSign := signature(rspMap, c.config.AppKey)
	if rspSign != rspMap["sign"] {
		return nil, fmt.Errorf("signature failed, expected %s, got %s", rspSign, rspMap["sign"])
	}

	if result.ResultCode != Success {
		return nil, fmt.Errorf("err code %s, err code desc %s", result.ErrCode, result.ErrCodeDesc)
	}

	return result, nil
}

// AnswerAsyncNotify returns a xml in string answering Weixin asynchronous notification.
func (c *Client) AnswerAsyncNotify(returnCode, returnMsg string) string {
	retMap := map[string]string{
		"return_code": returnCode,
		"return_msg":  returnMsg,
	}
	return toXMLStr(retMap)
}

// GetSandBoxSignKey gets sandox sign key from Weixin.
func (c *Client) GetSandBoxSignKey() (*GetSandBoxSignKeyRsp, error) {
	req := getSandBoxSignKeyReq{
		MchID:    c.config.MchID,
		NonceStr: generateNonceStr(),
	}

	reqMap, err := toMap(req)
	if err != nil {
		return nil, err
	}

	reqMap["sign"] = signature(reqMap, c.config.AppKey)
	xmlStr := toXMLStr(reqMap)

	data, err := c.doHTTPRequest(req.SandBoxURI(), xmlStr)
	if err != nil {
		return nil, err
	}

	rsp := &GetSandBoxSignKeyRsp{}
	if err = xml.NewDecoder(bytes.NewReader(data)).Decode(rsp); err != nil {
		return nil, err
	}

	if rsp.ReturnCode != Success {
		return nil, fmt.Errorf("return code %s, return msg %s", rsp.ReturnCode, rsp.ReturnMsg)
	}

	return rsp, nil
}

// AsyncNotificationResult is the result return from Weixin.
type AsyncNotificationResult struct {
	ReturnCode     string `xml:"return_code"`
	ReturnMsg      string `xml:"return_msg"`
	AppID          string `xml:"appid"`
	MchID          string `xml:"mch_id"`
	NonceStr       string `xml:"nonce_str"`
	Sign           string `xml:"sign"`
	ResultCode     string `xml:"result_code"`
	ErrCode        string `xml:"err_code"`
	ErrCodeDesc    string `xml:"err_code_des"`
	DeviceInfo     string `xml:"device_info"`
	OpenID         string `xml:"open_id"`
	IsSubscribe    string `xml:"is_subscribe"`
	TradeType      string `xml:"trade_type"`
	BankType       string `xml:"bank_type"`
	TotalFee       string `xml:"total_fee"`
	FeeType        string `xml:"fee_type"`
	CashFee        string `xml:"cash_fee"`
	CashFeeType    string `xml:"cash_fee_type"`
	CouponFee      string `xml:"coupon_fee"`
	CouponCount    string `xml:"coupon_count"`
	TransactionID  string `xml:"transaction_id"`
	OutTradeNo     string `xml:"out_trade_no"`
	Attach         string `xml:"attach"`
	TimeEnd        string `xml:"time_end"`
	TradeStateDesc string `xml:"trade_state_desc"`
}

func (c *Client) doHTTPRequest(uri string, xmlStr string) ([]byte, error) {
	req, err := http.NewRequest(http.MethodPost, uri, bytes.NewReader([]byte(xmlStr)))
	if err != nil {
		return nil, err
	}
	req.Header.Add("Content-type", "application/x-www-form-urlencoded;charset=UTF-8")

	rsp, err := c.tlsClient.Do(req)
	if err != nil {
		return nil, err
	}
	defer rsp.Body.Close()

	data, err := ioutil.ReadAll(rsp.Body)
	if err != nil {
		return nil, err
	}

	return data, nil
}
<|endoftext|>


<commit_before>package permutation

import (
	"bytes"
	"testing"
)

type byteSlice []byte

func (p byteSlice) Len() int              { return len(p) }
func (p byteSlice) Less(i, j int) bool    { return p[i] < p[j] }
func (p byteSlice) Swap(i, j int)         { p[i], p[j] = p[j], p[i] }
func (p byteSlice) Equal(q Sequence) bool { return bytes.Compare(p, q.(byteSlice)) == 0 }
func (p byteSlice) Copy() Sequence        { return p[:] }

type permTest struct {
	seq   []byte
	perms [][]byte
}

var permsPositive = [...]permTest{
	{
		seq: []byte("bac"),
		perms: [][]byte{
			[]byte("abc"),
			[]byte("acb"),
			[]byte("bac"),
			[]byte("bca"),
			[]byte("cab"),
			[]byte("cba"),
		},
	},
}

func TestNext(t *testing.T) {
	for test, a := range permsPositive {
		p := New(byteSlice(a.seq))
		for i, ok, seq := 0, true, p.Current().(byteSlice); ok; i, ok, seq = i+1, p.Next(), p.Current().(byteSlice) {
			if string(seq) != string(a.perms[i]) {
				t.Errorf("%d: seq=%s, want=%s, got=%s", test, a.seq, a.perms[i], seq)
			} else {
				t.Logf("%d: seq=%s, want=%s, got=%s", test, a.seq, a.perms[i], seq)
			}
		}
	}
}

func TestLen(t *testing.T) {
	for test, a := range permsPositive {
		p := New(byteSlice(a.seq))
		if len(a.perms) != p.Len() {
			t.Errorf("%d: seq=%s, want=%v, got=%v", test, a.seq, len(a.perms), p.Len())
		} else {
			t.Logf("%d: seq=%s, want=%v, got=%v", test, a.seq, len(a.perms), p.Len())
		}
	}
}
<commit_msg>more and better testing<commit_after>package permutation

import (
	"bytes"
	"testing"
)

type byteSlice []byte

func (p byteSlice) Len() int              { return len(p) }
func (p byteSlice) Less(i, j int) bool    { return p[i] < p[j] }
func (p byteSlice) Swap(i, j int)         { p[i], p[j] = p[j], p[i] }
func (p byteSlice) Equal(q Sequence) bool { return bytes.Equal(p, q.(byteSlice)) }
func (p byteSlice) Copy() Sequence        { q := make(byteSlice, len(p), len(p)); copy(q, p); return q }

type permTest struct {
	seq   []byte
	perms [][]byte
}

var permsPositive = [...]permTest{
	{
		seq: []byte("bac"),
		perms: [][]byte{
			[]byte("abc"),
			[]byte("acb"),
			[]byte("bac"),
			[]byte("bca"),
			[]byte("cab"),
			[]byte("cba"),
		},
	},
}

func TestIteration(t *testing.T) {
	for test, a := range permsPositive {
		p := New(byteSlice(a.seq))
		for i, ok, seq := 0, true, p.Current().(byteSlice); ok; i, ok, seq = i+1, p.Next(), p.Current().(byteSlice) {
			if string(seq) != string(a.perms[i]) {
				t.Errorf("%d: seq=%s, want=%s, got=%s", test, a.seq, a.perms[i], seq)
			} else {
				t.Logf("%d: seq=%s, want=%s, got=%s", test, a.seq, a.perms[i], seq)
			}
		}
	}
}

func TestCompleteness(t *testing.T) {
	for test, a := range permsPositive {
		seen := map[string]bool{}
		for i := 0; i < len(a.perms); i++ {
			seen[string(a.perms[i])] = false
		}
		p := New(byteSlice(a.seq))
		for ok, seq := true, p.Current().(byteSlice); ok; ok, seq = p.Next(), p.Current().(byteSlice) {
			seen[string(seq)] = true
		}
		for seq, ok := range seen {
			if ok {
				t.Logf("%d: seen=%s", test, seq)
			} else {
				t.Errorf("%d: missing=%s", test, seq)
			}
		}
	}
}

func TestLen(t *testing.T) {
	for test, a := range permsPositive {
		p := New(byteSlice(a.seq))
		if len(a.perms) != p.Len() {
			t.Errorf("%d: seq=%s, want=%v, got=%v", test, a.seq, len(a.perms), p.Len())
		} else {
			t.Logf("%d: seq=%s, want=%v, got=%v", test, a.seq, len(a.perms), p.Len())
		}
	}
}
<|endoftext|>


<commit_before>package pgeventstore

import (
	"database/sql"
	"errors"
	log "github.com/Sirupsen/logrus"
	"github.com/lib/pq"
	"github.com/xtracdev/goes"
	"os"
	"time"
)

const (
	EventPublishEnvVar = "ES_PUBLISH_EVENTS"
)

var (
	ErrConcurrency = errors.New("Concurrency Exception")
	ErrPayloadType = errors.New("Only payloads of type []byte are allowed")
	ErrEventInsert = errors.New("Error inserting record into events table")
	ErrPubInsert   = errors.New("Error inserting record into pub table")
)

type PGEventStore struct {
	db      *sql.DB
	publish bool
}

func NewPGEventStore(db *sql.DB) (*PGEventStore, error) {
	log.Infof("Creating event store...")
	publishEvents := os.Getenv(EventPublishEnvVar)
	switch publishEvents {
	case "1":
		log.Info("Event store configured to write records to publish table")
	default:
		log.Info("Event store will not write records to publish table - export ",
			EventPublishEnvVar, "= 1 to enable writing to publish table")

	}

	return &PGEventStore{
		db:      db,
		publish: publishEvents == "1",
	}, nil
}

func (es *PGEventStore) GetMaxVersionForAggregate(aggId string) (*int, error) {
	row, err := es.db.Query("select max(version) from t_aeev_events where aggregate_id = $1", aggId)
	if err != nil {
		return nil, err
	}

	var max int
	row.Scan(&max)

	err = row.Err()
	if err != nil {
		return nil, err
	}

	return &max, nil
}

func (pg *PGEventStore) StoreEvents(agg *goes.Aggregate) error {
	//Select max for the aggregate id
	max, err := pg.GetMaxVersionForAggregate(agg.AggregateID)
	if err != nil {
		return err
	}

	//If the stored version is not smaller than the agg version then
	//its a concurrency exception. Note we'll have a null max if no record
	//exists
	if !(*max < agg.Version) {
		return ErrConcurrency
	}

	//Store the events
	return pg.writeEvents(agg)
}

func (pg *PGEventStore) writeEvents(agg *goes.Aggregate) error {

	log.Println("start transaction")
	tx, err := pg.db.Begin()
	if err != nil {
		return err
	}
	defer tx.Rollback()

	log.Println("create statement")
	stmt, err := tx.Prepare("insert into t_aeev_events (aggregate_id, version, typecode, payload) values ($1, $2, $3, $4)")
	if err != nil {
		return err
	}

	var pubStmt *sql.Stmt
	if pg.publish {
		log.Println("create publish statement")
		var pubstmtErr error
		pubStmt, pubstmtErr = tx.Prepare("insert into t_aepb_publish (aggregate_id, version, typecode, payload) values ($1, $2, $3, $4)")
		if pubstmtErr != nil {
			return pubstmtErr
		}
	}

	for _, e := range agg.Events {
		log.Printf("process event %v\n", e)
		eventBytes, ok := e.Payload.([]byte)
		if !ok {
			stmt.Close()
			return ErrPayloadType
		}

		log.Println("execute statement")
		_, execerr := stmt.Exec(agg.AggregateID, e.Version, e.TypeCode, eventBytes)
		if execerr != nil {
			stmt.Close()
			log.Println(execerr.Error())
			return ErrEventInsert
		}

		if pg.publish {
			log.Println("execute publish statement")
			_, puberr := pubStmt.Exec(agg.AggregateID, e.Version, e.TypeCode, eventBytes)
			if puberr != nil {
				log.Println(puberr.Error())
				return ErrPubInsert
			}
		}
	}

	stmt.Close()
	if pubStmt != nil {
		pubStmt.Close()
	}

	log.Println("commit transaction")
	err = tx.Commit()
	if err != nil {
		return err
	}

	return nil
}

func (ps *PGEventStore) RetrieveEvents(aggID string) ([]goes.Event, error) {
	var events []goes.Event

	//Select the events, ordered by version
	rows, err := ps.db.Query(`select version, typecode, payload from t_aeev_events where aggregate_id = $1 order by version`, aggID)
	if err != nil {
		return nil, err
	}

	defer rows.Close()

	var version int
	var typecode string
	var payload []byte

	for rows.Next() {
		rows.Scan(&version, &typecode, &payload)
		event := goes.Event{
			Source:   aggID,
			Version:  version,
			TypeCode: typecode,
			Payload:  payload,
		}

		events = append(events, event)

	}

	err = rows.Err()

	return events, err
}

func (ps *PGEventStore) RepublishAllEvents() error {

	var tx *sql.Tx = nil

	log.Debug("execute query")
	rows, err := ps.db.Query(`select event_time, aggregate_id, version, typecode, payload from t_aeev_events order by event_time`)
	if err != nil {
		return err
	}

	defer rows.Close()

	var version int
	var typecode string
	var payload []byte
	var eventTime time.Time
	var aggregateID string

	log.Debug("create transaction")

	for rows.Next() {
		tx, err = ps.db.Begin()
		if err != nil {
			return err
		}

		log.Debug("scan row")
		rows.Scan(&eventTime, &aggregateID, &version, &typecode, &payload)

		log.Debug("insert row")
		log.Infof("Publishing %s %d - %v", aggregateID, version, eventTime)
		_, err := tx.Exec(`insert into t_aepb_publish (event_time, aggregate_id, version, typecode, payload)  values($1,$2,$3,$4,$5)`,
			eventTime, aggregateID, version, typecode, payload,
		)

		if err != nil {
			pqError := err.(*pq.Error)
			log.Debug("%v", pqError.Code.Name())
			tx.Rollback()
			if pqError.Code.Name() != "unique_violation" {
				log.Debug("rollback transaction")
				return err
			} else {
				continue
			}
		}

		log.Debug("commit tx")
		err = tx.Commit()
		if err != nil {
			tx.Rollback()
			return err
		}

	}

	return nil
}
<commit_msg>close rows in GetMaxVersionForAggregate as causing DB connection pool leak<commit_after>package pgeventstore

import (
	"database/sql"
	"errors"
	"os"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/lib/pq"
	"github.com/xtracdev/goes"
)

const (
	EventPublishEnvVar = "ES_PUBLISH_EVENTS"
)

var (
	ErrConcurrency = errors.New("Concurrency Exception")
	ErrPayloadType = errors.New("Only payloads of type []byte are allowed")
	ErrEventInsert = errors.New("Error inserting record into events table")
	ErrPubInsert   = errors.New("Error inserting record into pub table")
)

type PGEventStore struct {
	db      *sql.DB
	publish bool
}

func NewPGEventStore(db *sql.DB) (*PGEventStore, error) {
	log.Infof("Creating event store...")
	publishEvents := os.Getenv(EventPublishEnvVar)
	switch publishEvents {
	case "1":
		log.Info("Event store configured to write records to publish table")
	default:
		log.Info("Event store will not write records to publish table - export ",
			EventPublishEnvVar, "= 1 to enable writing to publish table")

	}

	return &PGEventStore{
		db:      db,
		publish: publishEvents == "1",
	}, nil
}

func (es *PGEventStore) GetMaxVersionForAggregate(aggId string) (*int, error) {
	row, err := es.db.Query("select max(version) from t_aeev_events where aggregate_id = $1", aggId)
	if err != nil {
		return nil, err
	}
	defer row.Close()

	var max int
	row.Scan(&max)

	err = row.Err()
	if err != nil {
		return nil, err
	}

	return &max, nil
}

func (pg *PGEventStore) StoreEvents(agg *goes.Aggregate) error {
	//Select max for the aggregate id
	max, err := pg.GetMaxVersionForAggregate(agg.AggregateID)
	if err != nil {
		return err
	}

	//If the stored version is not smaller than the agg version then
	//its a concurrency exception. Note we'll have a null max if no record
	//exists
	if !(*max < agg.Version) {
		return ErrConcurrency
	}

	//Store the events
	return pg.writeEvents(agg)
}

func (pg *PGEventStore) writeEvents(agg *goes.Aggregate) error {

	log.Println("start transaction")
	tx, err := pg.db.Begin()
	if err != nil {
		return err
	}
	defer tx.Rollback()

	log.Println("create statement")
	stmt, err := tx.Prepare("insert into t_aeev_events (aggregate_id, version, typecode, payload) values ($1, $2, $3, $4)")
	if err != nil {
		return err
	}

	var pubStmt *sql.Stmt
	if pg.publish {
		log.Println("create publish statement")
		var pubstmtErr error
		pubStmt, pubstmtErr = tx.Prepare("insert into t_aepb_publish (aggregate_id, version, typecode, payload) values ($1, $2, $3, $4)")
		if pubstmtErr != nil {
			return pubstmtErr
		}
	}

	for _, e := range agg.Events {
		log.Printf("process event %v\n", e)
		eventBytes, ok := e.Payload.([]byte)
		if !ok {
			stmt.Close()
			return ErrPayloadType
		}

		log.Println("execute statement")
		_, execerr := stmt.Exec(agg.AggregateID, e.Version, e.TypeCode, eventBytes)
		if execerr != nil {
			stmt.Close()
			log.Println(execerr.Error())
			return ErrEventInsert
		}

		if pg.publish {
			log.Println("execute publish statement")
			_, puberr := pubStmt.Exec(agg.AggregateID, e.Version, e.TypeCode, eventBytes)
			if puberr != nil {
				log.Println(puberr.Error())
				return ErrPubInsert
			}
		}
	}

	stmt.Close()
	if pubStmt != nil {
		pubStmt.Close()
	}

	log.Println("commit transaction")
	err = tx.Commit()
	if err != nil {
		return err
	}

	return nil
}

func (ps *PGEventStore) RetrieveEvents(aggID string) ([]goes.Event, error) {
	var events []goes.Event

	//Select the events, ordered by version
	rows, err := ps.db.Query(`select version, typecode, payload from t_aeev_events where aggregate_id = $1 order by version`, aggID)
	if err != nil {
		return nil, err
	}

	defer rows.Close()

	var version int
	var typecode string
	var payload []byte

	for rows.Next() {
		rows.Scan(&version, &typecode, &payload)
		event := goes.Event{
			Source:   aggID,
			Version:  version,
			TypeCode: typecode,
			Payload:  payload,
		}

		events = append(events, event)

	}

	err = rows.Err()

	return events, err
}

func (ps *PGEventStore) RepublishAllEvents() error {

	var tx *sql.Tx = nil

	log.Debug("execute query")
	rows, err := ps.db.Query(`select event_time, aggregate_id, version, typecode, payload from t_aeev_events order by event_time`)
	if err != nil {
		return err
	}

	defer rows.Close()

	var version int
	var typecode string
	var payload []byte
	var eventTime time.Time
	var aggregateID string

	log.Debug("create transaction")

	for rows.Next() {
		tx, err = ps.db.Begin()
		if err != nil {
			return err
		}

		log.Debug("scan row")
		rows.Scan(&eventTime, &aggregateID, &version, &typecode, &payload)

		log.Debug("insert row")
		log.Infof("Publishing %s %d - %v", aggregateID, version, eventTime)
		_, err := tx.Exec(`insert into t_aepb_publish (event_time, aggregate_id, version, typecode, payload)  values($1,$2,$3,$4,$5)`,
			eventTime, aggregateID, version, typecode, payload,
		)

		if err != nil {
			pqError := err.(*pq.Error)
			log.Debug("%v", pqError.Code.Name())
			tx.Rollback()
			if pqError.Code.Name() != "unique_violation" {
				log.Debug("rollback transaction")
				return err
			} else {
				continue
			}
		}

		log.Debug("commit tx")
		err = tx.Commit()
		if err != nil {
			tx.Rollback()
			return err
		}

	}

	return nil
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.

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 importx

import (
	"context"
	"encoding/json"
	"flag"
	"os"

	"github.com/vmware/govmomi/ovf"
	"github.com/vmware/govmomi/vim25/types"
)

type Property struct {
	types.KeyValue
	Spec *ovf.Property `json:",omitempty"`
}

type Network struct {
	Name    string
	Network string
}

type Options struct {
	AllDeploymentOptions []string `json:",omitempty"`
	Deployment           string

	AllDiskProvisioningOptions []string `json:",omitempty"`
	DiskProvisioning           string

	AllIPAllocationPolicyOptions []string `json:",omitempty"`
	IPAllocationPolicy           string

	AllIPProtocolOptions []string `json:",omitempty"`
	IPProtocol           string

	PropertyMapping []Property `json:",omitempty"`

	NetworkMapping []Network `json:",omitempty"`

	Annotation string `json:",omitempty"`

	PowerOn      bool
	InjectOvfEnv bool
	WaitForIP    bool
	Name         *string
}

type OptionsFlag struct {
	Options Options

	path string
}

func newOptionsFlag(ctx context.Context) (*OptionsFlag, context.Context) {
	return &OptionsFlag{}, ctx
}

func (flag *OptionsFlag) Register(ctx context.Context, f *flag.FlagSet) {
	f.StringVar(&flag.path, "options", "", "Options spec file path for VM deployment")
}

func (flag *OptionsFlag) Process(ctx context.Context) error {
	if len(flag.path) > 0 {
		f, err := os.Open(flag.path)
		if err != nil {
			return err
		}
		defer f.Close()

		if err := json.NewDecoder(f).Decode(&flag.Options); err != nil {
			return err
		}
	}

	return nil
}
<commit_msg>Support stdin as import options source<commit_after>/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.

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 importx

import (
	"context"
	"encoding/json"
	"flag"
	"os"

	"github.com/vmware/govmomi/ovf"
	"github.com/vmware/govmomi/vim25/types"
)

type Property struct {
	types.KeyValue
	Spec *ovf.Property `json:",omitempty"`
}

type Network struct {
	Name    string
	Network string
}

type Options struct {
	AllDeploymentOptions []string `json:",omitempty"`
	Deployment           string

	AllDiskProvisioningOptions []string `json:",omitempty"`
	DiskProvisioning           string

	AllIPAllocationPolicyOptions []string `json:",omitempty"`
	IPAllocationPolicy           string

	AllIPProtocolOptions []string `json:",omitempty"`
	IPProtocol           string

	PropertyMapping []Property `json:",omitempty"`

	NetworkMapping []Network `json:",omitempty"`

	Annotation string `json:",omitempty"`

	PowerOn      bool
	InjectOvfEnv bool
	WaitForIP    bool
	Name         *string
}

type OptionsFlag struct {
	Options Options

	path string
}

func newOptionsFlag(ctx context.Context) (*OptionsFlag, context.Context) {
	return &OptionsFlag{}, ctx
}

func (flag *OptionsFlag) Register(ctx context.Context, f *flag.FlagSet) {
	f.StringVar(&flag.path, "options", "", "Options spec file path for VM deployment")
}

func (flag *OptionsFlag) Process(ctx context.Context) error {
	if len(flag.path) == 0 {
		return nil
	}

	var err error
	in := os.Stdin

	if flag.path != "-" {
		in, err = os.Open(flag.path)
		if err != nil {
			return err
		}
		defer in.Close()
	}

	return json.NewDecoder(in).Decode(&flag.Options)
}
<|endoftext|>


<commit_before>package graylog

import (
	"os"
	"testing"
)

const namespaceName = "test-18F81907-7C88-438E-A648-2069EF5B95B2"
const userName = "testaccount"

func TestMain(m *testing.M) {
	/*
	os.Setenv("GRAYLOG_BASE_URL", "")
	os.Setenv("GRAYLOG_ADMIN_USER", "")
	os.Setenv("GRAYLOG_ADMIN_PASSWORD", "")
	*/
	ret := m.Run()
	os.Exit(ret)
}

func TestCreateStream(t *testing.T) {
	done, _ := CreateStream(namespaceName)
	if !done {
		t.Fail()
	}
	done2, _ := CreateStream(namespaceName)
	if !done2 {
		t.Fail()
	}
	DeleteStream(namespaceName)
}

func TestIsStreamAlreadyPresent(t *testing.T) {
	isCreated, _ := isStreamAlreadyCreated(namespaceName)
	if isCreated {
		t.Fail()
	}
	done, _ := CreateStream(namespaceName)
	if !done {
		t.Fail()
	}
	isCreated, _ = isStreamAlreadyCreated(namespaceName)
	if !isCreated {
		t.Fail()
	}
	DeleteStream(namespaceName)
	isCreated, _ = isStreamAlreadyCreated(namespaceName)
	if isCreated {
		t.Fail()
	}

}

func TestGetStreamByNamespaceName(t *testing.T) {
	done, _ := CreateStream(namespaceName)
	if !done {
		t.Fail()
	}
	str, err := getStreamByNamespaceName(namespaceName)
	if err != nil {
		t.Error(err)
	}
	if str.Title != namespaceName {
		t.Fail()
	}
	DeleteStream(namespaceName)
}

func TestDeleteStream(t *testing.T) {
	done, _ := CreateStream(namespaceName)
	if !done {
		t.Fail()
	}
	DeleteStream(namespaceName)
	if cond, _ := isStreamAlreadyCreated(namespaceName); cond == true {
		t.Fail()
	}
}

func TestGrandAndTakePermissionForStream(t *testing.T) {
	done, _ := CreateStream(namespaceName)
	if !done {
		t.Fail()
	}
	success := GrantPermissionForStream(namespaceName, userName)
	if !success {
		t.Fail()
	}
	succesTake := TakePermissionForStream(namespaceName, userName)
	if !succesTake {
		t.Fail()
	}
	DeleteStream(namespaceName)
}

func TestGetGraylogUser(t *testing.T) {
	// must not fail
	user, err := getGraylogUser("admin")
	if err != nil {
		t.Fail()
	}
	if user == nil || user.Username != "admin" {
		t.Fail()
	}

	// must fail
	user2, err2 := getGraylogUser("UserUnknown1337")
	if err2 == nil || user2 != nil{
		t.Fail()
	}

}
<commit_msg>commented out graylog tests<commit_after>package graylog
/*
import (
	"os"
	"testing"
)

const namespaceName = "test-18F81907-7C88-438E-A648-2069EF5B95B2"
const userName = "testaccount"

func TestMain(m *testing.M) {

	os.Setenv("GRAYLOG_BASE_URL", "")
	os.Setenv("GRAYLOG_ADMIN_USER", "")
	os.Setenv("GRAYLOG_ADMIN_PASSWORD", "")

	ret := m.Run()
	os.Exit(ret)
}

func TestCreateStream(t *testing.T) {
	done, _ := CreateStream(namespaceName)
	if !done {
		t.Fail()
	}
	done2, _ := CreateStream(namespaceName)
	if !done2 {
		t.Fail()
	}
	DeleteStream(namespaceName)
}

func TestIsStreamAlreadyPresent(t *testing.T) {
	isCreated, _ := isStreamAlreadyCreated(namespaceName)
	if isCreated {
		t.Fail()
	}
	done, _ := CreateStream(namespaceName)
	if !done {
		t.Fail()
	}
	isCreated, _ = isStreamAlreadyCreated(namespaceName)
	if !isCreated {
		t.Fail()
	}
	DeleteStream(namespaceName)
	isCreated, _ = isStreamAlreadyCreated(namespaceName)
	if isCreated {
		t.Fail()
	}

}

func TestGetStreamByNamespaceName(t *testing.T) {
	done, _ := CreateStream(namespaceName)
	if !done {
		t.Fail()
	}
	str, err := getStreamByNamespaceName(namespaceName)
	if err != nil {
		t.Error(err)
	}
	if str.Title != namespaceName {
		t.Fail()
	}
	DeleteStream(namespaceName)
}

func TestDeleteStream(t *testing.T) {
	done, _ := CreateStream(namespaceName)
	if !done {
		t.Fail()
	}
	DeleteStream(namespaceName)
	if cond, _ := isStreamAlreadyCreated(namespaceName); cond == true {
		t.Fail()
	}
}

func TestGrandAndTakePermissionForStream(t *testing.T) {
	done, _ := CreateStream(namespaceName)
	if !done {
		t.Fail()
	}
	success := GrantPermissionForStream(namespaceName, userName)
	if !success {
		t.Fail()
	}
	succesTake := TakePermissionForStream(namespaceName, userName)
	if !succesTake {
		t.Fail()
	}
	DeleteStream(namespaceName)
}

func TestGetGraylogUser(t *testing.T) {
	// must not fail
	user, err := getGraylogUser("admin")
	if err != nil {
		t.Fail()
	}
	if user == nil || user.Username != "admin" {
		t.Fail()
	}

	// must fail
	user2, err2 := getGraylogUser("UserUnknown1337")
	if err2 == nil || user2 != nil{
		t.Fail()
	}

}
*/<|endoftext|>


<commit_before>package hashtable

import (
	"fmt"
	"math"
)

const (
	A       = 0.6180339887 // A = (sqrt(t) -1)/2，来自算法导论第三版
	MinSize = 10
)

type KeyError struct {
	s string
}

func (e *KeyError) Error() string {
	return e.s
}

type item struct {
	key   interface{}
	value interface{}
}

type HashTable struct {
	items []*item
	size  int
}

func NewHT(size int) *HashTable {
	if size >= MinSize {
		return &HashTable{size: size, items: make([]*item, size, size)}
	}
	panic(fmt.Sprintf("size must > %d", MinSize))
}

// 散列函数，支持int、string类型的key
func (ht *HashTable) hash(key interface{}) int {
	var tmp int
	switch k := key.(type) {
	case int:
		tmp = int(k)
	case string:
		// http://algs4.cs.princeton.edu/lectures/34HashTables.pdf
		// Horner's Method to hash string of length L (O(L))
		hash := int32(0)
		for i := 0; i < len(k); i++ {
			// 31 * i == (i << 5) - i
			hash = int32(k[i]) + int32(hash<<5-hash)
		}
		tmp = int(math.Abs(float64(hash)))
	}

	// 乘法散列法，来自算法导论第三版
	multip := float64(tmp) * A
	decimalPart := multip - float64(int(multip))
	return int(math.Floor(float64(ht.size) * decimalPart))
}

func (ht *HashTable) linearProbing(hash, i int) int {
	return (hash + i) % ht.size
}

func (ht *HashTable) Put(key, value interface{}) {
	hash := ht.hash(key)
	for i := 0; i < ht.size; i++ {
		tmp := ht.linearProbing(hash, i)
		if res := ht.items[tmp]; res == nil {
			ht.items[tmp] = &item{key: key, value: value}
			return
		} else if res.key == key {
			// update
			res.value = value
			return
		}
	}
	panic("hash table overflow")
}

func (ht *HashTable) Get(key interface{}) (value interface{}, err error) {
	hash := ht.hash(key)
	if ht.items[hash] != nil && ht.items[hash].key == key {
		return ht.items[hash].value, nil
	}
	return nil, &KeyError{"key no exists"}
}
<commit_msg>finished Get method<commit_after>package hashtable

import (
	"fmt"
	"math"
)

const (
	A       = 0.6180339887 // A = (sqrt(t) -1)/2，来自算法导论第三版
	MinSize = 10
)

type KeyError struct {
	s string
}

func (e *KeyError) Error() string {
	return e.s
}

type item struct {
	key   interface{}
	value interface{}
}

type HashTable struct {
	items []*item
	size  int
}

func NewHT(size int) *HashTable {
	if size >= MinSize {
		return &HashTable{size: size, items: make([]*item, size, size)}
	}
	panic(fmt.Sprintf("size must > %d", MinSize))
}

// 散列函数，支持int、string类型的key
func (ht *HashTable) hash(key interface{}) int {
	var tmp int
	switch k := key.(type) {
	case int:
		tmp = int(k)
	case string:
		// http://algs4.cs.princeton.edu/lectures/34HashTables.pdf
		// Horner's Method to hash string of length L (O(L))
		hash := int32(0)
		for i := 0; i < len(k); i++ {
			// 31 * i == (i << 5) - i
			hash = int32(k[i]) + int32(hash<<5-hash)
		}
		tmp = int(math.Abs(float64(hash)))
	}

	// 乘法散列法，来自算法导论第三版
	multip := float64(tmp) * A
	decimalPart := multip - float64(int(multip))
	return int(math.Floor(float64(ht.size) * decimalPart))
}

func (ht *HashTable) linearProbing(hash, i int) int {
	return (hash + i) % ht.size
}

func (ht *HashTable) Put(key, value interface{}) {
	hash := ht.hash(key)
	for i := 0; i < ht.size; i++ {
		tmp := ht.linearProbing(hash, i)
		if res := ht.items[tmp]; res == nil {
			ht.items[tmp] = &item{key: key, value: value}
			return
		} else if res.key == key {
			// update
			res.value = value
			return
		}
	}
	panic("hash table overflow")
}

func (ht *HashTable) Get(key interface{}) (value interface{}, err error) {
	hash := ht.hash(key)
	for i := 0; i < ht.size; i++ {
		tmp := ht.linearProbing(hash, i)
		// 如果找不到则必定不存在，否则，逐个比较key
		if ht.items[tmp] == nil {
			break
		} else if ht.items[tmp].key == key {
			return ht.items[tmp].value, nil
		}
	}
	return nil, &KeyError{"key no exists"}
}
<|endoftext|>