<commit_before>package structflag

import (
	"encoding/json"
	"encoding/xml"
	"errors"
	"flag"
	"io/ioutil"
	"os"
	"path/filepath"
	"reflect"
	"strconv"
	"strings"
	"time"
)

// Set is the minimal interface structflag needs to work.
// It is a subset of flag.FlagSet
type Set interface {
	BoolVar(p *bool, name string, value bool, usage string)
	DurationVar(p *time.Duration, name string, value time.Duration, usage string)
	Float64Var(p *float64, name string, value float64, usage string)
	Int64Var(p *int64, name string, value int64, usage string)
	IntVar(p *int, name string, value int, usage string)
	Parse(arguments []string) error
	PrintDefaults()
	StringVar(p *string, name string, value string, usage string)
	Uint64Var(p *uint64, name string, value uint64, usage string)
	UintVar(p *uint, name string, value uint, usage string)
	Var(value flag.Value, name string, usage string)
}

var (
	set Set

	// NewSet  defaults to flag.CommandLine of the standard flag package.
	NewSet = func() Set { return flag.NewFlagSet(os.Args[0], flag.ExitOnError) }
)

var (
	// NameTag is the struct tag used to overwrite
	// the struct field name as flag name.
	// Struct fields with NameTag of "-" will be ignored.
	NameTag = "flag"

	// UsageTag is the struct tag used to give
	// the usage description of a flag
	UsageTag = "usage"

	// DefaultTag is the struct tag used to
	// define the default value for the field
	// (if that default value is different from the zero value)
	DefaultTag = "default"

	// NameFunc is called as last operation for every flag name
	NameFunc = func(name string) string { return name }
)

var (
	flagValueType    = reflect.TypeOf((*flag.Value)(nil)).Elem()
	timeDurationType = reflect.TypeOf(time.Duration(0))
)

// StructVar defines the fields of a struct as flags.
// structPtr must be a pointer to a struct.
// Anonoymous embedded fields are flattened.
// Struct fields with NameTag of "-" will be ignored.
func StructVar(structPtr interface{}) {
	if set == nil {
		set = NewSet()
	}
	structVar(structPtr, set, false)
}

func structVar(structPtr interface{}, set Set, fieldValuesAsDefault bool) {
	var err error
	fields := flatStructFields(reflect.ValueOf(structPtr))
	for _, field := range fields {
		name := field.Tag.Get(NameTag)
		if name == "-" {
			continue
		}
		if name == "" {
			name = field.Name
		}
		name = NameFunc(name)

		usage := field.Tag.Get(UsageTag)

		if field.Type.Implements(flagValueType) {
			set.Var(field.Value.Addr().Interface().(flag.Value), name, usage)
			continue
		}

		defaultStr, hasDefault := field.Tag.Lookup(DefaultTag)

		if field.Type == timeDurationType {
			var value time.Duration
			if fieldValuesAsDefault {
				value = field.Value.Interface().(time.Duration)
			} else if hasDefault {
				value, err = time.ParseDuration(defaultStr)
				if err != nil {
					panic(err)
				}
			}
			set.DurationVar(field.Value.Addr().Interface().(*time.Duration), name, value, usage)
			continue
		}

		switch field.Type.Kind() {
		case reflect.Bool:
			var value bool
			if fieldValuesAsDefault {
				value = field.Value.Interface().(bool)
			} else if hasDefault {
				value, err = strconv.ParseBool(defaultStr)
				if err != nil {
					panic(err)
				}
			}
			set.BoolVar(field.Value.Addr().Interface().(*bool), name, value, usage)

		case reflect.Float64:
			var value float64
			if fieldValuesAsDefault {
				value = field.Value.Interface().(float64)
			} else if hasDefault {
				value, err = strconv.ParseFloat(defaultStr, 64)
				if err != nil {
					panic(err)
				}
			}
			set.Float64Var(field.Value.Addr().Interface().(*float64), name, value, usage)

		case reflect.Int64:
			var value int64
			if fieldValuesAsDefault {
				value = field.Value.Interface().(int64)
			} else if hasDefault {
				value, err = strconv.ParseInt(defaultStr, 0, 64)
				if err != nil {
					panic(err)
				}
			}
			set.Int64Var(field.Value.Addr().Interface().(*int64), name, value, usage)

		case reflect.Int:
			var value int64
			if fieldValuesAsDefault {
				value = int64(field.Value.Interface().(int))
			} else if hasDefault {
				value, err = strconv.ParseInt(defaultStr, 0, 64)
				if err != nil {
					panic(err)
				}
			}
			set.IntVar(field.Value.Addr().Interface().(*int), name, int(value), usage)

		case reflect.String:
			var value string
			if fieldValuesAsDefault {
				value = field.Value.Interface().(string)
			} else if hasDefault {
				value = defaultStr
			}
			set.StringVar(field.Value.Addr().Interface().(*string), name, value, usage)

		case reflect.Uint64:
			var value uint64
			if fieldValuesAsDefault {
				value = field.Value.Interface().(uint64)
			} else if hasDefault {
				value, err = strconv.ParseUint(defaultStr, 0, 64)
				if err != nil {
					panic(err)
				}
			}
			set.Uint64Var(field.Value.Addr().Interface().(*uint64), name, value, usage)

		case reflect.Uint:
			var value uint64
			if fieldValuesAsDefault {
				value = uint64(field.Value.Interface().(uint))
			} else if hasDefault {
				value, err = strconv.ParseUint(defaultStr, 0, 64)
				if err != nil {
					panic(err)
				}
			}
			set.UintVar(field.Value.Addr().Interface().(*uint), name, uint(value), usage)
		}
	}
}

// Parse parses args, or if no args are given os.Args[1:]
func Parse(args ...string) error {
	if set == nil {
		set = NewSet()
	}
	return parse(args, set)
}

func parse(args []string, set Set) error {
	if len(args) == 0 {
		args = os.Args[1:]
	}
	return set.Parse(args)
}

// PrintDefaults prints to standard error the default values of all defined command-line flags in the set.
func PrintDefaults() {
	if set == nil {
		set = NewSet()
	}
	set.PrintDefaults()
}

// LoadFileAndParseCommandLine loads the configuration from filename
// into structPtr and then parses the command line.
// Every value that is present in command line overwrites the
// value loaded from the configuration file.
// Values not present in the command line won't effect the Values
// loaded from the configuration file.
// If there is an error loading the configuration file,
// then the command line still gets parsed.
// The error os.ErrNotExist can be ignored if the existence
// of the configuration file is optional.
func LoadFileAndParseCommandLine(filename string, structPtr interface{}) error {
	// Initialize global variable set with unchanged default values
	// so that a later PrintDefaults() prints the correct default values.
	StructVar(structPtr)

	// Load and unmarshal struct from file
	loadErr := LoadFile(filename, structPtr)

	// Use the existing struct values as defaults for tempSet
	// so that not existing args don't overwrite existing values
	// that have been loaded from the confriguration file
	tempSet := NewSet()
	structVar(structPtr, tempSet, true)
	err := tempSet.Parse(os.Args[1:])
	if err != nil {
		return err
	}
	return loadErr
}

// MustLoadFileAndParseCommandLine same as LoadFileAndParseCommandLine but panics on error
func MustLoadFileAndParseCommandLine(filename string, structPtr interface{}) {
	err := LoadFileAndParseCommandLine(filename, structPtr)
	if err != nil {
		panic(err)
	}
}

// LoadFileIfExistsAndMustParseCommandLine same as LoadFileAndParseCommandLine but panics on error
func LoadFileIfExistsAndMustParseCommandLine(filename string, structPtr interface{}) {
	err := LoadFileAndParseCommandLine(filename, structPtr)
	if err != nil && err != os.ErrNotExist {
		panic(err)
	}
}

type structFieldAndValue struct {
	reflect.StructField
	Value reflect.Value
}

// flatStructFields returns the structFieldAndValue of flattened struct fields,
// meaning that the fields of anonoymous embedded fields are flattened
// to the top level of the struct.
func flatStructFields(v reflect.Value) []structFieldAndValue {
	for v.Kind() == reflect.Ptr {
		v = v.Elem()
	}
	t := v.Type()
	numField := t.NumField()
	fields := make([]structFieldAndValue, 0, numField)
	for i := 0; i < numField; i++ {
		ft := t.Field(i)
		fv := v.Field(i)
		if ft.Anonymous {
			fields = append(fields, flatStructFields(fv)...)
		} else {
			fields = append(fields, structFieldAndValue{ft, fv})
		}
	}
	return fields
}

// LoadFile loads a struct from a JSON or XML file.
// The file type is determined by the file extension.
func LoadFile(filename string, structPtr interface{}) error {
	// Load and unmarshal struct from file
	ext := strings.ToLower(filepath.Ext(filename))
	switch ext {
	case ".json":
		return LoadJSON(filename, structPtr)
	case ".xml":
		return LoadXML(filename, structPtr)
	}
	return errors.New("File extension not supported: " + ext)
}

// LoadXML loads a struct from a XML file
func LoadXML(filename string, structPtr interface{}) error {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return err
	}
	return xml.Unmarshal(data, structPtr)
}

// SaveXML saves a struct as a XML file
func SaveXML(filename string, structPtr interface{}, indent ...string) error {
	data, err := xml.MarshalIndent(structPtr, "", strings.Join(indent, ""))
	if err != nil {
		return err
	}
	data = append([]byte(xml.Header), data...)
	return ioutil.WriteFile(filename, data, 0660)
}

// LoadJSON loads a struct from a JSON file
func LoadJSON(filename string, structPtr interface{}) error {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return err
	}
	return json.Unmarshal(data, structPtr)
}

// SaveJSON saves a struct as a JSON file
func SaveJSON(filename string, structPtr interface{}, indent ...string) error {
	data, err := json.MarshalIndent(structPtr, "", strings.Join(indent, ""))
	if err != nil {
		return err
	}
	return ioutil.WriteFile(filename, data, 0660)
}
<commit_msg>return non flag cli flags from parse functions<commit_after>package structflag

import (
	"encoding/json"
	"encoding/xml"
	"errors"
	"flag"
	"io/ioutil"
	"os"
	"path/filepath"
	"reflect"
	"strconv"
	"strings"
	"time"
)

// Set is the minimal interface structflag needs to work.
// It is a subset of flag.FlagSet
type Set interface {
	Args() []string
	BoolVar(p *bool, name string, value bool, usage string)
	DurationVar(p *time.Duration, name string, value time.Duration, usage string)
	Float64Var(p *float64, name string, value float64, usage string)
	Int64Var(p *int64, name string, value int64, usage string)
	IntVar(p *int, name string, value int, usage string)
	Parse(arguments []string) error
	PrintDefaults()
	StringVar(p *string, name string, value string, usage string)
	Uint64Var(p *uint64, name string, value uint64, usage string)
	UintVar(p *uint, name string, value uint, usage string)
	Var(value flag.Value, name string, usage string)
}

var (
	set Set

	// NewSet  defaults to flag.CommandLine of the standard flag package.
	NewSet = func() Set { return flag.NewFlagSet(os.Args[0], flag.ExitOnError) }
)

var (
	// NameTag is the struct tag used to overwrite
	// the struct field name as flag name.
	// Struct fields with NameTag of "-" will be ignored.
	NameTag = "flag"

	// UsageTag is the struct tag used to give
	// the usage description of a flag
	UsageTag = "usage"

	// DefaultTag is the struct tag used to
	// define the default value for the field
	// (if that default value is different from the zero value)
	DefaultTag = "default"

	// NameFunc is called as last operation for every flag name
	NameFunc = func(name string) string { return name }
)

var (
	flagValueType    = reflect.TypeOf((*flag.Value)(nil)).Elem()
	timeDurationType = reflect.TypeOf(time.Duration(0))
)

// StructVar defines the fields of a struct as flags.
// structPtr must be a pointer to a struct.
// Anonoymous embedded fields are flattened.
// Struct fields with NameTag of "-" will be ignored.
func StructVar(structPtr interface{}) {
	if set == nil {
		set = NewSet()
	}
	structVar(structPtr, set, false)
}

