<commit_before>package main

import (
	"bytes"
	"encoding/binary"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"strings"

	"github.com/boltdb/bolt"
	"github.com/elgs/gojq"
	homedir "github.com/mitchellh/go-homedir"

	kingpin "gopkg.in/alecthomas/kingpin.v2"
)

var (
	verbose = kingpin.Flag("verbose", "Verbose mode").Short('v').Bool()

	dbFile string

	scheme     string
	usedScheme bool

	host     string
	usedHost bool

	port     int
	usedPort bool

	service    string
	path       string
	data       string
	noHeaders  bool
	headers    map[string]string
	query      string
	parameters map[string]string
)

func init() {
	headers = make(map[string]string)
	parameters = make(map[string]string)

	use.Arg("service", "the service to use").Required().StringVar(&service)

	dir, err := homedir.Dir()
	if err != nil {
		panic(err)
	}
	dbFile = fmt.Sprintf("%s/%s", dir, ".rest.db")

	kingpin.Flag("db", "which config database to use").Default(dbFile).StringVar(&dbFile)
}

func main() {
	command := kingpin.Parse()

	switch command {
	case "init":
		if err := setValues(); err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	case "use":
		if err := useService(); err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	case "config":
		if err := displayConfig(); err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

	case "get", "post", "put", "delete":
		resp, err := makeRequest(command)
		if err != nil {
			log.Println(err)
			os.Exit(1)
		}

		if err := showRequest(resp); err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	}
}

func useService() error {
	db, err := bolt.Open(dbFile, 0600, nil)
	if err != nil {
		return err
	}
	defer db.Close()

	err = db.Update(func(tx *bolt.Tx) error {
		serviceBucket := tx.Bucket([]byte("services"))
		if serviceBucket == nil {
			return ErrNoServicesBucket
		}

		if b := serviceBucket.Bucket([]byte(service)); b == nil {
			return ErrNoService{Name: service}
		}

		info, err := tx.CreateBucketIfNotExists([]byte("info"))
		if err != nil {
			return err
		}

		err = info.Put([]byte("current"), []byte(service))
		if err != nil {
			return err
		}

		return nil
	})

	return err
}

func getValues() (*url.URL, error) {
	db, err := bolt.Open(dbFile, 0600, nil)
	if err != nil {
		return nil, err
	}
	defer db.Close()

	u := &url.URL{}
	err = db.View(func(tx *bolt.Tx) error {
		info := tx.Bucket([]byte("info"))
		if info == nil {
			return ErrNoInfoBucket
		}

		current := info.Get([]byte("current"))
		if current == nil {
			return ErrNoServiceSet
		}

		serviceBucket := tx.Bucket([]byte("services"))
		if serviceBucket == nil {
			return ErrNoServicesBucket
		}

		b := serviceBucket.Bucket(current)
		if b == nil {
			return ErrNoService{Name: string(current)}
		}

		if usedScheme {
			u.Scheme = scheme
		} else {
			u.Scheme = string(b.Get([]byte("scheme")))

		}

		hostname := host
		if !usedHost {
			hostname = string(b.Get([]byte("host")))
		}

		if !usedPort {
			p, err := binary.ReadVarint(bytes.NewReader(b.Get([]byte("port"))))
			if err != nil {
				return err
			}
			port = int(p)
		}

		u.Host = fmt.Sprintf("%s:%d", hostname, port)

		head := make(map[string]string)
		if h := b.Bucket([]byte("headers")); h != nil {
			c := h.Cursor()
			for k, v := c.First(); k != nil; k, v = c.Next() {
				head[string(k)] = string(v)
			}
		}
		for key, value := range headers {
			head[key] = value
		}
		headers = head

		param := make(map[string]string)
		if p := b.Bucket([]byte("parameters")); p != nil {
			c := p.Cursor()
			for k, v := c.First(); k != nil; k, v = c.Next() {
				param[string(k)] = string(v)
			}
		}
		for key, value := range parameters {
			param[key] = value
		}
		parameters = param

		return nil
	})

	return u, err
}

func makeRequest(reqType string) (*http.Response, error) {
	u, err := getValues()
	if err != nil {
		return nil, err
	}

	rep := make([]string, 0, len(parameters))
	for key, value := range parameters {
		rep = append(rep, ":"+key)
		rep = append(rep, value)
	}
	paramReplacer := strings.NewReplacer(rep...)

	u.Path = paramReplacer.Replace(path)
	if *verbose {
		fmt.Println(u)
	}

	client := &http.Client{}

	req, err := http.NewRequest(strings.ToUpper(reqType), u.String(), strings.NewReader(data))

	if !noHeaders {
		for key, value := range headers {
			req.Header.Set(key, value)
		}
	}

	if err != nil {
		return nil, err
	}

	return client.Do(req)
}

func usedFlag(b *bool) func(*kingpin.ParseContext) error {
	return func(*kingpin.ParseContext) error {
		*b = true
		return nil
	}
}

func showRequest(r *http.Response) error {
	defer r.Body.Close()
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return err
	}

	if query == "" {
		fmt.Println(string(body))
		return nil
	}

	parser, err := gojq.NewStringQuery(string(body))
	if err != nil {
		return err
	}

	result, err := parser.Query(query)
	if err != nil {
		return err
	}

	out, err := json.Marshal(result)
	if err != nil {
		return err
	}

	fmt.Println(string(out))
	return nil
}
<commit_msg>Add parameter replacement in post/put data<commit_after>package main

import (
	"bytes"
	"encoding/binary"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"strings"

	"github.com/boltdb/bolt"
	"github.com/elgs/gojq"
	homedir "github.com/mitchellh/go-homedir"

	kingpin "gopkg.in/alecthomas/kingpin.v2"
)

var (
	verbose = kingpin.Flag("verbose", "Verbose mode").Short('v').Bool()

	dbFile string

	scheme     string
	usedScheme bool

	host     string
	usedHost bool

	port     int
	usedPort bool

	service    string
	path       string
	data       string
	noHeaders  bool
	headers    map[string]string
	query      string
	parameters map[string]string
)

func init() {
	headers = make(map[string]string)
	parameters = make(map[string]string)

	use.Arg("service", "the service to use").Required().StringVar(&service)

	dir, err := homedir.Dir()
	if err != nil {
		panic(err)
	}
	dbFile = fmt.Sprintf("%s/%s", dir, ".rest.db")

	kingpin.Flag("db", "which config database to use").Default(dbFile).StringVar(&dbFile)
}

func main() {
	command := kingpin.Parse()

	switch command {
	case "init":
		if err := setValues(); err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	case "use":
		if err := useService(); err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	case "config":
		if err := displayConfig(); err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

	case "get", "post", "put", "delete":
		resp, err := makeRequest(command)
		if err != nil {
			log.Println(err)
			os.Exit(1)
		}

		if err := showRequest(resp); err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	}
}

func useService() error {
	db, err := bolt.Open(dbFile, 0600, nil)
	if err != nil {
		return err
	}
	defer db.Close()

	err = db.Update(func(tx *bolt.Tx) error {
		serviceBucket := tx.Bucket([]byte("services"))
		if serviceBucket == nil {
			return ErrNoServicesBucket
		}

		if b := serviceBucket.Bucket([]byte(service)); b == nil {
			return ErrNoService{Name: service}
		}

		info, err := tx.CreateBucketIfNotExists([]byte("info"))
		if err != nil {
			return err
		}

		err = info.Put([]byte("current"), []byte(service))
		if err != nil {
			return err
		}

		return nil
	})

	return err
}

func getValues() (*url.URL, error) {
	db, err := bolt.Open(dbFile, 0600, nil)
	if err != nil {
		return nil, err
	}
	defer db.Close()

	u := &url.URL{}
	err = db.View(func(tx *bolt.Tx) error {
		info := tx.Bucket([]byte("info"))
		if info == nil {
			return ErrNoInfoBucket
		}

		current := info.Get([]byte("current"))
		if current == nil {
			return ErrNoServiceSet
		}

		serviceBucket := tx.Bucket([]byte("services"))
		if serviceBucket == nil {
			return ErrNoServicesBucket
		}

		b := serviceBucket.Bucket(current)
		if b == nil {
			return ErrNoService{Name: string(current)}
		}

		if usedScheme {
			u.Scheme = scheme
		} else {
			u.Scheme = string(b.Get([]byte("scheme")))

		}

		hostname := host
		if !usedHost {
			hostname = string(b.Get([]byte("host")))
		}

		if !usedPort {
			p, err := binary.ReadVarint(bytes.NewReader(b.Get([]byte("port"))))
			if err != nil {
				return err
			}
			port = int(p)
		}

		u.Host = fmt.Sprintf("%s:%d", hostname, port)

		head := make(map[string]string)
		if h := b.Bucket([]byte("headers")); h != nil {
			c := h.Cursor()
			for k, v := c.First(); k != nil; k, v = c.Next() {
				head[string(k)] = string(v)
			}
		}
		for key, value := range headers {
			head[key] = value
		}
		headers = head

		param := make(map[string]string)
		if p := b.Bucket([]byte("parameters")); p != nil {
			c := p.Cursor()
			for k, v := c.First(); k != nil; k, v = c.Next() {
				param[string(k)] = string(v)
			}
		}
		for key, value := range parameters {
			param[key] = value
		}
		parameters = param

		return nil
	})

	return u, err
}

func makeRequest(reqType string) (*http.Response, error) {
	u, err := getValues()
	if err != nil {
		return nil, err
	}

	params := paramReplacer(parameters)
	u.Path = params.Replace(path)
	data = params.Replace(data)
	if *verbose {
		fmt.Println(u)
	}

	client := &http.Client{}

	req, err := http.NewRequest(strings.ToUpper(reqType), u.String(), strings.NewReader(data))

	if !noHeaders {
		for key, value := range headers {
			req.Header.Set(key, value)
		}
	}

	if err != nil {
		return nil, err
	}

	return client.Do(req)
}

func usedFlag(b *bool) func(*kingpin.ParseContext) error {
	return func(*kingpin.ParseContext) error {
		*b = true
		return nil
	}
}

func showRequest(r *http.Response) error {
	defer r.Body.Close()
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return err
	}

	if query == "" {
		fmt.Println(string(body))
		return nil
	}

	parser, err := gojq.NewStringQuery(string(body))
	if err != nil {
		return err
	}

	result, err := parser.Query(query)
	if err != nil {
		return err
	}

	out, err := json.Marshal(result)
	if err != nil {
		return err
	}

	fmt.Println(string(out))
	return nil
}

func paramReplacer(parameters map[string]string) *strings.Replacer {
	rep := make([]string, 0, len(parameters))
	for key, value := range parameters {
		rep = append(rep, ":"+key)
		rep = append(rep, value)
	}
	return strings.NewReplacer(rep...)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strings"

	_ "github.com/candid82/joker/base64"
	. "github.com/candid82/joker/core"
	_ "github.com/candid82/joker/json"
	_ "github.com/candid82/joker/os"
	_ "github.com/candid82/joker/string"
	"gopkg.in/readline.v1"
)

type (
	ReplContext struct {
		first  *Var
		second *Var
		third  *Var
		exc    *Var
	}
)

const VERSION = "v0.7.1"

func NewReplContext(env *Env) *ReplContext {
	first, _ := env.Resolve(MakeSymbol("joker.core/*1"))
	second, _ := env.Resolve(MakeSymbol("joker.core/*2"))
	third, _ := env.Resolve(MakeSymbol("joker.core/*3"))
	exc, _ := env.Resolve(MakeSymbol("joker.core/*e"))
	first.Value = NIL
	second.Value = NIL
	third.Value = NIL
	exc.Value = NIL
	return &ReplContext{
		first:  first,
		second: second,
		third:  third,
		exc:    exc,
	}
}

func (ctx *ReplContext) PushValue(obj Object) {
	ctx.third.Value = ctx.second.Value
	ctx.second.Value = ctx.first.Value
	ctx.first.Value = obj
}

func (ctx *ReplContext) PushException(exc Object) {
	ctx.exc.Value = exc
}

func processFile(filename string, phase Phase) error {
	var reader *Reader
	if filename == "--" {
		reader = NewReader(bufio.NewReader(os.Stdin), "<stdin>")
		filename = ""
	} else {
		f, err := os.Open(filename)
		if err != nil {
			fmt.Fprintln(os.Stderr, "Error: ", err)
			return err
		}
		reader = NewReader(bufio.NewReader(f), filename)
	}
	return ProcessReader(reader, filename, phase)
}

func skipRestOfLine(reader *Reader) {
	for {
		switch reader.Get() {
		case EOF, '\n':
			return
		}
	}
}

func processReplCommand(reader *Reader, phase Phase, parseContext *ParseContext, replContext *ReplContext) (exit bool) {

	defer func() {
		if r := recover(); r != nil {
			switch r := r.(type) {
			case *ParseError:
				replContext.PushException(r)
				fmt.Fprintln(os.Stderr, r)
			case *EvalError:
				replContext.PushException(r)
				fmt.Fprintln(os.Stderr, r)
			case Error:
				replContext.PushException(r)
				fmt.Fprintln(os.Stderr, r)
			// case *runtime.TypeAssertionError:
			// 	fmt.Fprintln(os.Stderr, r)
			default:
				panic(r)
			}
		}
	}()

	obj, err := TryRead(reader)
	if err == io.EOF {
		return true
	}
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		skipRestOfLine(reader)
		return
	}

	if phase == READ {
		fmt.Println(obj.ToString(true))
		return false
	}

	expr := Parse(obj, parseContext)
	if phase == PARSE {
		fmt.Println(expr)
		return false
	}

	res := Eval(expr, nil)
	replContext.PushValue(res)
	fmt.Println(res.ToString(true))
	return false
}

