<commit_before>// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.

package gconv

import (
	"errors"
	"fmt"
	"github.com/gogf/gf/errors/gerror"
	"github.com/gogf/gf/internal/empty"
	"reflect"
	"regexp"
	"strings"

	"github.com/gogf/gf/internal/structs"
	"github.com/gogf/gf/internal/utils"
)

var (
	// replaceCharReg is the regular expression object for replacing chars
	// in map keys and attribute names.
	replaceCharReg, _ = regexp.Compile(`[\-\.\_\s]+`)
)

// Struct maps the params key-value pairs to the corresponding struct object's attributes.
// The third parameter <mapping> is unnecessary, indicating the mapping rules between the
// custom key name and the attribute name(case sensitive).
//
// Note:
// 1. The <params> can be any type of map/struct, usually a map.
// 2. The second parameter <pointer> should be a pointer to the struct object.
// 3. Only the public attributes of struct object can be mapped.
// 4. If <params> is a map, the key of the map <params> can be lowercase.
//    It will automatically convert the first letter of the key to uppercase
//    in mapping procedure to do the matching.
//    It ignores the map key, if it does not match.
func Struct(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
	if params == nil {
		return errors.New("params cannot be nil")
	}
	if pointer == nil {
		return errors.New("object pointer cannot be nil")
	}
	defer func() {
		// Catch the panic, especially the reflect operation panics.
		if e := recover(); e != nil {
			err = gerror.NewfSkip(1, "%v", e)
		}
	}()

	// paramsMap is the map[string]interface{} type variable for params.
	paramsMap := Map(params)
	if paramsMap == nil {
		return fmt.Errorf("invalid params: %v", params)
	}

	// UnmarshalValue.
	// Assign value with interface UnmarshalValue.
	// Note that only pointer can implement interface UnmarshalValue.
	if v, ok := pointer.(apiUnmarshalValue); ok {
		return v.UnmarshalValue(params)
	}

	// Using reflect to do the converting,
	// it also supports type of reflect.Value for <pointer>(always in internal usage).
	elem, ok := pointer.(reflect.Value)
	if !ok {
		rv := reflect.ValueOf(pointer)
		if kind := rv.Kind(); kind != reflect.Ptr {
			return fmt.Errorf("object pointer should be type of '*struct', but got '%v'", kind)
		}
		// Using IsNil on reflect.Ptr variable is OK.
		if !rv.IsValid() || rv.IsNil() {
			return errors.New("object pointer cannot be nil")
		}
		elem = rv.Elem()
	}

	// It automatically creates struct object if necessary.
	// For example, if <pointer> is **User, then <elem> is *User, which is a pointer to User.
	if elem.Kind() == reflect.Ptr {
		if !elem.IsValid() || elem.IsNil() {
			e := reflect.New(elem.Type().Elem()).Elem()
			elem.Set(e.Addr())
			elem = e
		} else {
			elem = elem.Elem()
		}
	}

	// UnmarshalValue.
	// Assign value with interface UnmarshalValue.
	// Note that only pointer can implement interface UnmarshalValue.
	if elem.Kind() == reflect.Struct {
		if v, ok := elem.Addr().Interface().(apiUnmarshalValue); ok {
			return v.UnmarshalValue(params)
		}
	}

	// It only performs one converting to the same attribute.
	// doneMap is used to check repeated converting, its key is the real attribute name
	// of the struct.
	doneMap := make(map[string]struct{})
	// It first checks the passed mapping rules.
	if len(mapping) > 0 && len(mapping[0]) > 0 {
		for mapK, mapV := range mapping[0] {
			// mapV is the the attribute name of the struct.
			if v, ok := paramsMap[mapK]; ok {
				doneMap[mapV] = struct{}{}
				if err := bindVarToStructAttr(elem, mapV, v); err != nil {
					return err
				}
			}
		}
	}

	// The key of the attrMap is the attribute name of the struct,
	// and the value is its replaced name for later comparison to improve performance.
	var (
		attrMap  = make(map[string]string)
		elemType = elem.Type()
		tempName = ""
	)
	for i := 0; i < elem.NumField(); i++ {
		// Only do converting to public attributes.
		if !utils.IsLetterUpper(elemType.Field(i).Name[0]) {
			continue
		}
		tempName = elemType.Field(i).Name
		attrMap[tempName] = replaceCharReg.ReplaceAllString(tempName, "")
	}
	if len(attrMap) == 0 {
		return nil
	}

	// The key of the tagMap is the attribute name of the struct,
	// and the value is its replaced tag name for later comparison to improve performance.
	tagMap := make(map[string]string)
	for k, v := range structs.TagMapName(pointer, structTagPriority, true) {
		tagMap[v] = replaceCharReg.ReplaceAllString(k, "")
	}

	var (
		attrName  string
		checkName string
	)
	for mapK, mapV := range paramsMap {
		attrName = ""
		checkName = replaceCharReg.ReplaceAllString(mapK, "")
		// Loop to find the matched attribute name with or without
		// string cases and chars like '-'/'_'/'.'/' '.

		// Matching the parameters to struct tag names.
		// The <tagV> is the attribute name of the struct.
		for attrKey, cmpKey := range tagMap {
			if strings.EqualFold(checkName, cmpKey) {
				attrName = attrKey
				break
			}
		}

		// Matching the parameters to struct attributes.
		for attrKey, cmpKey := range attrMap {
			// Eg:
			// UserName  eq user_name
			// User-Name eq username
			// username  eq userName
			// etc.
			if strings.EqualFold(checkName, cmpKey) {
				attrName = attrKey
				break
			}
		}

		// No matching, give up this attribute converting.
		if attrName == "" {
			continue
		}
		// If the attribute name is already checked converting, then skip it.
		if _, ok := doneMap[attrName]; ok {
			continue
		}
		// Mark it done.
		doneMap[attrName] = struct{}{}
		if err := bindVarToStructAttr(elem, attrName, mapV); err != nil {
			return err
		}
	}
	return nil
}

// StructDeep do Struct function recursively.
// See Struct.
func StructDeep(params interface{}, pointer interface{}, mapping ...map[string]string) error {
	if params == nil {
		return nil
	}
	if err := Struct(params, pointer, mapping...); err != nil {
		return err
	} else {
		rv, ok := pointer.(reflect.Value)
		if !ok {
			rv = reflect.ValueOf(pointer)
		}
		kind := rv.Kind()
		for kind == reflect.Ptr {
			rv = rv.Elem()
			kind = rv.Kind()
		}
		switch kind {
		case reflect.Struct:
			rt := rv.Type()
			for i := 0; i < rv.NumField(); i++ {
				// Only do converting to public attributes.
				if !utils.IsLetterUpper(rt.Field(i).Name[0]) {
					continue
				}
				trv := rv.Field(i)
				switch trv.Kind() {
				case reflect.Struct:
					if err := StructDeep(params, trv, mapping...); err != nil {
						return err
					}
				}
			}
		}
	}
	return nil
}

// bindVarToStructAttr sets value to struct object attribute by name.
func bindVarToStructAttr(elem reflect.Value, name string, value interface{}) (err error) {
	structFieldValue := elem.FieldByName(name)
	if !structFieldValue.IsValid() {
		return nil
	}
	// CanSet checks whether attribute is public accessible.
	if !structFieldValue.CanSet() {
		return nil
	}
	defer func() {
		if recover() != nil {
			err = bindVarToReflectValue(structFieldValue, value)
		}
	}()
	if empty.IsNil(value) {
		structFieldValue.Set(reflect.Zero(structFieldValue.Type()))
	} else {
		structFieldValue.Set(reflect.ValueOf(Convert(value, structFieldValue.Type().String())))
	}
	return nil
}

// bindVarToReflectValue sets <value> to reflect value object <structFieldValue>.
func bindVarToReflectValue(structFieldValue reflect.Value, value interface{}) (err error) {
	kind := structFieldValue.Kind()

	// Converting using interface, for some kinds.
	switch kind {
	case reflect.Slice, reflect.Array, reflect.Ptr, reflect.Interface:
		if !structFieldValue.IsNil() {
			if v, ok := structFieldValue.Interface().(apiSet); ok {
				v.Set(value)
				return nil
			} else if v, ok := structFieldValue.Interface().(apiUnmarshalValue); ok {
				err = v.UnmarshalValue(value)
				if err == nil {
					return err
				}
			}
		}
	}

	// Converting by kind.
	switch kind {
	case reflect.Struct:
		if err := Struct(value, structFieldValue); err != nil {
			// Note there's reflect conversion mechanism here.
			structFieldValue.Set(reflect.ValueOf(value).Convert(structFieldValue.Type()))
		}
	// Note that the slice element might be type of struct,
	// so it uses Struct function doing the converting internally.
	case reflect.Slice, reflect.Array:
		a := reflect.Value{}
		v := reflect.ValueOf(value)
		if v.Kind() == reflect.Slice || v.Kind() == reflect.Array {
			a = reflect.MakeSlice(structFieldValue.Type(), v.Len(), v.Len())
			if v.Len() > 0 {
				t := a.Index(0).Type()
				for i := 0; i < v.Len(); i++ {
					if t.Kind() == reflect.Ptr {
						e := reflect.New(t.Elem()).Elem()
						if err := Struct(v.Index(i).Interface(), e); err != nil {
							// Note there's reflect conversion mechanism here.
							e.Set(reflect.ValueOf(v.Index(i).Interface()).Convert(t))
						}
						a.Index(i).Set(e.Addr())
					} else {
						e := reflect.New(t).Elem()
						if err := Struct(v.Index(i).Interface(), e); err != nil {
							// Note there's reflect conversion mechanism here.
							e.Set(reflect.ValueOf(v.Index(i).Interface()).Convert(t))
						}
						a.Index(i).Set(e)
					}
				}
			}
		} else {
			a = reflect.MakeSlice(structFieldValue.Type(), 1, 1)
			t := a.Index(0).Type()
			if t.Kind() == reflect.Ptr {
				e := reflect.New(t.Elem()).Elem()
				if err := Struct(value, e); err != nil {
					// Note there's reflect conversion mechanism here.
					e.Set(reflect.ValueOf(value).Convert(t))
				}
				a.Index(0).Set(e.Addr())
			} else {
				e := reflect.New(t).Elem()
				if err := Struct(value, e); err != nil {
					// Note there's reflect conversion mechanism here.
					e.Set(reflect.ValueOf(value).Convert(t))
				}
				a.Index(0).Set(e)
			}
		}
		structFieldValue.Set(a)

	case reflect.Ptr:
		item := reflect.New(structFieldValue.Type().Elem())
		// Assign value with interface Set.
		// Note that only pointer can implement interface Set.
		if v, ok := item.Interface().(apiUnmarshalValue); ok {
			err = v.UnmarshalValue(value)
			structFieldValue.Set(item)
			return err
		}
		elem := item.Elem()
		if err = bindVarToReflectValue(elem, value); err == nil {
			structFieldValue.Set(elem.Addr())
		}

	// It mainly and specially handles the interface of nil value.
	case reflect.Interface:
		if value == nil {
			// Specially.
			structFieldValue.Set(reflect.ValueOf((*interface{})(nil)))
		} else {
			// Note there's reflect conversion mechanism here.
			structFieldValue.Set(reflect.ValueOf(value).Convert(structFieldValue.Type()))
		}

	default:
		defer func() {
			if e := recover(); e != nil {
				err = errors.New(
					fmt.Sprintf(`cannot convert value "%+v" to type "%s"`,
						value,
						structFieldValue.Type().String(),
					),
				)
			}
		}()
		// It here uses reflect converting <value> to type of the attribute and assigns
		// the result value to the attribute. It might fail and panic if the usual Go
		// conversion rules do not allow conversion.
		structFieldValue.Set(reflect.ValueOf(value).Convert(structFieldValue.Type()))
	}
	return nil
}
<commit_msg>improve function Struct for package gconv<commit_after>// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.

package gconv

import (
	"errors"
	"fmt"
	"github.com/gogf/gf/errors/gerror"
	"github.com/gogf/gf/internal/empty"
	"reflect"
	"regexp"
	"strings"

	"github.com/gogf/gf/internal/structs"
	"github.com/gogf/gf/internal/utils"
)

var (
	// replaceCharReg is the regular expression object for replacing chars
	// in map keys and attribute names.
	replaceCharReg, _ = regexp.Compile(`[\-\.\_\s]+`)
)