func structVar(structPtr interface{}, set Set, fieldValuesAsDefault bool) {
	var err error
	fields := flatStructFields(reflect.ValueOf(structPtr))
	for _, field := range fields {
		name := field.Tag.Get(NameTag)
		if name == "-" {
			continue
		}
		if name == "" {
			name = field.Name
		}
		name = NameFunc(name)

		usage := field.Tag.Get(UsageTag)

		if field.Type.Implements(flagValueType) {
			set.Var(field.Value.Addr().Interface().(flag.Value), name, usage)
			continue
		}

		defaultStr, hasDefault := field.Tag.Lookup(DefaultTag)

		if field.Type == timeDurationType {
			var value time.Duration
			if fieldValuesAsDefault {
				value = field.Value.Interface().(time.Duration)
			} else if hasDefault {
				value, err = time.ParseDuration(defaultStr)
				if err != nil {
					panic(err)
				}
			}
			set.DurationVar(field.Value.Addr().Interface().(*time.Duration), name, value, usage)
			continue
		}

		switch field.Type.Kind() {
		case reflect.Bool:
			var value bool
			if fieldValuesAsDefault {
				value = field.Value.Interface().(bool)
			} else if hasDefault {
				value, err = strconv.ParseBool(defaultStr)
				if err != nil {
					panic(err)
				}
			}
			set.BoolVar(field.Value.Addr().Interface().(*bool), name, value, usage)

		case reflect.Float64:
			var value float64
			if fieldValuesAsDefault {
				value = field.Value.Interface().(float64)
			} else if hasDefault {
				value, err = strconv.ParseFloat(defaultStr, 64)
				if err != nil {
					panic(err)
				}
			}
			set.Float64Var(field.Value.Addr().Interface().(*float64), name, value, usage)

		case reflect.Int64:
			var value int64
			if fieldValuesAsDefault {
				value = field.Value.Interface().(int64)
			} else if hasDefault {
				value, err = strconv.ParseInt(defaultStr, 0, 64)
				if err != nil {
					panic(err)
				}
			}
			set.Int64Var(field.Value.Addr().Interface().(*int64), name, value, usage)

		case reflect.Int:
			var value int64
			if fieldValuesAsDefault {
				value = int64(field.Value.Interface().(int))
			} else if hasDefault {
				value, err = strconv.ParseInt(defaultStr, 0, 64)
				if err != nil {
					panic(err)
				}
			}
			set.IntVar(field.Value.Addr().Interface().(*int), name, int(value), usage)

		case reflect.String:
			var value string
			if fieldValuesAsDefault {
				value = field.Value.Interface().(string)
			} else if hasDefault {
				value = defaultStr
			}
			set.StringVar(field.Value.Addr().Interface().(*string), name, value, usage)

		case reflect.Uint64:
			var value uint64
			if fieldValuesAsDefault {
				value = field.Value.Interface().(uint64)
			} else if hasDefault {
				value, err = strconv.ParseUint(defaultStr, 0, 64)
				if err != nil {
					panic(err)
				}
			}
			set.Uint64Var(field.Value.Addr().Interface().(*uint64), name, value, usage)

		case reflect.Uint:
			var value uint64
			if fieldValuesAsDefault {
				value = uint64(field.Value.Interface().(uint))
			} else if hasDefault {
				value, err = strconv.ParseUint(defaultStr, 0, 64)
				if err != nil {
					panic(err)
				}
			}
			set.UintVar(field.Value.Addr().Interface().(*uint), name, uint(value), usage)
		}
	}
}

// Parse parses args, or if no args are given os.Args[1:]
func Parse(args ...string) ([]string, error) {
	if set == nil {
		set = NewSet()
	}
	return parse(args, set)
}

func parse(args []string, set Set) ([]string, error) {
	if len(args) == 0 {
		args = os.Args[1:]
	}
	err := set.Parse(args)
	if err != nil {
		return nil, err
	}
	return set.Args(), nil
}

// PrintDefaults prints to standard error the default values of all defined command-line flags in the set.
func PrintDefaults() {
	if set == nil {
		set = NewSet()
	}
	set.PrintDefaults()
}

// LoadFileAndParseCommandLine loads the configuration from filename
// into structPtr and then parses the command line.
// Every value that is present in command line overwrites the
// value loaded from the configuration file.
// Values not present in the command line won't effect the Values
// loaded from the configuration file.
// If there is an error loading the configuration file,
// then the command line still gets parsed.
// The error os.ErrNotExist can be ignored if the existence
// of the configuration file is optional.
func LoadFileAndParseCommandLine(filename string, structPtr interface{}) ([]string, error) {
	// Initialize global variable set with unchanged default values
	// so that a later PrintDefaults() prints the correct default values.
	StructVar(structPtr)

	// Load and unmarshal struct from file
	loadErr := LoadFile(filename, structPtr)

	// Use the existing struct values as defaults for tempSet
	// so that not existing args don't overwrite existing values
	// that have been loaded from the confriguration file
	tempSet := NewSet()
	structVar(structPtr, tempSet, true)
	err := tempSet.Parse(os.Args[1:])
	if err != nil {
		return nil, err
	}
	return tempSet.Args(), loadErr
}

// MustLoadFileAndParseCommandLine same as LoadFileAndParseCommandLine but panics on error
func MustLoadFileAndParseCommandLine(filename string, structPtr interface{}) []string {
	args, err := LoadFileAndParseCommandLine(filename, structPtr)
	if err != nil {
		panic(err)
	}
	return args
}

// LoadFileIfExistsAndMustParseCommandLine same as LoadFileAndParseCommandLine but panics on error
func LoadFileIfExistsAndMustParseCommandLine(filename string, structPtr interface{}) []string {
	args, err := LoadFileAndParseCommandLine(filename, structPtr)
	if err != nil && err != os.ErrNotExist {
		panic(err)
	}
	return args
}

type structFieldAndValue struct {
	reflect.StructField
	Value reflect.Value
}

// flatStructFields returns the structFieldAndValue of flattened struct fields,
// meaning that the fields of anonoymous embedded fields are flattened
// to the top level of the struct.
func flatStructFields(v reflect.Value) []structFieldAndValue {
	for v.Kind() == reflect.Ptr {
		v = v.Elem()
	}
	t := v.Type()
	numField := t.NumField()
	fields := make([]structFieldAndValue, 0, numField)
	for i := 0; i < numField; i++ {
		ft := t.Field(i)
		fv := v.Field(i)
		if ft.Anonymous {
			fields = append(fields, flatStructFields(fv)...)
		} else {
			fields = append(fields, structFieldAndValue{ft, fv})
		}
	}
	return fields
}

// LoadFile loads a struct from a JSON or XML file.
// The file type is determined by the file extension.
func LoadFile(filename string, structPtr interface{}) error {
	// Load and unmarshal struct from file
	ext := strings.ToLower(filepath.Ext(filename))
	switch ext {
	case ".json":
		return LoadJSON(filename, structPtr)
	case ".xml":
		return LoadXML(filename, structPtr)
	}
	return errors.New("File extension not supported: " + ext)
}

// LoadXML loads a struct from a XML file
func LoadXML(filename string, structPtr interface{}) error {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return err
	}
	return xml.Unmarshal(data, structPtr)
}

// SaveXML saves a struct as a XML file
func SaveXML(filename string, structPtr interface{}, indent ...string) error {
	data, err := xml.MarshalIndent(structPtr, "", strings.Join(indent, ""))
	if err != nil {
		return err
	}
	data = append([]byte(xml.Header), data...)
	return ioutil.WriteFile(filename, data, 0660)
}

// LoadJSON loads a struct from a JSON file
func LoadJSON(filename string, structPtr interface{}) error {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return err
	}
	return json.Unmarshal(data, structPtr)
}

// SaveJSON saves a struct as a JSON file
func SaveJSON(filename string, structPtr interface{}, indent ...string) error {
	data, err := json.MarshalIndent(structPtr, "", strings.Join(indent, ""))
	if err != nil {
		return err
	}
	return ioutil.WriteFile(filename, data, 0660)
}
<|endoftext|>


<commit_before>package avatar

import (
	"errors"
	"image"
	"image/color"
	"strings"
	"unicode"

	"stathat.com/c/consistent"
)

var (
	avatarBgColors = map[string]*color.RGBA{
		"45BDF3": &color.RGBA{69, 189, 243, 255},
		"E08F70": &color.RGBA{224, 143, 112, 255},
		"4DB6AC": &color.RGBA{77, 182, 172, 255},
		"9575CD": &color.RGBA{149, 117, 205, 255},
		"B0855E": &color.RGBA{176, 133, 94, 255},
		"F06292": &color.RGBA{240, 98, 146, 255},
		"A3D36C": &color.RGBA{163, 211, 108, 255},
		"7986CB": &color.RGBA{121, 134, 203, 255},
		"F1B91D": &color.RGBA{241, 185, 29, 255},
	}

	defaultColorKey = "45BDF3"

	ErrUnsupportChar = errors.New("unsupport character")

	c = consistent.New()
)

type InitialsAvatar struct {
	drawer *drawer
}

func New(fontFile string) *InitialsAvatar {
	avatar := new(InitialsAvatar)
	avatar.drawer = newDrawer(fontFile)
	return avatar
}
func (a *InitialsAvatar) Draw(name string, size int) (image.Image, error) {
	if size <= 0 {
		size = 48 // default size
	}
	name = strings.TrimSpace(name)
	firstRune := []rune(name)[0]
	if !isHan(firstRune) && !unicode.IsLetter(firstRune) {
		return nil, ErrUnsupportChar
	}
	initials := getInitials(name)
	bgcolor := getColorByName(name)

	return a.drawer.Draw(initials, size, bgcolor), nil
}

// is Chinese?
func isHan(r rune) bool {
	if unicode.Is(unicode.Scripts["Han"], r) {
		return true
	}
	return false
}

// random color
func getColorByName(name string) *color.RGBA {
	key, err := c.Get(name)
	if err != nil {
		key = defaultColorKey
	}
	return avatarBgColors[key]
}

//TODO: enhance
func getInitials(name string) string {
	if len(name) <= 0 {
		return ""
	}
	return strings.ToUpper(string([]rune(name)[0]))
}

func init() {
	for key := range avatarBgColors {
		c.Add(key)
	}
}
<commit_msg>fix typo<commit_after>package avatar

import (
	"errors"
	"image"
	"image/color"
	"strings"
	"unicode"

	"stathat.com/c/consistent"
)

var (
	avatarBgColors = map[string]*color.RGBA{
		"45BDF3": &color.RGBA{69, 189, 243, 255},
		"E08F70": &color.RGBA{224, 143, 112, 255},
		"4DB6AC": &color.RGBA{77, 182, 172, 255},
		"9575CD": &color.RGBA{149, 117, 205, 255},
		"B0855E": &color.RGBA{176, 133, 94, 255},
		"F06292": &color.RGBA{240, 98, 146, 255},
		"A3D36C": &color.RGBA{163, 211, 108, 255},
		"7986CB": &color.RGBA{121, 134, 203, 255},
		"F1B91D": &color.RGBA{241, 185, 29, 255},
	}

	defaultColorKey = "45BDF3"

	ErrUnsupportChar = errors.New("unsupported character")

	c = consistent.New()
)

type InitialsAvatar struct {
	drawer *drawer
}

func New(fontFile string) *InitialsAvatar {
	avatar := new(InitialsAvatar)
	avatar.drawer = newDrawer(fontFile)
	return avatar
}
func (a *InitialsAvatar) Draw(name string, size int) (image.Image, error) {
	if size <= 0 {
		size = 48 // default size
	}
	name = strings.TrimSpace(name)
	firstRune := []rune(name)[0]
	if !isHan(firstRune) && !unicode.IsLetter(firstRune) {
		return nil, ErrUnsupportChar
	}
	initials := getInitials(name)
	bgcolor := getColorByName(name)

	return a.drawer.Draw(initials, size, bgcolor), nil
}

// is Chinese?
func isHan(r rune) bool {
	if unicode.Is(unicode.Scripts["Han"], r) {
		return true
	}
	return false
}

// random color
func getColorByName(name string) *color.RGBA {
	key, err := c.Get(name)
	if err != nil {
		key = defaultColorKey
	}
	return avatarBgColors[key]
}

//TODO: enhance
func getInitials(name string) string {
	if len(name) <= 0 {
		return ""
	}
	return strings.ToUpper(string([]rune(name)[0]))
}