func repl(phase Phase) {
	fmt.Printf("Welcome to joker %s. Use ctrl-c to exit.\n", VERSION)
	parseContext := &ParseContext{GlobalEnv: GLOBAL_ENV}
	replContext := NewReplContext(parseContext.GlobalEnv)

	rl, err := readline.New("")
	if err != nil {
		fmt.Println("Error: " + err.Error())
	}
	defer rl.Close()

	reader := NewReader(NewLineRuneReader(rl), "<repl>")

	for {
		rl.SetPrompt(GLOBAL_ENV.CurrentNamespace().Name.ToString(false) + "=> ")
		if processReplCommand(reader, phase, parseContext, replContext) {
			return
		}
	}
}

func makeDialectKeyword(dialect Dialect) Keyword {
	switch dialect {
	case EDN:
		return MakeKeyword("clj")
	case CLJ:
		return MakeKeyword("clj")
	case CLJS:
		return MakeKeyword("cljs")
	default:
		return MakeKeyword("joker ")
	}
}

func configureLinterMode(dialect Dialect) {
	LINTER_MODE = true
	DIALECT = dialect
	lm, _ := GLOBAL_ENV.Resolve(MakeSymbol("joker.core/*linter-mode*"))
	lm.Value = Bool{B: true}
	GLOBAL_ENV.Features = GLOBAL_ENV.Features.Disjoin(MakeKeyword("joker")).Conj(makeDialectKeyword(dialect)).(Set)
	ProcessLinterData(dialect)
}

func detectDialect(filename string) Dialect {
	switch {
	case strings.HasSuffix(filename, ".edn"):
		return EDN
	case strings.HasSuffix(filename, ".cljs"):
		return CLJS
	case strings.HasSuffix(filename, ".joke"):
		return JOKER
	}
	return CLJ
}

func lintFile(filename string, dialect Dialect) {
	phase := PARSE
	if dialect == EDN {
		phase = READ
	}
	configureLinterMode(dialect)
	if processFile(filename, phase) == nil {
		WarnOnUnusedNamespaces()
		WarnOnUnusedVars()
	}
}

func main() {
	GLOBAL_ENV.FindNamespace(MakeSymbol("user")).ReferAll(GLOBAL_ENV.CoreNamespace)
	if len(os.Args) == 1 {
		repl(EVAL)
		return
	}
	if len(os.Args) == 2 {
		if os.Args[1] == "-v" || os.Args[1] == "--version" {
			println(VERSION)
			return
		}
		processFile(os.Args[1], EVAL)
		return
	}
	switch os.Args[1] {
	case "--read":
		processFile(os.Args[2], READ)
	case "--parse":
		processFile(os.Args[2], PARSE)
	case "--lint":
		dialect := detectDialect(os.Args[2])
		lintFile(os.Args[2], dialect)
	case "--lintclj":
		lintFile(os.Args[2], CLJ)
	case "--lintcljs":
		lintFile(os.Args[2], CLJS)
	case "--lintjoker":
		lintFile(os.Args[2], JOKER)
	case "--lintedn":
		lintFile(os.Args[2], EDN)
	default:
		processFile(os.Args[1], EVAL)
	}
}
<commit_msg>v0.7.2<commit_after>package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strings"

	_ "github.com/candid82/joker/base64"
	. "github.com/candid82/joker/core"
	_ "github.com/candid82/joker/json"
	_ "github.com/candid82/joker/os"
	_ "github.com/candid82/joker/string"
	"gopkg.in/readline.v1"
)

type (
	ReplContext struct {
		first  *Var
		second *Var
		third  *Var
		exc    *Var
	}
)

const VERSION = "v0.7.2"

func NewReplContext(env *Env) *ReplContext {
	first, _ := env.Resolve(MakeSymbol("joker.core/*1"))
	second, _ := env.Resolve(MakeSymbol("joker.core/*2"))
	third, _ := env.Resolve(MakeSymbol("joker.core/*3"))
	exc, _ := env.Resolve(MakeSymbol("joker.core/*e"))
	first.Value = NIL
	second.Value = NIL
	third.Value = NIL
	exc.Value = NIL
	return &ReplContext{
		first:  first,
		second: second,
		third:  third,
		exc:    exc,
	}
}

func (ctx *ReplContext) PushValue(obj Object) {
	ctx.third.Value = ctx.second.Value
	ctx.second.Value = ctx.first.Value
	ctx.first.Value = obj
}

func (ctx *ReplContext) PushException(exc Object) {
	ctx.exc.Value = exc
}

func processFile(filename string, phase Phase) error {
	var reader *Reader
	if filename == "--" {
		reader = NewReader(bufio.NewReader(os.Stdin), "<stdin>")
		filename = ""
	} else {
		f, err := os.Open(filename)
		if err != nil {
			fmt.Fprintln(os.Stderr, "Error: ", err)
			return err
		}
		reader = NewReader(bufio.NewReader(f), filename)
	}
	return ProcessReader(reader, filename, phase)
}

func skipRestOfLine(reader *Reader) {
	for {
		switch reader.Get() {
		case EOF, '\n':
			return
		}
	}
}

func processReplCommand(reader *Reader, phase Phase, parseContext *ParseContext, replContext *ReplContext) (exit bool) {

	defer func() {
		if r := recover(); r != nil {
			switch r := r.(type) {
			case *ParseError:
				replContext.PushException(r)
				fmt.Fprintln(os.Stderr, r)
			case *EvalError:
				replContext.PushException(r)
				fmt.Fprintln(os.Stderr, r)
			case Error:
				replContext.PushException(r)
				fmt.Fprintln(os.Stderr, r)
			// case *runtime.TypeAssertionError:
			// 	fmt.Fprintln(os.Stderr, r)
			default:
				panic(r)
			}
		}
	}()

	obj, err := TryRead(reader)
	if err == io.EOF {
		return true
	}
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		skipRestOfLine(reader)
		return
	}

	if phase == READ {
		fmt.Println(obj.ToString(true))
		return false
	}

	expr := Parse(obj, parseContext)
	if phase == PARSE {
		fmt.Println(expr)
		return false
	}

	res := Eval(expr, nil)
	replContext.PushValue(res)
	fmt.Println(res.ToString(true))
	return false
}

func repl(phase Phase) {
	fmt.Printf("Welcome to joker %s. Use ctrl-c to exit.\n", VERSION)
	parseContext := &ParseContext{GlobalEnv: GLOBAL_ENV}
	replContext := NewReplContext(parseContext.GlobalEnv)

	rl, err := readline.New("")
	if err != nil {
		fmt.Println("Error: " + err.Error())
	}
	defer rl.Close()

	reader := NewReader(NewLineRuneReader(rl), "<repl>")

	for {
		rl.SetPrompt(GLOBAL_ENV.CurrentNamespace().Name.ToString(false) + "=> ")
		if processReplCommand(reader, phase, parseContext, replContext) {
			return
		}
	}
}

func makeDialectKeyword(dialect Dialect) Keyword {
	switch dialect {
	case EDN:
		return MakeKeyword("clj")
	case CLJ:
		return MakeKeyword("clj")
	case CLJS:
		return MakeKeyword("cljs")
	default:
		return MakeKeyword("joker ")
	}
}

func configureLinterMode(dialect Dialect) {
	LINTER_MODE = true
	DIALECT = dialect
	lm, _ := GLOBAL_ENV.Resolve(MakeSymbol("joker.core/*linter-mode*"))
	lm.Value = Bool{B: true}
	GLOBAL_ENV.Features = GLOBAL_ENV.Features.Disjoin(MakeKeyword("joker")).Conj(makeDialectKeyword(dialect)).(Set)
	ProcessLinterData(dialect)
}

func detectDialect(filename string) Dialect {
	switch {
	case strings.HasSuffix(filename, ".edn"):
		return EDN
	case strings.HasSuffix(filename, ".cljs"):
		return CLJS
	case strings.HasSuffix(filename, ".joke"):
		return JOKER
	}
	return CLJ
}

func lintFile(filename string, dialect Dialect) {
	phase := PARSE
	if dialect == EDN {
		phase = READ
	}
	configureLinterMode(dialect)
	if processFile(filename, phase) == nil {
		WarnOnUnusedNamespaces()
		WarnOnUnusedVars()
	}
}