// Struct maps the params key-value pairs to the corresponding struct object's attributes.
// The third parameter <mapping> is unnecessary, indicating the mapping rules between the
// custom key name and the attribute name(case sensitive).
//
// Note:
// 1. The <params> can be any type of map/struct, usually a map.
// 2. The second parameter <pointer> should be a pointer to the struct object.
// 3. Only the public attributes of struct object can be mapped.
// 4. If <params> is a map, the key of the map <params> can be lowercase.
//    It will automatically convert the first letter of the key to uppercase
//    in mapping procedure to do the matching.
//    It ignores the map key, if it does not match.
func Struct(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
	if params == nil {
		return errors.New("params cannot be nil")
	}
	if pointer == nil {
		return errors.New("object pointer cannot be nil")
	}
	defer func() {
		// Catch the panic, especially the reflect operation panics.
		if e := recover(); e != nil {
			err = gerror.NewfSkip(1, "%v", e)
		}
	}()

	// paramsMap is the map[string]interface{} type variable for params.
	paramsMap := Map(params)
	if paramsMap == nil {
		return fmt.Errorf("invalid params: %v", params)
	}

	// UnmarshalValue.
	// Assign value with interface UnmarshalValue.
	// Note that only pointer can implement interface UnmarshalValue.
	if v, ok := pointer.(apiUnmarshalValue); ok {
		return v.UnmarshalValue(params)
	}

	// Using reflect to do the converting,
	// it also supports type of reflect.Value for <pointer>(always in internal usage).
	elem, ok := pointer.(reflect.Value)
	if !ok {
		rv := reflect.ValueOf(pointer)
		if kind := rv.Kind(); kind != reflect.Ptr {
			return fmt.Errorf("object pointer should be type of '*struct', but got '%v'", kind)
		}
		// Using IsNil on reflect.Ptr variable is OK.
		if !rv.IsValid() || rv.IsNil() {
			return errors.New("object pointer cannot be nil")
		}
		elem = rv.Elem()
	}

	// It automatically creates struct object if necessary.
	// For example, if <pointer> is **User, then <elem> is *User, which is a pointer to User.
	if elem.Kind() == reflect.Ptr {
		if !elem.IsValid() || elem.IsNil() {
			e := reflect.New(elem.Type().Elem()).Elem()
			elem.Set(e.Addr())
			elem = e
		} else {
			elem = elem.Elem()
		}
	}

	// UnmarshalValue.
	// Assign value with interface UnmarshalValue.
	// Note that only pointer can implement interface UnmarshalValue.
	if elem.Kind() == reflect.Struct {
		if v, ok := elem.Addr().Interface().(apiUnmarshalValue); ok {
			return v.UnmarshalValue(params)
		}
	}

	// It only performs one converting to the same attribute.
	// doneMap is used to check repeated converting, its key is the real attribute name
	// of the struct.
	doneMap := make(map[string]struct{})
	// It first checks the passed mapping rules.
	if len(mapping) > 0 && len(mapping[0]) > 0 {
		for mapK, mapV := range mapping[0] {
			// mapV is the the attribute name of the struct.
			if v, ok := paramsMap[mapK]; ok {
				doneMap[mapV] = struct{}{}
				if err := bindVarToStructAttr(elem, mapV, v); err != nil {
					return err
				}
			}
		}
	}

	// The key of the attrMap is the attribute name of the struct,
	// and the value is its replaced name for later comparison to improve performance.
	var (
		attrMap  = make(map[string]string)
		elemType = elem.Type()
		tempName = ""
	)
	for i := 0; i < elem.NumField(); i++ {
		// Only do converting to public attributes.
		if !utils.IsLetterUpper(elemType.Field(i).Name[0]) {
			continue
		}
		tempName = elemType.Field(i).Name
		attrMap[tempName] = replaceCharReg.ReplaceAllString(tempName, "")
	}
	if len(attrMap) == 0 {
		return nil
	}

	// The key of the tagMap is the attribute name of the struct,
	// and the value is its replaced tag name for later comparison to improve performance.
	tagMap := make(map[string]string)
	for k, v := range structs.TagMapName(pointer, structTagPriority, true) {
		tagMap[v] = replaceCharReg.ReplaceAllString(k, "")
	}

	var (
		attrName  string
		checkName string
	)
	for mapK, mapV := range paramsMap {
		attrName = ""
		checkName = replaceCharReg.ReplaceAllString(mapK, "")
		// Loop to find the matched attribute name with or without
		// string cases and chars like '-'/'_'/'.'/' '.

		// Matching the parameters to struct tag names.
		// The <tagV> is the attribute name of the struct.
		for attrKey, cmpKey := range tagMap {
			if strings.EqualFold(checkName, cmpKey) {
				attrName = attrKey
				break
			}
		}

		// Matching the parameters to struct attributes.
		for attrKey, cmpKey := range attrMap {
			// Eg:
			// UserName  eq user_name
			// User-Name eq username
			// username  eq userName
			// etc.
			if strings.EqualFold(checkName, cmpKey) {
				attrName = attrKey
				break
			}
		}

		// No matching, give up this attribute converting.
		if attrName == "" {
			continue
		}
		// If the attribute name is already checked converting, then skip it.
		if _, ok := doneMap[attrName]; ok {
			continue
		}
		// Mark it done.
		doneMap[attrName] = struct{}{}
		if err := bindVarToStructAttr(elem, attrName, mapV); err != nil {
			return err
		}
	}
	return nil
}

// StructDeep do Struct function recursively.
// See Struct.
func StructDeep(params interface{}, pointer interface{}, mapping ...map[string]string) error {
	if params == nil {
		return nil
	}
	if err := Struct(params, pointer, mapping...); err != nil {
		return err
	} else {
		rv, ok := pointer.(reflect.Value)
		if !ok {
			rv = reflect.ValueOf(pointer)
		}
		kind := rv.Kind()
		for kind == reflect.Ptr {
			rv = rv.Elem()
			kind = rv.Kind()
		}
		switch kind {
		case reflect.Struct:
			rt := rv.Type()
			for i := 0; i < rv.NumField(); i++ {
				// Only do converting to public attributes.
				if !utils.IsLetterUpper(rt.Field(i).Name[0]) {
					continue
				}
				trv := rv.Field(i)
				switch trv.Kind() {
				case reflect.Struct:
					if err := StructDeep(params, trv, mapping...); err != nil {
						return err
					}
				}
			}
		}
	}
	return nil
}

// bindVarToStructAttr sets value to struct object attribute by name.
func bindVarToStructAttr(elem reflect.Value, name string, value interface{}) (err error) {
	structFieldValue := elem.FieldByName(name)
	if !structFieldValue.IsValid() {
		return nil
	}
	// CanSet checks whether attribute is public accessible.
	if !structFieldValue.CanSet() {
		return nil
	}
	defer func() {
		if recover() != nil {
			err = bindVarToReflectValue(structFieldValue, value)
		}
	}()
	if empty.IsNil(value) {
		structFieldValue.Set(reflect.Zero(structFieldValue.Type()))
	} else {
		structFieldValue.Set(reflect.ValueOf(Convert(value, structFieldValue.Type().String())))
	}
	return nil
}

// bindVarToReflectValue sets <value> to reflect value object <structFieldValue>.
func bindVarToReflectValue(structFieldValue reflect.Value, value interface{}) (err error) {
	kind := structFieldValue.Kind()

	// Converting using interface, for some kinds.
	switch kind {
	case reflect.Slice, reflect.Array, reflect.Ptr, reflect.Interface:
		if !structFieldValue.IsNil() {
			if v, ok := structFieldValue.Interface().(apiSet); ok {
				v.Set(value)
				return nil
			} else if v, ok := structFieldValue.Interface().(apiUnmarshalValue); ok {
				err = v.UnmarshalValue(value)
				if err == nil {
					return err
				}
			}
		}
	}

	// Converting by kind.
	switch kind {
	case reflect.Struct:
		// UnmarshalValue.
		if v, ok := structFieldValue.Addr().Interface().(apiUnmarshalValue); ok {
			return v.UnmarshalValue(value)
		}

		if err := Struct(value, structFieldValue); err != nil {
			// Note there's reflect conversion mechanism here.
			structFieldValue.Set(reflect.ValueOf(value).Convert(structFieldValue.Type()))
		}
	// Note that the slice element might be type of struct,
	// so it uses Struct function doing the converting internally.
	case reflect.Slice, reflect.Array:
		a := reflect.Value{}
		v := reflect.ValueOf(value)
		if v.Kind() == reflect.Slice || v.Kind() == reflect.Array {
			a = reflect.MakeSlice(structFieldValue.Type(), v.Len(), v.Len())
			if v.Len() > 0 {
				t := a.Index(0).Type()
				for i := 0; i < v.Len(); i++ {
					if t.Kind() == reflect.Ptr {
						e := reflect.New(t.Elem()).Elem()
						if err := Struct(v.Index(i).Interface(), e); err != nil {
							// Note there's reflect conversion mechanism here.
							e.Set(reflect.ValueOf(v.Index(i).Interface()).Convert(t))
						}
						a.Index(i).Set(e.Addr())
					} else {
						e := reflect.New(t).Elem()
						if err := Struct(v.Index(i).Interface(), e); err != nil {
							// Note there's reflect conversion mechanism here.
							e.Set(reflect.ValueOf(v.Index(i).Interface()).Convert(t))
						}
						a.Index(i).Set(e)
					}
				}
			}
		} else {
			a = reflect.MakeSlice(structFieldValue.Type(), 1, 1)
			t := a.Index(0).Type()
			if t.Kind() == reflect.Ptr {
				e := reflect.New(t.Elem()).Elem()
				if err := Struct(value, e); err != nil {
					// Note there's reflect conversion mechanism here.
					e.Set(reflect.ValueOf(value).Convert(t))
				}
				a.Index(0).Set(e.Addr())
			} else {
				e := reflect.New(t).Elem()
				if err := Struct(value, e); err != nil {
					// Note there's reflect conversion mechanism here.
					e.Set(reflect.ValueOf(value).Convert(t))
				}
				a.Index(0).Set(e)
			}
		}
		structFieldValue.Set(a)

	case reflect.Ptr:
		item := reflect.New(structFieldValue.Type().Elem())
		// Assign value with interface Set.
		// Note that only pointer can implement interface Set.
		if v, ok := item.Interface().(apiUnmarshalValue); ok {
			err = v.UnmarshalValue(value)
			structFieldValue.Set(item)
			return err
		}
		elem := item.Elem()
		if err = bindVarToReflectValue(elem, value); err == nil {
			structFieldValue.Set(elem.Addr())
		}

	// It mainly and specially handles the interface of nil value.
	case reflect.Interface:
		if value == nil {
			// Specially.
			structFieldValue.Set(reflect.ValueOf((*interface{})(nil)))
		} else {
			// Note there's reflect conversion mechanism here.
			structFieldValue.Set(reflect.ValueOf(value).Convert(structFieldValue.Type()))
		}

	default:
		defer func() {
			if e := recover(); e != nil {
				err = errors.New(
					fmt.Sprintf(`cannot convert value "%+v" to type "%s"`,
						value,
						structFieldValue.Type().String(),
					),
				)
			}
		}()
		// It here uses reflect converting <value> to type of the attribute and assigns
		// the result value to the attribute. It might fail and panic if the usual Go
		// conversion rules do not allow conversion.
		structFieldValue.Set(reflect.ValueOf(value).Convert(structFieldValue.Type()))
	}
	return nil
}
<|endoftext|>


<commit_before>package upload

import (
	"math/rand"
	"testing"
	"time"
)

const (
	Gig       int = 1024 * 1024 * 1024
	chunkSize     = 1024 * 1024
)

var (
	uploader = NewUploader(".")
)

func TestUpload(t *testing.T) {
	sess := uploader.AddSession()
	data := make([]byte, Gig)
	start, end := 0, chunkSize

	randomBytes(data)
	sess.Init()

	for end != len(data) {
		if end = start + chunkSize; end > len(data) {
			end = len(data)
		}
		chunk := data[start:end]
		start += chunkSize

		if err := sess.Put(chunk); err != nil {
			t.Fatal("Failed to upload chunk", err)
		}
	}

	if err := sess.Commit("./randomfile.txt"); err != nil {
		t.Fatal("Failed to commit upload", err)
	}
	if err := sess.Cleanup(); err != nil {
		t.Fatal("Failed to cleanup session", err)
	}
}

func randomBytes(p []byte) {
	r := rand.NewSource(time.Now().UnixNano())
	todo := len(p)
	offset := 0

	for {
		val := int64(r.Int63())

		for i := 0; i < 8; i++ {
			p[offset] = byte(val)
			todo--

			if todo == 0 {
				return
			}
			offset++
			val >>= 8
		}
	}
}
<commit_msg>upload_test: remove unnecessary cleanup call<commit_after>package upload

import (
	"math/rand"
	"testing"
	"time"
)

const (
	Gig       int = 1024 * 1024 * 1024
	chunkSize     = 1024 * 1024
)

var (
	uploader = NewUploader(".")
)

func TestUpload(t *testing.T) {
	sess := uploader.AddSession()
	data := make([]byte, Gig)
	start, end := 0, chunkSize

	randomBytes(data)
	sess.Init()

	for end != len(data) {
		if end = start + chunkSize; end > len(data) {
			end = len(data)
		}
		chunk := data[start:end]
		start += chunkSize

		if err := sess.Put(chunk); err != nil {
			t.Fatal("Failed to upload chunk", err)
		}
	}

	if err := sess.Commit("./randomfile.txt"); err != nil {
		t.Fatal("Failed to commit upload", err)
	}
}