func init() {
	for key := range avatarBgColors {
		c.Add(key)
	}
}
<|endoftext|>


<commit_before>// +build windows

package tty

import (
	"os"
	"syscall"
	"unsafe"

	"github.com/mattn/go-isatty"
)

const (
	rightAltPressed  = 1
	leftAltPressed   = 2
	rightCtrlPressed = 4
	leftCtrlPressed  = 8
	ctrlPressed      = rightCtrlPressed | leftCtrlPressed
	altPressed       = rightAltPressed | leftAltPressed
)

const (
	enableProcessedInput = 0x1
	enableLineInput      = 0x2
	enableEchoInput      = 0x4
	enableWindowInput    = 0x8
	enableMouseInput     = 0x10
	enableInsertMode     = 0x20
	enableQuickEditMode  = 0x40
	enableExtendedFlag   = 0x80

	enableProcessedOutput = 1
	enableWrapAtEolOutput = 2

	keyEvent              = 0x1
	mouseEvent            = 0x2
	windowBufferSizeEvent = 0x4
)

var kernel32 = syscall.NewLazyDLL("kernel32.dll")

var (
	procAllocConsole                = kernel32.NewProc("AllocConsole")
	procSetStdHandle                = kernel32.NewProc("SetStdHandle")
	procGetStdHandle                = kernel32.NewProc("GetStdHandle")
	procSetConsoleScreenBufferSize  = kernel32.NewProc("SetConsoleScreenBufferSize")
	procCreateConsoleScreenBuffer   = kernel32.NewProc("CreateConsoleScreenBuffer")
	procGetConsoleScreenBufferInfo  = kernel32.NewProc("GetConsoleScreenBufferInfo")
	procWriteConsoleOutputCharacter = kernel32.NewProc("WriteConsoleOutputCharacterW")
	procWriteConsoleOutputAttribute = kernel32.NewProc("WriteConsoleOutputAttribute")
	procGetConsoleCursorInfo        = kernel32.NewProc("GetConsoleCursorInfo")
	procSetConsoleCursorInfo        = kernel32.NewProc("SetConsoleCursorInfo")
	procSetConsoleCursorPosition    = kernel32.NewProc("SetConsoleCursorPosition")
	procReadConsoleInput            = kernel32.NewProc("ReadConsoleInputW")
	procGetConsoleMode              = kernel32.NewProc("GetConsoleMode")
	procSetConsoleMode              = kernel32.NewProc("SetConsoleMode")
	procFillConsoleOutputCharacter  = kernel32.NewProc("FillConsoleOutputCharacterW")
	procFillConsoleOutputAttribute  = kernel32.NewProc("FillConsoleOutputAttribute")
	procScrollConsoleScreenBuffer   = kernel32.NewProc("ScrollConsoleScreenBufferW")
)

type wchar uint16
type short int16
type dword uint32
type word uint16

type coord struct {
	x short
	y short
}

type smallRect struct {
	left   short
	top    short
	right  short
	bottom short
}

type consoleScreenBufferInfo struct {
	size              coord
	cursorPosition    coord
	attributes        word
	window            smallRect
	maximumWindowSize coord
}

type consoleCursorInfo struct {
	size    dword
	visible int32
}

type inputRecord struct {
	eventType word
	_         [2]byte
	event     [16]byte
}

type keyEventRecord struct {
	keyDown         int32
	repeatCount     word
	virtualKeyCode  word
	virtualScanCode word
	unicodeChar     wchar
	controlKeyState dword
}

type windowBufferSizeRecord struct {
	size coord
}

type mouseEventRecord struct {
	mousePos        coord
	buttonState     dword
	controlKeyState dword
	eventFlags      dword
}

type charInfo struct {
	unicodeChar wchar
	attributes  word
}

type TTY struct {
	in  *os.File
	out *os.File
	st  uint32
	rs  []rune
}

func readConsoleInput(fd uintptr, record *inputRecord) (err error) {
	var w uint32
	r1, _, err := procReadConsoleInput.Call(fd, uintptr(unsafe.Pointer(record)), 1, uintptr(unsafe.Pointer(&w)))
	if r1 == 0 {
		return err
	}
	return nil
}

func open() (*TTY, error) {
	tty := new(TTY)
	if false && isatty.IsTerminal(os.Stdin.Fd()) {
		tty.in = os.Stdin
	} else {
		conin, err := os.Open("CONIN$")
		if err != nil {
			return nil, err
		}
		tty.in = conin
	}

	if isatty.IsTerminal(os.Stdout.Fd()) {
		tty.out = os.Stdout
	} else {
		procAllocConsole.Call()
		out, err := syscall.Open("CONOUT$", syscall.O_RDWR, 0)
		if err != nil {
			return nil, err
		}

		tty.out = os.NewFile(uintptr(out), "/dev/tty")
	}

	h := tty.in.Fd()
	var st uint32
	r1, _, err := procGetConsoleMode.Call(h, uintptr(unsafe.Pointer(&st)))
	if r1 == 0 {
		return nil, err
	}
	tty.st = st

	st &^= enableEchoInput
	st &^= enableInsertMode
	st &^= enableLineInput
	st &^= enableMouseInput
	st &^= enableWindowInput
	st &^= enableExtendedFlag
	st &^= enableQuickEditMode
	st |= enableProcessedInput

	// ignore error
	procSetConsoleMode.Call(h, uintptr(st))

	return tty, nil
}

func (tty *TTY) buffered() bool {
	return len(tty.rs) > 0
}

func (tty *TTY) readRune() (rune, error) {
	if len(tty.rs) > 0 {
		r := tty.rs[0]
		tty.rs = tty.rs[1:]
		return r, nil
	}
	var ir inputRecord
	err := readConsoleInput(tty.in.Fd(), &ir)
	if err != nil {
		return 0, err
	}

	if ir.eventType == keyEvent {
		kr := (*keyEventRecord)(unsafe.Pointer(&ir.event))
		if kr.keyDown != 0 {
			if kr.controlKeyState&altPressed != 0 && kr.unicodeChar > 0 {
				tty.rs = []rune{rune(kr.unicodeChar)}
				return rune(0x1b), nil
			}
			if kr.unicodeChar > 0 {
				return rune(kr.unicodeChar), nil
			}
			vk := kr.virtualKeyCode
			switch vk {
			case 0x21: // page-up
				tty.rs = []rune{0x5b, 0x35, 0x7e}
				return rune(0x1b), nil
			case 0x22: // page-down
				tty.rs = []rune{0x5b, 0x36, 0x7e}
				return rune(0x1b), nil
			case 0x23: // end
				tty.rs = []rune{0x5b, 0x46}
				return rune(0x1b), nil
			case 0x24: // home
				tty.rs = []rune{0x5b, 0x48}
				return rune(0x1b), nil
			case 0x25: // left
				tty.rs = []rune{0x5b, 0x44}
				return rune(0x1b), nil
			case 0x26: // up
				tty.rs = []rune{0x5b, 0x41}
				return rune(0x1b), nil
			case 0x27: // right
				tty.rs = []rune{0x5b, 0x43}
				return rune(0x1b), nil
			case 0x28: // down
				tty.rs = []rune{0x5b, 0x42}
				return rune(0x1b), nil
			case 0x2e: // delete
				tty.rs = []rune{0x5b, 0x33, 0x7e}
				return rune(0x1b), nil
			case 0x70, 0x71, 0x72, 0x73: // F1,F2,F3,F4
				tty.rs = []rune{0x5b, 0x4f, rune(vk) - 0x20}
				return rune(0x1b), nil
			case 0x074, 0x75, 0x76, 0x77: // F5,F6,F7,F8
				tty.rs = []rune{0x5b, 0x31, rune(vk) - 0x3f, 0x7e}
				return rune(0x1b), nil
			case 0x78, 0x79: // F9,F10
				tty.rs = []rune{0x5b, 0x32, rune(vk) - 0x48, 0x7e}
				return rune(0x1b), nil
			case 0x7a, 0x7b: // F11,F12
				tty.rs = []rune{0x5b, 0x32, rune(vk) - 0x47, 0x7e}
				return rune(0x1b), nil
			}
			return 0, nil
		}
	}
	return 0, nil
}

func (tty *TTY) close() error {
	procSetConsoleMode.Call(tty.in.Fd(), uintptr(tty.st))
	return nil
}

func (tty *TTY) size() (int, int, error) {
	var csbi consoleScreenBufferInfo
	r1, _, err := procGetConsoleScreenBufferInfo.Call(tty.out.Fd(), uintptr(unsafe.Pointer(&csbi)))
	if r1 == 0 {
		return 0, 0, err
	}
	return int(csbi.window.right - csbi.window.left), int(csbi.window.bottom - csbi.window.top), nil
}

func (tty *TTY) input() *os.File {
	return tty.in
}

func (tty *TTY) output() *os.File {
	return tty.out
}

func (tty *TTY) raw() (func() error, error) {
	var st uint32
	r1, _, err := procGetConsoleMode.Call(tty.in.Fd(), uintptr(unsafe.Pointer(&st)))
	if r1 == 0 {
		return nil, err
	}
	mode := st &^ (enableEchoInput | enableProcessedInput | enableLineInput | enableProcessedOutput)
	r1, _, err = procSetConsoleMode.Call(tty.in.Fd(), uintptr(mode))
	if r1 == 0 {
		return nil, err
	}
	return func() error {
		r1, _, err := procSetConsoleMode.Call(tty.in.Fd(), uintptr(st))
		if r1 == 0 {
			return err
		}
		return nil
	}, nil
}
<commit_msg>handle shift-tab<commit_after>// +build windows

package tty

import (
	"os"
	"syscall"
	"unsafe"

	"github.com/mattn/go-isatty"
)

const (
	rightAltPressed  = 1
	leftAltPressed   = 2
	rightCtrlPressed = 4
	leftCtrlPressed  = 8
	shiftPressed     = 0x0010
	ctrlPressed      = rightCtrlPressed | leftCtrlPressed
	altPressed       = rightAltPressed | leftAltPressed
)

const (
	enableProcessedInput = 0x1
	enableLineInput      = 0x2
	enableEchoInput      = 0x4
	enableWindowInput    = 0x8
	enableMouseInput     = 0x10
	enableInsertMode     = 0x20
	enableQuickEditMode  = 0x40
	enableExtendedFlag   = 0x80

	enableProcessedOutput = 1
	enableWrapAtEolOutput = 2

	keyEvent              = 0x1
	mouseEvent            = 0x2
	windowBufferSizeEvent = 0x4
)

var kernel32 = syscall.NewLazyDLL("kernel32.dll")

var (
	procAllocConsole                = kernel32.NewProc("AllocConsole")
	procSetStdHandle                = kernel32.NewProc("SetStdHandle")
	procGetStdHandle                = kernel32.NewProc("GetStdHandle")
	procSetConsoleScreenBufferSize  = kernel32.NewProc("SetConsoleScreenBufferSize")
	procCreateConsoleScreenBuffer   = kernel32.NewProc("CreateConsoleScreenBuffer")
	procGetConsoleScreenBufferInfo  = kernel32.NewProc("GetConsoleScreenBufferInfo")
	procWriteConsoleOutputCharacter = kernel32.NewProc("WriteConsoleOutputCharacterW")
	procWriteConsoleOutputAttribute = kernel32.NewProc("WriteConsoleOutputAttribute")
	procGetConsoleCursorInfo        = kernel32.NewProc("GetConsoleCursorInfo")
	procSetConsoleCursorInfo        = kernel32.NewProc("SetConsoleCursorInfo")
	procSetConsoleCursorPosition    = kernel32.NewProc("SetConsoleCursorPosition")
	procReadConsoleInput            = kernel32.NewProc("ReadConsoleInputW")
	procGetConsoleMode              = kernel32.NewProc("GetConsoleMode")
	procSetConsoleMode              = kernel32.NewProc("SetConsoleMode")
	procFillConsoleOutputCharacter  = kernel32.NewProc("FillConsoleOutputCharacterW")
	procFillConsoleOutputAttribute  = kernel32.NewProc("FillConsoleOutputAttribute")
	procScrollConsoleScreenBuffer   = kernel32.NewProc("ScrollConsoleScreenBufferW")
)

type wchar uint16
type short int16
type dword uint32
type word uint16