func main() {
	GLOBAL_ENV.FindNamespace(MakeSymbol("user")).ReferAll(GLOBAL_ENV.CoreNamespace)
	if len(os.Args) == 1 {
		repl(EVAL)
		return
	}
	if len(os.Args) == 2 {
		if os.Args[1] == "-v" || os.Args[1] == "--version" {
			println(VERSION)
			return
		}
		processFile(os.Args[1], EVAL)
		return
	}
	switch os.Args[1] {
	case "--read":
		processFile(os.Args[2], READ)
	case "--parse":
		processFile(os.Args[2], PARSE)
	case "--lint":
		dialect := detectDialect(os.Args[2])
		lintFile(os.Args[2], dialect)
	case "--lintclj":
		lintFile(os.Args[2], CLJ)
	case "--lintcljs":
		lintFile(os.Args[2], CLJS)
	case "--lintjoker":
		lintFile(os.Args[2], JOKER)
	case "--lintedn":
		lintFile(os.Args[2], EDN)
	default:
		processFile(os.Args[1], EVAL)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"log"
	"os"
	"runtime"
	"time"

	"github.com/fatih/color"
	"github.com/justwatchcom/gopass/action"
	"github.com/mattn/go-colorable"
	"github.com/urfave/cli"
)

const (
	name = "gopass"
)

var (
	// Version is the released version of gopass
	Version string
	// BuildTime is the time the binary was built
	BuildTime string
	// Commit is the git hash the binary was built from
	Commit string
)

type errorWriter struct {
	out io.Writer
}

func (e errorWriter) Write(p []byte) (int, error) {
	return e.out.Write([]byte("\n" + color.RedString("Error: "+string(p))))
}

func main() {
	cli.ErrWriter = errorWriter{
		out: colorable.NewColorableStderr(),
	}

	cli.VersionPrinter = func(c *cli.Context) {
		buildtime := ""
		if bt, err := time.Parse("2006-01-02T15:04:05-0700", BuildTime); err == nil {
			buildtime = bt.Format("2006-01-02 15:04:05")
		}
		if Version == "" {
			Version = "HEAD"
		}
		if Commit == "" {
			Commit = "n/a"
		}
		fmt.Printf("%s %s (%s %s) %s\n",
			name,
			Version,
			Commit,
			buildtime,
			runtime.Version(),
		)
	}

	action := action.New(Version)
	app := cli.NewApp()

	app.Name = name
	app.Version = Version
	app.Usage = "The standard unix password manager - rewritten in Go"
	app.EnableBashCompletion = true
	app.BashComplete = func(c *cli.Context) {
		cli.DefaultAppComplete(c)
		action.Complete(c)
	}

	app.Action = func(c *cli.Context) error {
		if err := action.Initialized(c); err != nil {
			return err
		}

		if c.Args().Present() {
			return action.Show(c)
		}
		return action.List(c)
	}

	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "clip, c",
			Usage: "Copy the first line of the secret into the clipboard",
		},
	}

	app.Commands = []cli.Command{
		{
			Name:        "clone",
			Usage:       "Clone a new store",
			Description: "To clone a remote repo",
			Action:      action.Clone,
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "path",
					Usage: "Path to clone the repo to",
				},
			},
		},
		{
			Name:  "completion",
			Usage: "Source the output with bash or zsh to get auto completion",
			Subcommands: []cli.Command{{
				Name:   "bash",
				Usage:  "Source for auto completion in bash",
				Action: action.CompletionBash,
			}, {
				Name:   "zsh",
				Usage:  "Source for auto completion in zsh",
				Action: action.CompletionZSH,
			}, {
				Name:   "dmenu",
				Usage:  "Completion output for dmenu",
				Action: action.CompletionDMenu,
				Flags: []cli.Flag{
					cli.BoolFlag{
						Name:  "type",
						Usage: "Type the password with xdotool",
					},
					cli.StringFlag{
						Name:  "args",
						Usage: "Arguments passed to dmenu itself",
					},
				},
			}},
		},
		{
			Name:        "config",
			Usage:       "Edit configuration",
			Description: "To manipulate the gopass configuration",
			Action:      action.Config,
		},
		{
			Name:         "copy",
			Aliases:      []string{"cp"},
			Usage:        "Copies old-path to new-path, optionally forcefully, selectively reencrypting.",
			Before:       action.Initialized,
			Action:       action.Copy,
			BashComplete: action.Complete,
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "force, f",
					Usage: "Force to copy the secret and overwrite existing one",
				},
			},
		},
		{
			Name:         "delete",
			Usage:        "Remove existing secret or directory, optionally forcefully.",
			Aliases:      []string{"remove", "rm"},
			Before:       action.Initialized,
			Action:       action.Delete,
			BashComplete: action.Complete,
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "recursive, r",
					Usage: "f",
				},
				cli.BoolFlag{
					Name:  "force, f",
					Usage: "Force to delete the secret",
				},
			},
		},
		{
			Name:         "edit",
			Usage:        "Insert a new secret or edit an existing secret using $EDITOR.",
			Before:       action.Initialized,
			Action:       action.Edit,
			BashComplete: action.Complete,
		},
		{
			Name:         "find",
			Usage:        "List secrets that match the search term.",
			Before:       action.Initialized,
			Action:       action.Find,
			Aliases:      []string{"search"},
			BashComplete: action.Complete,
		},
		{
			Name:        "fsck",
			Usage:       "Check store integrity",
			Description: "Check integrity of all stores",
			Before:      action.Initialized,
			Action:      action.Fsck,
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "check, c",
					Usage: "Only report",
				},
				cli.BoolFlag{
					Name:  "force, f",
					Usage: "Auto-correct any errors, do not ask",
				},
			},
		},
		{
			Name:  "generate",
			Usage: "Generate a new password of the specified length with optionally no symbols.",
			Description: "" +
				"Generate a new password of the specified length with optionally no symbols. " +
				"Optionally put it on the clipboard and clear board after 45 seconds. " +
				"Prompt before overwriting existing password unless forced. " +
				"Optionally replace only the first line of an existing file with a new password.",
			Before:       action.Initialized,
			Action:       action.Generate,
			BashComplete: action.Complete,
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "clip, c",
					Usage: "Copy the password into the clipboard",
				},
				cli.BoolFlag{
					Name:  "force, f",
					Usage: "Force to overwrite existing password",
				},
				cli.BoolFlag{
					Name:  "no-symbols, n",
					Usage: "Don't use symbols in the password",
				},
			},
		},
		{
			Name:        "git",
			Usage:       "Do git things",
			Description: "If the password store is a git repository, execute a git command specified by git-command-args.",
			Before:      action.Initialized,
			Action:      action.Git,
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "store",
					Usage: "Store to operate on",
				},
			},
			Subcommands: []cli.Command{
				{
					Name:        "init",
					Usage:       "Init git repo",
					Description: "Create and initialize a new git repo in the store",
					Before:      action.Initialized,
					Action:      action.GitInit,
					Flags: []cli.Flag{
						cli.StringFlag{
							Name:  "store",
							Usage: "Store to operate on",
						},
						cli.StringFlag{
							Name:  "sign-key",
							Usage: "GPG Key to sign commits",
						},
					},
				},
			},
		},
		{
			Name:   "grep",
			Usage:  "Search for secrets files containing search-string when decrypted.",
			Before: action.Initialized,
			Action: action.Grep,
		},
		{
			Name:  "init",
			Usage: "Initialize new password storage and use gpg-id for encryption.",
			Description: "" +
				"Initialize new password storage and use gpg-id for encryption.",
			Action: action.Init,
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "store, s",
					Usage: "Set the sub store to operate on",
				},
				cli.BoolFlag{
					Name:  "nogit",
					Usage: "Do not init git repo",
				},
			},
		},
		{
			Name:  "insert",
			Usage: "Insert new secret",
			Description: "" +
				"Insert new secret. Optionally, echo the secret back to the console during entry. " +
				"Or, optionally, the entry may be multiline. " +
				"Prompt before overwriting existing secret unless forced.",
			Before:       action.Initialized,
			Action:       action.Insert,
			BashComplete: action.Complete,
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "echo, e",
					Usage: "Display secret while typing",
				},
				cli.BoolFlag{
					Name:  "multiline, m",
					Usage: "Insert using $EDITOR",
				},
				cli.BoolFlag{
					Name:  "force, f",
					Usage: "Overwrite any existing secret and do not prompt to confirm recipients",
				},
			},
		},
		{
			Name:         "list",
			Usage:        "List secrets.",
			Aliases:      []string{"ls"},
			Before:       action.Initialized,
			Action:       action.List,
			BashComplete: action.Complete,
		},
		{
			Name:         "move",
			Aliases:      []string{"mv"},
			Usage:        "Renames or moves old-path to new-path, optionally forcefully, selectively reencrypting.",
			Before:       action.Initialized,
			Action:       action.Move,
			BashComplete: action.Complete,
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "force, f",
					Usage: "Force to move the secret and overwrite existing one",
				},
			},
		},
		{
			Name:        "mounts",
			Usage:       "Edit mounts",
			Description: "To manipulate gopass mounts",
			Before:      action.Initialized,
			Action:      action.MountsPrint,
			Subcommands: []cli.Command{
				{
					Name:        "add",
					Usage:       "Add mount",
					Description: "To add a new mounted sub store",
					Before:      action.Initialized,
					Action:      action.MountAdd,
					Flags: []cli.Flag{
						cli.StringFlag{
							Name:  "init, i",
							Usage: "Init the store with the given recpient key",
						},
					},
				},
				{
					Name:         "remove",
					Usage:        "Remove mount",
					Description:  "To remove a mounted sub store",
					Before:       action.Initialized,
					Action:       action.MountRemove,
					BashComplete: action.MountsComplete,
				},
			},
		},
		{
			Name:        "recipients",
			Usage:       "List Recipients",
			Description: "To show all recipients",
			Before:      action.Initialized,
			Action:      action.RecipientsPrint,
			Subcommands: []cli.Command{
				{
					Name:        "add",
					Usage:       "Add any number of Recipients",
					Description: "To add any number of recipients to a store",
					Before:      action.Initialized,
					Action:      action.RecipientsAdd,
					Flags: []cli.Flag{
						cli.StringFlag{
							Name:  "store",
							Usage: "Store to operate on",
						},
					},
				},
				{
					Name:         "remove",
					Usage:        "Remove any number of Recipients",
					Description:  "To remove any number of recipients from a store",
					Before:       action.Initialized,
					Action:       action.RecipientsRemove,
					BashComplete: action.RecipientsComplete,
					Flags: []cli.Flag{
						cli.StringFlag{
							Name:  "store",
							Usage: "Store to operate on",
						},
					},
				},
			},
		},
		{
			Name:  "show",
			Usage: "Show existing secret and optionally put its first line on the clipboard.",
			Description: "" +
				"Show existing secret and optionally put its first line on the clipboard. " +
				"If put on the clipboard, it will be cleared in 45 seconds.",
			Before:       action.Initialized,
			Action:       action.Show,
			BashComplete: action.Complete,
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "clip, c",
					Usage: "Copy the first line of the secret into the clipboard",
				},
				cli.BoolFlag{
					Name:  "qr",
					Usage: "Print the first line of the secret as QR Code",
				},
				cli.BoolFlag{
					Name:  "force, f",
					Usage: "Display the password even if safecontent is enabled",
				},
			},
		},
		{
			Name:  "templates",
			Usage: "List and edit secret templates.",
			Description: "" +
				"List existing templates in the password store and allow for editing " +
				"and creating them.",
			Before: action.Initialized,
			Action: action.TemplatesPrint,
			Subcommands: []cli.Command{
				{
					Name:         "show",
					Usage:        "Show a secret template.",
					Description:  "Dispaly an existing template",
					Aliases:      []string{"cat"},
					Before:       action.Initialized,
					Action:       action.TemplatePrint,
					BashComplete: action.TemplatesComplete,
				},
				{
					Name:         "edit",
					Usage:        "Edit secret templates.",
					Description:  "Edit an existing or new template",
					Aliases:      []string{"create", "new"},
					Before:       action.Initialized,
					Action:       action.TemplateEdit,
					BashComplete: action.TemplatesComplete,
				},
				{
					Name:         "remove",
					Usage:        "Remove secret templates.",
					Description:  "Remove an existing template",
					Before:       action.Initialized,
					Action:       action.TemplateRemove,
					BashComplete: action.TemplatesComplete,
				},
			},
		},
		{
			Name:        "unclip",
			Usage:       "Internal command to clear clipboard",
			Description: "Clear the clipboard if the content matches the checksum",
			Action:      action.Unclip,
			Hidden:      true,
			Flags: []cli.Flag{
				cli.IntFlag{
					Name:  "timeout",
					Usage: "Time to wait",
				},
			},
		},
		{
			Name:        "version",
			Usage:       "Print gopass version",
			Description: "Display version and build time information",
			Action:      action.Version,
		},
	}

	if err := app.Run(os.Args); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Add rm aliases to remove commands (#119)<commit_after>package main

import (
	"fmt"
	"io"
	"log"
	"os"
	"runtime"
	"time"

	"github.com/fatih/color"
	"github.com/justwatchcom/gopass/action"
	colorable "github.com/mattn/go-colorable"
	"github.com/urfave/cli"
)

const (
	name = "gopass"
)

var (
	// Version is the released version of gopass
	Version string
	// BuildTime is the time the binary was built
	BuildTime string
	// Commit is the git hash the binary was built from
	Commit string
)

type errorWriter struct {
	out io.Writer
}

func (e errorWriter) Write(p []byte) (int, error) {
	return e.out.Write([]byte("\n" + color.RedString("Error: "+string(p))))
}

func main() {
	cli.ErrWriter = errorWriter{
		out: colorable.NewColorableStderr(),
	}

	cli.VersionPrinter = func(c *cli.Context) {
		buildtime := ""
		if bt, err := time.Parse("2006-01-02T15:04:05-0700", BuildTime); err == nil {
			buildtime = bt.Format("2006-01-02 15:04:05")
		}
		if Version == "" {
			Version = "HEAD"
		}
		if Commit == "" {
			Commit = "n/a"
		}
		fmt.Printf("%s %s (%s %s) %s\n",
			name,
			Version,
			Commit,
			buildtime,
			runtime.Version(),
		)
	}

	action := action.New(Version)
	app := cli.NewApp()

	app.Name = name
	app.Version = Version
	app.Usage = "The standard unix password manager - rewritten in Go"
	app.EnableBashCompletion = true
	app.BashComplete = func(c *cli.Context) {
		cli.DefaultAppComplete(c)
		action.Complete(c)
	}

	app.Action = func(c *cli.Context) error {
		if err := action.Initialized(c); err != nil {
			return err
		}

		if c.Args().Present() {
			return action.Show(c)
		}
		return action.List(c)
	}

	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "clip, c",
			Usage: "Copy the first line of the secret into the clipboard",
		},
	}

	app.Commands = []cli.Command{
		{
			Name:        "clone",
			Usage:       "Clone a new store",
			Description: "To clone a remote repo",
			Action:      action.Clone,
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "path",
					Usage: "Path to clone the repo to",
				},
			},
		},
		{
			Name:  "completion",
			Usage: "Source the output with bash or zsh to get auto completion",
			Subcommands: []cli.Command{{
				Name:   "bash",
				Usage:  "Source for auto completion in bash",
				Action: action.CompletionBash,
			}, {
				Name:   "zsh",
				Usage:  "Source for auto completion in zsh",
				Action: action.CompletionZSH,
			}, {
				Name:   "dmenu",
				Usage:  "Completion output for dmenu",
				Action: action.CompletionDMenu,
				Flags: []cli.Flag{
					cli.BoolFlag{
						Name:  "type",
						Usage: "Type the password with xdotool",
					},
					cli.StringFlag{
						Name:  "args",
						Usage: "Arguments passed to dmenu itself",
					},
				},
			}},
		},
		{
			Name:        "config",
			Usage:       "Edit configuration",
			Description: "To manipulate the gopass configuration",
			Action:      action.Config,
		},
		{
			Name:         "copy",
			Aliases:      []string{"cp"},
			Usage:        "Copies old-path to new-path, optionally forcefully, selectively reencrypting.",
			Before:       action.Initialized,
			Action:       action.Copy,
			BashComplete: action.Complete,
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "force, f",
					Usage: "Force to copy the secret and overwrite existing one",
				},
			},
		},
		{
			Name:         "delete",
			Usage:        "Remove existing secret or directory, optionally forcefully.",
			Aliases:      []string{"remove", "rm"},
			Before:       action.Initialized,
			Action:       action.Delete,
			BashComplete: action.Complete,
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "recursive, r",
					Usage: "f",
				},
				cli.BoolFlag{
					Name:  "force, f",
					Usage: "Force to delete the secret",
				},
			},
		},
		{
			Name:         "edit",
			Usage:        "Insert a new secret or edit an existing secret using $EDITOR.",
			Before:       action.Initialized,
			Action:       action.Edit,
			BashComplete: action.Complete,
		},
		{
			Name:         "find",
			Usage:        "List secrets that match the search term.",
			Before:       action.Initialized,
			Action:       action.Find,
			Aliases:      []string{"search"},
			BashComplete: action.Complete,
		},
		{
			Name:        "fsck",
			Usage:       "Check store integrity",
			Description: "Check integrity of all stores",
			Before:      action.Initialized,
			Action:      action.Fsck,
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "check, c",
					Usage: "Only report",
				},
				cli.BoolFlag{
					Name:  "force, f",
					Usage: "Auto-correct any errors, do not ask",
				},
			},
		},
		{
			Name:  "generate",
			Usage: "Generate a new password of the specified length with optionally no symbols.",
			Description: "" +
				"Generate a new password of the specified length with optionally no symbols. " +
				"Optionally put it on the clipboard and clear board after 45 seconds. " +
				"Prompt before overwriting existing password unless forced. " +
				"Optionally replace only the first line of an existing file with a new password.",
			Before:       action.Initialized,
			Action:       action.Generate,
			BashComplete: action.Complete,
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "clip, c",
					Usage: "Copy the password into the clipboard",
				},
				cli.BoolFlag{
					Name:  "force, f",
					Usage: "Force to overwrite existing password",
				},
				cli.BoolFlag{
					Name:  "no-symbols, n",
					Usage: "Don't use symbols in the password",
				},
			},
		},
		{
			Name:        "git",
			Usage:       "Do git things",
			Description: "If the password store is a git repository, execute a git command specified by git-command-args.",
			Before:      action.Initialized,
			Action:      action.Git,
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "store",
					Usage: "Store to operate on",
				},
			},
			Subcommands: []cli.Command{
				{
					Name:        "init",
					Usage:       "Init git repo",
					Description: "Create and initialize a new git repo in the store",
					Before:      action.Initialized,
					Action:      action.GitInit,
					Flags: []cli.Flag{
						cli.StringFlag{
							Name:  "store",
							Usage: "Store to operate on",
						},
						cli.StringFlag{
							Name:  "sign-key",
							Usage: "GPG Key to sign commits",
						},
					},
				},
			},
		},
		{
			Name:   "grep",
			Usage:  "Search for secrets files containing search-string when decrypted.",
			Before: action.Initialized,
			Action: action.Grep,
		},
		{
			Name:  "init",
			Usage: "Initialize new password storage and use gpg-id for encryption.",
			Description: "" +
				"Initialize new password storage and use gpg-id for encryption.",
			Action: action.Init,
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "store, s",
					Usage: "Set the sub store to operate on",
				},
				cli.BoolFlag{
					Name:  "nogit",
					Usage: "Do not init git repo",
				},
			},
		},
		{
			Name:  "insert",
			Usage: "Insert new secret",
			Description: "" +
				"Insert new secret. Optionally, echo the secret back to the console during entry. " +
				"Or, optionally, the entry may be multiline. " +
				"Prompt before overwriting existing secret unless forced.",
			Before:       action.Initialized,
			Action:       action.Insert,
			BashComplete: action.Complete,
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "echo, e",
					Usage: "Display secret while typing",
				},
				cli.BoolFlag{
					Name:  "multiline, m",
					Usage: "Insert using $EDITOR",
				},
				cli.BoolFlag{
					Name:  "force, f",
					Usage: "Overwrite any existing secret and do not prompt to confirm recipients",
				},
			},
		},
		{
			Name:         "list",
			Usage:        "List secrets.",
			Aliases:      []string{"ls"},
			Before:       action.Initialized,
			Action:       action.List,
			BashComplete: action.Complete,
		},
		{
			Name:         "move",
			Aliases:      []string{"mv"},
			Usage:        "Renames or moves old-path to new-path, optionally forcefully, selectively reencrypting.",
			Before:       action.Initialized,
			Action:       action.Move,
			BashComplete: action.Complete,
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "force, f",
					Usage: "Force to move the secret and overwrite existing one",
				},
			},
		},
		{
			Name:        "mounts",
			Usage:       "Edit mounts",
			Description: "To manipulate gopass mounts",
			Before:      action.Initialized,
			Action:      action.MountsPrint,
			Subcommands: []cli.Command{
				{
					Name:        "add",
					Usage:       "Add mount",
					Description: "To add a new mounted sub store",
					Before:      action.Initialized,
					Action:      action.MountAdd,
					Flags: []cli.Flag{
						cli.StringFlag{
							Name:  "init, i",
							Usage: "Init the store with the given recpient key",
						},
					},
				},
				{
					Name:         "remove",
					Aliases:      []string{"rm"},
					Usage:        "Remove mount",
					Description:  "To remove a mounted sub store",
					Before:       action.Initialized,
					Action:       action.MountRemove,
					BashComplete: action.MountsComplete,
				},
			},
		},
		{
			Name:        "recipients",
			Usage:       "List Recipients",
			Description: "To show all recipients",
			Before:      action.Initialized,
			Action:      action.RecipientsPrint,
			Subcommands: []cli.Command{
				{
					Name:        "add",
					Usage:       "Add any number of Recipients",
					Description: "To add any number of recipients to a store",
					Before:      action.Initialized,
					Action:      action.RecipientsAdd,
					Flags: []cli.Flag{
						cli.StringFlag{
							Name:  "store",
							Usage: "Store to operate on",
						},
					},
				},
				{
					Name:         "remove",
					Aliases:      []string{"rm"},
					Usage:        "Remove any number of Recipients",
					Description:  "To remove any number of recipients from a store",
					Before:       action.Initialized,
					Action:       action.RecipientsRemove,
					BashComplete: action.RecipientsComplete,
					Flags: []cli.Flag{
						cli.StringFlag{
							Name:  "store",
							Usage: "Store to operate on",
						},
					},
				},
			},
		},
		{
			Name:  "show",
			Usage: "Show existing secret and optionally put its first line on the clipboard.",
			Description: "" +
				"Show existing secret and optionally put its first line on the clipboard. " +
				"If put on the clipboard, it will be cleared in 45 seconds.",
			Before:       action.Initialized,
			Action:       action.Show,
			BashComplete: action.Complete,
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "clip, c",
					Usage: "Copy the first line of the secret into the clipboard",
				},
				cli.BoolFlag{
					Name:  "qr",
					Usage: "Print the first line of the secret as QR Code",
				},
				cli.BoolFlag{
					Name:  "force, f",
					Usage: "Display the password even if safecontent is enabled",
				},
			},
		},
		{
			Name:  "templates",
			Usage: "List and edit secret templates.",
			Description: "" +
				"List existing templates in the password store and allow for editing " +
				"and creating them.",
			Before: action.Initialized,
			Action: action.TemplatesPrint,
			Subcommands: []cli.Command{
				{
					Name:         "show",
					Usage:        "Show a secret template.",
					Description:  "Dispaly an existing template",
					Aliases:      []string{"cat"},
					Before:       action.Initialized,
					Action:       action.TemplatePrint,
					BashComplete: action.TemplatesComplete,
				},
				{
					Name:         "edit",
					Usage:        "Edit secret templates.",
					Description:  "Edit an existing or new template",
					Aliases:      []string{"create", "new"},
					Before:       action.Initialized,
					Action:       action.TemplateEdit,
					BashComplete: action.TemplatesComplete,
				},
				{
					Name:         "remove",
					Aliases:      []string{"rm"},
					Usage:        "Remove secret templates.",
					Description:  "Remove an existing template",
					Before:       action.Initialized,
					Action:       action.TemplateRemove,
					BashComplete: action.TemplatesComplete,
				},
			},
		},
		{
			Name:        "unclip",
			Usage:       "Internal command to clear clipboard",
			Description: "Clear the clipboard if the content matches the checksum",
			Action:      action.Unclip,
			Hidden:      true,
			Flags: []cli.Flag{
				cli.IntFlag{
					Name:  "timeout",
					Usage: "Time to wait",
				},
			},
		},
		{
			Name:        "version",
			Usage:       "Print gopass version",
			Description: "Display version and build time information",
			Action:      action.Version,
		},
	}

	if err := app.Run(os.Args); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"errors"
	"flag"
	"fmt"
	"io"
	"math/big"
	"os"
	"path/filepath"
	"strings"

	"github.com/tv42/base58"
)