func randomBytes(p []byte) {
	r := rand.NewSource(time.Now().UnixNano())
	todo := len(p)
	offset := 0

	for {
		val := int64(r.Int63())

		for i := 0; i < 8; i++ {
			p[offset] = byte(val)
			todo--

			if todo == 0 {
				return
			}
			offset++
			val >>= 8
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package util_test

import (
	"fmt"
	"testing"

	. "github.com/pingcap/check"
	"github.com/pingcap/tidb/kv"
	"github.com/pingcap/tidb/store/tikv"
	"github.com/pingcap/tidb/util"
	"github.com/pingcap/tidb/util/testleak"
	goctx "golang.org/x/net/context"
)

const (
	startIndex = 0
	testCount  = 12
	testPow    = 10
)

func TestT(t *testing.T) {
	CustomVerboseFlag = true
	TestingT(t)
}

var _ = Suite(&testPrefixSuite{})

type testPrefixSuite struct {
	s kv.Storage
}

func (s *testPrefixSuite) SetUpSuite(c *C) {
	store, err := tikv.NewMockTikvStore()
	c.Assert(err, IsNil)
	s.s = store

}

func (s *testPrefixSuite) TearDownSuite(c *C) {
	err := s.s.Close()
	c.Assert(err, IsNil)
}

func encodeInt(n int) []byte {
	return []byte(fmt.Sprintf("%d", n))
}

type MockContext struct {
	prefix int
	values map[fmt.Stringer]interface{}
	kv.Storage
	txn kv.Transaction
}

func (c *MockContext) SetValue(key fmt.Stringer, value interface{}) {
	c.values[key] = value
}

func (c *MockContext) Value(key fmt.Stringer) interface{} {
	value := c.values[key]
	return value
}

func (c *MockContext) ClearValue(key fmt.Stringer) {
	delete(c.values, key)
}

func (c *MockContext) GetTxn(forceNew bool) (kv.Transaction, error) {
	var err error
	c.txn, err = c.Begin()
	if err != nil {
		return nil, err
	}

	return c.txn, nil
}

func (c *MockContext) fillTxn() error {
	if c.txn == nil {
		return nil
	}

	var err error
	for i := startIndex; i < testCount; i++ {
		val := encodeInt(i + (c.prefix * testPow))
		err = c.txn.Set(val, val)
		if err != nil {
			return err
		}
	}

	return nil
}

func (c *MockContext) CommitTxn() error {
	if c.txn == nil {
		return nil
	}
	return c.txn.Commit(goctx.Background())
}

func (s *testPrefixSuite) TestPrefix(c *C) {
	defer testleak.AfterTest(c)()
	ctx := &MockContext{10000000, make(map[fmt.Stringer]interface{}), s.s, nil}
	ctx.fillTxn()
	txn, err := ctx.GetTxn(false)
	c.Assert(err, IsNil)
	err = util.DelKeyWithPrefix(txn, encodeInt(ctx.prefix))
	c.Assert(err, IsNil)
	err = ctx.CommitTxn()
	c.Assert(err, IsNil)

	txn, err = s.s.Begin()
	c.Assert(err, IsNil)
	k := []byte("key100jfowi878230")
	err = txn.Set(k, []byte("val32dfaskli384757^*&%^"))
	c.Assert(err, IsNil)
	err = util.ScanMetaWithPrefix(txn, k, func(kv.Key, []byte) bool {
		return true
	})
	c.Assert(err, IsNil)
	err = txn.Commit(goctx.Background())
	c.Assert(err, IsNil)
}

func (s *testPrefixSuite) TestPrefixFilter(c *C) {
	defer testleak.AfterTest(c)()
	rowKey := []byte("test@#$%l(le[0]..prefix) 2uio")
	rowKey[8] = 0x00
	rowKey[9] = 0x00
	f := util.RowKeyPrefixFilter(rowKey)
	b := f(append(rowKey, []byte("akjdf3*(34")...))
	c.Assert(b, IsFalse)
	buf := f([]byte("sjfkdlsaf"))
	c.Assert(buf, IsTrue)
}
<commit_msg>util: fix a test leak in testPrefixSuite (#5122)<commit_after>// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package util_test

import (
	"fmt"
	"testing"

	. "github.com/pingcap/check"
	"github.com/pingcap/tidb/kv"
	"github.com/pingcap/tidb/store/tikv"
	"github.com/pingcap/tidb/util"
	"github.com/pingcap/tidb/util/testleak"
	goctx "golang.org/x/net/context"
)

const (
	startIndex = 0
	testCount  = 12
	testPow    = 10
)

func TestT(t *testing.T) {
	CustomVerboseFlag = true
	TestingT(t)
}

var _ = Suite(&testPrefixSuite{})

type testPrefixSuite struct {
	s kv.Storage
}

func (s *testPrefixSuite) SetUpSuite(c *C) {
	testleak.BeforeTest()
	store, err := tikv.NewMockTikvStore()
	c.Assert(err, IsNil)
	s.s = store

}

func (s *testPrefixSuite) TearDownSuite(c *C) {
	err := s.s.Close()
	c.Assert(err, IsNil)
	testleak.AfterTest(c)()
}

func encodeInt(n int) []byte {
	return []byte(fmt.Sprintf("%d", n))
}

type MockContext struct {
	prefix int
	values map[fmt.Stringer]interface{}
	kv.Storage
	txn kv.Transaction
}

func (c *MockContext) SetValue(key fmt.Stringer, value interface{}) {
	c.values[key] = value
}

func (c *MockContext) Value(key fmt.Stringer) interface{} {
	value := c.values[key]
	return value
}

func (c *MockContext) ClearValue(key fmt.Stringer) {
	delete(c.values, key)
}

func (c *MockContext) GetTxn(forceNew bool) (kv.Transaction, error) {
	var err error
	c.txn, err = c.Begin()
	if err != nil {
		return nil, err
	}

	return c.txn, nil
}

func (c *MockContext) fillTxn() error {
	if c.txn == nil {
		return nil
	}

	var err error
	for i := startIndex; i < testCount; i++ {
		val := encodeInt(i + (c.prefix * testPow))
		err = c.txn.Set(val, val)
		if err != nil {
			return err
		}
	}

	return nil
}

func (c *MockContext) CommitTxn() error {
	if c.txn == nil {
		return nil
	}
	return c.txn.Commit(goctx.Background())
}

func (s *testPrefixSuite) TestPrefix(c *C) {
	ctx := &MockContext{10000000, make(map[fmt.Stringer]interface{}), s.s, nil}
	ctx.fillTxn()
	txn, err := ctx.GetTxn(false)
	c.Assert(err, IsNil)
	err = util.DelKeyWithPrefix(txn, encodeInt(ctx.prefix))
	c.Assert(err, IsNil)
	err = ctx.CommitTxn()
	c.Assert(err, IsNil)

	txn, err = s.s.Begin()
	c.Assert(err, IsNil)
	k := []byte("key100jfowi878230")
	err = txn.Set(k, []byte("val32dfaskli384757^*&%^"))
	c.Assert(err, IsNil)
	err = util.ScanMetaWithPrefix(txn, k, func(kv.Key, []byte) bool {
		return true
	})
	c.Assert(err, IsNil)
	err = txn.Commit(goctx.Background())
	c.Assert(err, IsNil)
}

func (s *testPrefixSuite) TestPrefixFilter(c *C) {
	rowKey := []byte("test@#$%l(le[0]..prefix) 2uio")
	rowKey[8] = 0x00
	rowKey[9] = 0x00
	f := util.RowKeyPrefixFilter(rowKey)
	b := f(append(rowKey, []byte("akjdf3*(34")...))
	c.Assert(b, IsFalse)
	buf := f([]byte("sjfkdlsaf"))
	c.Assert(buf, IsTrue)
}
<|endoftext|>


<commit_before>// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gps

import (
	"os"
	"path/filepath"
	"strings"

	"github.com/pkg/errors"
)

// fsLink represents a symbolic link.
type fsLink struct {
	path string
	to   string

	// circular denotes if evaluating the symlink fails with "too many links" error.
	// This errors means that it's very likely that the symlink has circual refernce.
	circular bool

	// broken denotes that attempting to resolve the link fails, most likely because
	// the destaination doesn't exist.
	broken bool
}

// filesystemState represents the state of a file system.
type filesystemState struct {
	root  string
	dirs  []string
	files []string
	links []fsLink
}

func (s filesystemState) setup() error {
	for _, dir := range s.dirs {
		p := filepath.Join(s.root, dir)

		if err := os.MkdirAll(p, 0777); err != nil {
			return errors.Errorf("os.MkdirAll(%q, 0777) err=%q", p, err)
		}
	}

	for _, file := range s.files {
		p := filepath.Join(s.root, file)

		f, err := os.Create(p)
		if err != nil {
			return errors.Errorf("os.Create(%q) err=%q", p, err)
		}

		if err := f.Close(); err != nil {
			return errors.Errorf("file %q Close() err=%q", p, err)
		}
	}

	for _, link := range s.links {
		p := filepath.Join(s.root, link.path)

		// On Windows, relative symlinks confuse filepath.Walk. So, we'll just sigh
		// and do absolute links, assuming they are relative to the directory of
		// link.path.
		//
		// Reference: https://github.com/golang/go/issues/17540
		//
		// TODO(ibrasho): This was fixed in Go 1.9. Remove this when support for
		// 1.8 is dropped.
		dir := filepath.Dir(p)
		to := ""
		if link.to != "" {
			to = filepath.Join(dir, link.to)
		}

		if err := os.Symlink(to, p); err != nil {
			return errors.Errorf("os.Symlink(%q, %q) err=%q", to, p, err)
		}
	}

	return nil
}

// deriveFilesystemState returns a filesystemState based on the state of
// the filesystem on root.
func deriveFilesystemState(root string) (filesystemState, error) {
	fs := filesystemState{root: root}

	err := filepath.Walk(fs.root, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if path == fs.root {
			return nil
		}

		relPath, err := filepath.Rel(fs.root, path)
		if err != nil {
			return err
		}

		if (info.Mode() & os.ModeSymlink) != 0 {
			l := fsLink{path: relPath}

			l.to, err = filepath.EvalSymlinks(path)
			if err != nil && strings.HasSuffix(err.Error(), "too many links") {
				l.circular = true
			} else if err != nil && os.IsNotExist(err) {
				l.broken = true
			} else if err != nil {
				return err
			}

			fs.links = append(fs.links, l)

			return nil
		}

		if info.IsDir() {
			fs.dirs = append(fs.dirs, relPath)

			return nil
		}

		fs.files = append(fs.files, relPath)

		return nil
	})

	if err != nil {
		return filesystemState{}, err
	}

	return fs, nil
}
<commit_msg>Fix typos<commit_after>// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gps

import (
	"os"
	"path/filepath"
	"strings"

	"github.com/pkg/errors"
)

// fsLink represents a symbolic link.
type fsLink struct {
	path string
	to   string

	// circular denotes if evaluating the symlink fails with "too many links" error.
	// This error means that it's very likely that the symlink has a circular reference.
	circular bool

	// broken denotes that attempting to resolve the link fails, most likely because
	// the destaination doesn't exist.
	broken bool
}

// filesystemState represents the state of a file system.
type filesystemState struct {
	root  string
	dirs  []string
	files []string
	links []fsLink
}

func (s filesystemState) setup() error {
	for _, dir := range s.dirs {
		p := filepath.Join(s.root, dir)

		if err := os.MkdirAll(p, 0777); err != nil {
			return errors.Errorf("os.MkdirAll(%q, 0777) err=%q", p, err)
		}
	}

	for _, file := range s.files {
		p := filepath.Join(s.root, file)

		f, err := os.Create(p)
		if err != nil {
			return errors.Errorf("os.Create(%q) err=%q", p, err)
		}

		if err := f.Close(); err != nil {
			return errors.Errorf("file %q Close() err=%q", p, err)
		}
	}

	for _, link := range s.links {
		p := filepath.Join(s.root, link.path)

		// On Windows, relative symlinks confuse filepath.Walk. So, we'll just sigh
		// and do absolute links, assuming they are relative to the directory of
		// link.path.
		//
		// Reference: https://github.com/golang/go/issues/17540
		//
		// TODO(ibrasho): This was fixed in Go 1.9. Remove this when support for
		// 1.8 is dropped.
		dir := filepath.Dir(p)
		to := ""
		if link.to != "" {
			to = filepath.Join(dir, link.to)
		}

		if err := os.Symlink(to, p); err != nil {
			return errors.Errorf("os.Symlink(%q, %q) err=%q", to, p, err)
		}
	}

	return nil
}

// deriveFilesystemState returns a filesystemState based on the state of
// the filesystem on root.
func deriveFilesystemState(root string) (filesystemState, error) {
	fs := filesystemState{root: root}

	err := filepath.Walk(fs.root, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if path == fs.root {
			return nil
		}

		relPath, err := filepath.Rel(fs.root, path)
		if err != nil {
			return err
		}

		if (info.Mode() & os.ModeSymlink) != 0 {
			l := fsLink{path: relPath}

			l.to, err = filepath.EvalSymlinks(path)
			if err != nil && strings.HasSuffix(err.Error(), "too many links") {
				l.circular = true
			} else if err != nil && os.IsNotExist(err) {
				l.broken = true
			} else if err != nil {
				return err
			}

			fs.links = append(fs.links, l)

			return nil
		}

		if info.IsDir() {
			fs.dirs = append(fs.dirs, relPath)

			return nil
		}

		fs.files = append(fs.files, relPath)

		return nil
	})

	if err != nil {
		return filesystemState{}, err
	}

	return fs, nil
}
<|endoftext|>


<commit_before>package golangQL

import (
	"reflect"
	"sync"
)

type filterFunc func(val reflect.Value, tree *node) (interface{}, error)

func (g *golangQL) filter(v interface{}, query string) (interface{}, error) {
	if len(query) == 0 {
		return v, nil
	}

	tree, err := parse(query)
	if err != nil {
		return nil, err
	}

	val := reflect.ValueOf(v)
	filter := g.getFilter(val.Type(), tree)

	result, err := filter(val, tree)
	if err != nil {
		return nil, err
	}

	return result, nil
}

func (g *golangQL) getFilter(typ reflect.Type, tree *node) filterFunc {
	g.RLock()
	key := newCacheKey(typ, tree)
	f := g.filters[key]
	g.RUnlock()
	if f != nil {
		return f
	}

	g.Lock()
	f = g.filters[key]
	if f != nil {
		g.Unlock()
		return f
	}

	recursive := sync.WaitGroup{}
	recursive.Add(1)
	g.filters[key] = func(val reflect.Value, tree *node) (interface{}, error) {
		recursive.Wait()
		return f(val, tree)
	}
	g.Unlock()

	f = g.newFilter(typ, tree)
	g.Lock()
	g.filters[key] = f
	g.Unlock()

	recursive.Done()
	return f
}

func (g *golangQL) newFilter(typ reflect.Type, tree *node) filterFunc {
	switch typ.Kind() {
	case reflect.Ptr:
		return g.newPtrFilter(typ, tree)
	case reflect.Struct:
		return g.newStructFilter(typ, tree)
	case reflect.Slice:
		return g.newSliceFilter(typ, tree)
	default:
		return defaultFilter()
	}
}

// Filter constructors

func defaultFilter() filterFunc {
	return func(val reflect.Value, tree *node) (interface{}, error) {
		return val.Interface(), nil
	}
}

func (g *golangQL) newPtrFilter(typ reflect.Type, tree *node) filterFunc {
	elemFilter := g.getFilter(typ.Elem(), tree)

	return func(val reflect.Value, tree *node) (interface{}, error) {
		v := val.Elem()

		return elemFilter(v, tree)
	}
}

func (g *golangQL) newSliceFilter(typ reflect.Type, tree *node) filterFunc {
	elemFilter := g.getFilter(typ.Elem(), tree)

	return func(val reflect.Value, tree *node) (interface{}, error) {
		resultMap := make([]map[string]interface{}, val.Len())
		resultMapValue := reflect.ValueOf(resultMap)
		for i := 0; i < val.Len(); i++ {
			v := val.Index(i)

			filteredStruct, err := elemFilter(v, tree)
			if err != nil {
				return nil, err
			}

			filteredValue := reflect.ValueOf(filteredStruct)

			resultMapValue.Index(i).Set(filteredValue)
		}

		return resultMap, nil
	}
}

func (g *golangQL) newStructFilter(typ reflect.Type, tree *node) filterFunc {
	fields := fieldsForType(typ)
	for i := range fields {
		fields[i].child = tree.findChildByName(fields[i].tag)
		if fields[i].child != nil {
			fields[i].filter = g.getFilter(fields[i].typ, fields[i].child)
			continue
		}

		fields[i].filter = g.getFilter(fields[i].typ, tree)
	}

	return func(val reflect.Value, tree *node) (interface{}, error) {
		typ := val.Type()
		resultMap := make(map[string]interface{}, typ.NumField())

		for _, field := range fields {
			fieldValue := fieldByIndex(val, field.index)
			child := tree.findChildByName(field.tag)
			if child != nil {
				childStruct, err := field.filter(fieldValue, child)
				if err != nil {
					return nil, err
				}

				resultMap[field.tag] = childStruct
				continue
			}

			if tree.containsField(field.tag) {
				resultMap[field.tag] = fieldValue.Interface()
			}
		}

		return resultMap, nil
	}
}
<commit_msg>fix panic for nil values<commit_after>package golangQL

import (
	"reflect"
	"sync"
)

type filterFunc func(val reflect.Value, tree *node) (interface{}, error)

func (g *golangQL) filter(v interface{}, query string) (interface{}, error) {
	if len(query) == 0 {
		return v, nil
	}

	tree, err := parse(query)
	if err != nil {
		return nil, err
	}

	val := reflect.ValueOf(v)
	filter := g.getFilter(val.Type(), tree)

	result, err := filter(val, tree)
	if err != nil {
		return nil, err
	}

	return result, nil
}

func (g *golangQL) getFilter(typ reflect.Type, tree *node) filterFunc {
	g.RLock()
	key := newCacheKey(typ, tree)
	f := g.filters[key]
	g.RUnlock()
	if f != nil {
		return f
	}

	g.Lock()
	f = g.filters[key]
	if f != nil {
		g.Unlock()
		return f
	}

	recursive := sync.WaitGroup{}
	recursive.Add(1)
	g.filters[key] = func(val reflect.Value, tree *node) (interface{}, error) {
		recursive.Wait()
		return f(val, tree)
	}
	g.Unlock()

	f = g.newFilter(typ, tree)
	g.Lock()
	g.filters[key] = f
	g.Unlock()

	recursive.Done()
	return f
}

func (g *golangQL) newFilter(typ reflect.Type, tree *node) filterFunc {
	switch typ.Kind() {
	case reflect.Ptr:
		return g.newPtrFilter(typ, tree)
	case reflect.Struct:
		return g.newStructFilter(typ, tree)
	case reflect.Slice:
		return g.newSliceFilter(typ, tree)
	default:
		return defaultFilter()
	}
}

// Filter constructors

func defaultFilter() filterFunc {
	return func(val reflect.Value, tree *node) (interface{}, error) {
		return val.Interface(), nil
	}
}

func (g *golangQL) newPtrFilter(typ reflect.Type, tree *node) filterFunc {
	elemFilter := g.getFilter(typ.Elem(), tree)

	return func(val reflect.Value, tree *node) (interface{}, error) {
		v := val.Elem()

		return elemFilter(v, tree)
	}
}

func (g *golangQL) newSliceFilter(typ reflect.Type, tree *node) filterFunc {
	elemFilter := g.getFilter(typ.Elem(), tree)

	return func(val reflect.Value, tree *node) (interface{}, error) {
		resultMap := make([]map[string]interface{}, val.Len())
		resultMapValue := reflect.ValueOf(resultMap)
		for i := 0; i < val.Len(); i++ {
			v := val.Index(i)

			filteredStruct, err := elemFilter(v, tree)
			if err != nil {
				return nil, err
			}

			filteredValue := reflect.ValueOf(filteredStruct)

			resultMapValue.Index(i).Set(filteredValue)
		}

		return resultMap, nil
	}
}

func (g *golangQL) newStructFilter(typ reflect.Type, tree *node) filterFunc {
	fields := fieldsForType(typ)
	for i := range fields {
		fields[i].child = tree.findChildByName(fields[i].tag)
		if fields[i].child != nil {
			fields[i].filter = g.getFilter(fields[i].typ, fields[i].child)
			continue
		}

		fields[i].filter = g.getFilter(fields[i].typ, tree)
	}

	return func(val reflect.Value, tree *node) (interface{}, error) {
		typ := val.Type()
		resultMap := make(map[string]interface{}, typ.NumField())

		for _, field := range fields {
			fieldValue := fieldByIndex(val, field.index)
			if !fieldValue.IsValid() {
				continue
			}

			child := tree.findChildByName(field.tag)
			if child != nil {
				childStruct, err := field.filter(fieldValue, child)
				if err != nil {
					return nil, err
				}

				resultMap[field.tag] = childStruct
				continue
			}

			if tree.containsField(field.tag) {
				resultMap[field.tag] = fieldValue.Interface()
			}
		}

		return resultMap, nil
	}
}
<|endoftext|>


<commit_before>package server
import (
	"strings"
	"strconv"
	"fmt"
	"crypto/sha1"
	"encoding/hex"
	"time"
	"net"
)

/*
 Authorization: user ts sha1(user + key + ts + method + uri)

 */
func (self *Session) auth() (username string, err error) {
	defer func() {
		// deley 1s on fail to prevent attack
		if err != nil {
			time.Sleep(1 * time.Second)
		}
	}()
	if !self.config.Auth.Enabled {
		return "", nil
	}
	authStr := self.req.Header.Get("Authorization")
	reqUser, reqHash, ts, err := parseAuthHeader(authStr)
	if err != nil {
		return "", err
	}
	user, ok := self.config.Users[reqUser]
	if !ok {
		return "", fmt.Errorf("user %s not found", reqUser)
	}
	if ! checkHosts(self.req.RemoteAddr, user.Hosts) {
		return reqUser, fmt.Errorf("remote host is denied")
	}
	if user.Key != "" {
		nowTs := time.Now().Unix()
		maxDelta := self.config.Auth.MaxTimeDelta
		if nowTs - ts > int64(maxDelta) || ts - nowTs > int64(maxDelta) {
			return reqUser, fmt.Errorf("timestamp delta too large")
		}
		strToHash := reqUser + user.Key + strconv.FormatInt(ts, 10) + self.req.Method + self.req.RequestURI
		sha1Sum := sha1.Sum([]byte(strToHash))
		realHash := hex.EncodeToString(sha1Sum[:])
		if reqHash != realHash {
			return reqUser, fmt.Errorf("auth failed")
		}
	}
	return reqUser, nil
}

func parseAuthHeader(authStr string) (user, hash string, ts int64, err error){
	segs := strings.SplitN(authStr, " ", 3)
	user = segs[0]
	if len(segs) < 3 {
		hash = ""
		ts = 0
		err = fmt.Errorf("bad auth header")
		return
	}
	tsStr := segs[1]
	hash = segs[2]
	ts, err = strconv.ParseInt(tsStr, 10, 64)
	return
}

func checkPermission(group string, allows []string) bool {
	for _, allow := range(allows) {
		if group == allow {
			return true
		}
	}
	return false
}

func (self *Session) checkPermission() bool {
	if self.username == "" {
		return true
	}
	return checkPermission(self.group, self.UserConfig().Allows[self.resource])
}

func checkHosts(remoteAddr string, hosts []string) bool {
	if len(hosts) <= 0 {
		return true
	}
	ok := false
	for _, host := range (hosts) {
		_, allowedNet, err := net.ParseCIDR(host)
		if err != nil {
			continue
		}
		if allowedNet.Contains(net.ParseIP(remoteAddr)) {
			ok = true
			break
		}
	}
	if !ok {
		return false
	}
	return true
}
<commit_msg>fix host auth<commit_after>package server
import (
	"strings"
	"strconv"
	"fmt"
	"crypto/sha1"
	"encoding/hex"
	"time"
	"net"
)

/*
 Authorization: user ts sha1(user + key + ts + method + uri)

 */
func (self *Session) auth() (username string, err error) {
	defer func() {
		// deley 1s on fail to prevent attack
		if err != nil {
			time.Sleep(1 * time.Second)
		}
	}()
	if !self.config.Auth.Enabled {
		return "", nil
	}
	authStr := self.req.Header.Get("Authorization")
	reqUser, reqHash, ts, err := parseAuthHeader(authStr)
	if err != nil {
		return "", err
	}
	user, ok := self.config.Users[reqUser]
	if !ok {
		return "", fmt.Errorf("user %s not found", reqUser)
	}
	remoteHost := strings.Split(self.req.RemoteAddr, ":")[0]
	if ! checkHosts(remoteHost, user.Hosts) {
		return reqUser, fmt.Errorf("remote host %s is denied", self.req.RemoteAddr)
	}
	if user.Key != "" {
		nowTs := time.Now().Unix()
		maxDelta := self.config.Auth.MaxTimeDelta
		if nowTs - ts > int64(maxDelta) || ts - nowTs > int64(maxDelta) {
			return reqUser, fmt.Errorf("timestamp delta too large")
		}
		strToHash := reqUser + user.Key + strconv.FormatInt(ts, 10) + self.req.Method + self.req.RequestURI
		sha1Sum := sha1.Sum([]byte(strToHash))
		realHash := hex.EncodeToString(sha1Sum[:])
		if reqHash != realHash {
			return reqUser, fmt.Errorf("auth failed")
		}
	}
	return reqUser, nil
}

func parseAuthHeader(authStr string) (user, hash string, ts int64, err error){
	segs := strings.SplitN(authStr, " ", 3)
	user = segs[0]
	if len(segs) < 3 {
		hash = ""
		ts = 0
		err = fmt.Errorf("bad auth header")
		return
	}
	tsStr := segs[1]
	hash = segs[2]
	ts, err = strconv.ParseInt(tsStr, 10, 64)
	return
}

func checkPermission(group string, allows []string) bool {
	for _, allow := range(allows) {
		if group == allow {
			return true
		}
	}
	return false
}

func (self *Session) checkPermission() bool {
	if self.username == "" {
		return true
	}
	return checkPermission(self.group, self.UserConfig().Allows[self.resource])
}

func checkHosts(remoteAddr string, hosts []string) bool {
	if len(hosts) <= 0 {
		return true
	}
	ok := false
	for _, host := range (hosts) {
		_, allowedNet, err := net.ParseCIDR(host)
		if err != nil {
			continue
		}
		if allowedNet.Contains(net.ParseIP(remoteAddr)) {
			ok = true
			break
		}
	}
	if !ok {
		return false
	}
	return true
}
<|endoftext|>


<commit_before>// Copyright © 2016 Jip J. Dekker <jip@dekker.li>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package compiler

import (
	"os"
	"path/filepath"

	log "github.com/Sirupsen/logrus"
	"github.com/jjdekker/ponder/helpers"
	"github.com/jjdekker/ponder/settings"
)

// compilePath calls the given function on all files that aren't in any
// of the ignored directories
func compilePath(root string, opts *settings.Settings,
	f func(string, os.FileInfo) error) filepath.WalkFunc {
	return func(path string, info os.FileInfo, walkError error) error {
		// Handle walking error
		if walkError != nil {
			log.WithFields(log.Fields{
				"error": walkError,
				"path":  path,
			}).Warning("error occurred transversing project path")
			return nil
		}

		if info.IsDir() {
			// Skip directories that are ignored
			relPath, err := filepath.Rel(root, path)
			helpers.Check(err, "Unable to create relative Path")
			for _, dir := range append(append(opts.IgnoreDirs, opts.LilypondIncludes...), opts.OutputDir) {
				if relPath == dir || (filepath.IsAbs(dir) && path == dir) {
					log.WithFields(log.Fields{"path": path}).Info("Ignoring directory")
					return filepath.SkipDir
				}
			}
		} else {
			// Call function on non-directory
			err := f(path, info)
			if err != nil {
				log.WithFields(log.Fields{
					"error": err,
					"path":  path,
				}).Error("error occured processing files")
			}
		}
		return nil
	}
}
<commit_msg>Move ignore messages to the debug output<commit_after>// Copyright © 2016 Jip J. Dekker <jip@dekker.li>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package compiler

import (
	"os"
	"path/filepath"

	log "github.com/Sirupsen/logrus"
	"github.com/jjdekker/ponder/helpers"
	"github.com/jjdekker/ponder/settings"
)

// compilePath calls the given function on all files that aren't in any
// of the ignored directories
func compilePath(root string, opts *settings.Settings,
	f func(string, os.FileInfo) error) filepath.WalkFunc {
	return func(path string, info os.FileInfo, walkError error) error {
		// Handle walking error
		if walkError != nil {
			log.WithFields(log.Fields{
				"error": walkError,
				"path":  path,
			}).Warning("error occurred transversing project path")
			return nil
		}

		if info.IsDir() {
			// Skip directories that are ignored
			relPath, err := filepath.Rel(root, path)
			helpers.Check(err, "Unable to create relative Path")
			for _, dir := range append(append(opts.IgnoreDirs, opts.LilypondIncludes...), opts.OutputDir) {
				if relPath == dir || (filepath.IsAbs(dir) && path == dir) {
					log.WithFields(log.Fields{"path": path}).Debug("Ignoring directory")
					return filepath.SkipDir
				}
			}
		} else {
			// Call function on non-directory
			err := f(path, info)
			if err != nil {
				log.WithFields(log.Fields{
					"error": err,
					"path":  path,
				}).Error("error occured processing files")
			}
		}
		return nil
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package gcsfake

import (
	"bytes"
	"crypto/md5"
	"errors"
	"fmt"
	"hash/crc32"
	"io"
	"io/ioutil"
	"net/http"
	"sort"
	"strings"
	"time"
	"unicode/utf8"

	"github.com/jacobsa/gcloud/gcs"
	"github.com/jacobsa/gcloud/syncutil"
	"golang.org/x/net/context"
	"google.golang.org/cloud/storage"
)

var crc32Table = crc32.MakeTable(crc32.Castagnoli)

// Create an in-memory bucket with the given name and empty contents.
func NewFakeBucket(name string) gcs.Bucket {
	b := &bucket{name: name}
	b.mu = syncutil.NewInvariantMutex(func() { b.checkInvariants() })
	return b
}

type fakeObject struct {
	// A storage.Object representing a GCS entry for this object.
	entry storage.Object

	// The contents of the object. These never change.
	contents string
}

// A slice of objects compared by name.
type fakeObjectSlice []fakeObject

func (s fakeObjectSlice) Len() int {
	return len(s)
}

func (s fakeObjectSlice) Less(i, j int) bool {
	return s[i].entry.Name < s[j].entry.Name
}

func (s fakeObjectSlice) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}

// Return the smallest i such that s[i].entry.Name >= name, or len(s) if there
// is no such i.
func (s fakeObjectSlice) lowerBound(name string) int {
	pred := func(i int) bool {
		return s[i].entry.Name >= name
	}

	return sort.Search(len(s), pred)
}

// Return the smallest i such that s[i].entry.Name == name, or len(s) if there
// is no such i.
func (s fakeObjectSlice) find(name string) int {
	lb := s.lowerBound(name)
	if lb < len(s) && s[lb].entry.Name == name {
		return lb
	}

	return len(s)
}

// Return the smallest string that is lexicographically larger than prefix and
// does not have prefix as a prefix. For the sole case where this is not
// possible (all strings consisting solely of 0xff bytes, including the empty
// string), return the empty string.
func prefixSuccessor(prefix string) string {
	// Attempt to increment the last byte. If that is a 0xff byte, erase it and
	// recurse. If we hit an empty string, then we know our task is impossible.
	limit := []byte(prefix)
	for len(limit) > 0 {
		b := limit[len(limit)-1]
		if b != 0xff {
			limit[len(limit)-1]++
			break
		}

		limit = limit[:len(limit)-1]
	}

	return string(limit)
}

// Return the smallest i such that prefix < s[i].entry.Name and
// !strings.HasPrefix(s[i].entry.Name, prefix).
func (s fakeObjectSlice) prefixUpperBound(prefix string) int {
	successor := prefixSuccessor(prefix)
	if successor == "" {
		return len(s)
	}

	return s.lowerBound(successor)
}

type bucket struct {
	name string
	mu   syncutil.InvariantMutex

	// The set of extant objects.
	//
	// INVARIANT: Strictly increasing.
	objects fakeObjectSlice // GUARDED_BY(mu)

	// The most recent generation number that was minted. The next object will
	// receive generation prevGeneration + 1.
	//
	// INVARIANT: This is an upper bound for generation numbers in objects.
	prevGeneration int64 // GUARDED_BY(mu)
}

// SHARED_LOCKS_REQUIRED(b.mu)
func (b *bucket) checkInvariants() {
	// Make sure 'objects' is strictly increasing.
	for i := 1; i < len(b.objects); i++ {
		objA := b.objects[i-1]
		objB := b.objects[i]
		if !(objA.entry.Name < objB.entry.Name) {
			panic(
				fmt.Sprintf(
					"Object names are not strictly increasing: %v vs. %v",
					objA.entry.Name,
					objB.entry.Name))
		}
	}

	// Make sure prevGeneration is an upper bound for object generation numbers.
	for _, o := range b.objects {
		if !(o.entry.Generation <= b.prevGeneration) {
			panic(
				fmt.Sprintf(
					"Object generation %v exceeds %v",
					o.entry.Generation,
					b.prevGeneration))
		}
	}
}

func (b *bucket) Name() string {
	return b.name
}

// LOCKS_EXCLUDED(b.mu)
func (b *bucket) ListObjects(
	ctx context.Context,
	query *storage.Query) (listing *storage.Objects, err error) {
	b.mu.RLock()
	defer b.mu.RUnlock()

	// Set up the result object.
	listing = new(storage.Objects)

	// Handle nil queries.
	if query == nil {
		query = &storage.Query{}
	}

	// Handle defaults.
	maxResults := query.MaxResults
	if maxResults == 0 {
		maxResults = 1000
	}

	// Find where in the space of object names to start.
	nameStart := query.Prefix
	if query.Cursor != "" && query.Cursor > nameStart {
		nameStart = query.Cursor
	}

	// Find the range of indexes within the array to scan.
	indexStart := b.objects.lowerBound(nameStart)
	prefixLimit := b.objects.prefixUpperBound(query.Prefix)
	indexLimit := minInt(indexStart+maxResults, prefixLimit)

	// Scan the array.
	var lastResultWasPrefix bool
	for i := indexStart; i < indexLimit; i++ {
		var o fakeObject = b.objects[i]
		name := o.entry.Name

		// Search for a delimiter if necessary.
		if query.Delimiter != "" {
			// Search only in the part after the prefix.
			nameMinusQueryPrefix := name[len(query.Prefix):]

			delimiterIndex := strings.Index(nameMinusQueryPrefix, query.Delimiter)
			if delimiterIndex >= 0 {
				resultPrefixLimit := delimiterIndex

				// Transform to an index within name.
				resultPrefixLimit += len(query.Prefix)

				// Include the delimiter in the result.
				resultPrefixLimit += len(query.Delimiter)

				// Save the result, but only if it's not a duplicate.
				resultPrefix := name[:resultPrefixLimit]
				if len(listing.Prefixes) == 0 ||
					listing.Prefixes[len(listing.Prefixes)-1] != resultPrefix {
					listing.Prefixes = append(listing.Prefixes, resultPrefix)
				}

				lastResultWasPrefix = true
				continue
			}
		}

		lastResultWasPrefix = false

		// Otherwise, return as an object result. Make a copy to avoid handing back
		// internal state.
		var oCopy storage.Object = o.entry
		listing.Results = append(listing.Results, &oCopy)
	}

	// Set up a cursor for where to start the next scan if we didn't exhaust the
	// results.
	if indexLimit < prefixLimit {
		listing.Next = &storage.Query{}
		*listing.Next = *query

		// Ion is if the final object we visited was returned as an element in
		// listing.Prefixes, we want to skip all other objects that would result in
		// the same so we don't return duplicate elements in listing.Prefixes
		// accross requests.
		if lastResultWasPrefix {
			lastResultPrefix := listing.Prefixes[len(listing.Prefixes)-1]
			listing.Next.Cursor = prefixSuccessor(lastResultPrefix)

			// Check an assumption: prefixSuccessor cannot result in the empty string
			// above because object names must be non-empty UTF-8 strings, and there
			// is no valid non-empty UTF-8 string that consists of entirely 0xff
			// bytes.
			if listing.Next.Cursor == "" {
				err = errors.New("Unexpected empty string from prefixSuccessor")
				return
			}
		} else {
			// Otherwise, we'll start scanning at the next object.
			listing.Next.Cursor = b.objects[indexLimit].entry.Name
		}
	}

	return
}

// LOCKS_EXCLUDED(b.mu)
func (b *bucket) NewReader(
	ctx context.Context,
	objectName string) (io.ReadCloser, error) {
	b.mu.RLock()
	defer b.mu.RUnlock()

	index := b.objects.find(objectName)
	if index == len(b.objects) {
		return nil, errors.New("object doesn't exist.")
	}

	return ioutil.NopCloser(strings.NewReader(b.objects[index].contents)), nil
}

func (b *bucket) CreateObject(
	ctx context.Context,
	req *gcs.CreateObjectRequest) (o *storage.Object, err error) {
	// Check that the object name is legal.
	name := req.Attrs.Name
	if len(name) == 0 || len(name) > 1024 {
		return nil, errors.New("Invalid object name: length must be in [1, 1024]")
	}

	if !utf8.ValidString(name) {
		return nil, errors.New("Invalid object name: not valid UTF-8")
	}

	for _, r := range name {
		if r == 0x0a || r == 0x0d {
			return nil, errors.New("Invalid object name: must not contain CR or LF")
		}
	}

	// Snarf the object contents.
	buf := new(bytes.Buffer)
	if _, err = io.Copy(buf, req.Contents); err != nil {
		return
	}

	contents := buf.String()

	// Store the object and return a copy of the new entry.
	o = new(storage.Object)
	*o = b.addObject(&req.Attrs, contents)

	return
}

// LOCKS_EXCLUDED(b.mu)
func (b *bucket) UpdateObject(
	ctx context.Context,
	req *gcs.UpdateObjectRequest) (o *storage.Object, err error) {
	b.mu.Lock()
	defer b.mu.Unlock()

	// Match real GCS in not allowing the removal of ContentType.
	if req.ContentType != nil && *req.ContentType == "" {
		err = errors.New("The ContentType field is required and cannot be removed.")
		return
	}

	// Does the object exist?
	index := b.objects.find(req.Name)
	if index == len(b.objects) {
		err = errors.New("Object not found.")
		return
	}

	var obj *storage.Object = &b.objects[index].entry

	// Update the entry's basic fields according to the request.
	if req.ContentType != nil {
		obj.ContentType = *req.ContentType
	}

	if req.ContentEncoding != nil {
		obj.ContentEncoding = *req.ContentEncoding
	}

	if req.ContentLanguage != nil {
		obj.ContentLanguage = *req.ContentLanguage
	}

	if req.CacheControl != nil {
		obj.CacheControl = *req.CacheControl
	}

	// Update the user metadata if necessary.
	if len(req.Metadata) > 0 {
		if obj.Metadata == nil {
			obj.Metadata = make(map[string]string)
		}

		for k, v := range req.Metadata {
			if v == nil {
				delete(obj.Metadata, k)
				continue
			}

			obj.Metadata[k] = *v
		}
	}

	// Bump up the entry generation number.
	obj.MetaGeneration++

	// Make a copy to avoid handing back internal state.
	var objCopy storage.Object = *obj
	o = &objCopy

	return
}

// LOCKS_EXCLUDED(b.mu)
func (b *bucket) DeleteObject(
	ctx context.Context,
	name string) error {
	b.mu.Lock()
	defer b.mu.Unlock()

	// Do we possess the object with the given name?
	index := b.objects.find(name)
	if index == len(b.objects) {
		return errors.New("Object Not Found.")
	}

	// Remove the object.
	b.objects = append(b.objects[:index], b.objects[index+1:]...)

	return nil
}

// Create an object struct for the given attributes and contents.
//
// EXCLUSIVE_LOCKS_REQUIRED(b.mu)
func (b *bucket) mintObject(
	attrs *storage.ObjectAttrs,
	contents string) (o fakeObject) {
	// Set up basic info.
	b.prevGeneration++
	o.entry = storage.Object{
		Bucket:          b.Name(),
		Name:            attrs.Name,
		ContentType:     attrs.ContentType,
		ContentLanguage: attrs.ContentLanguage,
		CacheControl:    attrs.CacheControl,
		Owner:           "user-fake",
		Size:            int64(len(contents)),
		ContentEncoding: attrs.ContentEncoding,
		CRC32C:          crc32.Checksum([]byte(contents), crc32Table),
		MediaLink:       "http://localhost/download/storage/fake/" + attrs.Name,
		Metadata:        attrs.Metadata,
		Generation:      b.prevGeneration,
		MetaGeneration:  1,
		StorageClass:    "STANDARD",
		Updated:         time.Now(),
	}

	// Fill in the MD5 field.
	md5Array := md5.Sum([]byte(contents))
	o.entry.MD5 = md5Array[:]

	// Set up contents.
	o.contents = contents

	// Match the real GCS client library's behavior of sniffing content types
	// when not explicitly specified.
	if o.entry.ContentType == "" {
		o.entry.ContentType = http.DetectContentType([]byte(contents))
	}

	return
}

// Add a record for an object with the given attributes and contents, then
// return a copy of the minted entry.
//
// LOCKS_EXCLUDED(b.mu)
func (b *bucket) addObject(
	attrs *storage.ObjectAttrs,
	contents string) storage.Object {
	b.mu.Lock()
	defer b.mu.Unlock()

	// Create an object record from the given attributes.
	var o fakeObject = b.mintObject(attrs, contents)

	// Replace an entry in or add an entry to our list of objects.
	existingIndex := b.objects.find(attrs.Name)
	if existingIndex < len(b.objects) {
		b.objects[existingIndex] = o
	} else {
		b.objects = append(b.objects, o)
		sort.Sort(b.objects)
	}

	return o.entry
}

func minInt(a, b int) int {
	if a < b {
		return a
	}

	return b
}

func maxInt(a, b int) int {
	if a > b {
		return a
	}

	return b
}
<commit_msg>Refactored the addObject helper method.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package gcsfake

import (
	"bytes"
	"crypto/md5"
	"errors"
	"fmt"
	"hash/crc32"
	"io"
	"io/ioutil"
	"net/http"
	"sort"
	"strings"
	"time"
	"unicode/utf8"

	"github.com/jacobsa/gcloud/gcs"
	"github.com/jacobsa/gcloud/syncutil"
	"golang.org/x/net/context"
	"google.golang.org/cloud/storage"
)

var crc32Table = crc32.MakeTable(crc32.Castagnoli)

// Create an in-memory bucket with the given name and empty contents.
func NewFakeBucket(name string) gcs.Bucket {
	b := &bucket{name: name}
	b.mu = syncutil.NewInvariantMutex(func() { b.checkInvariants() })
	return b
}

type fakeObject struct {
	// A storage.Object representing a GCS entry for this object.
	entry storage.Object

	// The contents of the object. These never change.
	contents string
}

// A slice of objects compared by name.
type fakeObjectSlice []fakeObject

func (s fakeObjectSlice) Len() int {
	return len(s)
}

func (s fakeObjectSlice) Less(i, j int) bool {
	return s[i].entry.Name < s[j].entry.Name
}

func (s fakeObjectSlice) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}

// Return the smallest i such that s[i].entry.Name >= name, or len(s) if there
// is no such i.
func (s fakeObjectSlice) lowerBound(name string) int {
	pred := func(i int) bool {
		return s[i].entry.Name >= name
	}

	return sort.Search(len(s), pred)
}

// Return the smallest i such that s[i].entry.Name == name, or len(s) if there
// is no such i.
func (s fakeObjectSlice) find(name string) int {
	lb := s.lowerBound(name)
	if lb < len(s) && s[lb].entry.Name == name {
		return lb
	}

	return len(s)
}

// Return the smallest string that is lexicographically larger than prefix and
// does not have prefix as a prefix. For the sole case where this is not
// possible (all strings consisting solely of 0xff bytes, including the empty
// string), return the empty string.
func prefixSuccessor(prefix string) string {
	// Attempt to increment the last byte. If that is a 0xff byte, erase it and
	// recurse. If we hit an empty string, then we know our task is impossible.
	limit := []byte(prefix)
	for len(limit) > 0 {
		b := limit[len(limit)-1]
		if b != 0xff {
			limit[len(limit)-1]++
			break
		}

		limit = limit[:len(limit)-1]
	}

	return string(limit)
}

// Return the smallest i such that prefix < s[i].entry.Name and
// !strings.HasPrefix(s[i].entry.Name, prefix).
func (s fakeObjectSlice) prefixUpperBound(prefix string) int {
	successor := prefixSuccessor(prefix)
	if successor == "" {
		return len(s)
	}

	return s.lowerBound(successor)
}

type bucket struct {
	name string
	mu   syncutil.InvariantMutex

	// The set of extant objects.
	//
	// INVARIANT: Strictly increasing.
	objects fakeObjectSlice // GUARDED_BY(mu)

	// The most recent generation number that was minted. The next object will
	// receive generation prevGeneration + 1.
	//
	// INVARIANT: This is an upper bound for generation numbers in objects.
	prevGeneration int64 // GUARDED_BY(mu)
}

// SHARED_LOCKS_REQUIRED(b.mu)
func (b *bucket) checkInvariants() {
	// Make sure 'objects' is strictly increasing.
	for i := 1; i < len(b.objects); i++ {
		objA := b.objects[i-1]
		objB := b.objects[i]
		if !(objA.entry.Name < objB.entry.Name) {
			panic(
				fmt.Sprintf(
					"Object names are not strictly increasing: %v vs. %v",
					objA.entry.Name,
					objB.entry.Name))
		}
	}

	// Make sure prevGeneration is an upper bound for object generation numbers.
	for _, o := range b.objects {
		if !(o.entry.Generation <= b.prevGeneration) {
			panic(
				fmt.Sprintf(
					"Object generation %v exceeds %v",
					o.entry.Generation,
					b.prevGeneration))
		}
	}
}

func (b *bucket) Name() string {
	return b.name
}

// LOCKS_EXCLUDED(b.mu)
func (b *bucket) ListObjects(
	ctx context.Context,
	query *storage.Query) (listing *storage.Objects, err error) {
	b.mu.RLock()
	defer b.mu.RUnlock()

	// Set up the result object.
	listing = new(storage.Objects)

	// Handle nil queries.
	if query == nil {
		query = &storage.Query{}
	}

	// Handle defaults.
	maxResults := query.MaxResults
	if maxResults == 0 {
		maxResults = 1000
	}

	// Find where in the space of object names to start.
	nameStart := query.Prefix
	if query.Cursor != "" && query.Cursor > nameStart {
		nameStart = query.Cursor
	}

	// Find the range of indexes within the array to scan.
	indexStart := b.objects.lowerBound(nameStart)
	prefixLimit := b.objects.prefixUpperBound(query.Prefix)
	indexLimit := minInt(indexStart+maxResults, prefixLimit)

	// Scan the array.
	var lastResultWasPrefix bool
	for i := indexStart; i < indexLimit; i++ {
		var o fakeObject = b.objects[i]
		name := o.entry.Name

		// Search for a delimiter if necessary.
		if query.Delimiter != "" {
			// Search only in the part after the prefix.
			nameMinusQueryPrefix := name[len(query.Prefix):]

			delimiterIndex := strings.Index(nameMinusQueryPrefix, query.Delimiter)
			if delimiterIndex >= 0 {
				resultPrefixLimit := delimiterIndex

				// Transform to an index within name.
				resultPrefixLimit += len(query.Prefix)

				// Include the delimiter in the result.
				resultPrefixLimit += len(query.Delimiter)

				// Save the result, but only if it's not a duplicate.
				resultPrefix := name[:resultPrefixLimit]
				if len(listing.Prefixes) == 0 ||
					listing.Prefixes[len(listing.Prefixes)-1] != resultPrefix {
					listing.Prefixes = append(listing.Prefixes, resultPrefix)
				}

				lastResultWasPrefix = true
				continue
			}
		}

		lastResultWasPrefix = false

		// Otherwise, return as an object result. Make a copy to avoid handing back
		// internal state.
		var oCopy storage.Object = o.entry
		listing.Results = append(listing.Results, &oCopy)
	}

	// Set up a cursor for where to start the next scan if we didn't exhaust the
	// results.
	if indexLimit < prefixLimit {
		listing.Next = &storage.Query{}
		*listing.Next = *query

		// Ion is if the final object we visited was returned as an element in
		// listing.Prefixes, we want to skip all other objects that would result in
		// the same so we don't return duplicate elements in listing.Prefixes
		// accross requests.
		if lastResultWasPrefix {
			lastResultPrefix := listing.Prefixes[len(listing.Prefixes)-1]
			listing.Next.Cursor = prefixSuccessor(lastResultPrefix)

			// Check an assumption: prefixSuccessor cannot result in the empty string
			// above because object names must be non-empty UTF-8 strings, and there
			// is no valid non-empty UTF-8 string that consists of entirely 0xff
			// bytes.
			if listing.Next.Cursor == "" {
				err = errors.New("Unexpected empty string from prefixSuccessor")
				return
			}
		} else {
			// Otherwise, we'll start scanning at the next object.
			listing.Next.Cursor = b.objects[indexLimit].entry.Name
		}
	}

	return
}

// LOCKS_EXCLUDED(b.mu)
func (b *bucket) NewReader(
	ctx context.Context,
	objectName string) (io.ReadCloser, error) {
	b.mu.RLock()
	defer b.mu.RUnlock()

	index := b.objects.find(objectName)
	if index == len(b.objects) {
		return nil, errors.New("object doesn't exist.")
	}

	return ioutil.NopCloser(strings.NewReader(b.objects[index].contents)), nil
}

func (b *bucket) CreateObject(
	ctx context.Context,
	req *gcs.CreateObjectRequest) (o *storage.Object, err error) {
	// Check that the object name is legal.
	name := req.Attrs.Name
	if len(name) == 0 || len(name) > 1024 {
		return nil, errors.New("Invalid object name: length must be in [1, 1024]")
	}

	if !utf8.ValidString(name) {
		return nil, errors.New("Invalid object name: not valid UTF-8")
	}

	for _, r := range name {
		if r == 0x0a || r == 0x0d {
			return nil, errors.New("Invalid object name: must not contain CR or LF")
		}
	}

	// Snarf the object contents.
	buf := new(bytes.Buffer)
	if _, err = io.Copy(buf, req.Contents); err != nil {
		return
	}

	contents := buf.String()

	// Lock and proceed.
	b.mu.Lock()
	defer b.mu.Unlock()

	obj, err := b.addObjectLocked(req, contents)
	if err != nil {
		return
	}

	o = &obj
	return
}

// LOCKS_EXCLUDED(b.mu)
func (b *bucket) UpdateObject(
	ctx context.Context,
	req *gcs.UpdateObjectRequest) (o *storage.Object, err error) {
	b.mu.Lock()
	defer b.mu.Unlock()

	// Match real GCS in not allowing the removal of ContentType.
	if req.ContentType != nil && *req.ContentType == "" {
		err = errors.New("The ContentType field is required and cannot be removed.")
		return
	}

	// Does the object exist?
	index := b.objects.find(req.Name)
	if index == len(b.objects) {
		err = errors.New("Object not found.")
		return
	}

	var obj *storage.Object = &b.objects[index].entry

	// Update the entry's basic fields according to the request.
	if req.ContentType != nil {
		obj.ContentType = *req.ContentType
	}

	if req.ContentEncoding != nil {
		obj.ContentEncoding = *req.ContentEncoding
	}

	if req.ContentLanguage != nil {
		obj.ContentLanguage = *req.ContentLanguage
	}

	if req.CacheControl != nil {
		obj.CacheControl = *req.CacheControl
	}

	// Update the user metadata if necessary.
	if len(req.Metadata) > 0 {
		if obj.Metadata == nil {
			obj.Metadata = make(map[string]string)
		}

		for k, v := range req.Metadata {
			if v == nil {
				delete(obj.Metadata, k)
				continue
			}

			obj.Metadata[k] = *v
		}
	}

	// Bump up the entry generation number.
	obj.MetaGeneration++

	// Make a copy to avoid handing back internal state.
	var objCopy storage.Object = *obj
	o = &objCopy

	return
}

// LOCKS_EXCLUDED(b.mu)
func (b *bucket) DeleteObject(
	ctx context.Context,
	name string) error {
	b.mu.Lock()
	defer b.mu.Unlock()

	// Do we possess the object with the given name?
	index := b.objects.find(name)
	if index == len(b.objects) {
		return errors.New("Object Not Found.")
	}

	// Remove the object.
	b.objects = append(b.objects[:index], b.objects[index+1:]...)

	return nil
}

// Create an object struct for the given attributes and contents.
//
// EXCLUSIVE_LOCKS_REQUIRED(b.mu)
func (b *bucket) mintObject(
	attrs *storage.ObjectAttrs,
	contents string) (o fakeObject) {
	// Set up basic info.
	b.prevGeneration++
	o.entry = storage.Object{
		Bucket:          b.Name(),
		Name:            attrs.Name,
		ContentType:     attrs.ContentType,
		ContentLanguage: attrs.ContentLanguage,
		CacheControl:    attrs.CacheControl,
		Owner:           "user-fake",
		Size:            int64(len(contents)),
		ContentEncoding: attrs.ContentEncoding,
		CRC32C:          crc32.Checksum([]byte(contents), crc32Table),
		MediaLink:       "http://localhost/download/storage/fake/" + attrs.Name,
		Metadata:        attrs.Metadata,
		Generation:      b.prevGeneration,
		MetaGeneration:  1,
		StorageClass:    "STANDARD",
		Updated:         time.Now(),
	}

	// Fill in the MD5 field.
	md5Array := md5.Sum([]byte(contents))
	o.entry.MD5 = md5Array[:]

	// Set up contents.
	o.contents = contents

	// Match the real GCS client library's behavior of sniffing content types
	// when not explicitly specified.
	if o.entry.ContentType == "" {
		o.entry.ContentType = http.DetectContentType([]byte(contents))
	}

	return
}

// Add a record and return a copy of the minted entry.
//
// EXCLUSIVE_LOCKS_REQUIRED(b.mu)
func (b *bucket) addObjectLocked(
	req *gcs.CreateObjectRequest,
	contents string) (entry storage.Object, err error) {
	// Create an object record from the given attributes.
	var o fakeObject = b.mintObject(&req.Attrs, contents)

	// Replace an entry in or add an entry to our list of objects.
	existingIndex := b.objects.find(req.Attrs.Name)
	if existingIndex < len(b.objects) {
		b.objects[existingIndex] = o
	} else {
		b.objects = append(b.objects, o)
		sort.Sort(b.objects)
	}

	entry = o.entry
	return
}

func minInt(a, b int) int {
	if a < b {
		return a
	}

	return b
}

func maxInt(a, b int) int {
	if a > b {
		return a
	}

	return b
}
<|endoftext|>


<commit_before>package jira

import (
	"fmt"
	"net/http"
)

// AuthenticationService handles authentication for the JIRA instance / API.
//
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#authentication
type AuthenticationService struct {
	client *Client
}

// Session represents a Session JSON response by the JIRA API.
type Session struct {
	Self    string `json:"self,omitempty"`
	Name    string `json:"name,omitempty"`
	Session struct {
		Name  string `json:"name"`
		Value string `json:"value"`
	} `json:"session,omitempty"`
	LoginInfo struct {
		FailedLoginCount    int    `json:"failedLoginCount"`
		LoginCount          int    `json:"loginCount"`
		LastFailedLoginTime string `json:"lastFailedLoginTime"`
		PreviousLoginTime   string `json:"previousLoginTime"`
	} `json:"loginInfo"`
	SetCoockie []*http.Cookie
}

// AcquireSessionCookie creates a new session for a user in JIRA.
// Once a session has been successfully created it can be used to access any of JIRA's remote APIs and also the web UI by passing the appropriate HTTP Cookie header.
// The header will by automatically applied to every API request.
// Note that it is generally preferrable to use HTTP BASIC authentication with the REST API.
// However, this resource may be used to mimic the behaviour of JIRA's log-in page (e.g. to display log-in errors to a user).
//
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#auth/1/session
func (s *AuthenticationService) AcquireSessionCookie(username, password string) (bool, error) {
	apiEndpoint := "rest/auth/1/session"
	body := struct {
		Username string `json:"username"`
		Password string `json:"password"`
	}{
		username,
		password,
	}

	req, err := s.client.NewRequest("POST", apiEndpoint, body)
	if err != nil {
		return false, err
	}

	session := new(Session)
	resp, err := s.client.Do(req, session)

	cookies := resp.Cookies()
	session.SetCoockie = cookies

	if err != nil {
		return false, fmt.Errorf("Auth at JIRA instance failed (HTTP(S) request). %s", err)
	}
	if resp != nil && resp.StatusCode != 200 {
		return false, fmt.Errorf("Auth at JIRA instance failed (HTTP(S) request). Status code: %d", resp.StatusCode)
	}

	s.client.session = session

	return true, nil
}

// TODO Missing API Call GET (Returns information about the currently authenticated user's session)
// See https://docs.atlassian.com/jira/REST/latest/#auth/1/session
// TODO Missing API Call DELETE (Logs the current user out of JIRA, destroying the existing session, if any.)
// See https://docs.atlassian.com/jira/REST/latest/#auth/1/session
<commit_msg>get Authenticated reports  session from main repository<commit_after>package jira

import (
	"fmt"
	"net/http"
)

// AuthenticationService handles authentication for the JIRA instance / API.
//
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#authentication
type AuthenticationService struct {
	client *Client
}

// Session represents a Session JSON response by the JIRA API.
type Session struct {
	Self    string `json:"self,omitempty"`
	Name    string `json:"name,omitempty"`
	Session struct {
		Name  string `json:"name"`
		Value string `json:"value"`
	} `json:"session,omitempty"`
	LoginInfo struct {
		FailedLoginCount    int    `json:"failedLoginCount"`
		LoginCount          int    `json:"loginCount"`
		LastFailedLoginTime string `json:"lastFailedLoginTime"`
		PreviousLoginTime   string `json:"previousLoginTime"`
	} `json:"loginInfo"`
	SetCoockie []*http.Cookie
}

// AcquireSessionCookie creates a new session for a user in JIRA.
// Once a session has been successfully created it can be used to access any of JIRA's remote APIs and also the web UI by passing the appropriate HTTP Cookie header.
// The header will by automatically applied to every API request.
// Note that it is generally preferrable to use HTTP BASIC authentication with the REST API.
// However, this resource may be used to mimic the behaviour of JIRA's log-in page (e.g. to display log-in errors to a user).
//
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#auth/1/session
func (s *AuthenticationService) AcquireSessionCookie(username, password string) (bool, error) {
	apiEndpoint := "rest/auth/1/session"
	body := struct {
		Username string `json:"username"`
		Password string `json:"password"`
	}{
		username,
		password,
	}

	req, err := s.client.NewRequest("POST", apiEndpoint, body)
	if err != nil {
		return false, err
	}

	session := new(Session)
	resp, err := s.client.Do(req, session)

	cookies := resp.Cookies()
	session.SetCoockie = cookies

	if err != nil {
		return false, fmt.Errorf("Auth at JIRA instance failed (HTTP(S) request). %s", err)
	}
	if resp != nil && resp.StatusCode != 200 {
		return false, fmt.Errorf("Auth at JIRA instance failed (HTTP(S) request). Status code: %d", resp.StatusCode)
	}

	s.client.session = session

	return true, nil
}

// Authenticated reports if the current Client has an authenticated session with JIRA
func (s *AuthenticationService) Authenticated() bool {
	if s != nil {
		return s.client.session != nil
	}
	return false
}

// TODO Missing API Call GET (Returns information about the currently authenticated user's session)
// See https://docs.atlassian.com/jira/REST/latest/#auth/1/session
// TODO Missing API Call DELETE (Logs the current user out of JIRA, destroying the existing session, if any.)
// See https://docs.atlassian.com/jira/REST/latest/#auth/1/session
<|endoftext|>


<commit_before>// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Native Client audio/video

// Package av implements audio and video access for Native Client
// binaries running standalone or embedded in a web browser window.
package av

import (
	"bytes";
	"draw";
	"log";
	"nacl/srpc";
	"os";
	"syscall";
	"unsafe";
)

var srpcEnabled = srpc.Enabled();

// native_client/src/trusted/service_runtime/include/sys/audio_video.h

// Subsystem values for Init.
const (
	SubsystemVideo = 1<<iota;
	SubsystemAudio;
	SubsystemEmbed;
)
//	SubsystemRawEvents;

// Audio formats.
const (
	AudioFormatStereo44K = iota;
	AudioFormatStereo48K;
)

// A Window represents a connection to the Native Client window.
// It implements draw.Context.
type Window struct {
	Embedded bool;	// running as part of a web page?
	*Image;		// screen image

	mousec chan draw.Mouse;
	kbdc chan int;
	quitc chan bool;
	resizec chan bool;
}

// *Window implements draw.Context
var _ draw.Context = (*Window)(nil)

func (w *Window) KeyboardChan() <-chan int {
	return w.kbdc;
}

func (w *Window) MouseChan() <-chan draw.Mouse {
	return w.mousec;
}

func (w *Window) QuitChan() <-chan bool {
	return w.quitc;
}

func (w *Window) ResizeChan() <-chan bool {
	return w.resizec;
}

func (w *Window) Screen() draw.Image {
	return w.Image;
}

// Init initializes the Native Client subsystems specified by subsys.
// Init must be called before using any of the other functions
// in this package, and it must be called only once.
//
// If the SubsystemVideo flag is set, Init requests a window of size dx×dy.
// When embedded in a web page, the web page's window specification
// overrides the parameters to Init, so the returned Window may have
// a different size than requested.
//
// If the SubsystemAudio flag is set, Init requests a connection to the
// audio device carrying 44 kHz 16-bit stereo PCM audio samples.
func Init(subsys int, dx, dy int) (*Window, os.Error) {
	xsubsys := subsys;
	if srpcEnabled {
		waitBridge();
		xsubsys &^= SubsystemVideo|SubsystemEmbed;
	}

	if xsubsys & SubsystemEmbed != 0 {
		return nil, os.NewError("not embedded");
	}

	w := new(Window);
	err := multimediaInit(xsubsys);
	if err != nil {
		return nil, err;
	}

	if subsys&SubsystemVideo != 0 {
		if dx, dy, err = videoInit(dx, dy); err != nil {
			return nil, err;
		}
		w.Image = newImage(dx, dy, bridge.pixel);
		w.resizec = make(chan bool, 64);
		w.kbdc = make(chan int, 64);
		w.mousec = make(chan draw.Mouse, 64);
		w.quitc = make(chan bool);
	}

	if subsys&SubsystemAudio != 0 {
		var n int;
		if n, err = audioInit(AudioFormatStereo44K, 2048); err != nil {
			return nil, err;
		}
		println("audio", n);
	}

	if subsys&SubsystemVideo != 0 {
		go w.readEvents();
	}

	return w, nil;
}

func (w *Window) FlushImage() {
	if w.Image == nil {
		return;
	}
	videoUpdate(w.Image.Linear);
}

func multimediaInit(subsys int) (err os.Error) {
	return os.NewSyscallError("multimedia_init", syscall.MultimediaInit(subsys));
}

func videoInit(dx, dy int) (ndx, ndy int, err os.Error) {
	if srpcEnabled {
		bridge.share.ready = 1;
		return int(bridge.share.width), int(bridge.share.height), nil;
	}
	if e := syscall.VideoInit(dx, dy); e != 0 {
		return 0, 0, os.NewSyscallError("video_init", int(e));
	}
	return dx, dy, nil;
}

func videoUpdate(data []Color) (err os.Error) {
	if srpcEnabled {
		bridge.flushRPC.Call("upcall", nil);
		return;
	}
	return os.NewSyscallError("video_update", syscall.VideoUpdate((*uint32)(&data[0])));
}

var noEvents = os.NewError("no events");

func videoPollEvent(ev []byte) (err os.Error) {
	if srpcEnabled {
		r := bridge.share.eq.ri;
		if r == bridge.share.eq.wi {
			return noEvents;
		}
		bytes.Copy(ev, &bridge.share.eq.event[r]);
		bridge.share.eq.ri = (r+1) % eqsize;
		return nil;
	}
	return os.NewSyscallError("video_poll_event", syscall.VideoPollEvent(&ev[0]));
}

func audioInit(fmt int, want int) (got int, err os.Error) {
	var x int;
	e := syscall.AudioInit(fmt, want, &x);
	if e == 0 {
		return x, nil;
	}
	return 0, os.NewSyscallError("audio_init", e);
}

var audioSize uintptr

// AudioStream provides access to the audio device.
// Each call to AudioStream writes the given data,
// which should be a slice of 16-bit stereo PCM audio samples,
// and returns the number of samples required by the next
// call to AudioStream.
//
// To find out the initial number of samples to write, call AudioStream(nil).
//
func AudioStream(data []uint16) (nextSize int, err os.Error) {
	if audioSize == 0 {
		e := os.NewSyscallError("audio_stream", syscall.AudioStream(nil, &audioSize));
		return int(audioSize), e;
	}
	if data == nil {
		return int(audioSize), nil;
	}
	if uintptr(len(data))*2 != audioSize {
		log.Stdoutf("invalid audio size want %d got %d", audioSize, len(data));
	}
	e := os.NewSyscallError("audio_stream", syscall.AudioStream(&data[0], &audioSize));
	return int(audioSize), e;
}

// Synchronization structure to wait for bridge to become ready.
var bridge struct {
	c chan bool;
	displayFd int;
	rpcFd int;
	share *videoShare;
	pixel []Color;
	client *srpc.Client;
	flushRPC *srpc.RPC;
}

// Wait for bridge to become ready.
// When chan is first created, there is nothing in it,
// so this blocks.  Once the bridge is ready, multimediaBridge.Run
// will drop a value into the channel.  Then any calls
// to waitBridge will finish, taking the value out and immediately putting it back.
func waitBridge() {
	bridge.c <- <-bridge.c;
}

const eqsize = 64;

// Data structure shared with host via mmap.
type videoShare struct {
	revision int32;	// definition below is rev 100 unless noted
	mapSize int32;

	// event queue
	eq struct {
		ri uint32;	// read index [0,eqsize)
		wi uint32;	// write index [0,eqsize)
		eof int32;
		event [eqsize][64]byte;
	};

	// now unused
	_, _, _, _ int32;

	// video backing store information
	width, height, _, size int32;
	ready int32;	// rev 0x101
}

// The frame buffer data is videoShareSize bytes after
// the videoShare begins.
const videoShareSize = 16*1024

type multimediaBridge struct{}

// If using SRPC, the runtime will call this method to pass in two file descriptors,
// one to mmap to get the display memory, and another to use for SRPCs back
// to the main process.
func (multimediaBridge) Run(arg, ret []interface{}, size []int) srpc.Errno {
	bridge.displayFd = arg[0].(int);
	bridge.rpcFd = arg[1].(int);

	var st syscall.Stat_t;
	if errno := syscall.Fstat(bridge.displayFd, &st); errno != 0 {
		log.Exitf("mmbridge stat display: %s", os.Errno(errno));
	}

	addr, _, errno := syscall.Syscall6(syscall.SYS_MMAP,
		0,
		uintptr(st.Size),
		syscall.PROT_READ|syscall.PROT_WRITE,
		syscall.MAP_SHARED,
		uintptr(bridge.displayFd),
		0);
	if errno != 0 {
		log.Exitf("mmap display: %s", os.Errno(errno));
	}

	bridge.share = (*videoShare)(unsafe.Pointer(addr));

	// Overestimate frame buffer size
	// (must use a compile-time constant)
	// and then reslice.  256 megapixels (1 GB) should be enough.
	fb := (*[256*1024*1024]Color)(unsafe.Pointer(addr+videoShareSize));
	bridge.pixel = fb[0:(st.Size - videoShareSize)/4];

	// Configure RPC connection back to client.
	var err os.Error;
	bridge.client, err = srpc.NewClient(bridge.rpcFd);
	if err != nil {
		log.Exitf("NewClient: %s", err);
	}
	bridge.flushRPC = bridge.client.NewRPC(nil);

	// Notify waiters that the bridge is ready.
	println("bridged", bridge.share.revision);
	bridge.c <- true;

	return srpc.OK;
}

func init() {
	bridge.c = make(chan bool, 1);
	if srpcEnabled {
		srpc.Add("nacl_multimedia_bridge", "hh:", multimediaBridge{});
	}
}

<commit_msg>add comment about C API. somehow managed not to Put this before.<commit_after>// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Native Client audio/video

// Package av implements audio and video access for Native Client
// binaries running standalone or embedded in a web browser window.
//
// The C version of the API is documented at
// http://nativeclient.googlecode.com/svn/data/docs_tarball/nacl/googleclient/native_client/scons-out/doc/html/group__audio__video.html
package av

import (
	"bytes";
	"draw";
	"log";
	"nacl/srpc";
	"os";
	"syscall";
	"unsafe";
)

var srpcEnabled = srpc.Enabled();

// native_client/src/trusted/service_runtime/include/sys/audio_video.h

// Subsystem values for Init.
const (
	SubsystemVideo = 1<<iota;
	SubsystemAudio;
	SubsystemEmbed;
)
//	SubsystemRawEvents;

// Audio formats.
const (
	AudioFormatStereo44K = iota;
	AudioFormatStereo48K;
)

// A Window represents a connection to the Native Client window.
// It implements draw.Context.
type Window struct {
	Embedded bool;	// running as part of a web page?
	*Image;		// screen image

	mousec chan draw.Mouse;
	kbdc chan int;
	quitc chan bool;
	resizec chan bool;
}

// *Window implements draw.Context
var _ draw.Context = (*Window)(nil)

func (w *Window) KeyboardChan() <-chan int {
	return w.kbdc;
}

func (w *Window) MouseChan() <-chan draw.Mouse {
	return w.mousec;
}

func (w *Window) QuitChan() <-chan bool {
	return w.quitc;
}

func (w *Window) ResizeChan() <-chan bool {
	return w.resizec;
}

func (w *Window) Screen() draw.Image {
	return w.Image;
}

// Init initializes the Native Client subsystems specified by subsys.
// Init must be called before using any of the other functions
// in this package, and it must be called only once.
//
// If the SubsystemVideo flag is set, Init requests a window of size dx×dy.
// When embedded in a web page, the web page's window specification
// overrides the parameters to Init, so the returned Window may have
// a different size than requested.
//
// If the SubsystemAudio flag is set, Init requests a connection to the
// audio device carrying 44 kHz 16-bit stereo PCM audio samples.
func Init(subsys int, dx, dy int) (*Window, os.Error) {
	xsubsys := subsys;
	if srpcEnabled {
		waitBridge();
		xsubsys &^= SubsystemVideo|SubsystemEmbed;
	}

	if xsubsys & SubsystemEmbed != 0 {
		return nil, os.NewError("not embedded");
	}

	w := new(Window);
	err := multimediaInit(xsubsys);
	if err != nil {
		return nil, err;
	}

	if subsys&SubsystemVideo != 0 {
		if dx, dy, err = videoInit(dx, dy); err != nil {
			return nil, err;
		}
		w.Image = newImage(dx, dy, bridge.pixel);
		w.resizec = make(chan bool, 64);
		w.kbdc = make(chan int, 64);
		w.mousec = make(chan draw.Mouse, 64);
		w.quitc = make(chan bool);
	}

	if subsys&SubsystemAudio != 0 {
		var n int;
		if n, err = audioInit(AudioFormatStereo44K, 2048); err != nil {
			return nil, err;
		}
		println("audio", n);
	}

	if subsys&SubsystemVideo != 0 {
		go w.readEvents();
	}

	return w, nil;
}

func (w *Window) FlushImage() {
	if w.Image == nil {
		return;
	}
	videoUpdate(w.Image.Linear);
}

func multimediaInit(subsys int) (err os.Error) {
	return os.NewSyscallError("multimedia_init", syscall.MultimediaInit(subsys));
}

func videoInit(dx, dy int) (ndx, ndy int, err os.Error) {
	if srpcEnabled {
		bridge.share.ready = 1;
		return int(bridge.share.width), int(bridge.share.height), nil;
	}
	if e := syscall.VideoInit(dx, dy); e != 0 {
		return 0, 0, os.NewSyscallError("video_init", int(e));
	}
	return dx, dy, nil;
}

func videoUpdate(data []Color) (err os.Error) {
	if srpcEnabled {
		bridge.flushRPC.Call("upcall", nil);
		return;
	}
	return os.NewSyscallError("video_update", syscall.VideoUpdate((*uint32)(&data[0])));
}

var noEvents = os.NewError("no events");

func videoPollEvent(ev []byte) (err os.Error) {
	if srpcEnabled {
		r := bridge.share.eq.ri;
		if r == bridge.share.eq.wi {
			return noEvents;
		}
		bytes.Copy(ev, &bridge.share.eq.event[r]);
		bridge.share.eq.ri = (r+1) % eqsize;
		return nil;
	}
	return os.NewSyscallError("video_poll_event", syscall.VideoPollEvent(&ev[0]));
}

func audioInit(fmt int, want int) (got int, err os.Error) {
	var x int;
	e := syscall.AudioInit(fmt, want, &x);
	if e == 0 {
		return x, nil;
	}
	return 0, os.NewSyscallError("audio_init", e);
}

var audioSize uintptr

// AudioStream provides access to the audio device.
// Each call to AudioStream writes the given data,
// which should be a slice of 16-bit stereo PCM audio samples,
// and returns the number of samples required by the next
// call to AudioStream.
//
// To find out the initial number of samples to write, call AudioStream(nil).
//
func AudioStream(data []uint16) (nextSize int, err os.Error) {
	if audioSize == 0 {
		e := os.NewSyscallError("audio_stream", syscall.AudioStream(nil, &audioSize));
		return int(audioSize), e;
	}
	if data == nil {
		return int(audioSize), nil;
	}
	if uintptr(len(data))*2 != audioSize {
		log.Stdoutf("invalid audio size want %d got %d", audioSize, len(data));
	}
	e := os.NewSyscallError("audio_stream", syscall.AudioStream(&data[0], &audioSize));
	return int(audioSize), e;
}

// Synchronization structure to wait for bridge to become ready.
var bridge struct {
	c chan bool;
	displayFd int;
	rpcFd int;
	share *videoShare;
	pixel []Color;
	client *srpc.Client;
	flushRPC *srpc.RPC;
}

// Wait for bridge to become ready.
// When chan is first created, there is nothing in it,
// so this blocks.  Once the bridge is ready, multimediaBridge.Run
// will drop a value into the channel.  Then any calls
// to waitBridge will finish, taking the value out and immediately putting it back.
func waitBridge() {
	bridge.c <- <-bridge.c;
}

const eqsize = 64;

// Data structure shared with host via mmap.
type videoShare struct {
	revision int32;	// definition below is rev 100 unless noted
	mapSize int32;

	// event queue
	eq struct {
		ri uint32;	// read index [0,eqsize)
		wi uint32;	// write index [0,eqsize)
		eof int32;
		event [eqsize][64]byte;
	};

	// now unused
	_, _, _, _ int32;

	// video backing store information
	width, height, _, size int32;
	ready int32;	// rev 0x101
}

// The frame buffer data is videoShareSize bytes after
// the videoShare begins.
const videoShareSize = 16*1024

type multimediaBridge struct{}

// If using SRPC, the runtime will call this method to pass in two file descriptors,
// one to mmap to get the display memory, and another to use for SRPCs back
// to the main process.
func (multimediaBridge) Run(arg, ret []interface{}, size []int) srpc.Errno {
	bridge.displayFd = arg[0].(int);
	bridge.rpcFd = arg[1].(int);

	var st syscall.Stat_t;
	if errno := syscall.Fstat(bridge.displayFd, &st); errno != 0 {
		log.Exitf("mmbridge stat display: %s", os.Errno(errno));
	}

	addr, _, errno := syscall.Syscall6(syscall.SYS_MMAP,
		0,
		uintptr(st.Size),
		syscall.PROT_READ|syscall.PROT_WRITE,
		syscall.MAP_SHARED,
		uintptr(bridge.displayFd),
		0);
	if errno != 0 {
		log.Exitf("mmap display: %s", os.Errno(errno));
	}

	bridge.share = (*videoShare)(unsafe.Pointer(addr));

	// Overestimate frame buffer size
	// (must use a compile-time constant)
	// and then reslice.  256 megapixels (1 GB) should be enough.
	fb := (*[256*1024*1024]Color)(unsafe.Pointer(addr+videoShareSize));
	bridge.pixel = fb[0:(st.Size - videoShareSize)/4];

	// Configure RPC connection back to client.
	var err os.Error;
	bridge.client, err = srpc.NewClient(bridge.rpcFd);
	if err != nil {
		log.Exitf("NewClient: %s", err);
	}
	bridge.flushRPC = bridge.client.NewRPC(nil);

	// Notify waiters that the bridge is ready.
	println("bridged", bridge.share.revision);
	bridge.c <- true;

	return srpc.OK;
}

func init() {
	bridge.c = make(chan bool, 1);
	if srpcEnabled {
		srpc.Add("nacl_multimedia_bridge", "hh:", multimediaBridge{});
	}
}

<|endoftext|>


<commit_before>// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package run

import (
	"flag"
	"fmt"
	"io"
	"os"

	"github.com/kardianos/govendor/help"

	"github.com/Bowery/prompt"
	"github.com/google/shlex"
)

func (r *runner) Shell(w io.Writer, subCmdArgs []string) (help.HelpMessage, error) {
	flags := flag.NewFlagSet("shell", flag.ContinueOnError)
	flags.SetOutput(nullWriter{})
	err := flags.Parse(subCmdArgs)
	if err != nil {
		return help.MsgShell, err
	}

	//	term, err := prompt.NewTerminal()
	//	if err != nil {
	//		return help.MsgNone, err
	//	}
	//	defer term.Close()
	out := os.Stdout

	for {
		line, err := prompt.Basic("> ", false)
		if err != nil {
			break
		}
		args, err := shlex.Split(line)
		if err != nil {
			fmt.Fprintf(out, "%v", err.Error())
		}
		if len(args) == 0 {
			continue
		}
		cmd := args[0]
		next := make([]string, 0, len(args)+1)
		next = append(next, "govendor")
		args = append(next, args...)
		switch cmd {
		case "exit", "q", "quit", "/q":
			return help.MsgNone, nil
		case "shell":
			continue
		}
		msg, err := r.run(out, args, nil)
		if err != nil {
			fmt.Fprintf(out, "%v", err.Error())
		}
		msgText := msg.String()
		if len(msgText) > 0 {
			fmt.Fprintf(out, "%s\tType \"exit\" to exit.\n", msgText)
		}
	}

	return help.MsgNone, nil
}
<commit_msg>run: remove unused comment<commit_after>// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package run

import (
	"flag"
	"fmt"
	"io"
	"os"

	"github.com/kardianos/govendor/help"

	"github.com/Bowery/prompt"
	"github.com/google/shlex"
)

func (r *runner) Shell(w io.Writer, subCmdArgs []string) (help.HelpMessage, error) {
	flags := flag.NewFlagSet("shell", flag.ContinueOnError)
	flags.SetOutput(nullWriter{})
	err := flags.Parse(subCmdArgs)
	if err != nil {
		return help.MsgShell, err
	}

	out := os.Stdout

	for {
		line, err := prompt.Basic("> ", false)
		if err != nil {
			break
		}
		args, err := shlex.Split(line)
		if err != nil {
			fmt.Fprintf(out, "%v", err.Error())
		}
		if len(args) == 0 {
			continue
		}
		cmd := args[0]
		next := make([]string, 0, len(args)+1)
		next = append(next, "govendor")
		args = append(next, args...)
		switch cmd {
		case "exit", "q", "quit", "/q":
			return help.MsgNone, nil
		case "shell":
			continue
		}
		msg, err := r.run(out, args, nil)
		if err != nil {
			fmt.Fprintf(out, "%v", err.Error())
		}
		msgText := msg.String()
		if len(msgText) > 0 {
			fmt.Fprintf(out, "%s\tType \"exit\" to exit.\n", msgText)
		}
	}

	return help.MsgNone, nil
}
<|endoftext|>