type coord struct {
	x short
	y short
}

type smallRect struct {
	left   short
	top    short
	right  short
	bottom short
}

type consoleScreenBufferInfo struct {
	size              coord
	cursorPosition    coord
	attributes        word
	window            smallRect
	maximumWindowSize coord
}

type consoleCursorInfo struct {
	size    dword
	visible int32
}

type inputRecord struct {
	eventType word
	_         [2]byte
	event     [16]byte
}

type keyEventRecord struct {
	keyDown         int32
	repeatCount     word
	virtualKeyCode  word
	virtualScanCode word
	unicodeChar     wchar
	controlKeyState dword
}

type windowBufferSizeRecord struct {
	size coord
}

type mouseEventRecord struct {
	mousePos        coord
	buttonState     dword
	controlKeyState dword
	eventFlags      dword
}

type charInfo struct {
	unicodeChar wchar
	attributes  word
}

type TTY struct {
	in  *os.File
	out *os.File
	st  uint32
	rs  []rune
}

func readConsoleInput(fd uintptr, record *inputRecord) (err error) {
	var w uint32
	r1, _, err := procReadConsoleInput.Call(fd, uintptr(unsafe.Pointer(record)), 1, uintptr(unsafe.Pointer(&w)))
	if r1 == 0 {
		return err
	}
	return nil
}

func open() (*TTY, error) {
	tty := new(TTY)
	if false && isatty.IsTerminal(os.Stdin.Fd()) {
		tty.in = os.Stdin
	} else {
		conin, err := os.Open("CONIN$")
		if err != nil {
			return nil, err
		}
		tty.in = conin
	}

	if isatty.IsTerminal(os.Stdout.Fd()) {
		tty.out = os.Stdout
	} else {
		procAllocConsole.Call()
		out, err := syscall.Open("CONOUT$", syscall.O_RDWR, 0)
		if err != nil {
			return nil, err
		}

		tty.out = os.NewFile(uintptr(out), "/dev/tty")
	}

	h := tty.in.Fd()
	var st uint32
	r1, _, err := procGetConsoleMode.Call(h, uintptr(unsafe.Pointer(&st)))
	if r1 == 0 {
		return nil, err
	}
	tty.st = st

	st &^= enableEchoInput
	st &^= enableInsertMode
	st &^= enableLineInput
	st &^= enableMouseInput
	st &^= enableWindowInput
	st &^= enableExtendedFlag
	st &^= enableQuickEditMode
	st |= enableProcessedInput

	// ignore error
	procSetConsoleMode.Call(h, uintptr(st))

	return tty, nil
}

func (tty *TTY) buffered() bool {
	return len(tty.rs) > 0
}

func (tty *TTY) readRune() (rune, error) {
	if len(tty.rs) > 0 {
		r := tty.rs[0]
		tty.rs = tty.rs[1:]
		return r, nil
	}
	var ir inputRecord
	err := readConsoleInput(tty.in.Fd(), &ir)
	if err != nil {
		return 0, err
	}

	if ir.eventType == keyEvent {
		kr := (*keyEventRecord)(unsafe.Pointer(&ir.event))
		if kr.keyDown != 0 {
			if kr.controlKeyState&altPressed != 0 && kr.unicodeChar > 0 {
				tty.rs = []rune{rune(kr.unicodeChar)}
				return rune(0x1b), nil
			}
			if kr.unicodeChar > 0 {
				if kr.controlKeyState&shiftPressed != 0 {
					switch kr.unicodeChar {
					case 0x09:
						tty.rs = []rune{0x5b, 0x5a}
						return rune(0x1b), nil
					}
				}
				return rune(kr.unicodeChar), nil
			}
			vk := kr.virtualKeyCode
			switch vk {
			case 0x21: // page-up
				tty.rs = []rune{0x5b, 0x35, 0x7e}
				return rune(0x1b), nil
			case 0x22: // page-down
				tty.rs = []rune{0x5b, 0x36, 0x7e}
				return rune(0x1b), nil
			case 0x23: // end
				tty.rs = []rune{0x5b, 0x46}
				return rune(0x1b), nil
			case 0x24: // home
				tty.rs = []rune{0x5b, 0x48}
				return rune(0x1b), nil
			case 0x25: // left
				tty.rs = []rune{0x5b, 0x44}
				return rune(0x1b), nil
			case 0x26: // up
				tty.rs = []rune{0x5b, 0x41}
				return rune(0x1b), nil
			case 0x27: // right
				tty.rs = []rune{0x5b, 0x43}
				return rune(0x1b), nil
			case 0x28: // down
				tty.rs = []rune{0x5b, 0x42}
				return rune(0x1b), nil
			case 0x2e: // delete
				tty.rs = []rune{0x5b, 0x33, 0x7e}
				return rune(0x1b), nil
			case 0x70, 0x71, 0x72, 0x73: // F1,F2,F3,F4
				tty.rs = []rune{0x5b, 0x4f, rune(vk) - 0x20}
				return rune(0x1b), nil
			case 0x074, 0x75, 0x76, 0x77: // F5,F6,F7,F8
				tty.rs = []rune{0x5b, 0x31, rune(vk) - 0x3f, 0x7e}
				return rune(0x1b), nil
			case 0x78, 0x79: // F9,F10
				tty.rs = []rune{0x5b, 0x32, rune(vk) - 0x48, 0x7e}
				return rune(0x1b), nil
			case 0x7a, 0x7b: // F11,F12
				tty.rs = []rune{0x5b, 0x32, rune(vk) - 0x47, 0x7e}
				return rune(0x1b), nil
			}
			return 0, nil
		}
	}
	return 0, nil
}

func (tty *TTY) close() error {
	procSetConsoleMode.Call(tty.in.Fd(), uintptr(tty.st))
	return nil
}

func (tty *TTY) size() (int, int, error) {
	var csbi consoleScreenBufferInfo
	r1, _, err := procGetConsoleScreenBufferInfo.Call(tty.out.Fd(), uintptr(unsafe.Pointer(&csbi)))
	if r1 == 0 {
		return 0, 0, err
	}
	return int(csbi.window.right - csbi.window.left), int(csbi.window.bottom - csbi.window.top), nil
}

func (tty *TTY) input() *os.File {
	return tty.in
}

func (tty *TTY) output() *os.File {
	return tty.out
}

func (tty *TTY) raw() (func() error, error) {
	var st uint32
	r1, _, err := procGetConsoleMode.Call(tty.in.Fd(), uintptr(unsafe.Pointer(&st)))
	if r1 == 0 {
		return nil, err
	}
	mode := st &^ (enableEchoInput | enableProcessedInput | enableLineInput | enableProcessedOutput)
	r1, _, err = procSetConsoleMode.Call(tty.in.Fd(), uintptr(mode))
	if r1 == 0 {
		return nil, err
	}
	return func() error {
		r1, _, err := procSetConsoleMode.Call(tty.in.Fd(), uintptr(st))
		if r1 == 0 {
			return err
		}
		return nil
	}, nil
}
<|endoftext|>


<commit_before>package wake

import "log"

func go_(fn func()) {
	go func() {
		defer func() {
			err := recover()
			if err != nil {
				log.Print("panic: %s", err)
			}
		}()
		fn()
	}()
}

func ignore_(err error) {
	if err != nil {
		log.Printf("ignored: %s", err)
	}
}
<commit_msg>runtime fixes<commit_after>package wake

import (
	"fmt"
	"log"
)

func go_(fn func()) {
	go func() {
		defer func() { ignore_(recover_()) }()
		fn()
	}()
}

func recover_() (err error) {
	var ok bool
	pnc := recover()
	if err, ok = pnc.(error); !ok {
		err = fmt.Errorf("panic: %s", pnc)
	}
	return
}

func ignore_(err error) {
	if err != nil {
		log.Printf("ignored: %s", err)
	}
}
<|endoftext|>


<commit_before>package torrent

import (
	"encoding/hex"
	"reflect"
	"testing"
)

var (
	exampleMagnetURI = `magnet:?xt=urn:btih:51340689c960f0778a4387aef9b4b52fd08390cd&dn=Shit+Movie+%281985%29+1337p+-+Eru&tr=http%3A%2F%2Fhttp.was.great%21&tr=udp%3A%2F%2Fanti.piracy.honeypot%3A6969`
	exampleMagnet    = Magnet{
		DisplayName: "Shit Movie (1985) 1337p - Eru",
		Trackers: []string{
			"http://http.was.great!",
			"udp://anti.piracy.honeypot:6969",
		},
	}
)

// Converting from our Magnet type to URL string.
func TestMagnetString(t *testing.T) {
	hex.Decode(exampleMagnet.InfoHash[:], []byte("51340689c960f0778a4387aef9b4b52fd08390cd"))
	s := exampleMagnet.String()
	if s != exampleMagnetURI {
		t.Fatalf("\nexpected:\n\t%q\nactual\n\t%q", exampleMagnetURI, s)
	}
}

func TestParseMagnetURI(t *testing.T) {
	var uri string
	var m Magnet
	var err error

	// parsing the legit Magnet URI with btih-formatted xt should not return errors
	uri = "magnet:?xt=urn:btih:ZOCMZQIPFFW7OLLMIC5HUB6BPCSDEOQU"
	_, err = ParseMagnetURI(uri)
	if err != nil {
		t.Errorf("Attempting parsing the proper Magnet btih URI:\"%v\" failed with err: %v", uri, err)
	}

	// Checking if the magnet instance struct is built correctly from parsing
	m, err = ParseMagnetURI(exampleMagnetURI)
	if err != nil || !reflect.DeepEqual(exampleMagnet, m) {
		t.Errorf("ParseMagnetURI(%e) returned %v, expected %v", uri, err)
	}

	// empty string URI case
	_, err = ParseMagnetURI("")
	if err == nil {
		t.Errorf("Parsing empty string as URI should have returned an error but didn't")
	}

	// only BTIH (BitTorrent info hash)-formatted magnet links are currently supported
	// must return error correctly when encountering other URN formats
	uri = "magnet:?xt=urn:sha1:YNCKHTQCWBTRNJIV4WNAE52SJUQCZO5C"
	_, err = ParseMagnetURI(uri)
	if err == nil {
		t.Errorf("Magnet URI with non-BTIH URNs (like \"%v\") are not supported and should return an error", uri)
	}

	// resilience to the broken hash
	uri = "magnet:?xt=urn:btih:this hash is really broken"
	_, err = ParseMagnetURI(uri)
	if err == nil {
		t.Errorf("Failed to detect broken Magnet URI: %v", uri)
	}

}
<commit_msg>Fix test error message<commit_after>package torrent

import (
	"encoding/hex"
	"reflect"
	"testing"
)

var (
	exampleMagnetURI = `magnet:?xt=urn:btih:51340689c960f0778a4387aef9b4b52fd08390cd&dn=Shit+Movie+%281985%29+1337p+-+Eru&tr=http%3A%2F%2Fhttp.was.great%21&tr=udp%3A%2F%2Fanti.piracy.honeypot%3A6969`
	exampleMagnet    = Magnet{
		DisplayName: "Shit Movie (1985) 1337p - Eru",
		Trackers: []string{
			"http://http.was.great!",
			"udp://anti.piracy.honeypot:6969",
		},
	}
)

// Converting from our Magnet type to URL string.
func TestMagnetString(t *testing.T) {
	hex.Decode(exampleMagnet.InfoHash[:], []byte("51340689c960f0778a4387aef9b4b52fd08390cd"))
	s := exampleMagnet.String()
	if s != exampleMagnetURI {
		t.Fatalf("\nexpected:\n\t%q\nactual\n\t%q", exampleMagnetURI, s)
	}
}