const Extension = ".cypher"

func main() {
	fmt.Println("Hello")

	var password, input string
	var decrypt bool
	flag.StringVar(&password, "p", "", "-password	for encrypt/decrypt files")
	flag.StringVar(&input, "i", "", "-input	file or directory")
	flag.BoolVar(&decrypt, "d", false, "--decrypt	input")

	flag.Parse()

	if len(password) == 0 {

		// Get password
		fmt.Print("Enter a password:")
		fmt.Scan(&password)

		// Get conformation
		var conformation string
		fmt.Print("Confirm a password:")
		fmt.Scan(&conformation)

		if password != conformation {
			fmt.Println("Passwords does not match")
			os.Exit(1)
		}
	}

	if len(input) == 0 {

		var err error
		input, err = os.Getwd()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	}

	err := filepath.Walk(input, visit)
	fmt.Printf("filepath.Walk() returned %v\n", err)
}

var skipPath string

func visit(path string, f os.FileInfo, err error) error {

	filename := f.Name()

	if err != nil {

		return err

	} else if len(skipPath) > 0 && strings.HasPrefix(path, skipPath) {

		return nil

	} else if string(filename[0]) == "." {

		skipPath = path
		return nil

	} else if f.IsDir() {

		return nil

	} else if strings.HasSuffix(filename, Extension) {

		return nil
	}

	key := key(password)

	encName, err := encrypt([]byte("example key 1234"), []byte(filename))
	if err != nil {
		panic(err)
	}
	fmt.Printf("%s -> %s%s(%s)\n", filename, encodeBase58(encName), Extension, encName)

	return nil
}

func key(text string) ([]byte, error) {
	len := len(text)
	if len < 16 {
		len = 16
	} else if len < 24 {
		len = 24
	} else if len < 32 {
		len = 32
	} else {
		return nil, errors.New("The password cannot be more than 32 char")
	}
	vector := make([]byte, len)
	copy(vector[:], text)
	return vector
}

func encrypt(key, text []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	ciphertext := make([]byte, aes.BlockSize+len(text))
	iv := ciphertext[:aes.BlockSize]
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		return nil, err
	}
	cfb := cipher.NewCFBEncrypter(block, iv)
	cfb.XORKeyStream(ciphertext[aes.BlockSize:], text)
	return ciphertext, nil
}

func decrypt(key, text []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	if len(text) < aes.BlockSize {
		return nil, errors.New("ciphertext too short")
	}
	iv := text[:aes.BlockSize]
	text = text[aes.BlockSize:]
	cfb := cipher.NewCFBDecrypter(block, iv)
	cfb.XORKeyStream(text, text)
	return text, nil
}

func encodeBase58(text []byte) []byte {
	num := new(big.Int)
	num.SetBytes(text)
	return base58.EncodeBig(nil, num)
}

func decodeBase58(text []byte) []byte {
	dec, _ := base58.DecodeToBig(text)
	return dec.Bytes()
}
<commit_msg>Added is directory check<commit_after>package main

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"errors"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"math/big"
	"os"
	"path/filepath"
	"strings"

	"github.com/tv42/base58"
)

// Extesion of the chipher files
const Extension = ".cypher"

var Key []byte

func main() {
	fmt.Println("Hello")

	var password, input string
	var decrypt bool
	flag.StringVar(&password, "p", "", "-password	for encrypt/decrypt files")
	flag.StringVar(&input, "i", "", "-input	file or directory")
	flag.BoolVar(&decrypt, "d", false, "--decrypt	input")
	flag.Parse()

	if len(password) == 0 {

		// Get password
		fmt.Print("Enter a password:")
		fmt.Scan(&password)

		// Get conformation
		var conformation string
		fmt.Print("Confirm a password:")
		fmt.Scan(&conformation)

		if password != conformation {
			fmt.Println("Passwords does not match")
			os.Exit(1)
		}
	}

	if len(input) == 0 {

		var err error
		input, err = os.Getwd()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	}

	// Get the key
	var err error
	Key, err = key(password)

	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	// Check is directory of file
	var isDir bool
	isDir, err = IsDirectory(input)

	if decrypt {

		err = filepath.Walk(input, decryptWalker)

	} else {

		err = filepath.Walk(input, encryptWalker)

	}

	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}

var skipPath string

func decryptWalker(path string, f os.FileInfo, err error) error {

	filename := f.Name()

	if err != nil {

		return err

	} else if strings.HasSuffix(filename, Extension) {

		// Decrypt name
		name := strings.TrimSuffix(filename, Extension)
		nameBytes := decodeBase58([]byte(name))

		nameBytes, err := decrypt(Key, nameBytes)
		if err != nil {
			return err
		}

		// read content from your file
		var data []byte
		data, err = ioutil.ReadFile(path)
		if err != nil {
			return err
		}

		// Set new filepath
		newFilepath := strings.TrimSuffix(path, filename)
		newFilepath = fmt.Sprintf("%s%s", newFilepath, nameBytes)

		// Check the file existing
		if _, err := os.Stat(newFilepath); err == nil {
			fmt.Printf("%s file already exists\n", newFilepath)
			return nil
		}

		// create a new file for saving the encrypted data.
		var file *os.File
		file, err = os.Create(newFilepath)
		if err != nil {
			return err
		}

		// Encrypt file
		data, err = decrypt(Key, data)
		if err != nil {
			return err
		}

		_, err = io.Copy(file, bytes.NewReader(data))
		if err != nil {
			return err
		}

		// Finaly delete encrypted file
		err = os.Remove(path)
		if err != nil {
			return err
		}

		fmt.Printf("%s -> %s\n", filename, nameBytes)

		return nil
	}

	return nil
}

func encryptWalker(path string, f os.FileInfo, err error) error {

	filename := f.Name()

	if err != nil {

		return err

	} else if len(skipPath) > 0 && strings.HasPrefix(path, skipPath) {

		return nil

	} else if string(filename[0]) == "." {

		skipPath = path
		return nil

	} else if f.IsDir() {

		return nil

	} else if strings.HasSuffix(filename, Extension) {

		return nil
	}

	// Encrypt name
	var encryptedName []byte
	encryptedName, err = encrypt(Key, []byte(filename))
	if err != nil {
		return err
	}
	encryptedName = encodeBase58(encryptedName)
	// Print it to console
	fmt.Printf("%s -> %s%s\n", filename, encryptedName, Extension)

	// read content from your file
	var data []byte
	data, err = ioutil.ReadFile(path)
	if err != nil {
		return err
	}

	// Set new filepath
	newFilepath := strings.TrimSuffix(path, filename)
	newFilepath = fmt.Sprintf("%s%s%s", newFilepath, encryptedName, Extension)

	// create a new file for saving the encrypted data.
	var file *os.File
	file, err = os.Create(newFilepath)
	if err != nil {
		return err
	}

	// Encrypt file
	data, err = encrypt(Key, data)
	if err != nil {
		return err
	}

	_, err = io.Copy(file, bytes.NewReader(data))
	if err != nil {
		return err
	}

	return nil
}

func key(text string) ([]byte, error) {
	len := len(text)
	if len < 16 {
		len = 16
	} else if len < 24 {
		len = 24
	} else if len < 32 {
		len = 32
	} else {
		return nil, errors.New("The password cannot be more than 32 char")
	}
	vector := make([]byte, len)
	copy(vector[:], text)
	return vector, nil
}

func IsDirectory(path string) (bool, error) {
	fileInfo, err := os.Stat(path)
	return fileInfo.IsDir(), err
}

func encrypt(key, text []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	ciphertext := make([]byte, aes.BlockSize+len(text))
	iv := ciphertext[:aes.BlockSize]
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		return nil, err
	}
	cfb := cipher.NewCFBEncrypter(block, iv)
	cfb.XORKeyStream(ciphertext[aes.BlockSize:], text)
	return ciphertext, nil
}

func decrypt(key, text []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	if len(text) < aes.BlockSize {
		return nil, errors.New("ciphertext too short")
	}
	iv := text[:aes.BlockSize]
	text = text[aes.BlockSize:]
	cfb := cipher.NewCFBDecrypter(block, iv)
	cfb.XORKeyStream(text, text)
	return text, nil
}

func encodeBase58(text []byte) []byte {
	num := new(big.Int)
	num.SetBytes(text)
	return base58.EncodeBig(nil, num)
}

func decodeBase58(text []byte) []byte {
	dec, _ := base58.DecodeToBig(text)
	return dec.Bytes()
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"encoding/xml"
	"errors"
	"flag"
	"fmt"
	"os"
	"strconv"

	"github.com/fatih/motion/astcontext"
	"github.com/fatih/motion/vim"
)

var (
	flagFile   = flag.String("file", "", "Filename to be parsed")
	flagOffset = flag.String("offset", "", "Byte offset of the cursor position")
	flagFormat = flag.String("format", "plain",
		"Output format. One of {plain, json, xml, vim}")
	flagParseComments = flag.Bool("parse-comments", false,
		"Parse comments and add them to AST")
	flagMode = flag.String("mode", "", "Running mode. One of {enclosing, next, prev}")
)

func main() {
	if err := realMain(); err != nil {
		fmt.Fprint(os.Stderr, err.Error())
		os.Exit(1)
	}
}

func realMain() error {
	flag.Parse()

	if *flagOffset == "" {
		return errors.New("no offset is passed")
	}
	if *flagMode == "" {
		return errors.New("no mode is passed")
	}
	if *flagFile == "" {
		return errors.New("no file is passed")
	}

	offset, err := strconv.Atoi(*flagOffset)
	if err != nil {
		return err
	}

	opts := &astcontext.ParserOptions{
		ParseComments: *flagParseComments,
	}

	parser, err := astcontext.NewParser().SetOptions(opts).ParseFile(*flagFile)
	if err != nil {
		return err
	}

	var fn *astcontext.Func
	switch *flagMode {
	case "enclosing":
		fn, err = parser.Funcs().EnclosingFunc(offset)
	case "next":
		fn, err = parser.Funcs().Declarations().NextFunc(offset)
	case "prev":
		fn, err = parser.Funcs().Declarations().PrevFunc(offset)
	default:
		return fmt.Errorf("wrong mode %q passed", *flagMode)
	}

	if err != nil {
		return err
	}

	switch *flagFormat {
	case "json", "plain", "xml", "vim":
	default:
		return fmt.Errorf("wrong -format value: %q.\n", *flagFormat)
	}

	// Print the result.
	switch *flagFormat {
	case "json":
		b, err := json.MarshalIndent(&fn, "", "\t")
		if err != nil {
			return fmt.Errorf("JSON error: %s\n", err)
		}
		os.Stdout.Write(b)
	case "xml":
		b, err := xml.MarshalIndent(&fn, "", "\t")
		if err != nil {
			return fmt.Errorf("XML error: %s\n", err)
		}
		os.Stdout.Write(b)
	case "vim":
		b, err := vim.Marshal(&fn)
		if err != nil {
			return fmt.Errorf("XML error: %s\n", err)
		}
		os.Stdout.Write(b)
	case "plain":
		fmt.Print(fn)
	}

	return nil
}
<commit_msg>motion: remove xml (who uses it?) and send something parsable<commit_after>package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"os"
	"strconv"

	"github.com/fatih/motion/astcontext"
	"github.com/fatih/motion/vim"
)

var (
	flagFile   = flag.String("file", "", "Filename to be parsed")
	flagOffset = flag.String("offset", "", "Byte offset of the cursor position")
	flagFormat = flag.String("format", "plain",
		"Output format. One of {plain, json, vim}")
	flagParseComments = flag.Bool("parse-comments", false,
		"Parse comments and add them to AST")
	flagMode = flag.String("mode", "", "Running mode. One of {enclosing, next, prev}")
)

func main() {
	if err := realMain(); err != nil {
		fmt.Fprint(os.Stderr, err.Error())
		os.Exit(1)
	}
}

func realMain() error {
	flag.Parse()

	if *flagOffset == "" {
		return errors.New("no offset is passed")
	}
	if *flagMode == "" {
		return errors.New("no mode is passed")
	}
	if *flagFile == "" {
		return errors.New("no file is passed")
	}

	offset, err := strconv.Atoi(*flagOffset)
	if err != nil {
		return err
	}

	opts := &astcontext.ParserOptions{
		ParseComments: *flagParseComments,
	}

	parser, err := astcontext.NewParser().SetOptions(opts).ParseFile(*flagFile)
	if err != nil {
		return err
	}

	var fn *astcontext.Func
	switch *flagMode {
	case "enclosing":
		fn, err = parser.Funcs().EnclosingFunc(offset)
	case "next":
		fn, err = parser.Funcs().Declarations().NextFunc(offset)
	case "prev":
		fn, err = parser.Funcs().Declarations().PrevFunc(offset)
	default:
		return fmt.Errorf("wrong mode %q passed", *flagMode)
	}

	var res interface{} = fn

	// do no return, instead pass it to the editor so it can parse it
	if err != nil {
		res = struct {
			Err string `json:"err" vim:"err"`
		}{
			Err: err.Error(),
		}
	}

	switch *flagFormat {
	case "json", "plain", "vim":
	default:
		return fmt.Errorf("wrong -format value: %q.\n", *flagFormat)
	}

	switch *flagFormat {
	case "json":
		b, err := json.MarshalIndent(&res, "", "\t")
		if err != nil {
			return fmt.Errorf("JSON error: %s\n", err)
		}
		os.Stdout.Write(b)
	case "vim":
		b, err := vim.Marshal(&res)
		if err != nil {
			return fmt.Errorf("VIM error: %s\n", err)
		}
		os.Stdout.Write(b)
	case "plain":
		fmt.Print(res)
	}

	return nil
}
<|endoftext|>


<commit_before>package bench

import (
	"assert"
	"math/rand"
	"reflect"
	"testing"
	"testing/quick"
	"time"
)

// Used for benchmark result assignment
// (to disappoint Go optimizer).
var gScore int

// Default random generator for input data.
var random = rand.New(rand.NewSource(time.Now().Unix()))

// Run executes given function b.N times
// and collects the result (score).
// Score pointer is passed into benchmarking function.
func Run(b *testing.B, bench func(*int)) {
	score := 0
	for i := 0; i < b.N; i++ {
		bench(&score)
	}
	gScore = score
}

// RandInt64Slice generates slice of 50 random int64 elements.
func RandInt64Slice() []int64 {
	res, ok := quick.Value(reflect.TypeOf([]int64{}), random)
	assert.True(ok)
	return res.Interface().([]int64)
}

// RandFloat64Slice generates slice of 50 random float64 elements.
func RandFloat64Slice() []float64 {
	res, ok := quick.Value(reflect.TypeOf([]float64{}), random)
	assert.True(ok)
	return res.Interface().([]float64)
}

// RandStringSlice generates slice of 50 random string elements.
func RandStringSlice() []string {
	res, ok := quick.Value(reflect.TypeOf([]string{}), random)
	assert.True(ok)
	return res.Interface().([]string)
}
<commit_msg>+ bench.RandIntSlice()<commit_after>package bench

import (
	"assert"
	"math/rand"
	"reflect"
	"testing"
	"testing/quick"
	"time"
)

// Used for benchmark result assignment
// (to disappoint Go optimizer).
var gScore int

// Default random generator for input data.
var random = rand.New(rand.NewSource(time.Now().Unix()))

// Run executes given function b.N times
// and collects the result (score).
// Score pointer is passed into benchmarking function.
func Run(b *testing.B, bench func(*int)) {
	score := 0
	for i := 0; i < b.N; i++ {
		bench(&score)
	}
	gScore = score
}

// RandIntSlice generates slice of 50 random int elements.
func RandIntSlice() []int {
	res, ok := quick.Value(reflect.TypeOf([]int{}), random)
	assert.True(ok)
	return res.Interface().([]int)
}

// RandInt64Slice generates slice of 50 random int64 elements.
func RandInt64Slice() []int64 {
	res, ok := quick.Value(reflect.TypeOf([]int64{}), random)
	assert.True(ok)
	return res.Interface().([]int64)
}

// RandFloat64Slice generates slice of 50 random float64 elements.
func RandFloat64Slice() []float64 {
	res, ok := quick.Value(reflect.TypeOf([]float64{}), random)
	assert.True(ok)
	return res.Interface().([]float64)
}

// RandStringSlice generates slice of 50 random string elements.
func RandStringSlice() []string {
	res, ok := quick.Value(reflect.TypeOf([]string{}), random)
	assert.True(ok)
	return res.Interface().([]string)
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"os"
	"sync"
	"time"

	"github.com/codegangsta/cli"
	docker "github.com/fsouza/go-dockerclient"
	"github.com/montanaflynn/stats"
)

func worker(requests int, image string, completeCh chan time.Duration) {
	client, err := docker.NewClientFromEnv()
	if err != nil {
		panic(err)
	}

	for i := 0; i < requests; i++ {
		start := time.Now()

		container, err := client.CreateContainer(docker.CreateContainerOptions{
			Config: &docker.Config{
				Image: image,
			}})
		if err != nil {
			panic(err)
		}

		err = client.StartContainer(container.ID, nil)
		if err != nil {
			panic(err)
		}

		completeCh <- time.Since(start)
	}
}

func session(requests, concurrency int, image string, completeCh chan time.Duration) {
	var wg sync.WaitGroup

	n := requests / concurrency

	for i := 0; i < concurrency; i++ {
		wg.Add(1)
		go func() {
			worker(n, image, completeCh)
			wg.Done()
		}()
	}
	wg.Wait()

}

func bench(requests, concurrency int, image string) {
	start := time.Now()

	timings := make([]float64, requests)
	completeCh := make(chan time.Duration)
	current := 0
	prevPercent := -1
	go func() {
		for timing := range completeCh {
			timings = append(timings, timing.Seconds())
			current++
			percent := int(float64(current) / float64(requests) * 100)
			if percent > prevPercent {
				log.Printf("[%3.0d%%] %d/%d containers started (%vms)", percent, current, requests, int(timing.Seconds()*1000))
				prevPercent = percent
			}
		}
	}()
	session(requests, concurrency, image, completeCh)
	close(completeCh)

	total := time.Since(start)
	p50th, _ := stats.Median(timings)
	p90th, _ := stats.Percentile(timings, 90)
	p99th, _ := stats.Percentile(timings, 99)

	log.Printf("---")
	log.Printf("Time taken for tests: %s", total.String())
	log.Printf("Time per container: %vms [50th] | %vms [90th] | %vms [99th]", int(p50th*1000), int(p90th*1000), int(p99th*1000))
}

func main() {
	app := cli.NewApp()
	app.Name = "docker-bench"
	app.Usage = "docker benchmarking tool"
	app.Flags = []cli.Flag{
		cli.IntFlag{
			Name:  "concurrency, c",
			Value: 1,
			Usage: "Number of multiple requests to perform at a time. Default is one request at a time.",
		},
		cli.IntFlag{
			Name:  "requests, n",
			Value: 1,
			Usage: "Number of containers to start for the benchmarking session. The default is to just start a single container.",
		},
		cli.StringFlag{
			Name:  "image, i",
			Value: "helloworld",
			Usage: "Image to use for benchmarking.",
		},
	}

	app.Action = func(c *cli.Context) {
		bench(c.Int("requests"), c.Int("concurrency"), c.String("image"))
	}

	app.Run(os.Args)
}
<commit_msg>Output messages using fmt rather than log.<commit_after>package main

import (
	"fmt"
	"os"
	"sync"
	"time"

	"github.com/codegangsta/cli"
	docker "github.com/fsouza/go-dockerclient"
	"github.com/montanaflynn/stats"
)

func worker(requests int, image string, completeCh chan time.Duration) {
	client, err := docker.NewClientFromEnv()
	if err != nil {
		panic(err)
	}

	for i := 0; i < requests; i++ {
		start := time.Now()

		container, err := client.CreateContainer(docker.CreateContainerOptions{
			Config: &docker.Config{
				Image: image,
			}})
		if err != nil {
			panic(err)
		}

		err = client.StartContainer(container.ID, nil)
		if err != nil {
			panic(err)
		}

		completeCh <- time.Since(start)
	}
}

func session(requests, concurrency int, image string, completeCh chan time.Duration) {
	var wg sync.WaitGroup

	n := requests / concurrency

	for i := 0; i < concurrency; i++ {
		wg.Add(1)
		go func() {
			worker(n, image, completeCh)
			wg.Done()
		}()
	}
	wg.Wait()

}