func TestParseMagnetURI(t *testing.T) {
	var uri string
	var m Magnet
	var err error

	// parsing the legit Magnet URI with btih-formatted xt should not return errors
	uri = "magnet:?xt=urn:btih:ZOCMZQIPFFW7OLLMIC5HUB6BPCSDEOQU"
	_, err = ParseMagnetURI(uri)
	if err != nil {
		t.Errorf("Attempting parsing the proper Magnet btih URI:\"%v\" failed with err: %v", uri, err)
	}

	// Checking if the magnet instance struct is built correctly from parsing
	m, err = ParseMagnetURI(exampleMagnetURI)
	if err != nil || !reflect.DeepEqual(exampleMagnet, m) {
		t.Errorf("ParseMagnetURI(%e) returned %v, expected %v", uri, m, exampleMagnet)
	}

	// empty string URI case
	_, err = ParseMagnetURI("")
	if err == nil {
		t.Errorf("Parsing empty string as URI should have returned an error but didn't")
	}

	// only BTIH (BitTorrent info hash)-formatted magnet links are currently supported
	// must return error correctly when encountering other URN formats
	uri = "magnet:?xt=urn:sha1:YNCKHTQCWBTRNJIV4WNAE52SJUQCZO5C"
	_, err = ParseMagnetURI(uri)
	if err == nil {
		t.Errorf("Magnet URI with non-BTIH URNs (like \"%v\") are not supported and should return an error", uri)
	}

	// resilience to the broken hash
	uri = "magnet:?xt=urn:btih:this hash is really broken"
	_, err = ParseMagnetURI(uri)
	if err == nil {
		t.Errorf("Failed to detect broken Magnet URI: %v", uri)
	}

}
<|endoftext|>


<commit_before>package alicloudkms

import (
	"context"
	"errors"
	"fmt"
	"os"
	"sync/atomic"

	"github.com/aliyun/alibaba-cloud-sdk-go/sdk"
	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/providers"
	"github.com/aliyun/alibaba-cloud-sdk-go/services/kms"
	"github.com/hashicorp/errwrap"
	log "github.com/hashicorp/go-hclog"
	"github.com/hashicorp/vault/physical"
	"github.com/hashicorp/vault/vault/seal"
)

const (
	EnvAliCloudKMSSealKeyID = "VAULT_ALICLOUDKMS_SEAL_KEY_ID"
)

type AliCloudKMSSeal struct {
	logger       log.Logger
	client       kmsClient
	domain       string
	keyID        string
	currentKeyID *atomic.Value
}

// Ensure that we are implementing AutoSealAccess
var _ seal.Access = (*AliCloudKMSSeal)(nil)

func NewSeal(logger log.Logger) *AliCloudKMSSeal {
	k := &AliCloudKMSSeal{
		logger:       logger,
		currentKeyID: new(atomic.Value),
	}
	k.currentKeyID.Store("")
	return k
}

// SetConfig sets the fields on the AliCloudKMSSeal object based on
// values from the config parameter.
//
// Order of precedence AliCloud values:
// * Environment variable
// * Value from Vault configuration file
// * Instance metadata role (access key and secret key)
func (k *AliCloudKMSSeal) SetConfig(config map[string]string) (map[string]string, error) {
	if config == nil {
		config = map[string]string{}
	}

	// Check and set KeyID
	switch {
	case os.Getenv(EnvAliCloudKMSSealKeyID) != "":
		k.keyID = os.Getenv(EnvAliCloudKMSSealKeyID)
	case config["kms_key_id"] != "":
		k.keyID = config["kms_key_id"]
	default:
		return nil, fmt.Errorf("'kms_key_id' not found for AliCloud KMS sealconfiguration")
	}

	region := ""
	if k.client == nil {

		// Check and set region.
		region = os.Getenv("ALICLOUD_REGION")
		if region == "" {
			ok := false
			if region, ok = config["region"]; !ok {
				region = "us-east-1"
			}
		}

		// A domain isn't required, but it can be used to override the endpoint
		// returned by the region. An example value for a domain would be:
		// "kms.us-east-1.aliyuncs.com".
		k.domain = os.Getenv("ALICLOUD_DOMAIN")
		if k.domain == "" {
			k.domain = config["domain"]
		}

		// Build the optional, configuration-based piece of the credential chain.
		credConfig := &providers.Configuration{}

		if accessKey, ok := config["access_key"]; ok {
			credConfig.AccessKeyID = accessKey
		}

		if accessSecret, ok := config["access_secret"]; ok {
			credConfig.AccessKeySecret = accessSecret
		}

		credentialChain := []providers.Provider{
			providers.NewEnvCredentialProvider(),
			providers.NewConfigurationCredentialProvider(credConfig),
			providers.NewInstanceMetadataProvider(),
		}
		credProvider := providers.NewChainProvider(credentialChain)

		creds, err := credProvider.Retrieve()
		if err != nil {
			return nil, err
		}
		clientConfig := sdk.NewConfig()
		clientConfig.Scheme = "https"
		client, err := kms.NewClientWithOptions(region, clientConfig, creds)
		if err != nil {
			return nil, err
		}
		k.client = client
	}

	// Test the client connection using provided key ID
	input := kms.CreateDescribeKeyRequest()
	input.KeyId = k.keyID
	input.Domain = k.domain

	keyInfo, err := k.client.DescribeKey(input)
	if err != nil {
		return nil, errwrap.Wrapf("error fetching AliCloud KMS sealkey information: {{err}}", err)
	}
	if keyInfo == nil || keyInfo.KeyMetadata.KeyId == "" {
		return nil, errors.New("no key information returned")
	}
	k.currentKeyID.Store(keyInfo.KeyMetadata.KeyId)

	// Map that holds non-sensitive configuration info
	sealInfo := make(map[string]string)
	sealInfo["region"] = region
	sealInfo["kms_key_id"] = k.keyID
	if k.domain != "" {
		sealInfo["domain"] = k.domain
	}

	return sealInfo, nil
}

// Init is called during core.Initialize. No-op at the moment.
func (k *AliCloudKMSSeal) Init(_ context.Context) error {
	return nil
}

// Finalize is called during shutdown. This is a no-op since
// AliCloudKMSSeal doesn't require any cleanup.
func (k *AliCloudKMSSeal) Finalize(_ context.Context) error {
	return nil
}

// SealType returns the seal type for this particular seal implementation.
func (k *AliCloudKMSSeal) SealType() string {
	return seal.AliCloudKMS
}

// KeyID returns the last known key id.
func (k *AliCloudKMSSeal) KeyID() string {
	return k.currentKeyID.Load().(string)
}

// Encrypt is used to encrypt the master key using the the AliCloud CMK.
// This returns the ciphertext, and/or any errors from this
// call. This should be called after the KMS client has been instantiated.
func (k *AliCloudKMSSeal) Encrypt(_ context.Context, plaintext []byte) (*physical.EncryptedBlobInfo, error) {
	if plaintext == nil {
		return nil, fmt.Errorf("given plaintext for encryption is nil")
	}

	env, err := seal.NewEnvelope().Encrypt(plaintext)
	if err != nil {
		return nil, errwrap.Wrapf("error wrapping data: {{err}}", err)
	}

	input := kms.CreateEncryptRequest()
	input.KeyId = k.keyID
	input.Plaintext = string(env.Key)
	input.Domain = k.domain

	output, err := k.client.Encrypt(input)
	if err != nil {
		return nil, errwrap.Wrapf("error encrypting data: {{err}}", err)
	}

	// Store the current key id.
	keyID := output.KeyId
	k.currentKeyID.Store(keyID)

	ret := &physical.EncryptedBlobInfo{
		Ciphertext: env.Ciphertext,
		IV:         env.IV,
		KeyInfo: &physical.SealKeyInfo{
			KeyID:      keyID,
			WrappedKey: []byte(output.CiphertextBlob),
		},
	}

	return ret, nil
}

// Decrypt is used to decrypt the ciphertext. This should be called after Init.
func (k *AliCloudKMSSeal) Decrypt(_ context.Context, in *physical.EncryptedBlobInfo) ([]byte, error) {
	if in == nil {
		return nil, fmt.Errorf("given input for decryption is nil")
	}

	// KeyID is not passed to this call because AWS handles this
	// internally based on the metadata stored with the encrypted data
	input := kms.CreateDecryptRequest()
	input.CiphertextBlob = string(in.KeyInfo.WrappedKey)
	input.Domain = k.domain

	output, err := k.client.Decrypt(input)
	if err != nil {
		return nil, errwrap.Wrapf("error decrypting data encryption key: {{err}}", err)
	}

	envInfo := &seal.EnvelopeInfo{
		Key:        []byte(output.Plaintext),
		IV:         in.IV,
		Ciphertext: in.Ciphertext,
	}
	plaintext, err := seal.NewEnvelope().Decrypt(envInfo)
	if err != nil {
		return nil, errwrap.Wrapf("error decrypting data: {{err}}", err)
	}

	return plaintext, nil
}

type kmsClient interface {
	Decrypt(request *kms.DecryptRequest) (response *kms.DecryptResponse, err error)
	DescribeKey(request *kms.DescribeKeyRequest) (response *kms.DescribeKeyResponse, err error)
	Encrypt(request *kms.EncryptRequest) (response *kms.EncryptResponse, err error)
}
<commit_msg>matching config name to storage backend (#5670)<commit_after>package alicloudkms

import (
	"context"
	"errors"
	"fmt"
	"os"
	"sync/atomic"

	"github.com/aliyun/alibaba-cloud-sdk-go/sdk"
	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/providers"
	"github.com/aliyun/alibaba-cloud-sdk-go/services/kms"
	"github.com/hashicorp/errwrap"
	log "github.com/hashicorp/go-hclog"
	"github.com/hashicorp/vault/physical"
	"github.com/hashicorp/vault/vault/seal"
)

const (
	EnvAliCloudKMSSealKeyID = "VAULT_ALICLOUDKMS_SEAL_KEY_ID"
)

type AliCloudKMSSeal struct {
	logger       log.Logger
	client       kmsClient
	domain       string
	keyID        string
	currentKeyID *atomic.Value
}

// Ensure that we are implementing AutoSealAccess
var _ seal.Access = (*AliCloudKMSSeal)(nil)

func NewSeal(logger log.Logger) *AliCloudKMSSeal {
	k := &AliCloudKMSSeal{
		logger:       logger,
		currentKeyID: new(atomic.Value),
	}
	k.currentKeyID.Store("")
	return k
}

// SetConfig sets the fields on the AliCloudKMSSeal object based on
// values from the config parameter.
//
// Order of precedence AliCloud values:
// * Environment variable
// * Value from Vault configuration file
// * Instance metadata role (access key and secret key)
func (k *AliCloudKMSSeal) SetConfig(config map[string]string) (map[string]string, error) {
	if config == nil {
		config = map[string]string{}
	}

	// Check and set KeyID
	switch {
	case os.Getenv(EnvAliCloudKMSSealKeyID) != "":
		k.keyID = os.Getenv(EnvAliCloudKMSSealKeyID)
	case config["kms_key_id"] != "":
		k.keyID = config["kms_key_id"]
	default:
		return nil, fmt.Errorf("'kms_key_id' not found for AliCloud KMS sealconfiguration")
	}

	region := ""
	if k.client == nil {

		// Check and set region.
		region = os.Getenv("ALICLOUD_REGION")
		if region == "" {
			ok := false
			if region, ok = config["region"]; !ok {
				region = "us-east-1"
			}
		}

		// A domain isn't required, but it can be used to override the endpoint
		// returned by the region. An example value for a domain would be:
		// "kms.us-east-1.aliyuncs.com".
		k.domain = os.Getenv("ALICLOUD_DOMAIN")
		if k.domain == "" {
			k.domain = config["domain"]
		}

		// Build the optional, configuration-based piece of the credential chain.
		credConfig := &providers.Configuration{}

		if accessKey, ok := config["access_key"]; ok {
			credConfig.AccessKeyID = accessKey
		}

		if secretKey, ok := config["secret_key"]; ok {
			credConfig.AccessKeySecret = secretKey
		} else {
			if accessSecret, ok := config["access_secret"]; ok {
				credConfig.AccessKeySecret = accessSecret
			}
		}

		credentialChain := []providers.Provider{
			providers.NewEnvCredentialProvider(),
			providers.NewConfigurationCredentialProvider(credConfig),
			providers.NewInstanceMetadataProvider(),
		}
		credProvider := providers.NewChainProvider(credentialChain)

		creds, err := credProvider.Retrieve()
		if err != nil {
			return nil, err
		}
		clientConfig := sdk.NewConfig()
		clientConfig.Scheme = "https"
		client, err := kms.NewClientWithOptions(region, clientConfig, creds)
		if err != nil {
			return nil, err
		}
		k.client = client
	}

	// Test the client connection using provided key ID
	input := kms.CreateDescribeKeyRequest()
	input.KeyId = k.keyID
	input.Domain = k.domain

	keyInfo, err := k.client.DescribeKey(input)
	if err != nil {
		return nil, errwrap.Wrapf("error fetching AliCloud KMS sealkey information: {{err}}", err)
	}
	if keyInfo == nil || keyInfo.KeyMetadata.KeyId == "" {
		return nil, errors.New("no key information returned")
	}
	k.currentKeyID.Store(keyInfo.KeyMetadata.KeyId)

	// Map that holds non-sensitive configuration info
	sealInfo := make(map[string]string)
	sealInfo["region"] = region
	sealInfo["kms_key_id"] = k.keyID
	if k.domain != "" {
		sealInfo["domain"] = k.domain
	}

	return sealInfo, nil
}

// Init is called during core.Initialize. No-op at the moment.
func (k *AliCloudKMSSeal) Init(_ context.Context) error {
	return nil
}

// Finalize is called during shutdown. This is a no-op since
// AliCloudKMSSeal doesn't require any cleanup.
func (k *AliCloudKMSSeal) Finalize(_ context.Context) error {
	return nil
}

// SealType returns the seal type for this particular seal implementation.
func (k *AliCloudKMSSeal) SealType() string {
	return seal.AliCloudKMS
}

// KeyID returns the last known key id.
func (k *AliCloudKMSSeal) KeyID() string {
	return k.currentKeyID.Load().(string)
}

// Encrypt is used to encrypt the master key using the the AliCloud CMK.
// This returns the ciphertext, and/or any errors from this
// call. This should be called after the KMS client has been instantiated.
func (k *AliCloudKMSSeal) Encrypt(_ context.Context, plaintext []byte) (*physical.EncryptedBlobInfo, error) {
	if plaintext == nil {
		return nil, fmt.Errorf("given plaintext for encryption is nil")
	}

	env, err := seal.NewEnvelope().Encrypt(plaintext)
	if err != nil {
		return nil, errwrap.Wrapf("error wrapping data: {{err}}", err)
	}

	input := kms.CreateEncryptRequest()
	input.KeyId = k.keyID
	input.Plaintext = string(env.Key)
	input.Domain = k.domain

	output, err := k.client.Encrypt(input)
	if err != nil {
		return nil, errwrap.Wrapf("error encrypting data: {{err}}", err)
	}

	// Store the current key id.
	keyID := output.KeyId
	k.currentKeyID.Store(keyID)

	ret := &physical.EncryptedBlobInfo{
		Ciphertext: env.Ciphertext,
		IV:         env.IV,
		KeyInfo: &physical.SealKeyInfo{
			KeyID:      keyID,
			WrappedKey: []byte(output.CiphertextBlob),
		},
	}

	return ret, nil
}

// Decrypt is used to decrypt the ciphertext. This should be called after Init.
func (k *AliCloudKMSSeal) Decrypt(_ context.Context, in *physical.EncryptedBlobInfo) ([]byte, error) {
	if in == nil {
		return nil, fmt.Errorf("given input for decryption is nil")
	}

	// KeyID is not passed to this call because AWS handles this
	// internally based on the metadata stored with the encrypted data
	input := kms.CreateDecryptRequest()
	input.CiphertextBlob = string(in.KeyInfo.WrappedKey)
	input.Domain = k.domain

	output, err := k.client.Decrypt(input)
	if err != nil {
		return nil, errwrap.Wrapf("error decrypting data encryption key: {{err}}", err)
	}

	envInfo := &seal.EnvelopeInfo{
		Key:        []byte(output.Plaintext),
		IV:         in.IV,
		Ciphertext: in.Ciphertext,
	}
	plaintext, err := seal.NewEnvelope().Decrypt(envInfo)
	if err != nil {
		return nil, errwrap.Wrapf("error decrypting data: {{err}}", err)
	}

	return plaintext, nil
}

type kmsClient interface {
	Decrypt(request *kms.DecryptRequest) (response *kms.DecryptResponse, err error)
	DescribeKey(request *kms.DescribeKeyRequest) (response *kms.DescribeKeyResponse, err error)
	Encrypt(request *kms.EncryptRequest) (response *kms.EncryptResponse, err error)
}
<|endoftext|>


<commit_before>package main

import (
	. "github.com/reevoo/tracker"
	"os"
	"syscall"
)

var (
	dynamoUri           = os.Getenv("DYNAMODB_URI")
	env                 = os.Getenv("GO_ENV")
	Term      os.Signal = syscall.SIGTERM
)

func main() {
	// Release mode reduces the amount of logging.
	if env == "production" {
		SetServerMode("release")
	}

	server := NewServer(ServerParams{
		EventStore:  DynamoDBEventStore{},
		ErrorLogger: SentryErrorLogger{},
	})

	server.Run(":3000")
}
<commit_msg>Whoops<commit_after>package main

import (
	. "github.com/reevoo/tracker"
	"os"
	"syscall"
)

var (
	dynamoUri           = os.Getenv("DYNAMODB_URI")
	env                 = os.Getenv("GO_ENV")
	Term      os.Signal = syscall.SIGTERM
)

func main() {
	// Release mode reduces the amount of logging.
	if env == "production" {
		SetServerMode("release")
	}

	server := NewServer(ServerParams{
		EventStore:  NewEventLog(nil),
		ErrorLogger: SentryErrorLogger{},
	})

	server.Run(":3000")
}
<|endoftext|>


<commit_before>package db

import (
	"database/sql"
	"sync"
	"time"

	"github.com/OpenBazaar/openbazaar-go/repo"
	"github.com/OpenBazaar/wallet-interface"
	"github.com/btcsuite/btcd/chaincfg/chainhash"
)

type TxnsDB struct {
	modelStore
	coinType wallet.CoinType
}

func NewTransactionStore(db *sql.DB, lock *sync.Mutex, coinType wallet.CoinType) repo.TransactionStore {
	return &TxnsDB{modelStore{db, lock}, coinType}
}

func (t *TxnsDB) Put(raw []byte, txid string, value, height int, timestamp time.Time, watchOnly bool) error {
	t.lock.Lock()
	defer t.lock.Unlock()
	tx, err := t.db.Begin()
	if err != nil {
		return err
	}
	stmt, err := tx.Prepare("insert or replace into txns(coin, txid, value, height, timestamp, watchOnly, tx) values(?,?,?,?,?,?,?)")
	if err != nil {
		tx.Rollback()
		return err
	}
	defer stmt.Close()
	watchOnlyInt := 0
	if watchOnly {
		watchOnlyInt = 1
	}
	_, err = stmt.Exec(t.coinType.CurrencyCode(), txid, value, height, int(timestamp.Unix()), watchOnlyInt, raw)
	if err != nil {
		tx.Rollback()
		return err
	}
	tx.Commit()
	return nil
}

func (t *TxnsDB) Get(txid chainhash.Hash) (wallet.Txn, error) {
	t.lock.Lock()
	defer t.lock.Unlock()
	var txn wallet.Txn
	stmt, err := t.db.Prepare("select tx, value, height, timestamp, watchOnly from txns where txid=? and coin=?")
	if err != nil {
		return txn, err
	}
	defer stmt.Close()
	var raw []byte
	var height int
	var timestamp int
	var value int
	var watchOnlyInt int
	err = stmt.QueryRow(txid.String(), t.coinType.CurrencyCode()).Scan(&raw, &value, &height, &timestamp, &watchOnlyInt)
	if err != nil {
		return txn, err
	}
	watchOnly := false
	if watchOnlyInt > 0 {
		watchOnly = true
	}
	txn = wallet.Txn{
		Txid:      txid.String(),
		Value:     int64(value),
		Height:    int32(height),
		Timestamp: time.Unix(int64(timestamp), 0),
		WatchOnly: watchOnly,
		Bytes:     raw,
	}
	return txn, nil
}

func (t *TxnsDB) GetAll(includeWatchOnly bool) ([]wallet.Txn, error) {
	t.lock.Lock()
	defer t.lock.Unlock()
	var ret []wallet.Txn
	stm := "select tx, txid, value, height, timestamp, watchOnly from txns where coin=?"
	rows, err := t.db.Query(stm, t.coinType.CurrencyCode())
	if err != nil {
		return ret, err
	}
	defer rows.Close()
	for rows.Next() {
		var raw []byte
		var txid string
		var value int
		var height int
		var timestamp int
		var watchOnlyInt int
		if err := rows.Scan(&raw, &txid, &value, &height, &timestamp, &watchOnlyInt); err != nil {
			continue
		}

		watchOnly := false
		if watchOnlyInt > 0 {
			if !includeWatchOnly {
				continue
			}
			watchOnly = true
		}

		txn := wallet.Txn{
			Txid:      txid,
			Value:     int64(value),
			Height:    int32(height),
			Timestamp: time.Unix(int64(timestamp), 0),
			WatchOnly: watchOnly,
			Bytes:     raw,
		}

		ret = append(ret, txn)
	}
	return ret, nil
}

func (t *TxnsDB) Delete(txid *chainhash.Hash) error {
	t.lock.Lock()
	defer t.lock.Unlock()
	_, err := t.db.Exec("delete from txns where txid=? and coin=?", txid.String(), t.coinType.CurrencyCode())
	if err != nil {
		return err
	}
	return nil
}

func (t *TxnsDB) UpdateHeight(txid chainhash.Hash, height int, timestamp time.Time) error {
	t.lock.Lock()
	defer t.lock.Unlock()
	tx, err := t.db.Begin()
	if err != nil {
		return err
	}
	stmt, err := tx.Prepare("update txns set height=?, timestamp=? where txid=? and coin=?")
	if err != nil {
		return err
	}
	defer stmt.Close()
	_, err = stmt.Exec(height, int(timestamp.Unix()), txid.String(), t.coinType.CurrencyCode())
	if err != nil {
		tx.Rollback()
		return err
	}
	tx.Commit()
	return nil
}
<commit_msg>[#1554] Resolve transactions on all exits in repo/db/txns.UpdateHeight<commit_after>package db

import (
	"database/sql"
	"fmt"
	"sync"
	"time"

	"github.com/OpenBazaar/openbazaar-go/repo"
	"github.com/OpenBazaar/wallet-interface"
	"github.com/btcsuite/btcd/chaincfg/chainhash"
)

type TxnsDB struct {
	modelStore
	coinType wallet.CoinType
}

func NewTransactionStore(db *sql.DB, lock *sync.Mutex, coinType wallet.CoinType) repo.TransactionStore {
	return &TxnsDB{modelStore{db, lock}, coinType}
}

func (t *TxnsDB) Put(raw []byte, txid string, value, height int, timestamp time.Time, watchOnly bool) error {
	t.lock.Lock()
	defer t.lock.Unlock()
	tx, err := t.db.Begin()
	if err != nil {
		return err
	}
	stmt, err := tx.Prepare("insert or replace into txns(coin, txid, value, height, timestamp, watchOnly, tx) values(?,?,?,?,?,?,?)")
	if err != nil {
		tx.Rollback()
		return err
	}
	defer stmt.Close()
	watchOnlyInt := 0
	if watchOnly {
		watchOnlyInt = 1
	}
	_, err = stmt.Exec(t.coinType.CurrencyCode(), txid, value, height, int(timestamp.Unix()), watchOnlyInt, raw)
	if err != nil {
		tx.Rollback()
		return err
	}
	tx.Commit()
	return nil
}

func (t *TxnsDB) Get(txid chainhash.Hash) (wallet.Txn, error) {
	t.lock.Lock()
	defer t.lock.Unlock()
	var txn wallet.Txn
	stmt, err := t.db.Prepare("select tx, value, height, timestamp, watchOnly from txns where txid=? and coin=?")
	if err != nil {
		return txn, err
	}
	defer stmt.Close()
	var raw []byte
	var height int
	var timestamp int
	var value int
	var watchOnlyInt int
	err = stmt.QueryRow(txid.String(), t.coinType.CurrencyCode()).Scan(&raw, &value, &height, &timestamp, &watchOnlyInt)
	if err != nil {
		return txn, err
	}
	watchOnly := false
	if watchOnlyInt > 0 {
		watchOnly = true
	}
	txn = wallet.Txn{
		Txid:      txid.String(),
		Value:     int64(value),
		Height:    int32(height),
		Timestamp: time.Unix(int64(timestamp), 0),
		WatchOnly: watchOnly,
		Bytes:     raw,
	}
	return txn, nil
}

func (t *TxnsDB) GetAll(includeWatchOnly bool) ([]wallet.Txn, error) {
	t.lock.Lock()
	defer t.lock.Unlock()
	var ret []wallet.Txn
	stm := "select tx, txid, value, height, timestamp, watchOnly from txns where coin=?"
	rows, err := t.db.Query(stm, t.coinType.CurrencyCode())
	if err != nil {
		return ret, err
	}
	defer rows.Close()
	for rows.Next() {
		var raw []byte
		var txid string
		var value int
		var height int
		var timestamp int
		var watchOnlyInt int
		if err := rows.Scan(&raw, &txid, &value, &height, &timestamp, &watchOnlyInt); err != nil {
			continue
		}

		watchOnly := false
		if watchOnlyInt > 0 {
			if !includeWatchOnly {
				continue
			}
			watchOnly = true
		}

		txn := wallet.Txn{
			Txid:      txid,
			Value:     int64(value),
			Height:    int32(height),
			Timestamp: time.Unix(int64(timestamp), 0),
			WatchOnly: watchOnly,
			Bytes:     raw,
		}

		ret = append(ret, txn)
	}
	return ret, nil
}

func (t *TxnsDB) Delete(txid *chainhash.Hash) error {
	t.lock.Lock()
	defer t.lock.Unlock()
	_, err := t.db.Exec("delete from txns where txid=? and coin=?", txid.String(), t.coinType.CurrencyCode())
	if err != nil {
		return err
	}
	return nil
}

func (t *TxnsDB) UpdateHeight(txid chainhash.Hash, height int, timestamp time.Time) error {
	t.lock.Lock()
	defer t.lock.Unlock()
	tx, err := t.db.Begin()
	if err != nil {
		return err
	}
	stmt, err := tx.Prepare("update txns set height=?, timestamp=? where txid=? and coin=?")
	if err != nil {
		if rErr := tx.Rollback(); rErr != nil {
			return fmt.Errorf("%s (db rollback: %s)", err.Error(), rErr.Error())
		}
		return err
	}
	defer stmt.Close()
	_, err = stmt.Exec(height, int(timestamp.Unix()), txid.String(), t.coinType.CurrencyCode())
	if err != nil {
		if rErr := tx.Rollback(); rErr != nil {
			return fmt.Errorf("%s (db rollback: %s)", err.Error(), rErr.Error())
		}
		return err
	}
	if err := tx.Commit(); err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	//"code.google.com/p/go.crypto/ssh"
)

func main() {
	fmt.Println("sandhog: tunnel server")
	// usage: sandhog [--log <log-path>] <listen-port>

}
<commit_msg>Basic skeleton for using the SSH libs<commit_after>package main

import (
	"code.google.com/p/go.crypto/ssh"
	"crypto"
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"os"
)

var (
	logger *log.Logger
)

type SandhogClientKeyring struct {
	key *rsa.PrivateKey
}

func LoadKeyring(keyPath string) (*SandhogClientKeyring, error) {
	// Read the key material
	privateKeyPEM, err := ioutil.ReadFile(keyPath)
	if err != nil {
		return nil, err
	}

	// Decode the key material
	block, _ := pem.Decode(privateKeyPEM)

	// Parse the key
	rsaKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
	if err != nil {
		// Could not parse the key from the decoded PEM
		return nil, err
	}

	keyring := &SandhogClientKeyring{rsaKey}

	// Everything turned out fine!
	return keyring, nil
}

func (keyring *SandhogClientKeyring) Key(i int) (ssh.PublicKey, error) {
	// Only support one key
	if i != 0 {
		return nil, nil
	}

	// Wrap the RSA public key in the SSH package's PublicKey wrapper
	publicKey, err := ssh.NewPublicKey(keyring.key.PublicKey)
	if err != nil {
		return nil, err
	}

	return publicKey, nil
}

func (keyring *SandhogClientKeyring) Sign(i int, rand io.Reader, data []byte) (sig []byte, err error) {
	// Only support one key
	if i != 0 {
		return nil, nil
	}

	hashImpl := crypto.SHA1
	hashFunc := hashImpl.New()
	hashFunc.Write(data)
	digest := hashFunc.Sum(nil)
	return rsa.SignPKCS1v15(rand, keyring.key, hashImpl, digest)
}

func loadConfig() (*configStruct, error) {
	var config configStruct

	flag.IntVar(&config.localPort, "local-port", 0, "Local port on which to listen to forward from remote")
	flag.IntVar(&config.remotePort, "remote-port", 0, "Remote port on which to listen to forward to local")
	flag.StringVar(&config.keyPath, "key", "", "Path to id_rsa")
	flag.StringVar(&config.remoteHost, "host", "", "Remote host to forward data from")

	flag.Parse()

	if config.localPort == 0 {
		return nil, configError{"Local port must be specified"}
	}
	if config.remotePort == 0 {
		return nil, configError{"Remote port must be specified"}
	}
	if config.keyPath == "" {
		return nil, configError{"Key path must be specified"}
	}
	if config.remoteHost == "" {
		return nil, configError{"Remote host must be specified"}
	}

	return &config, nil
}

type configError struct {
	errorString string
}

func (e configError) Error() string {
	return e.errorString
}

type configStruct struct {
	keyPath    string
	localPort  int
	remotePort int
	remoteHost string
}

func printUsage() {
	fmt.Println("usage: sandhog -key <id_rsa> -local-port <port> -remote-port <port> -host <remote-host>")
}

func handleConn(remoteConn net.Conn, configData configStruct) {
	// TODO Create local connection
	localDestination := fmt.Sprintf("127.0.0.1:%d", configData.localPort)
	logger.Printf("making connection from %s to %s\n", remoteConn, localDestination)

	// Read/write forever

}

func main() {
	logger = log.New(os.Stdout, "wam: ", log.LstdFlags|log.Lshortfile)
	logger.Println("sandhog")

	configData, err := loadConfig()
	if err != nil {
		printUsage()
		logger.Fatalln(err)
	}

	keyring, err := LoadKeyring(configData.keyPath)
	if err != nil {
		logger.Fatalln(err)
	}
	logger.Printf("loaded keyring: %s", keyring)

	sshConfig := &ssh.ClientConfig{
		User: "wam",
		Auth: []ssh.ClientAuth{
			ssh.ClientAuthKeyring(keyring),
		},
	}
	logger.Printf("created SSH client config: %s", sshConfig)

	// Dial your ssh server.
	logger.Println("connecting")
	conn, err := ssh.Dial("tcp", "localhost:22", sshConfig)
	if err != nil {
		logger.Fatalf("unable to connect: %s\n", err)
	}
	defer conn.Close()
	logger.Println("connected!")

	// Request the remote side to open port 8080 on all interfaces.
	// When they
	remoteListenEndpoint := fmt.Sprintf("127.0.0.1:%d", configData.remotePort)
	logger.Printf("requesting remote host listen on: %s\n", remoteListenEndpoint)
	listener, err := conn.Listen("tcp", remoteListenEndpoint)
	if err != nil {
		log.Fatalf("unable to register tcp forward: %s", err)
	}
	defer listener.Close()

	logger.Printf("remote host listening on %s\n", remoteListenEndpoint)

	for {
		conn, err := listener.Accept()
		if err != nil {
			logger.Println(err)
			break
		}
		go handleConn(conn, configData)
	}
	// Serve HTTP with your SSH server acting as a reverse proxy.
	http.Serve(listener, http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
		fmt.Fprintf(resp, "Hello world!\n")
	}))
}
<|endoftext|>