func bench(requests, concurrency int, image string) {
	start := time.Now()

	timings := make([]float64, requests)
	completeCh := make(chan time.Duration)
	current := 0
	go func() {
		for timing := range completeCh {
			timings = append(timings, timing.Seconds())
			current++
			percent := int(float64(current) / float64(requests) * 100)
			fmt.Printf("[%3.0d%%] %d/%d containers started\n", percent, current, requests)
		}
	}()
	session(requests, concurrency, image, completeCh)
	close(completeCh)

	total := time.Since(start)
	p50th, _ := stats.Median(timings)
	p90th, _ := stats.Percentile(timings, 90)
	p99th, _ := stats.Percentile(timings, 99)

	fmt.Println("")
	fmt.Printf("Time taken for tests: %s\n", total.String())
	fmt.Printf("Time per container: %vms [50th] | %vms [90th] | %vms [99th]\n", int(p50th*1000), int(p90th*1000), int(p99th*1000))
}

func main() {
	app := cli.NewApp()
	app.Name = "swarm-bench"
	app.Usage = "Swarm Benchmarking Tool"
	app.Flags = []cli.Flag{
		cli.IntFlag{
			Name:  "concurrency, c",
			Value: 1,
			Usage: "Number of multiple requests to perform at a time. Default is one request at a time.",
		},
		cli.IntFlag{
			Name:  "requests, n",
			Value: 1,
			Usage: "Number of containers to start for the benchmarking session. The default is to just start a single container.",
		},
		cli.StringFlag{
			Name:  "image, i",
			Value: "helloworld",
			Usage: "Image to use for benchmarking.",
		},
	}

	app.Action = func(c *cli.Context) {
		bench(c.Int("requests"), c.Int("concurrency"), c.String("image"))
	}

	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package main

import "fmt"

func main() {
	fmt.Printf("hello world!\n")
}
<commit_msg>english teacher in me breaking out!<commit_after>package main

import "fmt"

func main() {
	fmt.Printf("Hello, world!\n")
}
<|endoftext|>


<commit_before>package main

import (
	"strings"
	"time"

	"github.com/levenlabs/go-llog"
	"github.com/mediocregopher/lever"
	"github.com/miekg/dns"
)

var dnsServerGroups [][]string
var client dns.Client

type NewReq struct {
	Msg     *dns.Msg
	ReplyCh chan *dns.Msg
}

type RespReq struct {
	OrigMsg *dns.Msg
	Reply   *dns.Msg
}

var newCh = make(chan NewReq)
var respCh = make(chan RespReq)

//need to use init and not main for main_test.go
func init() {
	go reqSpin()
}

//Note: check len(msg.Answer) to make sure the response from this actually has an answer
func tryProxy(m *dns.Msg, addr string) *dns.Msg {
	aM, _, err := client.Exchange(m, addr)
	if err != nil {
		llog.Error("forwarding error in tryProxy", llog.KV{"addr": addr, "err": err})
		return nil
	}
	return aM
}

func queryGroup(r *dns.Msg, servers []string) *dns.Msg {
	chs := make([]chan *dns.Msg, len(servers))
	for i := range servers {
		chs[i] = make(chan *dns.Msg, 1)
		go func(ch chan *dns.Msg, addr string) {
			ch <- tryProxy(r, addr)
		}(chs[i], servers[i])
	}

	var m *dns.Msg
	for i := range servers {
		if m = <-chs[i]; m != nil && len(m.Answer) > 0 {
			break
		}
	}
	return m
}

func queryAllGroups(r *dns.Msg) {
	var m *dns.Msg
	for i := range dnsServerGroups {
		m = queryGroup(r, dnsServerGroups[i])
		if m != nil && len(m.Answer) > 0 {
			break
		}
	}
	respCh <- RespReq{r, m}
}

func handleRequest(w dns.ResponseWriter, r *dns.Msg) {
	kv := llog.KV{"question": "", "type": ""}
	var m *dns.Msg
	if len(r.Question) > 0 {
		kv["type"], _ = dns.TypeToString[r.Question[0].Qtype]
		kv["question"] = r.Question[0].Name
		llog.Info("handling request", kv)
		rr := NewReq{r, make(chan *dns.Msg)}
		newCh <- rr
		m = <-rr.ReplyCh
	}
	if m == nil {
		llog.Info("error handling request", kv)
		dns.HandleFailed(w, r)
		return
	}
	kv["rcode"], _ = dns.RcodeToString[m.Rcode]
	if len(m.Answer) > 0 {
		kv["answer"] = m.Answer[0]
	}
	llog.Info("responding to request", kv)
	//we need to make sure the ID matches the replied one
	if m.Id != r.Id {
		//since it doesn't match, copy the struct and replace the ID
		m2 := *m
		m2.Id = r.Id
		m = &m2
	}
	//do not call SetReply since m is already a reply for r
	w.WriteMsg(m)
}

func main() {
	l := lever.New("struggledns", nil)
	l.Add(lever.Param{
		Name:        "--listen-addr",
		Description: "Address to listen on for dns requests. Will bind to both tcp and udp",
		Default:     ":53",
	})
	l.Add(lever.Param{
		Name:        "--fwd-to",
		Description: "Address (ip:port) of a dns server to attempt forward requests to. Specify multiple times to make multiple request attempts. Order specified dictates precedence should more than one server respond for a request",
	})
	l.Add(lever.Param{
		Name:        "--parallel",
		Description: "If sent the query will be sent to all addresses in parallel",
		Flag:        true,
	})
	l.Add(lever.Param{
		Name:        "--timeout",
		Description: "Timeout in milliseconds for each request",
		Default:     "300",
	})
	l.Add(lever.Param{
		Name:        "--log-level",
		Description: "Minimum log level to show, either debug, info, warn, error, or fatal",
		Default:     "warn",
	})
	l.Parse()

	addr, _ := l.ParamStr("--listen-addr")
	dnsServers, _ := l.ParamStrs("--fwd-to")
	combineGroups := l.ParamFlag("--parallel")
	timeout, _ := l.ParamInt("--timeout")

	logLevel, _ := l.ParamStr("--log-level")
	llog.SetLevelFromString(logLevel)

	if combineGroups {
		//combine all the servers sent into one group
		dnsServerGroups = make([][]string, 1)
		var groupServers []string
		for i := range dnsServers {
			groupServers = strings.Split(dnsServers[i], ",")
			dnsServerGroups[0] = append(dnsServerGroups[0], groupServers...)
		}
	} else {
		dnsServerGroups = make([][]string, len(dnsServers))
		for i := range dnsServers {
			dnsServerGroups[i] = strings.Split(dnsServers[i], ",")
		}
	}

	client = dns.Client{
		//since this is UDP, the Dial/Write timeouts don't mean much
		//we really only care about setting the read
		DialTimeout:  time.Millisecond * 100,
		WriteTimeout: time.Millisecond * 100,
		ReadTimeout:  time.Millisecond * time.Duration(timeout),
	}

	handler := dns.HandlerFunc(handleRequest)
	go func() {
		llog.Info("listening on udp", llog.KV{"addr": addr})
		err := dns.ListenAndServe(addr, "udp", handler)
		llog.Fatal("error listening on udp", llog.KV{"err": err})
	}()
	go func() {
		llog.Info("listening on tcp", llog.KV{"addr": addr})
		err := dns.ListenAndServe(addr, "tcp", handler)
		llog.Fatal("error listening on tcp", llog.KV{"err": err})
	}()

	select {}
}

func getQuestionKey(q dns.Question) string {
	t := "nop"
	if t1, ok := dns.TypeToString[q.Qtype]; ok {
		t = t1
	}
	c := "nop"
	if c1, ok := dns.ClassToString[q.Qclass]; ok {
		c = c1
	}
	n := q.Name
	return n + t + c
}

func getMsgKey(r *dns.Msg) string {
	k := ""
	for _, q := range r.Question {
		k += getQuestionKey(q)
	}
	return k
}

func reqSpin() {
	var k string
	inFlight := make(map[string][]chan *dns.Msg)
	for {
		select {
		case r := <-newCh:
			k = getMsgKey(r.Msg)
			_, ok := inFlight[k]
			inFlight[k] = append(inFlight[k], r.ReplyCh)
			if !ok {
				go queryAllGroups(r.Msg)
			}
		case r := <-respCh:
			k = getMsgKey(r.OrigMsg)
			for _, ch := range inFlight[k] {
				ch <- r.Reply
			}
			delete(inFlight, k)
		}
	}
}
<commit_msg>make the forwarding error into a warn<commit_after>package main

import (
	"strings"
	"time"

	"github.com/levenlabs/go-llog"
	"github.com/mediocregopher/lever"
	"github.com/miekg/dns"
)

var dnsServerGroups [][]string
var client dns.Client

type NewReq struct {
	Msg     *dns.Msg
	ReplyCh chan *dns.Msg
}

type RespReq struct {
	OrigMsg *dns.Msg
	Reply   *dns.Msg
}

var newCh = make(chan NewReq)
var respCh = make(chan RespReq)

//need to use init and not main for main_test.go
func init() {
	go reqSpin()
}

//Note: check len(msg.Answer) to make sure the response from this actually has an answer
func tryProxy(m *dns.Msg, addr string) *dns.Msg {
	aM, _, err := client.Exchange(m, addr)
	if err != nil {
		llog.Warn("forwarding error in tryProxy", llog.KV{"addr": addr, "err": err})
		return nil
	}
	return aM
}

func queryGroup(r *dns.Msg, servers []string) *dns.Msg {
	chs := make([]chan *dns.Msg, len(servers))
	for i := range servers {
		chs[i] = make(chan *dns.Msg, 1)
		go func(ch chan *dns.Msg, addr string) {
			ch <- tryProxy(r, addr)
		}(chs[i], servers[i])
	}

	var m *dns.Msg
	for i := range servers {
		if m = <-chs[i]; m != nil && len(m.Answer) > 0 {
			break
		}
	}
	return m
}

func queryAllGroups(r *dns.Msg) {
	var m *dns.Msg
	for i := range dnsServerGroups {
		m = queryGroup(r, dnsServerGroups[i])
		if m != nil && len(m.Answer) > 0 {
			break
		}
	}
	respCh <- RespReq{r, m}
}

func handleRequest(w dns.ResponseWriter, r *dns.Msg) {
	kv := llog.KV{"question": "", "type": ""}
	var m *dns.Msg
	if len(r.Question) > 0 {
		kv["type"], _ = dns.TypeToString[r.Question[0].Qtype]
		kv["question"] = r.Question[0].Name
		llog.Info("handling request", kv)
		rr := NewReq{r, make(chan *dns.Msg)}
		newCh <- rr
		m = <-rr.ReplyCh
	}
	if m == nil {
		llog.Info("error handling request", kv)
		dns.HandleFailed(w, r)
		return
	}
	kv["rcode"], _ = dns.RcodeToString[m.Rcode]
	if len(m.Answer) > 0 {
		kv["answer"] = m.Answer[0]
	}
	llog.Info("responding to request", kv)
	//we need to make sure the ID matches the replied one
	if m.Id != r.Id {
		//since it doesn't match, copy the struct and replace the ID
		m2 := *m
		m2.Id = r.Id
		m = &m2
	}
	//do not call SetReply since m is already a reply for r
	w.WriteMsg(m)
}

func main() {
	l := lever.New("struggledns", nil)
	l.Add(lever.Param{
		Name:        "--listen-addr",
		Description: "Address to listen on for dns requests. Will bind to both tcp and udp",
		Default:     ":53",
	})
	l.Add(lever.Param{
		Name:        "--fwd-to",
		Description: "Address (ip:port) of a dns server to attempt forward requests to. Specify multiple times to make multiple request attempts. Order specified dictates precedence should more than one server respond for a request",
	})
	l.Add(lever.Param{
		Name:        "--parallel",
		Description: "If sent the query will be sent to all addresses in parallel",
		Flag:        true,
	})
	l.Add(lever.Param{
		Name:        "--timeout",
		Description: "Timeout in milliseconds for each request",
		Default:     "300",
	})
	l.Add(lever.Param{
		Name:        "--log-level",
		Description: "Minimum log level to show, either debug, info, warn, error, or fatal",
		Default:     "warn",
	})
	l.Parse()

	addr, _ := l.ParamStr("--listen-addr")
	dnsServers, _ := l.ParamStrs("--fwd-to")
	combineGroups := l.ParamFlag("--parallel")
	timeout, _ := l.ParamInt("--timeout")

	logLevel, _ := l.ParamStr("--log-level")
	llog.SetLevelFromString(logLevel)

	if combineGroups {
		//combine all the servers sent into one group
		dnsServerGroups = make([][]string, 1)
		var groupServers []string
		for i := range dnsServers {
			groupServers = strings.Split(dnsServers[i], ",")
			dnsServerGroups[0] = append(dnsServerGroups[0], groupServers...)
		}
	} else {
		dnsServerGroups = make([][]string, len(dnsServers))
		for i := range dnsServers {
			dnsServerGroups[i] = strings.Split(dnsServers[i], ",")
		}
	}

	client = dns.Client{
		//since this is UDP, the Dial/Write timeouts don't mean much
		//we really only care about setting the read
		DialTimeout:  time.Millisecond * 100,
		WriteTimeout: time.Millisecond * 100,
		ReadTimeout:  time.Millisecond * time.Duration(timeout),
	}

	handler := dns.HandlerFunc(handleRequest)
	go func() {
		llog.Info("listening on udp", llog.KV{"addr": addr})
		err := dns.ListenAndServe(addr, "udp", handler)
		llog.Fatal("error listening on udp", llog.KV{"err": err})
	}()
	go func() {
		llog.Info("listening on tcp", llog.KV{"addr": addr})
		err := dns.ListenAndServe(addr, "tcp", handler)
		llog.Fatal("error listening on tcp", llog.KV{"err": err})
	}()

	select {}
}

func getQuestionKey(q dns.Question) string {
	t := "nop"
	if t1, ok := dns.TypeToString[q.Qtype]; ok {
		t = t1
	}
	c := "nop"
	if c1, ok := dns.ClassToString[q.Qclass]; ok {
		c = c1
	}
	n := q.Name
	return n + t + c
}

func getMsgKey(r *dns.Msg) string {
	k := ""
	for _, q := range r.Question {
		k += getQuestionKey(q)
	}
	return k
}

func reqSpin() {
	var k string
	inFlight := make(map[string][]chan *dns.Msg)
	for {
		select {
		case r := <-newCh:
			k = getMsgKey(r.Msg)
			_, ok := inFlight[k]
			inFlight[k] = append(inFlight[k], r.ReplyCh)
			if !ok {
				go queryAllGroups(r.Msg)
			}
		case r := <-respCh:
			k = getMsgKey(r.OrigMsg)
			for _, ch := range inFlight[k] {
				ch <- r.Reply
			}
			delete(inFlight, k)
		}
	}
}
<|endoftext|>


<commit_before>// WorkQueue - Go implementation of DMWM WorkQueue
//
// Copyright (c) 2017 - Valentin Kuznetsov <vkuznet@gmail.com>
//
package main

import (
	"encoding/json"
	"flag"
	"io/ioutil"
	"os"
	"runtime"
	"strings"
	"time"

	"github.com/pkg/profile"
	log "github.com/sirupsen/logrus"

	"github.com/vkuznet/WorkQueue/server"
	"github.com/vkuznet/WorkQueue/utils"
)

func main() {

	// server options
	var configFile string
	flag.StringVar(&configFile, "config", "", "configuration file")
	var verbose int
	flag.IntVar(&verbose, "verbose", 0, "verbose level")
	var authVar bool
	flag.BoolVar(&authVar, "auth", true, "To disable the auth layer")
	mode := flag.String("profileMode", "", "enable profiling mode, one of [cpu, mem, block]")
	flag.Parse()
	switch *mode {
	case "cpu":
		defer profile.Start(profile.CPUProfile, profile.ProfilePath(".")).Stop()
	case "mem":
		defer profile.Start(profile.MemProfile, profile.ProfilePath(".")).Stop()
	case "block":
		defer profile.Start(profile.BlockProfile, profile.ProfilePath(".")).Stop()
	default:
		// do nothing
	}

	if authVar {
		utils.CheckX509()
	}
	utils.VERBOSE = verbose
	if configFile == "" {
		log.Println("Please provide configuration file")
		os.Exit(1)
	}
	data, err := ioutil.ReadFile(configFile)
	if err != nil {
		log.Println("Unable to read", configFile, err)
		os.Exit(1)
	}
	var config server.Config
	err = json.Unmarshal(data, &config)
	if err != nil {
		log.Println("Unable to parse", configFile, err)
		os.Exit(1)
	}
	// set logger settings depending on configuration
	if strings.Contains(strings.ToLower(config.LogFormatter), "json") {
		log.SetFormatter(&log.JSONFormatter{})
	}
	if strings.Contains(strings.ToLower(config.LogLevel), "info") {
		log.SetLevel(log.InfoLevel)
	}
	if strings.Contains(strings.ToLower(config.LogLevel), "warn") {
		log.SetLevel(log.WarnLevel)
	}
	if strings.Contains(strings.ToLower(config.LogLevel), "err") {
		log.SetLevel(log.ErrorLevel)
	}
	if strings.Contains(strings.ToLower(config.LogLevel), "debug") {
		utils.VERBOSE = 2 // overwrite default since we want to get deep view
		log.SetLevel(log.DebugLevel)
	}
	log.Println("VERBOSE", utils.VERBOSE)
	// measure in backround memory usage of the server
	var m runtime.MemStats
	go func() {
		for {
			if utils.VERBOSE > 0 {
				runtime.ReadMemStats(&m)
				log.WithFields(log.Fields{
					"system":  m.HeapSys,
					"alloc":   m.HeapAlloc,
					"idle":    m.HeapIdle,
					"release": m.HeapReleased,
				}).Info("heap memory")
			}
			time.Sleep(time.Duration(1) * time.Second) // wait for a job
		}
	}()
	// Start the server
	server.Server(config)
}
<commit_msg>Use LogSettings<commit_after>// WorkQueue - Go implementation of DMWM WorkQueue
//
// Copyright (c) 2017 - Valentin Kuznetsov <vkuznet@gmail.com>
//
package main

import (
	"encoding/json"
	"flag"
	"io/ioutil"
	"os"
	"runtime"
	"time"

	"github.com/pkg/profile"
	log "github.com/sirupsen/logrus"

	"github.com/vkuznet/WorkQueue/server"
	"github.com/vkuznet/WorkQueue/utils"
)

func main() {

	// server options
	var configFile string
	flag.StringVar(&configFile, "config", "", "configuration file")
	var verbose int
	flag.IntVar(&verbose, "verbose", 0, "verbose level")
	var authVar bool
	flag.BoolVar(&authVar, "auth", true, "To disable the auth layer")
	mode := flag.String("profileMode", "", "enable profiling mode, one of [cpu, mem, block]")
	flag.Parse()
	switch *mode {
	case "cpu":
		defer profile.Start(profile.CPUProfile, profile.ProfilePath(".")).Stop()
	case "mem":
		defer profile.Start(profile.MemProfile, profile.ProfilePath(".")).Stop()
	case "block":
		defer profile.Start(profile.BlockProfile, profile.ProfilePath(".")).Stop()
	default:
		// do nothing
	}

	if authVar {
		utils.CheckX509()
	}
	utils.VERBOSE = verbose
	if configFile == "" {
		log.Println("Please provide configuration file")
		os.Exit(1)
	}
	data, err := ioutil.ReadFile(configFile)
	if err != nil {
		log.Println("Unable to read", configFile, err)
		os.Exit(1)
	}
	var config server.Config
	err = json.Unmarshal(data, &config)
	if err != nil {
		log.Println("Unable to parse", configFile, err)
		os.Exit(1)
	}
	utils.LogSettings(config.LogLevel, config.LogFormatter)
	log.Println("VERBOSE", utils.VERBOSE)

	// measure in backround memory usage of the server
	var m runtime.MemStats
	go func() {
		for {
			if utils.MEMORY {
				runtime.ReadMemStats(&m)
				log.WithFields(log.Fields{
					"system":  m.HeapSys,
					"alloc":   m.HeapAlloc,
					"idle":    m.HeapIdle,
					"release": m.HeapReleased,
				}).Info("heap memory")
			}
			time.Sleep(time.Duration(1) * time.Second) // wait for a job
		}
	}()
	// Start the server
	server.Server(config)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/textproto"
	"os"
	"strconv"

	"github.com/omar-h/goimage/util"
	"github.com/gorilla/csrf"
	"github.com/gorilla/mux"
)

// viewData is the data parsed to the
// ViewHandler's template
type viewData struct {
	Id       string
	ImageUrl string
	Ext      string
}

// config is the parsed JSON config
type config struct {
	Port              int      `json:"port"`
	Secure            bool     `json:"secure"`
	AuthKey           string   `json:"32-byte-auth-key"`
	AllowedMimeTypes  []string `json:"allowed-mime-types"`
	AllowedExtensions []string `json:"allowed-extensions"`
	ImageNameLength   int      `json:"image-name-length"`
	MaxFileSize       int64    `json:"max-file-size"`
	ImageDirectory    string   `json:"image-directory"`
	TemplateDirectory string   `json:"template-directory"`
	PublicDirectory   string   `json:"public-directory"`
	ImageUrl          string   `json:"image-url"`
	CSRF              bool     `json:"csrf"`
}

var parsedConfig config

func main() {
	jsonFiles, err := ioutil.ReadFile("./config.json")
	if err != nil {
		log.Fatal(err)
		return
	}
	json.Unmarshal(jsonFiles, &parsedConfig)

	CSRF := csrf.Protect(
		[]byte(parsedConfig.AuthKey),
		csrf.RequestHeader("X-CSRF-Token"),
		csrf.FieldName("_csrf"),
		csrf.Secure(parsedConfig.Secure),
	)
	r := mux.NewRouter()
	err = os.MkdirAll(parsedConfig.TemplateDirectory, 644)
	if err != nil {
		log.Fatal("Unable to create Template Directory")
	}
	err = os.MkdirAll(parsedConfig.PublicDirectory, 644)
	if err != nil {
		log.Fatal("Unable to create Public Directory")
	}
	err = os.MkdirAll(parsedConfig.ImageDirectory, 644)
	if err != nil {
		log.Fatal("Unable to create Image Directory")
	}

	templates := template.Must(template.ParseGlob(parsedConfig.TemplateDirectory + "*.html"))

	r.HandleFunc("/{id}/", viewHandler(templates)).Methods("GET")
	r.HandleFunc("/upload/", uploadHandler).Methods("POST")
	r.PathPrefix("/").HandlerFunc(rootHandler(templates)).Methods("GET")

	log.Print("Listening on port " + strconv.Itoa(parsedConfig.Port))
	if parsedConfig.CSRF {
		log.Fatal(http.ListenAndServe(":"+strconv.Itoa(parsedConfig.Port), CSRF(r)))
	} else {
		log.Fatal(http.ListenAndServe(":"+strconv.Itoa(parsedConfig.Port), r))
	}
}

// rootHandler handles the root route.
// This includes the homepage and the
// file system.
func rootHandler(t *template.Template) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		switch url := r.URL.Path; url {
		case "/":
			if parsedConfig.CSRF {
				w.Header().Set("X-CSRF-Token", csrf.Token(r))
				err := t.ExecuteTemplate(w, "index.html", map[string]interface{}{
					csrf.TemplateTag: csrf.TemplateField(r),
				})
				if err != nil {
					w.WriteHeader(http.StatusInternalServerError)
				}
			} else {
				err := t.ExecuteTemplate(w, "index.html", map[string]interface{}{
					csrf.TemplateTag: "",
				})
				if err != nil {
					w.WriteHeader(http.StatusInternalServerError)
				}
			}
		default:
			if _, err := os.Stat(parsedConfig.PublicDirectory + url); err != nil {
				w.Header().Add("Content-Type", "text/html; charset=utf-8")
				w.WriteHeader(http.StatusNotFound)
				http.ServeFile(w, r, parsedConfig.TemplateDirectory+"404.html")
			} else {
				http.ServeFile(w, r, parsedConfig.PublicDirectory+url)
			}
		}

	}
}

// viewHandler handles the ability to view your image.
// It checks if the file exists, and returns
// an appropriate response.
//
// If the image exists, it serves a template
// which is defined in
// TemplateDirectory/view.html.
func viewHandler(t *template.Template) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		vars := mux.Vars(r)
		id := vars["id"]
		ext := util.GetFileExtFromDir(id, parsedConfig.ImageDirectory)
		if ext != "" {
			err := t.ExecuteTemplate(w, "view.html", viewData{
				Id:       id,
				ImageUrl: parsedConfig.ImageUrl,
				Ext:      ext,
			})
			if err != nil {
				w.WriteHeader(http.StatusInternalServerError)
				log.Fatal(err)
				return
			}
		} else {
			w.Header().Add("Content-Type", "text/html; charset=utf-8")
			w.WriteHeader(http.StatusNotFound)
			http.ServeFile(w, r, parsedConfig.TemplateDirectory+"404.html")
		}
	}
}

// uploadHandler handles the upload route.
// It checks the file, and uploads the
// image to the ImageDirectory defined
// in the config.json
func uploadHandler(w http.ResponseWriter, r *http.Request) {
	r.ParseMultipartForm(30000000)
	file, handler, err := r.FormFile("file")
	if err != nil {
		log.Fatal(err)
		return
	}
	defer file.Close()

	if checkFileType(handler.Header) == false {
		http.Redirect(w, r, "/", http.StatusSeeOther)
		return
	}

	name := generateName(parsedConfig.ImageNameLength)
	f, err := os.OpenFile(parsedConfig.ImageDirectory+name+util.GetFileExt(handler.Header["Content-Disposition"][0]), os.O_WRONLY|os.O_CREATE, 0644)
	if err != nil {
		log.Fatal(err)
		return
	}

	io.Copy(f, file)
	fStat, err := f.Stat()
	if err != nil {
		log.Fatal(err)
	}
	size := fStat.Size()
	if size > parsedConfig.MaxFileSize {
		f.Close()
		err = os.RemoveAll(parsedConfig.ImageDirectory + name + util.GetFileExt(handler.Header["Content-Disposition"][0]))
		if err != nil {
			log.Fatal(err)
		}
		http.Redirect(w, r, "/", http.StatusSeeOther)
	} else {
		http.Redirect(w, r, "/"+name+"/", http.StatusSeeOther)
		f.Close()
	}
}

// checkFileType checks if the uploaded
// file's extension is allowed.
// It accepts a textproto.MIMEHeader
// which is received from the http.Request
// FormFile function, as the handler.Header
func checkFileType(f textproto.MIMEHeader) bool {
	ext := util.GetFileExt(f["Content-Disposition"][0])

	if !util.Contains(parsedConfig.AllowedMimeTypes, f["Content-Type"][0]) || !util.Contains(parsedConfig.AllowedExtensions, ext) {
		return false
	}

	return true
}