<commit_before>/*
Package framed provides an implementation of io.ReadWriteCloser that reads and
writes whole frames only.

Frames are length-prefixed.  The first two bytes are an unsigned 16 bit int
stored in little-endian byte order indicating the length of the content.  The
remaining bytes are the actual content of the frame.

The use of a uint16 means that the maximum possible frame size (MaxFrameSize)
is 65535.
*/
package framed

import (
	"encoding/binary"
	"fmt"
	"io"
	"sync"
)

const (
	// FrameHeaderSize is the size of the frame header in bytes
	FrameHeaderSize = 2

	// MaxFrameSize is the maximum possible size of a frame (not including the
	// length prefix)
	MaxFrameSize = 65535
)

var endianness = binary.LittleEndian

/*
A Reader enhances an io.ReadCloser to read data in contiguous frames. It
implements the io.Reader interface, but unlike typical io.Readers it only
returns whole frames.

A Reader also supports the ability to read frames using dynamically allocated
buffers via the ReadFrame method.
*/
type Reader struct {
	Stream io.Reader // the raw underlying connection
	mutex  sync.Mutex
}

/*
A Writer enhances an io.WriteCLoser to write data in contiguous frames. It
implements the io.Writer interface, but unlike typical io.Writers, it includes
information that allows a corresponding Reader to read whole frames without them
being fragmented.

A Writer also supports a method that writes multiple buffers to the underlying
stream as a single frame.
*/
type Writer struct {
	Stream io.Writer // the raw underlying connection
	mutex  sync.Mutex
}

func NewReader(r io.Reader) *Reader {
	return &Reader{Stream: r}
}

func NewWriter(w io.Writer) *Writer {
	return &Writer{Stream: w}
}

/*
Read implements the function from io.Reader.  Unlike io.Reader.Read,
frame.Read only returns full frames of data (assuming that the data was written
by a framed.Writer).
*/
func (framed *Reader) Read(buffer []byte) (n int, err error) {
	framed.mutex.Lock()
	defer framed.mutex.Unlock()

	var nb uint16
	err = binary.Read(framed.Stream, endianness, &nb)
	if err != nil {
		return
	}

	n = int(nb)

	bufferSize := len(buffer)
	if n > bufferSize {
		return 0, fmt.Errorf("Buffer of size %d is too small to hold frame of size %d", bufferSize, n)
	}

	// Read into buffer
	n, err = io.ReadFull(framed.Stream, buffer[:n])
	return
}

// ReadFrame reads the next frame, using a new buffer sized to hold the frame.
func (framed *Reader) ReadFrame() (frame []byte, err error) {
	framed.mutex.Lock()
	defer framed.mutex.Unlock()

	var nb uint16
	err = binary.Read(framed.Stream, endianness, &nb)
	if err != nil {
		return
	}

	l := int(nb)
	frame = make([]byte, l)

	// Read into buffer
	n, err := io.ReadFull(framed.Stream, frame)
	if n != l {
		return nil, fmt.Errorf("Read wrong number of bytes. Expected frame of length %d, got %d", n, l)
	}
	return
}

/*
Write implements the Write method from io.Writer.  It prepends a frame length
header that allows the framed.Reader on the other end to read the whole frame.
*/
func (framed *Writer) Write(frame []byte) (n int, err error) {
	framed.mutex.Lock()
	defer framed.mutex.Unlock()

	n = len(frame)

	// Write the length header
	if err = binary.Write(framed.Stream, endianness, uint16(n)); err != nil {
		return
	}

	// Write the data
	var written int
	if written, err = framed.Stream.Write(frame); err != nil {
		return
	}
	if written != n {
		err = fmt.Errorf("%d bytes written, expected to write %d", written, n)
	}
	return
}

func (framed *Writer) WritePieces(pieces ...[]byte) (n int, err error) {
	framed.mutex.Lock()
	defer framed.mutex.Unlock()

	for _, piece := range pieces {
		n = n + len(piece)
	}

	// Write the length header
	if err = binary.Write(framed.Stream, endianness, uint16(n)); err != nil {
		return
	}

	// Write the data
	var written int
	for _, piece := range pieces {
		var nw int
		if nw, err = framed.Stream.Write(piece); err != nil {
			return
		}
		written = written + nw
	}
	if written != n {
		err = fmt.Errorf("%d bytes written, expected to write %d", written, n)
	}
	return
}
<commit_msg>Re-expressed size constants for clarity<commit_after>/*
Package framed provides an implementation of io.ReadWriteCloser that reads and
writes whole frames only.

Frames are length-prefixed.  The first two bytes are an unsigned 16 bit int
stored in little-endian byte order indicating the length of the content.  The
remaining bytes are the actual content of the frame.

The use of a uint16 means that the maximum possible frame size (MaxFrameSize)
is 65535.
*/
package framed