// generateName generates a name with
// a specified length, and checks if
// the name already exists, using the
// util functions for this.
func generateName(n int) string {
	name := util.GenerateName(n)

	for util.CheckExists(name, parsedConfig.ImageDirectory) {
		name = util.GenerateName(n)
	}

	return name
}
<commit_msg>Run gofmt<commit_after>package main

import (
	"encoding/json"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/textproto"
	"os"
	"strconv"

	"github.com/gorilla/csrf"
	"github.com/gorilla/mux"
	"github.com/omar-h/goimage/util"
)

// viewData is the data parsed to the
// ViewHandler's template
type viewData struct {
	Id       string
	ImageUrl string
	Ext      string
}

// config is the parsed JSON config
type config struct {
	Port              int      `json:"port"`
	Secure            bool     `json:"secure"`
	AuthKey           string   `json:"32-byte-auth-key"`
	AllowedMimeTypes  []string `json:"allowed-mime-types"`
	AllowedExtensions []string `json:"allowed-extensions"`
	ImageNameLength   int      `json:"image-name-length"`
	MaxFileSize       int64    `json:"max-file-size"`
	ImageDirectory    string   `json:"image-directory"`
	TemplateDirectory string   `json:"template-directory"`
	PublicDirectory   string   `json:"public-directory"`
	ImageUrl          string   `json:"image-url"`
	CSRF              bool     `json:"csrf"`
}

var parsedConfig config

func main() {
	jsonFiles, err := ioutil.ReadFile("./config.json")
	if err != nil {
		log.Fatal(err)
		return
	}
	json.Unmarshal(jsonFiles, &parsedConfig)

	CSRF := csrf.Protect(
		[]byte(parsedConfig.AuthKey),
		csrf.RequestHeader("X-CSRF-Token"),
		csrf.FieldName("_csrf"),
		csrf.Secure(parsedConfig.Secure),
	)
	r := mux.NewRouter()
	err = os.MkdirAll(parsedConfig.TemplateDirectory, 644)
	if err != nil {
		log.Fatal("Unable to create Template Directory")
	}
	err = os.MkdirAll(parsedConfig.PublicDirectory, 644)
	if err != nil {
		log.Fatal("Unable to create Public Directory")
	}
	err = os.MkdirAll(parsedConfig.ImageDirectory, 644)
	if err != nil {
		log.Fatal("Unable to create Image Directory")
	}

	templates := template.Must(template.ParseGlob(parsedConfig.TemplateDirectory + "*.html"))

	r.HandleFunc("/{id}/", viewHandler(templates)).Methods("GET")
	r.HandleFunc("/upload/", uploadHandler).Methods("POST")
	r.PathPrefix("/").HandlerFunc(rootHandler(templates)).Methods("GET")

	log.Print("Listening on port " + strconv.Itoa(parsedConfig.Port))
	if parsedConfig.CSRF {
		log.Fatal(http.ListenAndServe(":"+strconv.Itoa(parsedConfig.Port), CSRF(r)))
	} else {
		log.Fatal(http.ListenAndServe(":"+strconv.Itoa(parsedConfig.Port), r))
	}
}

// rootHandler handles the root route.
// This includes the homepage and the
// file system.
func rootHandler(t *template.Template) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		switch url := r.URL.Path; url {
		case "/":
			if parsedConfig.CSRF {
				w.Header().Set("X-CSRF-Token", csrf.Token(r))
				err := t.ExecuteTemplate(w, "index.html", map[string]interface{}{
					csrf.TemplateTag: csrf.TemplateField(r),
				})
				if err != nil {
					w.WriteHeader(http.StatusInternalServerError)
				}
			} else {
				err := t.ExecuteTemplate(w, "index.html", map[string]interface{}{
					csrf.TemplateTag: "",
				})
				if err != nil {
					w.WriteHeader(http.StatusInternalServerError)
				}
			}
		default:
			if _, err := os.Stat(parsedConfig.PublicDirectory + url); err != nil {
				w.Header().Add("Content-Type", "text/html; charset=utf-8")
				w.WriteHeader(http.StatusNotFound)
				http.ServeFile(w, r, parsedConfig.TemplateDirectory+"404.html")
			} else {
				http.ServeFile(w, r, parsedConfig.PublicDirectory+url)
			}
		}

	}
}

// viewHandler handles the ability to view your image.
// It checks if the file exists, and returns
// an appropriate response.
//
// If the image exists, it serves a template
// which is defined in
// TemplateDirectory/view.html.
func viewHandler(t *template.Template) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		vars := mux.Vars(r)
		id := vars["id"]
		ext := util.GetFileExtFromDir(id, parsedConfig.ImageDirectory)
		if ext != "" {
			err := t.ExecuteTemplate(w, "view.html", viewData{
				Id:       id,
				ImageUrl: parsedConfig.ImageUrl,
				Ext:      ext,
			})
			if err != nil {
				w.WriteHeader(http.StatusInternalServerError)
				log.Fatal(err)
				return
			}
		} else {
			w.Header().Add("Content-Type", "text/html; charset=utf-8")
			w.WriteHeader(http.StatusNotFound)
			http.ServeFile(w, r, parsedConfig.TemplateDirectory+"404.html")
		}
	}
}

// uploadHandler handles the upload route.
// It checks the file, and uploads the
// image to the ImageDirectory defined
// in the config.json
func uploadHandler(w http.ResponseWriter, r *http.Request) {
	r.ParseMultipartForm(30000000)
	file, handler, err := r.FormFile("file")
	if err != nil {
		log.Fatal(err)
		return
	}
	defer file.Close()

	if checkFileType(handler.Header) == false {
		http.Redirect(w, r, "/", http.StatusSeeOther)
		return
	}

	name := generateName(parsedConfig.ImageNameLength)
	f, err := os.OpenFile(parsedConfig.ImageDirectory+name+util.GetFileExt(handler.Header["Content-Disposition"][0]), os.O_WRONLY|os.O_CREATE, 0644)
	if err != nil {
		log.Fatal(err)
		return
	}

	io.Copy(f, file)
	fStat, err := f.Stat()
	if err != nil {
		log.Fatal(err)
	}
	size := fStat.Size()
	if size > parsedConfig.MaxFileSize {
		f.Close()
		err = os.RemoveAll(parsedConfig.ImageDirectory + name + util.GetFileExt(handler.Header["Content-Disposition"][0]))
		if err != nil {
			log.Fatal(err)
		}
		http.Redirect(w, r, "/", http.StatusSeeOther)
	} else {
		http.Redirect(w, r, "/"+name+"/", http.StatusSeeOther)
		f.Close()
	}
}

// checkFileType checks if the uploaded
// file's extension is allowed.
// It accepts a textproto.MIMEHeader
// which is received from the http.Request
// FormFile function, as the handler.Header
func checkFileType(f textproto.MIMEHeader) bool {
	ext := util.GetFileExt(f["Content-Disposition"][0])

	if !util.Contains(parsedConfig.AllowedMimeTypes, f["Content-Type"][0]) || !util.Contains(parsedConfig.AllowedExtensions, ext) {
		return false
	}

	return true
}

// generateName generates a name with
// a specified length, and checks if
// the name already exists, using the
// util functions for this.
func generateName(n int) string {
	name := util.GenerateName(n)

	for util.CheckExists(name, parsedConfig.ImageDirectory) {
		name = util.GenerateName(n)
	}

	return name
}
<|endoftext|>


<commit_before>package testlib

import (
	"fmt"
	"image/png"

	"github.com/remogatto/imagetest"
	"github.com/remogatto/mandala"
)

func (t *TestSuite) TestDraw() {
	request := mandala.LoadResourceRequest{
		Filename: "drawable/expected.png",
		Response: make(chan mandala.LoadResourceResponse),
	}

	mandala.ResourceManager() <- request
	response := <-request.Response
	buffer := response.Buffer

	t.True(response.Error == nil, "An error occured during resource opening")

	if buffer != nil {
		exp, err := png.Decode(buffer)
		t.True(err == nil, "An error occured during png decoding")

		distance := imagetest.CompareDistance(exp, <-t.testDraw, nil)
		t.True(distance < 0.1, fmt.Sprintf("Distance is %f", distance))
	}
}
<commit_msg>Fix test template<commit_after>package testlib

import (
	"bytes"
	"fmt"
	"image/png"

	"github.com/remogatto/imagetest"
	"github.com/remogatto/mandala"
)

func (t *TestSuite) TestDraw() {
	request := mandala.LoadResourceRequest{
		Filename: "drawable/expected.png",
		Response: make(chan mandala.LoadResourceResponse),
	}

	mandala.ResourceManager() <- request
	response := <-request.Response
	buffer := response.Buffer

	t.True(response.Error == nil, "An error occured during resource opening")

	if buffer != nil {
		exp, err := png.Decode(bytes.NewBuffer(buffer))
		t.True(err == nil, "An error occured during png decoding")

		distance := imagetest.CompareDistance(exp, <-t.testDraw, nil)
		t.True(distance < 0.1, fmt.Sprintf("Distance is %f", distance))
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	"github.com/codegangsta/cli"
	"github.com/isbadawi/octranspo/api"
)

func stopCommandHandler(stop string) {
	routes, err := api.GetNextTripsForStop(stop)
	if err != nil {
		fmt.Printf("error: %v\n", err.Error())
		return
	}

	for _, route := range routes {
		fmt.Printf("%v %v (%v): ", route.Number, route.Heading, route.Direction)
		if len(route.Trips) == 0 {
			fmt.Printf("no more trips today.")
		}
		fmt.Println()
		for _, trip := range route.Trips {
			fmt.Printf("  %v (%v)\n", trip.StartTime, trip.Destination)
		}
	}
}

func main() {
	app := cli.NewApp()
	app.Name = "octranspo"
	app.Usage = "OC Transpo CLI"
	app.Version = "1.0.0"
	app.Commands = []cli.Command{
		{
			Name:  "stop",
			Usage: "get upcoming trips for a given stop number",
			Action: func(c *cli.Context) {
				if len(c.Args()) == 0 {
					fmt.Println("usage: octranspo stop <number>")
					return
				}

				stopCommandHandler(c.Args()[0])

			},
		},
	}
	app.Run(os.Args)
}
<commit_msg>Remove extraneous whitespace.<commit_after>package main

import (
	"fmt"
	"os"

	"github.com/codegangsta/cli"
	"github.com/isbadawi/octranspo/api"
)

func stopCommandHandler(stop string) {
	routes, err := api.GetNextTripsForStop(stop)
	if err != nil {
		fmt.Printf("error: %v\n", err.Error())
		return
	}

	for _, route := range routes {
		fmt.Printf("%v %v (%v): ", route.Number, route.Heading, route.Direction)
		if len(route.Trips) == 0 {
			fmt.Printf("no more trips today.")
		}
		fmt.Println()
		for _, trip := range route.Trips {
			fmt.Printf("  %v (%v)\n", trip.StartTime, trip.Destination)
		}
	}
}

func main() {
	app := cli.NewApp()
	app.Name = "octranspo"
	app.Usage = "OC Transpo CLI"
	app.Version = "1.0.0"
	app.Commands = []cli.Command{
		{
			Name:  "stop",
			Usage: "get upcoming trips for a given stop number",
			Action: func(c *cli.Context) {
				if len(c.Args()) == 0 {
					fmt.Println("usage: octranspo stop <number>")
					return
				}
				stopCommandHandler(c.Args()[0])
			},
		},
	}
	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package main

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

	"github.com/ogier/pflag"
)

func main() {
	path := ""
	glob := ""
	pflag.StringVarP(&path, "tsconfig", "t", "tsconfig.json", "your tsconfig.json path")
	pflag.StringVarP(&glob, "glob", "g", "src/**/*.ts", "glob pattern")
	pflag.Parse()

	if err := Update(path, glob); err != nil {
		panic(err)
	}
}

func Update(tsconfigPath string, glob string) error {
	f, err := os.Open(tsconfigPath)
	if err != nil {
		return err
	}
	defer f.Close()

	v := make(map[string]interface{})
	if err := json.NewDecoder(f).Decode(&v); err != nil {
		return err
	}
	f.Close()

	ma, err := filepath.Glob(glob)
	if err != nil {
		return err
	}
	v["files"] = ma

	b, err := json.MarshalIndent(v, "", "  ")
	if err != nil {
		return err
	}

	ioutil.WriteFile(tsconfigPath, append(b, '\n'), 0644)

	return nil
}
<commit_msg>remove glob<commit_after>package main

import (
	"encoding/json"
	"io/ioutil"
	"os"

	"github.com/ogier/pflag"
)

func main() {
	path := ""
	pflag.StringVarP(&path, "tsconfig", "t", "tsconfig.json", "your tsconfig.json path")
	pflag.Parse()

	if err := Update(path, pflag.Args()); err != nil {
		panic(err)
	}
}

func Update(tsconfigPath string, files []string) error {
	f, err := os.Open(tsconfigPath)
	if err != nil {
		return err
	}
	defer f.Close()

	v := make(map[string]interface{})
	if err := json.NewDecoder(f).Decode(&v); err != nil {
		return err
	}
	f.Close()

	v["files"] = files

	b, err := json.MarshalIndent(v, "", "  ")
	if err != nil {
		return err
	}

	ioutil.WriteFile(tsconfigPath, append(b, '\n'), 0644)

	return nil
}
<|endoftext|>