import (
	"encoding/binary"
	"fmt"
	"io"
	"sync"
)

const (
	// FrameHeaderBits is the size of the frame header in bits
	FrameHeaderBits = 16

	// FrameHeaderSize is the size of the frame header in bytes
	FrameHeaderSize = 16 / 2

	// MaxFrameSize is the maximum possible size of a frame (not including the
	// length prefix)
	MaxFrameSize = 1<<FrameHeaderBits - 1
)

var endianness = binary.LittleEndian

/*
A Reader enhances an io.ReadCloser to read data in contiguous frames. It
implements the io.Reader interface, but unlike typical io.Readers it only
returns whole frames.

A Reader also supports the ability to read frames using dynamically allocated
buffers via the ReadFrame method.
*/
type Reader struct {
	Stream io.Reader // the raw underlying connection
	mutex  sync.Mutex
}

/*
A Writer enhances an io.WriteCLoser to write data in contiguous frames. It
implements the io.Writer interface, but unlike typical io.Writers, it includes
information that allows a corresponding Reader to read whole frames without them
being fragmented.

A Writer also supports a method that writes multiple buffers to the underlying
stream as a single frame.
*/
type Writer struct {
	Stream io.Writer // the raw underlying connection
	mutex  sync.Mutex
}

func NewReader(r io.Reader) *Reader {
	return &Reader{Stream: r}
}

func NewWriter(w io.Writer) *Writer {
	return &Writer{Stream: w}
}

/*
Read implements the function from io.Reader.  Unlike io.Reader.Read,
frame.Read only returns full frames of data (assuming that the data was written
by a framed.Writer).
*/
func (framed *Reader) Read(buffer []byte) (n int, err error) {
	framed.mutex.Lock()
	defer framed.mutex.Unlock()

	var nb uint16
	err = binary.Read(framed.Stream, endianness, &nb)
	if err != nil {
		return
	}

	n = int(nb)

	bufferSize := len(buffer)
	if n > bufferSize {
		return 0, fmt.Errorf("Buffer of size %d is too small to hold frame of size %d", bufferSize, n)
	}

	// Read into buffer
	n, err = io.ReadFull(framed.Stream, buffer[:n])
	return
}

// ReadFrame reads the next frame, using a new buffer sized to hold the frame.
func (framed *Reader) ReadFrame() (frame []byte, err error) {
	framed.mutex.Lock()
	defer framed.mutex.Unlock()

	var nb uint16
	err = binary.Read(framed.Stream, endianness, &nb)
	if err != nil {
		return
	}

	l := int(nb)
	frame = make([]byte, l)

	// Read into buffer
	n, err := io.ReadFull(framed.Stream, frame)
	if n != l {
		return nil, fmt.Errorf("Read wrong number of bytes. Expected frame of length %d, got %d", n, l)
	}
	return
}

/*
Write implements the Write method from io.Writer.  It prepends a frame length
header that allows the framed.Reader on the other end to read the whole frame.
*/
func (framed *Writer) Write(frame []byte) (n int, err error) {
	framed.mutex.Lock()
	defer framed.mutex.Unlock()

	n = len(frame)

	// Write the length header
	if err = binary.Write(framed.Stream, endianness, uint16(n)); err != nil {
		return
	}

	// Write the data
	var written int
	if written, err = framed.Stream.Write(frame); err != nil {
		return
	}
	if written != n {
		err = fmt.Errorf("%d bytes written, expected to write %d", written, n)
	}
	return
}

func (framed *Writer) WritePieces(pieces ...[]byte) (n int, err error) {
	framed.mutex.Lock()
	defer framed.mutex.Unlock()

	for _, piece := range pieces {
		n = n + len(piece)
	}

	// Write the length header
	if err = binary.Write(framed.Stream, endianness, uint16(n)); err != nil {
		return
	}

	// Write the data
	var written int
	for _, piece := range pieces {
		var nw int
		if nw, err = framed.Stream.Write(piece); err != nil {
			return
		}
		written = written + nw
	}
	if written != n {
		err = fmt.Errorf("%d bytes written, expected to write %d", written, n)
	}
	return
}
<|endoftext|>


<commit_before>/*

Package freeze enables the "freezing" of data, similar to JavaScript's
Object.freeze(). A frozen object cannot be modified; attempting to do so
will result in an unrecoverable panic.

To accomplish this, the mprotect syscall is used. Sadly, this necessitates
allocating new memory via mmap and copying the data into it. This performance
penalty should not be prohibitive, but it's something to be aware of.

Freezing is useful to providing soft guarantees of immutability. That is: the
compiler can't prevent you from mutating an frozen object, but the runtime
can. One of the unfortunate aspects of Go is its limited support for
constants: structs, slices, and even arrays cannot be declared as consts. This
becomes a problem when you want to pass a slice around to many consumers
without worrying about them modifying it. With freeze, you can guard against
these unwanted or intended behaviors.

Two functions are provided: Pointer and Slice. (I suppose these could have
been combined, but then the resulting function would have to be called Freeze,
which stutters.) To freeze a pointer, call Pointer like so:

	var x int = 3
	xp := freeze.Pointer(&x).(*int)
	println(*xp) // ok; prints 3
	*xp++        // not ok; panics

It is recommended that, where convenient, you reassign the returned pointer to
its original variable, as with append. Note that in the above example, x can
still be freely modified.

Likewise, to freeze a slice:

	xs := []int{1, 2, 3}
	xs = freeze.Slice(xs).([]int)
	println(xs[0]) // ok; prints 1
	xs[0]++        // not ok; panics

It may not be immediately obvious why these functions return a value that must
be reassigned. The reason is that we are allocating new memory, and therefore
the pointer must be updated. The same is true of the built-in append function.
Well, not quite; if a slice has greater capacity than length, then append will
use that memory. For the same reason, appending to a frozen slice with spare
capacity will trigger a panic.

Currently, only Unix is supported. Windows support is not planned, because it
doesn't support a syscall analogous to mprotect.
*/
package freeze

import (
	"reflect"
	"runtime"
	"unsafe"

	"golang.org/x/sys/unix"
)

// Pointer freezes v, which must be a pointer. Future writes to v's memory will
// result in a panic.
func Pointer(v interface{}) interface{} {
	typ := reflect.TypeOf(v)
	if typ.Kind() != reflect.Ptr {
		panic("Pointer called on non-pointer type")
	}

	// freeze the memory pointed to by the interface's data pointer
	size := typ.Elem().Size()
	ptrs := (*[2]uintptr)(unsafe.Pointer(&v))
	ptrs[1] = copyAndFreeze(ptrs[1], size)

	return v
}

// Slice freezes v, which must be a slice. Future writes to v's memory will
// result in a panic.
func Slice(v interface{}) interface{} {
	val := reflect.ValueOf(v)
	if val.Kind() != reflect.Slice {
		panic("Slice called on non-slice type")
	}

	// freeze the memory pointed to by the slice's data pointer
	size := val.Type().Elem().Size() * uintptr(val.Len())
	slice := (*[3]uintptr)(unsafe.Pointer((*[2]uintptr)(unsafe.Pointer(&v))[1]))
	slice[0] = copyAndFreeze(slice[0], size)

	return v
}

// copyAndFreeze copies n bytes from dataptr into new memory, freezes it, and
// returns a uintptr to the new memory.
func copyAndFreeze(dataptr, n uintptr) uintptr {
	// allocate new memory to be frozen
	newMem, err := unix.Mmap(-1, 0, int(n), unix.PROT_READ|unix.PROT_WRITE, unix.MAP_ANON|unix.MAP_PRIVATE)
	if err != nil {
		panic(err)
	}
	// set a finalizer to unmap the memory when it would normally be GC'd
	runtime.SetFinalizer(&newMem, func(b *[]byte) { unix.Munmap(*b) })

	// copy n bytes into newMem
	copy(newMem, *(*[]byte)(unsafe.Pointer(&[3]uintptr{dataptr, n, n})))

	// freeze the new memory
	if err = unix.Mprotect(newMem, unix.PROT_READ); err != nil {
		panic(err)
	}

	// return pointer to new memory
	return uintptr(unsafe.Pointer(&newMem[0]))
}
<commit_msg>appease go vet<commit_after>/*

Package freeze enables the "freezing" of data, similar to JavaScript's
Object.freeze(). A frozen object cannot be modified; attempting to do so
will result in an unrecoverable panic.

To accomplish this, the mprotect syscall is used. Sadly, this necessitates
allocating new memory via mmap and copying the data into it. This performance
penalty should not be prohibitive, but it's something to be aware of.

Freezing is useful to providing soft guarantees of immutability. That is: the
compiler can't prevent you from mutating an frozen object, but the runtime
can. One of the unfortunate aspects of Go is its limited support for
constants: structs, slices, and even arrays cannot be declared as consts. This
becomes a problem when you want to pass a slice around to many consumers
without worrying about them modifying it. With freeze, you can guard against
these unwanted or intended behaviors.

Two functions are provided: Pointer and Slice. (I suppose these could have
been combined, but then the resulting function would have to be called Freeze,
which stutters.) To freeze a pointer, call Pointer like so:

	var x int = 3
	xp := freeze.Pointer(&x).(*int)
	println(*xp) // ok; prints 3
	*xp++        // not ok; panics

It is recommended that, where convenient, you reassign the returned pointer to
its original variable, as with append. Note that in the above example, x can
still be freely modified.

Likewise, to freeze a slice:

	xs := []int{1, 2, 3}
	xs = freeze.Slice(xs).([]int)
	println(xs[0]) // ok; prints 1
	xs[0]++        // not ok; panics

It may not be immediately obvious why these functions return a value that must
be reassigned. The reason is that we are allocating new memory, and therefore
the pointer must be updated. The same is true of the built-in append function.
Well, not quite; if a slice has greater capacity than length, then append will
use that memory. For the same reason, appending to a frozen slice with spare
capacity will trigger a panic.

Currently, only Unix is supported. Windows support is not planned, because it
doesn't support a syscall analogous to mprotect.
*/
package freeze

import (
	"reflect"
	"runtime"
	"unsafe"

	"golang.org/x/sys/unix"
)

// Pointer freezes v, which must be a pointer. Future writes to v's memory will
// result in a panic.
func Pointer(v interface{}) interface{} {
	typ := reflect.TypeOf(v)
	if typ.Kind() != reflect.Ptr {
		panic("Pointer called on non-pointer type")
	}

	// freeze the memory pointed to by the interface's data pointer
	size := typ.Elem().Size()
	ptrs := (*[2]uintptr)(unsafe.Pointer(&v))
	ptrs[1] = copyAndFreeze(ptrs[1], size)

	return v
}

// Slice freezes v, which must be a slice. Future writes to v's memory will
// result in a panic.
func Slice(v interface{}) interface{} {
	val := reflect.ValueOf(v)
	if val.Kind() != reflect.Slice {
		panic("Slice called on non-slice type")
	}

	// freeze the memory pointed to by the slice's data pointer
	size := val.Type().Elem().Size() * uintptr(val.Len())
	slice := (*[3]uintptr)((*[2]unsafe.Pointer)(unsafe.Pointer(&v))[1]) // should be [2]uintptr, but go vet complains
	slice[0] = copyAndFreeze(slice[0], size)

	return v
}

// copyAndFreeze copies n bytes from dataptr into new memory, freezes it, and
// returns a uintptr to the new memory.
func copyAndFreeze(dataptr, n uintptr) uintptr {
	// allocate new memory to be frozen
	newMem, err := unix.Mmap(-1, 0, int(n), unix.PROT_READ|unix.PROT_WRITE, unix.MAP_ANON|unix.MAP_PRIVATE)
	if err != nil {
		panic(err)
	}
	// set a finalizer to unmap the memory when it would normally be GC'd
	runtime.SetFinalizer(&newMem, func(b *[]byte) { _ = unix.Munmap(*b) })

	// copy n bytes into newMem
	copy(newMem, *(*[]byte)(unsafe.Pointer(&[3]uintptr{dataptr, n, n})))

	// freeze the new memory
	if err = unix.Mprotect(newMem, unix.PROT_READ); err != nil {
		panic(err)
	}

	// return pointer to new memory
	return uintptr(unsafe.Pointer(&newMem[0]))
}
<|endoftext|>