<commit_before>package jsval

import (
	"errors"
	"math"
	"reflect"

	"github.com/lestrrat/go-pdebug"
)

// Enum specifies the values that this constraint can have
func (nc *NumberConstraint) Enum(l ...interface{}) *NumberConstraint {
	if nc.enums == nil {
		nc.enums = Enum()
	}
	nc.enums.Enum(l...)
	return nc
}

// Default specifies the default value for the given value
func (nc *NumberConstraint) Default(v interface{}) *NumberConstraint {
	nc.defaultValue.initialized = true
	nc.defaultValue.value = v
	return nc
}

// Maximum sepcifies the maximum value that the constraint can allow
func (nc *NumberConstraint) Maximum(n float64) *NumberConstraint {
	nc.applyMaximum = true
	nc.maximum = n
	return nc
}

// Minimum sepcifies the minimum value that the constraint can allow
func (nc *NumberConstraint) Minimum(n float64) *NumberConstraint {
	nc.applyMinimum = true
	nc.minimum = n
	return nc
}

// MultipleOf specifies the number that the given value must be
// divisible by. That is, the constraint will return an error unless
// the given value satisfies `math.Mod(v, n) == 0`
func (nc *NumberConstraint) MultipleOf(n float64) *NumberConstraint {
	nc.applyMultipleOf = true
	nc.multipleOf = n
	return nc
}

// ExclusiveMinimum specifies if the minimum value should be considered
// a valid value
func (nc *NumberConstraint) ExclusiveMinimum(b bool) *NumberConstraint {
	nc.exclusiveMinimum = b
	return nc
}

// ExclusiveMaximum specifies if the maximum value should be considered
// a valid value
func (nc *NumberConstraint) ExclusiveMaximum(b bool) *NumberConstraint {
	nc.exclusiveMaximum = b
	return nc
}

// Validate validates the value against this constraint
func (nc *NumberConstraint) Validate(v interface{}) (err error) {
	if pdebug.Enabled {
		g := pdebug.IPrintf("START NumberConstraint.Validate")
		defer func() {
			if err == nil {
				g.IRelease("END NumberConstraint.Validate (PASS)")
			} else {
				g.IRelease("END NumberConstraint.Validate (FAIL): %s", err)
			}
		}()
	}

	rv := reflect.ValueOf(v)
	switch rv.Kind() {
	case reflect.Ptr, reflect.Interface:
		rv = rv.Elem()
	}

	switch rv.Kind() {
	case reflect.Float32, reflect.Float64:
	default:
		return errors.New("value is not a float")
	}

	f := rv.Float()
	if nc.applyMinimum {
		if pdebug.Enabled {
			pdebug.Printf("Checking Minimum (%f)", nc.minimum)
		}

		if nc.exclusiveMinimum {
			if nc.minimum >= f {
				return errors.New("numeric value is less than the minimum (exclusive minimum)")
			}
		} else {
			if nc.minimum > f {
				return errors.New("numeric value is less than the minimum")
			}
		}
	}

	if nc.applyMaximum {
		if pdebug.Enabled {
			pdebug.Printf("Checking Maximum (%f)", nc.maximum)
		}
		if nc.exclusiveMaximum {
			if nc.maximum <= f {
				return errors.New("numeric value is greater than maximum (exclusive maximum)")
			}
		} else {
			if nc.maximum < f {
				return errors.New("numeric value is greater than maximum")
			}
		}
	}

	if nc.applyMultipleOf {
		if pdebug.Enabled {
			pdebug.Printf("Checking MultipleOf (%f)", nc.multipleOf)
		}

		if nc.multipleOf != 0 {
	    if math.Mod(f, nc.multipleOf) != 0 {
				return errors.New("numeric value is fails multipleOf validation")
			}
		}
	}

	if enum := nc.enums; enum != nil {
		if err := enum.Validate(f); err != nil {
			return err
		}
	}

	return nil
}

// Number creates a new NumberConstraint
func Number() *NumberConstraint {
	return &NumberConstraint{
		applyMinimum: false,
		applyMaximum: false,
	}
}

// Integer creates a new IntegerrConstraint
func Integer() *IntegerConstraint {
	c := &IntegerConstraint{}
	c.applyMinimum = false
	c.applyMaximum = false
	return c
}

// Maximum sepcifies the maximum value that the constraint can allow
func (ic *IntegerConstraint) Maximum(n float64) *IntegerConstraint {
	ic.applyMaximum = true
	ic.maximum = n
	return ic
}

// Minimum sepcifies the minimum value that the constraint can allow
func (ic *IntegerConstraint) Minimum(n float64) *IntegerConstraint {
	ic.applyMinimum = true
	ic.minimum = n
	return ic
}

// ExclusiveMinimum specifies if the minimum value should be considered
// a valid value
func (ic *IntegerConstraint) ExclusiveMinimum(b bool) *IntegerConstraint {
	ic.NumberConstraint.ExclusiveMinimum(b)
	return ic
}

// ExclusiveMaximum specifies if the maximum value should be considered
// a valid value
func (ic *IntegerConstraint) ExclusiveMaximum(b bool) *IntegerConstraint {
	ic.NumberConstraint.ExclusiveMaximum(b)
	return ic
}

// Validate validates the value against integer validation rules.
// Note that because when Go decodes JSON it FORCES float64 on numbers,
// this method will return true even if the *type* of the value is
// float32/64. We just check that `math.Floor(v) == v`
func (ic *IntegerConstraint) Validate(v interface{}) (err error) {
	if pdebug.Enabled {
		g := pdebug.IPrintf("START IntegerConstraint.Validate")
		defer func() {
			if err == nil {
				g.IRelease("END IntegerConstraint.Validate (PASS)")
			} else {
				g.IRelease("END IntegerConstraint.Validate (FAIL): %s", err)
			}
		}()
	}

	rv := reflect.ValueOf(v)
	switch rv.Kind() {
	case reflect.Interface, reflect.Ptr:
		rv = rv.Elem()
	}

	switch rv.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return ic.NumberConstraint.Validate(float64(rv.Int()))
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return ic.NumberConstraint.Validate(float64(rv.Uint()))
	case reflect.Float32, reflect.Float64:
		fv := rv.Float()
		if math.Floor(fv) != fv {
			return errors.New("value is not an int/uint")
		}
		return ic.NumberConstraint.Validate(fv)
	default:
		return errors.New("value is not numeric")
	}
}
<commit_msg>Implement Default() so that it returns the correct type<commit_after>package jsval

import (
	"errors"
	"math"
	"reflect"

	"github.com/lestrrat/go-pdebug"
)

// Enum specifies the values that this constraint can have
func (nc *NumberConstraint) Enum(l ...interface{}) *NumberConstraint {
	if nc.enums == nil {
		nc.enums = Enum()
	}
	nc.enums.Enum(l...)
	return nc
}

// Default specifies the default value for the given value
func (nc *NumberConstraint) Default(v interface{}) *NumberConstraint {
	nc.defaultValue.initialized = true
	nc.defaultValue.value = v
	return nc
}

// Maximum sepcifies the maximum value that the constraint can allow
func (nc *NumberConstraint) Maximum(n float64) *NumberConstraint {
	nc.applyMaximum = true
	nc.maximum = n
	return nc
}

// Minimum sepcifies the minimum value that the constraint can allow
func (nc *NumberConstraint) Minimum(n float64) *NumberConstraint {
	nc.applyMinimum = true
	nc.minimum = n
	return nc
}

// MultipleOf specifies the number that the given value must be
// divisible by. That is, the constraint will return an error unless
// the given value satisfies `math.Mod(v, n) == 0`
func (nc *NumberConstraint) MultipleOf(n float64) *NumberConstraint {
	nc.applyMultipleOf = true
	nc.multipleOf = n
	return nc
}

// ExclusiveMinimum specifies if the minimum value should be considered
// a valid value
func (nc *NumberConstraint) ExclusiveMinimum(b bool) *NumberConstraint {
	nc.exclusiveMinimum = b
	return nc
}

// ExclusiveMaximum specifies if the maximum value should be considered
// a valid value
func (nc *NumberConstraint) ExclusiveMaximum(b bool) *NumberConstraint {
	nc.exclusiveMaximum = b
	return nc
}

// Validate validates the value against this constraint
func (nc *NumberConstraint) Validate(v interface{}) (err error) {
	if pdebug.Enabled {
		g := pdebug.IPrintf("START NumberConstraint.Validate")
		defer func() {
			if err == nil {
				g.IRelease("END NumberConstraint.Validate (PASS)")
			} else {
				g.IRelease("END NumberConstraint.Validate (FAIL): %s", err)
			}
		}()
	}

	rv := reflect.ValueOf(v)
	switch rv.Kind() {
	case reflect.Ptr, reflect.Interface:
		rv = rv.Elem()
	}

	switch rv.Kind() {
	case reflect.Float32, reflect.Float64:
	default:
		return errors.New("value is not a float")
	}

	f := rv.Float()
	if nc.applyMinimum {
		if pdebug.Enabled {
			pdebug.Printf("Checking Minimum (%f)", nc.minimum)
		}

		if nc.exclusiveMinimum {
			if nc.minimum >= f {
				return errors.New("numeric value is less than the minimum (exclusive minimum)")
			}
		} else {
			if nc.minimum > f {
				return errors.New("numeric value is less than the minimum")
			}
		}
	}

	if nc.applyMaximum {
		if pdebug.Enabled {
			pdebug.Printf("Checking Maximum (%f)", nc.maximum)
		}
		if nc.exclusiveMaximum {
			if nc.maximum <= f {
				return errors.New("numeric value is greater than maximum (exclusive maximum)")
			}
		} else {
			if nc.maximum < f {
				return errors.New("numeric value is greater than maximum")
			}
		}
	}

	if nc.applyMultipleOf {
		if pdebug.Enabled {
			pdebug.Printf("Checking MultipleOf (%f)", nc.multipleOf)
		}

		if nc.multipleOf != 0 {
	    if math.Mod(f, nc.multipleOf) != 0 {
				return errors.New("numeric value is fails multipleOf validation")
			}
		}
	}

	if enum := nc.enums; enum != nil {
		if err := enum.Validate(f); err != nil {
			return err
		}
	}

	return nil
}

// Number creates a new NumberConstraint
func Number() *NumberConstraint {
	return &NumberConstraint{
		applyMinimum: false,
		applyMaximum: false,
	}
}

// Integer creates a new IntegerrConstraint
func Integer() *IntegerConstraint {
	c := &IntegerConstraint{}
	c.applyMinimum = false
	c.applyMaximum = false
	return c
}

// Default specifies the default value for the given value
func (ic *IntegerConstraint) Default(v interface{}) *IntegerConstraint {
	ic.NumberConstraint.Default(v)
	return ic
}

// Maximum sepcifies the maximum value that the constraint can allow
// Maximum sepcifies the maximum value that the constraint can allow
func (ic *IntegerConstraint) Maximum(n float64) *IntegerConstraint {
	ic.applyMaximum = true
	ic.maximum = n
	return ic
}

// Minimum sepcifies the minimum value that the constraint can allow
func (ic *IntegerConstraint) Minimum(n float64) *IntegerConstraint {
	ic.applyMinimum = true
	ic.minimum = n
	return ic
}

// ExclusiveMinimum specifies if the minimum value should be considered
// a valid value
func (ic *IntegerConstraint) ExclusiveMinimum(b bool) *IntegerConstraint {
	ic.NumberConstraint.ExclusiveMinimum(b)
	return ic
}

// ExclusiveMaximum specifies if the maximum value should be considered
// a valid value
func (ic *IntegerConstraint) ExclusiveMaximum(b bool) *IntegerConstraint {
	ic.NumberConstraint.ExclusiveMaximum(b)
	return ic
}

// Validate validates the value against integer validation rules.
// Note that because when Go decodes JSON it FORCES float64 on numbers,
// this method will return true even if the *type* of the value is
// float32/64. We just check that `math.Floor(v) == v`
func (ic *IntegerConstraint) Validate(v interface{}) (err error) {
	if pdebug.Enabled {
		g := pdebug.IPrintf("START IntegerConstraint.Validate")
		defer func() {
			if err == nil {
				g.IRelease("END IntegerConstraint.Validate (PASS)")
			} else {
				g.IRelease("END IntegerConstraint.Validate (FAIL): %s", err)
			}
		}()
	}

	rv := reflect.ValueOf(v)
	switch rv.Kind() {
	case reflect.Interface, reflect.Ptr:
		rv = rv.Elem()
	}

	switch rv.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return ic.NumberConstraint.Validate(float64(rv.Int()))
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return ic.NumberConstraint.Validate(float64(rv.Uint()))
	case reflect.Float32, reflect.Float64:
		fv := rv.Float()
		if math.Floor(fv) != fv {
			return errors.New("value is not an int/uint")
		}
		return ic.NumberConstraint.Validate(fv)
	default:
		return errors.New("value is not numeric")
	}
}
<|endoftext|>


<commit_before>package factom

import (
	"fmt"
	"testing"

	"encoding/json"
	ed "github.com/FactomProject/ed25519"
)

func TestGetIdentityChainID(t *testing.T) {
	name := []string{"John", "Jacob", "Jingleheimer-Schmidt"}
	observedChainID := GetIdentityChainID(name)
	expectedChainID := "e0cf1713b492e09e783d5d9f4fc6e2c71b5bdc9af4806a7937a5e935819717e9"
	if observedChainID != expectedChainID {
		t.Errorf("got: %s but expected: %s", observedChainID, expectedChainID)
	}
}

func TestNewIdentityChain(t *testing.T) {
	name := []string{"John", "Jacob", "Jingleheimer-Schmidt"}
	secretKeys := []string{
		"idsec2rChEHLz3SPQQx3syQtB11pHAmxyGjux5FntnS7xqTCieHxxTc",
		"idsec1xuUyeCCrJhsojf2wLAZqRxPzPFR8Gidd9DRRid1yGy8ncAJG3",
		"idsec2J3nNoqdiyboCBKDGauqN9Jb33dyFSqaJKZqTs6i5FmztsTn5f",
		"idsec1jztZ7dypqtwtPPWxybZFNpvvpUh6g8oog6Mnk2gGCm1pNBTgE",
	}
	var keys []string
	for _, v := range secretKeys {
		k, _ := GetIdentityKey(v)
		keys = append(keys, k.PubString())
	}

	newChain, err := NewIdentityChain(name, keys)
	if err != nil {
		t.Errorf("Failed to compose identity chain struct %s", err.Error())
	}
	expectedChainID := "e0cf1713b492e09e783d5d9f4fc6e2c71b5bdc9af4806a7937a5e935819717e9"
	t.Run("ChainID", func(t *testing.T) {
		if newChain.ChainID != expectedChainID {
			fmt.Println(newChain.ChainID)
			fmt.Println(expectedChainID)
			t.Fail()
		}
	})
	t.Run("Keys accessible from Content", func(t *testing.T) {
		var contentMap map[string]interface{}
		content := newChain.FirstEntry.Content
		err := json.Unmarshal(content, &contentMap)
		if err != nil {
			t.Errorf("Failed to unmarshal content")
		}
		for i, v := range contentMap["keys"].([]interface{}) {
			if keys[i] != v.(string) {
				t.Errorf("Keys not properly formatted")
			}
		}
	})

}

func TestNewIdentityKeyReplacementEntry(t *testing.T) {
	chainID := "e0cf1713b492e09e783d5d9f4fc6e2c71b5bdc9af4806a7937a5e935819717e9"
	oldKey, _ := GetIdentityKey("idsec1jztZ7dypqtwtPPWxybZFNpvvpUh6g8oog6Mnk2gGCm1pNBTgE")
	newKey, _ := GetIdentityKey("idsec2J3nNoqdiyboCBKDGauqN9Jb33dyFSqaJKZqTs6i5FmztsTn5f")
	signerKey, _ := GetIdentityKey("idsec2wH72BNR9QZhTMGDbxwLWGrghZQexZvLTros2wCekkc62N9h7s")

	observedEntry, err := NewIdentityKeyReplacementEntry(chainID, oldKey.PubString(), newKey.PubString(), signerKey)
	if err != nil {
		t.Errorf("Failed to compose key replacement entry struct %s", err.Error())
	}

	t.Run("ChainID", func(t *testing.T) {
		if observedEntry.ChainID != chainID {
			t.Fail()
		}
	})
	t.Run("ExtIDs", func(t *testing.T) {
		if len(observedEntry.ExtIDs) != 5 {
			t.Errorf("len(ExtIDs) != 5")
		}
		if string(observedEntry.ExtIDs[0]) != "ReplaceKey" {
			t.Errorf("ReplaceKey is not first ExtID")
		}
		if string(observedEntry.ExtIDs[1]) != oldKey.String() ||
			string(observedEntry.ExtIDs[2]) != newKey.String() ||
			string(observedEntry.ExtIDs[4]) != signerKey.String() {
			t.Errorf("Keys not formatted properly")
		}
	})
	t.Run("Signature", func(t *testing.T) {
		var observedSignature [64]byte
		copy(observedSignature[:], observedEntry.ExtIDs[3])
		message := []byte(oldKey.String() + newKey.String())
		if !ed.Verify(signerKey.Pub, message, &observedSignature) {
			t.Fail()
		}
	})
}

func TestNewIdentityAttributeEntry(t *testing.T) {
	receiverChainID := "5ef81cd345fd497a376ca5e5670ef10826d96e73c9f797b33ea46552a47834a3"
	destinationChainID := "5a402200c5cf278e47905ce52d7d64529a0291829a7bd230072c5468be709069"
	signerChainID := "e0cf1713b492e09e783d5d9f4fc6e2c71b5bdc9af4806a7937a5e935819717e9"
	signerKey, err := GetIdentityKey("idsec2J3nNoqdiyboCBKDGauqN9Jb33dyFSqaJKZqTs6i5FmztsTn5f")
	if err != nil {
		t.Errorf("Failed to get identity key")
	}
	attributesJSON := `[{"key":"email","value":"abc@def.ghi"}]`

	observedEntry := NewIdentityAttributeEntry(receiverChainID, destinationChainID, attributesJSON, signerKey, signerChainID)

	if !IsValidAttribute(observedEntry) {
		t.Errorf("Improperly formatted attribute")
	}

	var attributes []IdentityAttribute
	if err = json.Unmarshal(observedEntry.Content, &attributes); err != nil {
		t.Errorf("Failed to unmarshal content: %v", err)
	}
	if attributes[0].Key != "email" {
		t.Errorf("Incorrect key")
	}
	if attributes[0].Value != "abc@def.ghi" {
		t.Errorf("Incorrect value")
	}
}

func TestNewIdentityAttributeEndorsementEntry(t *testing.T) {
	destinationChainID := "5a402200c5cf278e47905ce52d7d64529a0291829a7bd230072c5468be709069"
	signerChainID := "e0cf1713b492e09e783d5d9f4fc6e2c71b5bdc9af4806a7937a5e935819717e9"
	signerKey, _ := GetIdentityKey("idsec2J3nNoqdiyboCBKDGauqN9Jb33dyFSqaJKZqTs6i5FmztsTn5f")
	entryHash := "52385948ea3ab6fd67b07664ac6a30ae5f6afa94427a547c142517beaa9054d0"

	observedEntry := NewIdentityAttributeEndorsementEntry(destinationChainID, entryHash, signerKey, signerChainID)

	if !IsValidEndorsement(observedEntry) {
		t.Errorf("Improperly formatted attribute endorsement")
	}
}
<commit_msg>minor updates for identity test<commit_after>package factom_test

import (
	"encoding/json"

	ed "github.com/FactomProject/ed25519"

	. "github.com/FactomProject/factom"

	"testing"
)

func TestGetIdentityChainID(t *testing.T) {
	name := []string{"John", "Jacob", "Jingleheimer-Schmidt"}
	observedChainID := GetIdentityChainID(name)
	expectedChainID := "e0cf1713b492e09e783d5d9f4fc6e2c71b5bdc9af4806a7937a5e935819717e9"
	if observedChainID != expectedChainID {
		t.Errorf("got: %s but expected: %s", observedChainID, expectedChainID)
	}
}

func TestNewIdentityChain(t *testing.T) {
	name := []string{"John", "Jacob", "Jingleheimer-Schmidt"}
	secretKeys := []string{
		"idsec2rChEHLz3SPQQx3syQtB11pHAmxyGjux5FntnS7xqTCieHxxTc",
		"idsec1xuUyeCCrJhsojf2wLAZqRxPzPFR8Gidd9DRRid1yGy8ncAJG3",
		"idsec2J3nNoqdiyboCBKDGauqN9Jb33dyFSqaJKZqTs6i5FmztsTn5f",
		"idsec1jztZ7dypqtwtPPWxybZFNpvvpUh6g8oog6Mnk2gGCm1pNBTgE",
	}
	var keys []string
	for _, v := range secretKeys {
		k, _ := GetIdentityKey(v)
		keys = append(keys, k.PubString())
	}

	newChain, err := NewIdentityChain(name, keys)
	if err != nil {
		t.Errorf("Failed to compose identity chain struct %s", err.Error())
	}
	expectedChainID := "e0cf1713b492e09e783d5d9f4fc6e2c71b5bdc9af4806a7937a5e935819717e9"
	t.Run("ChainID", func(t *testing.T) {
		if newChain.ChainID != expectedChainID {
			t.Errorf("expected:%s\nrecieved:%s", expectedChainID, newChain.ChainID)
		}
	})
	t.Run("Keys accessible from Content", func(t *testing.T) {
		var contentMap map[string]interface{}
		content := newChain.FirstEntry.Content
		err := json.Unmarshal(content, &contentMap)
		if err != nil {
			t.Errorf("Failed to unmarshal content")
		}
		for i, v := range contentMap["keys"].([]interface{}) {
			if keys[i] != v.(string) {
				t.Errorf("Keys not properly formatted")
			}
		}
	})
}

func TestNewIdentityKeyReplacementEntry(t *testing.T) {
	chainID := "e0cf1713b492e09e783d5d9f4fc6e2c71b5bdc9af4806a7937a5e935819717e9"
	oldKey, _ := GetIdentityKey("idsec1jztZ7dypqtwtPPWxybZFNpvvpUh6g8oog6Mnk2gGCm1pNBTgE")
	newKey, _ := GetIdentityKey("idsec2J3nNoqdiyboCBKDGauqN9Jb33dyFSqaJKZqTs6i5FmztsTn5f")
	signerKey, _ := GetIdentityKey("idsec2wH72BNR9QZhTMGDbxwLWGrghZQexZvLTros2wCekkc62N9h7s")

	observedEntry, err := NewIdentityKeyReplacementEntry(chainID, oldKey.PubString(), newKey.PubString(), signerKey)
	if err != nil {
		t.Errorf("Failed to compose key replacement entry struct %s", err.Error())
	}

	t.Run("ChainID", func(t *testing.T) {
		if observedEntry.ChainID != chainID {
			t.Fail()
		}
	})
	t.Run("ExtIDs", func(t *testing.T) {
		if len(observedEntry.ExtIDs) != 5 {
			t.Errorf("len(ExtIDs) != 5")
		}
		if string(observedEntry.ExtIDs[0]) != "ReplaceKey" {
			t.Errorf("ReplaceKey is not first ExtID")
		}
		if string(observedEntry.ExtIDs[1]) != oldKey.String() ||
			string(observedEntry.ExtIDs[2]) != newKey.String() ||
			string(observedEntry.ExtIDs[4]) != signerKey.String() {
			t.Errorf("Keys not formatted properly")
		}
	})
	t.Run("Signature", func(t *testing.T) {
		var observedSignature [64]byte
		copy(observedSignature[:], observedEntry.ExtIDs[3])
		message := []byte(oldKey.String() + newKey.String())
		if !ed.Verify(signerKey.Pub, message, &observedSignature) {
			t.Fail()
		}
	})
}

func TestNewIdentityAttributeEntry(t *testing.T) {
	receiverChainID := "5ef81cd345fd497a376ca5e5670ef10826d96e73c9f797b33ea46552a47834a3"
	destinationChainID := "5a402200c5cf278e47905ce52d7d64529a0291829a7bd230072c5468be709069"
	signerChainID := "e0cf1713b492e09e783d5d9f4fc6e2c71b5bdc9af4806a7937a5e935819717e9"
	signerKey, err := GetIdentityKey("idsec2J3nNoqdiyboCBKDGauqN9Jb33dyFSqaJKZqTs6i5FmztsTn5f")
	if err != nil {
		t.Errorf("Failed to get identity key")
	}
	attributesJSON := `[{"key":"email","value":"abc@def.ghi"}]`

	observedEntry := NewIdentityAttributeEntry(receiverChainID, destinationChainID, attributesJSON, signerKey, signerChainID)

	if !IsValidAttribute(observedEntry) {
		t.Errorf("Improperly formatted attribute")
	}

	var attributes []IdentityAttribute
	if err = json.Unmarshal(observedEntry.Content, &attributes); err != nil {
		t.Errorf("Failed to unmarshal content: %v", err)
	}
	if attributes[0].Key != "email" {
		t.Errorf("Incorrect key")
	}
	if attributes[0].Value != "abc@def.ghi" {
		t.Errorf("Incorrect value")
	}
}

func TestNewIdentityAttributeEndorsementEntry(t *testing.T) {
	destinationChainID := "5a402200c5cf278e47905ce52d7d64529a0291829a7bd230072c5468be709069"
	signerChainID := "e0cf1713b492e09e783d5d9f4fc6e2c71b5bdc9af4806a7937a5e935819717e9"
	signerKey, _ := GetIdentityKey("idsec2J3nNoqdiyboCBKDGauqN9Jb33dyFSqaJKZqTs6i5FmztsTn5f")
	entryHash := "52385948ea3ab6fd67b07664ac6a30ae5f6afa94427a547c142517beaa9054d0"

	observedEntry := NewIdentityAttributeEndorsementEntry(destinationChainID, entryHash, signerKey, signerChainID)

	if !IsValidEndorsement(observedEntry) {
		t.Errorf("Improperly formatted attribute endorsement")
	}
}
<|endoftext|>


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

package gitea

import (
	"encoding/json"
	"fmt"
)

// User represents a user
// swagger:model
type User struct {
	// the user's id
	ID int64 `json:"id"`
	// the user's username
	UserName string `json:"login"`
	// the user's full name
	FullName string `json:"full_name"`
	// swagger:strfmt email
	Email string `json:"email"`
	// URL to the user's avatar
	AvatarURL string `json:"avatar_url"`
	// User locale
	Language string `json:"language"`
}

// MarshalJSON implements the json.Marshaler interface for User, adding field(s) for backward compatibility
func (u User) MarshalJSON() ([]byte, error) {
	// Re-declaring User to avoid recursion
	type shadow User
	return json.Marshal(struct {
		shadow
		CompatUserName string `json:"username"`
	}{shadow(u), u.UserName})
}

// GetUserInfo get user info by user's name
func (c *Client) GetUserInfo(user string) (*User, error) {
	u := new(User)
	err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s", user), nil, nil, u)
	return u, err
}
<commit_msg>Add GetMyUserInfo (#111)<commit_after>// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package gitea

import (
	"encoding/json"
	"fmt"
)

// User represents a user
// swagger:model
type User struct {
	// the user's id
	ID int64 `json:"id"`
	// the user's username
	UserName string `json:"login"`
	// the user's full name
	FullName string `json:"full_name"`
	// swagger:strfmt email
	Email string `json:"email"`
	// URL to the user's avatar
	AvatarURL string `json:"avatar_url"`
	// User locale
	Language string `json:"language"`
}

// MarshalJSON implements the json.Marshaler interface for User, adding field(s) for backward compatibility
func (u User) MarshalJSON() ([]byte, error) {
	// Re-declaring User to avoid recursion
	type shadow User
	return json.Marshal(struct {
		shadow
		CompatUserName string `json:"username"`
	}{shadow(u), u.UserName})
}

// GetUserInfo get user info by user's name
func (c *Client) GetUserInfo(user string) (*User, error) {
	u := new(User)
	err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s", user), nil, nil, u)
	return u, err
}

// GetMyUserInfo get user info of current user
func (c *Client) GetMyUserInfo() (*User, error) {
	u := new(User)
	err := c.getParsedResponse("GET", "/user", nil, nil, u)
	return u, err
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"encoding/hex"
	"flag"
	"fmt"
	"io/ioutil"
	"unicode"
)

var uuidFlag = flag.String("uuid", "01234567890a", "uuid from /cloud")
var authkeyFlag = flag.String("authkey", "01234567", "authkey from /cloud")

func clean(data []byte) string {
	fields := bytes.FieldsFunc(data, func(r rune) bool {
		return !(unicode.IsDigit(r) || unicode.IsLetter(r) || unicode.IsPunct(r))
	})
	cleanData := bytes.Join(fields, []byte("?"))
	return string(cleanData)
}

func work() error {

	var err error
	//block, err := aes.NewCipher([]byte(*authkeyFlag + *authkeyFlag))
	//block, err := aes.NewCipher([]byte("00000000" + *authkeyFlag))

	//key := []byte(*authkeyFlag + "00000000")
	//key, err := hex.DecodeString("00000000" + "00000000" + "00000000" + *authkeyFlag)
	key, err := hex.DecodeString(*authkeyFlag + "00000000" + "00000000" + "00000000")

	if err != nil {
		return err
	}
	fmt.Println("key:", hex.EncodeToString(key))
	block, err := aes.NewCipher(key)
	if err != nil {
		return err
	}

	csvBytes, err := ioutil.ReadFile("ct30.log.csv")
	if err != nil {
		return err
	}

	lines := bytes.Split(csvBytes, []byte("\n"))

	for _, line := range lines {
		values := bytes.Split(line, []byte(","))
		fmt.Println(string(values[0]))

		eiv := make([]byte, hex.DecodedLen(len(values[2])))
		_, err = hex.Decode(eiv, values[2])
		if err != nil {
			return err
		}
		fmt.Printf("EIV[%d]: %s\n", len(eiv), string(values[2]))
		cbc := cipher.NewCBCDecrypter(block, eiv)

		req := make([]byte, hex.DecodedLen(len(values[1])))
		_, err = hex.Decode(req, values[1])
		if err != nil {
			return err
		}
		cbc.CryptBlocks(req, req)
		fmt.Println(len(req), clean(req))

		res := make([]byte, hex.DecodedLen(len(values[3])))
		_, err = hex.Decode(res, values[3])
		if err != nil {
			return err
		}
		fmt.Println(len(res), clean(res))
		fmt.Println()
	}
	return nil
}

func main() {
	flag.Parse()
	err := work()
	if err != nil {
		fmt.Println(err)
	}
}
<commit_msg>Update decoder.go<commit_after>package main

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"encoding/hex"
	"flag"
	"fmt"
	"io/ioutil"
	"unicode"
)

var uuidFlag = flag.String("uuid", "001122334455", "uuid from /cloud")
var authkeyFlag = flag.String("authkey", "00112233", "authkey from /cloud")

func clean(data []byte) string {
	fields := bytes.FieldsFunc(data, func(r rune) bool {
		return !(unicode.IsDigit(r) || unicode.IsLetter(r) || unicode.IsPunct(r))
	})
	cleanData := bytes.Join(fields, []byte("?"))
	return string(cleanData)
}

func work() error {

	var err error
	//block, err := aes.NewCipher([]byte(*authkeyFlag + *authkeyFlag))
	//block, err := aes.NewCipher([]byte("00000000" + *authkeyFlag))

	//key := []byte(*authkeyFlag + "00000000")
	//key, err := hex.DecodeString("00000000" + "00000000" + "00000000" + *authkeyFlag)
	key, err := hex.DecodeString(*authkeyFlag + "00000000" + "00000000" + "00000000")

	if err != nil {
		return err
	}
	fmt.Println("key:", hex.EncodeToString(key))
	block, err := aes.NewCipher(key)
	if err != nil {
		return err
	}

	csvBytes, err := ioutil.ReadFile("ct30.log.csv")
	if err != nil {
		return err
	}

	lines := bytes.Split(csvBytes, []byte("\n"))

	for _, line := range lines {
		values := bytes.Split(line, []byte(","))
		fmt.Println(string(values[0]))

		eiv := make([]byte, hex.DecodedLen(len(values[2])))
		_, err = hex.Decode(eiv, values[2])
		if err != nil {
			return err
		}
		fmt.Printf("EIV[%d]: %s\n", len(eiv), string(values[2]))
		cbc := cipher.NewCBCDecrypter(block, eiv)

		req := make([]byte, hex.DecodedLen(len(values[1])))
		_, err = hex.Decode(req, values[1])
		if err != nil {
			return err
		}
		cbc.CryptBlocks(req, req)
		fmt.Println(len(req), clean(req))

		res := make([]byte, hex.DecodedLen(len(values[3])))
		_, err = hex.Decode(res, values[3])
		if err != nil {
			return err
		}
		fmt.Println(len(res), clean(res))
		fmt.Println()
	}
	return nil
}

func main() {
	flag.Parse()
	err := work()
	if err != nil {
		fmt.Println(err)
	}
}
<|endoftext|>


<commit_before>package cgi

import (
	"bytes"
	"fmt"
	"net/http"
	"net/http/httptest"
	"os"
	"runtime"
	"strings"
	"testing"

	"github.com/mholt/caddy"
	"github.com/mholt/caddy/caddyhttp/httpserver"
)

// handleGet returns a cgi handler (which implements ServeHTTP) based on the
// specified directive string. The directive can contain more than one block,
// but only the first is associated with the returned handler.
func handlerGet(directiveStr, rootStr string) (hnd handlerType, err error) {
	var c *caddy.Controller
	var mids []httpserver.Middleware
	var cfg *httpserver.SiteConfig
	var ok bool
	var midLen int

	c = caddy.NewTestController("http", directiveStr)
	cfg = httpserver.GetConfig(c)
	cfg.Root = rootStr
	err = configureServer(c, cfg)
	if err == nil {
		mids = cfg.Middleware()
		midLen = len(mids)
		if midLen > 0 {
			hnd, ok = mids[0](httpserver.EmptyNext).(handlerType)
			if ok {
				// .. success
			} else {
				err = fmt.Errorf("expected middleware handler to be CGI handler")
			}
		} else {
			err = fmt.Errorf("no middlewares present")
		}
	}
	return
}

func TestServe(t *testing.T) {
	var err error
	var code int
	var hnd handlerType
	var srv *httptest.Server
	directiveList := []string{
		`cgi /servertime {.}/test/example`,
		`cgi {
  match /servertime
  except /servertime/1934/*/*
  exec {.}/test/example --example
  env CGI_GLOBAL=12
  empty_env CGI_LOCAL
}`,
	}

	requestList := []string{
		"/servertime",
		"/servertime/1930/05/11?name=Edsger%20W.%20Dijkstra",
		"/servertime/1934/02/15?name=Niklaus%20Wirth",
		"/example.txt",
	}

	expectStr := `=== Directive 0 ===
cgi /servertime {.}/test/example
--- Request /servertime ---
code [0], error [example error message]
PATH_INFO []
CGI_GLOBAL []
Arg 1 []
QUERY_STRING []
HTTP_TOKEN_CLAIM_USER [quixote]
CGI_LOCAL is unset
--- Request /servertime/1930/05/11?name=Edsger%20W.%20Dijkstra ---
code [0], error [example error message]
PATH_INFO [/1930/05/11]
CGI_GLOBAL []
Arg 1 []
QUERY_STRING [name=Edsger%20W.%20Dijkstra]
HTTP_TOKEN_CLAIM_USER [quixote]
CGI_LOCAL is unset
--- Request /servertime/1934/02/15?name=Niklaus%20Wirth ---
code [0], error [example error message]
PATH_INFO [/1934/02/15]
CGI_GLOBAL []
Arg 1 []
QUERY_STRING [name=Niklaus%20Wirth]
HTTP_TOKEN_CLAIM_USER [quixote]
CGI_LOCAL is unset
--- Request /example.txt ---
=== Directive 1 ===
cgi {
  match /servertime
  except /servertime/1934/*/*
  exec {.}/test/example --example
  env CGI_GLOBAL=12
  empty_env CGI_LOCAL
}
--- Request /servertime ---
code [0], error [example error message]
PATH_INFO []
CGI_GLOBAL [12]
Arg 1 [--example]
QUERY_STRING []
HTTP_TOKEN_CLAIM_USER [quixote]
CGI_LOCAL is set to []
--- Request /servertime/1930/05/11?name=Edsger%20W.%20Dijkstra ---
code [0], error [example error message]
PATH_INFO [/1930/05/11]
CGI_GLOBAL [12]
Arg 1 [--example]
QUERY_STRING [name=Edsger%20W.%20Dijkstra]
HTTP_TOKEN_CLAIM_USER [quixote]
CGI_LOCAL is set to []
--- Request /servertime/1934/02/15?name=Niklaus%20Wirth ---
--- Request /example.txt ---
`
	// Testing the ServeHTTP method requires OS-specific CGI scripts, because a
	// system call is made to respond to the request.
	if runtime.GOOS == "linux" || runtime.GOOS == "darwin" {
		var buf bytes.Buffer
		for dirJ := 0; dirJ < len(directiveList) && err == nil; dirJ++ {
			hnd, err = handlerGet(directiveList[dirJ], "./test")
			if err == nil {
				srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
					r.Header.Set("Token-Claim-User", "quixote")
					r.Header.Set("Token-Claim-Language", "en-GB")
					r.Header.Add("Token-Claim-Language", "en-AU")
					code, err = hnd.ServeHTTP(w, r)
					if err != nil {
						fmt.Fprintf(&buf, "code [%d], error [%s]\n", code, err)
					}
				}))
				fmt.Fprintf(&buf, "=== Directive %d ===\n%s\n", dirJ, directiveList[dirJ])
				for reqJ := 0; reqJ < len(requestList) && err == nil; reqJ++ {
					var res *http.Response
					fmt.Fprintf(&buf, "--- Request %s ---\n", requestList[reqJ])
					res, err = http.Get(srv.URL + requestList[reqJ])
					if err == nil {
						_, err = buf.ReadFrom(res.Body)
						res.Body.Close()
					}
				}
				srv.Close()
			}
		}
		if err == nil {
			gotStr := buf.String()
			if expectStr != gotStr {
				err = errorf("expected %s, got %s\n", expectStr, gotStr)
			}
		}
		if err != nil {
			t.Fatalf("%s", err)
		}
	}
}

func checkEnv(envStr string) (err error) {
	// envStr is reported by CGI program invoked with pass_all_env. It looks like
	// "key1=val1\nkey2=val2..." Place keys into map and make sure all actual
	// environment variables are included in this map. Some environment values get
	// legitimately changed for spawned executable, so verify keys only.
	list := strings.Split(envStr, "\n")
	mp := make(map[string]bool)
	for _, pr := range list {
		pos := strings.Index(pr, "=")
		if pos > 0 {
			mp[pr[:pos]] = true
		}
	}
	actualList := os.Environ()
	actualLen := len(actualList)
	for j := 0; j < actualLen && err == nil; j++ {
		actualStr := actualList[j]
		pos := strings.Index(actualStr, "=")
		if pos > 0 {
			k := actualStr[:pos]
			_, ok := mp[k]
			if !ok {
				err = fmt.Errorf("environment key \"%s\" not found in CGI environment", k)
			}
		}
	}
	return
}

func TestPassAll(t *testing.T) {
	var err error
	var code int
	var hnd handlerType
	var srv *httptest.Server
	request := `/full`
	directive := `cgi {
match /full
exec {.}/test/fullenv
pass_all_env
}`

	// Testing the ServeHTTP method requires OS-specific CGI scripts, because a
	// system call is made to respond to the request.
	if runtime.GOOS == "linux" {
		var buf bytes.Buffer
		hnd, err = handlerGet(directive, "./test")
		if err == nil {
			srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				code, err = hnd.ServeHTTP(w, r)
				if err != nil {
					fmt.Fprintf(&buf, "code [%d], error [%s]\n", code, err)
				}
			}))
			fmt.Fprintf(&buf, "=== Directive ===\n%s\n", directive)
			var res *http.Response
			fmt.Fprintf(&buf, "--- Request %s ---\n", request)
			res, err = http.Get(srv.URL + request)
			if err == nil {
				_, err = buf.ReadFrom(res.Body)
				res.Body.Close()
			}
			srv.Close()
		}
		if err == nil {
			err = checkEnv(buf.String())
		}
		if err != nil {
			t.Fatalf("%s", err)
		}
	}
}

func TestMatches(t *testing.T) {
	var ok bool
	var prefixStr, suffixStr string
	// [request, pattern, expected success:1/expected error:0, prefix, suffix]
	list := [][]string{
		{"/foo/bar/baz", "/foo", "1", "/foo", "/bar/baz"},
		{"/foo/bar/baz", "/foo/*/baz", "1", "/foo/bar/baz", ""},
		{"/foo/bar/baz", "/foo/bar", "1", "/foo/bar", "/baz"},
		{"/foo/bar/baz", "foo/bar", "0", "", ""},
	}

	for _, rec := range list {
		ok, prefixStr, suffixStr = match(rec[0], []string{rec[1]})
		if ok {
			if rec[2] == "0" || rec[3] != prefixStr || rec[4] != suffixStr {
				t.Fatalf("expected mismatch for \"%s\" and \"%s\"", rec[0], rec[1])
			}
		} else {
			if rec[2] == "1" {
				t.Fatalf("expected match for \"%s\" and \"%s\"", rec[0], rec[1])
			}
		}
	}
}

func TestExceptions(t *testing.T) {
	// [request, except pattern, expected success:1/expected error:0]
	list := [][]string{
		{"/foo/bar/baz.png", "/*/*/*.png", "1"},
		{"/foo/bar/baz.png", "/foo/*/baz*", "1"},
		{"/foo/bar/baz.png", "/foo/bar/baz.jpg", "0"},
		{"/foo/bar/baz.png", "foo/bar", "0"},
	}

	for _, rec := range list {
		ok := excluded(rec[0], []string{rec[1]})
		if ok && rec[2] == "0" {
			t.Fatalf("unexpected exception for \"%s\" and \"%s\"", rec[0], rec[1])
		} else if !ok && rec[2] == "1" {
			t.Fatalf("expected exception for \"%s\" and \"%s\"", rec[0], rec[1])
		}
	}
}

func TestInspect(t *testing.T) {
	var err error
	var hnd handlerType
	var srv *httptest.Server
	var buf bytes.Buffer

	block := `cgi {
  match /foo/*
  exec bar --baz --quux
  pass_env HOME
  env VERY_LONG_KEY_INTENDED_TO_TEST_INSPECTION_REPORT=foo
  inspect
}`

	hnd, err = handlerGet(block, "./test")
	if err == nil {
		srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			_, hndErr := hnd.ServeHTTP(w, r)
			if err == nil && hndErr != nil {
				err = hndErr
			}
		}))
		var res *http.Response
		res, err = http.Get(srv.URL + "/foo/bar.tcl")
		if err == nil {
			_, err = buf.ReadFrom(res.Body)
			if err == nil {
				str := buf.String()
				if !strings.Contains(str, "CGI for Caddy") {
					err = fmt.Errorf("unexpected response for \"inspect\" request")
				}
			}
			res.Body.Close()
		}
		srv.Close()
	}
	if err != nil {
		t.Fatalf("%s", err)
	}
}
<commit_msg>Relax pass_all_env test because of failure on Caddy server<commit_after>package cgi

import (
	"bytes"
	"fmt"
	"net/http"
	"net/http/httptest"
	"os"
	"runtime"
	"strings"
	"testing"

	"github.com/mholt/caddy"
	"github.com/mholt/caddy/caddyhttp/httpserver"
)

// handleGet returns a cgi handler (which implements ServeHTTP) based on the
// specified directive string. The directive can contain more than one block,
// but only the first is associated with the returned handler.
func handlerGet(directiveStr, rootStr string) (hnd handlerType, err error) {
	var c *caddy.Controller
	var mids []httpserver.Middleware
	var cfg *httpserver.SiteConfig
	var ok bool
	var midLen int

	c = caddy.NewTestController("http", directiveStr)
	cfg = httpserver.GetConfig(c)
	cfg.Root = rootStr
	err = configureServer(c, cfg)
	if err == nil {
		mids = cfg.Middleware()
		midLen = len(mids)
		if midLen > 0 {
			hnd, ok = mids[0](httpserver.EmptyNext).(handlerType)
			if ok {
				// .. success
			} else {
				err = fmt.Errorf("expected middleware handler to be CGI handler")
			}
		} else {
			err = fmt.Errorf("no middlewares present")
		}
	}
	return
}

func TestServe(t *testing.T) {
	var err error
	var code int
	var hnd handlerType
	var srv *httptest.Server
	directiveList := []string{
		`cgi /servertime {.}/test/example`,
		`cgi {
  match /servertime
  except /servertime/1934/*/*
  exec {.}/test/example --example
  env CGI_GLOBAL=12
  empty_env CGI_LOCAL
}`,
	}

	requestList := []string{
		"/servertime",
		"/servertime/1930/05/11?name=Edsger%20W.%20Dijkstra",
		"/servertime/1934/02/15?name=Niklaus%20Wirth",
		"/example.txt",
	}

	expectStr := `=== Directive 0 ===
cgi /servertime {.}/test/example
--- Request /servertime ---
code [0], error [example error message]
PATH_INFO []
CGI_GLOBAL []
Arg 1 []
QUERY_STRING []
HTTP_TOKEN_CLAIM_USER [quixote]
CGI_LOCAL is unset
--- Request /servertime/1930/05/11?name=Edsger%20W.%20Dijkstra ---
code [0], error [example error message]
PATH_INFO [/1930/05/11]
CGI_GLOBAL []
Arg 1 []
QUERY_STRING [name=Edsger%20W.%20Dijkstra]
HTTP_TOKEN_CLAIM_USER [quixote]
CGI_LOCAL is unset
--- Request /servertime/1934/02/15?name=Niklaus%20Wirth ---
code [0], error [example error message]
PATH_INFO [/1934/02/15]
CGI_GLOBAL []
Arg 1 []
QUERY_STRING [name=Niklaus%20Wirth]
HTTP_TOKEN_CLAIM_USER [quixote]
CGI_LOCAL is unset
--- Request /example.txt ---
=== Directive 1 ===
cgi {
  match /servertime
  except /servertime/1934/*/*
  exec {.}/test/example --example
  env CGI_GLOBAL=12
  empty_env CGI_LOCAL
}
--- Request /servertime ---
code [0], error [example error message]
PATH_INFO []
CGI_GLOBAL [12]
Arg 1 [--example]
QUERY_STRING []
HTTP_TOKEN_CLAIM_USER [quixote]
CGI_LOCAL is set to []
--- Request /servertime/1930/05/11?name=Edsger%20W.%20Dijkstra ---
code [0], error [example error message]
PATH_INFO [/1930/05/11]
CGI_GLOBAL [12]
Arg 1 [--example]
QUERY_STRING [name=Edsger%20W.%20Dijkstra]
HTTP_TOKEN_CLAIM_USER [quixote]
CGI_LOCAL is set to []
--- Request /servertime/1934/02/15?name=Niklaus%20Wirth ---
--- Request /example.txt ---
`
	// Testing the ServeHTTP method requires OS-specific CGI scripts, because a
	// system call is made to respond to the request.
	if runtime.GOOS == "linux" || runtime.GOOS == "darwin" {
		var buf bytes.Buffer
		for dirJ := 0; dirJ < len(directiveList) && err == nil; dirJ++ {
			hnd, err = handlerGet(directiveList[dirJ], "./test")
			if err == nil {
				srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
					r.Header.Set("Token-Claim-User", "quixote")
					r.Header.Set("Token-Claim-Language", "en-GB")
					r.Header.Add("Token-Claim-Language", "en-AU")
					code, err = hnd.ServeHTTP(w, r)
					if err != nil {
						fmt.Fprintf(&buf, "code [%d], error [%s]\n", code, err)
					}
				}))
				fmt.Fprintf(&buf, "=== Directive %d ===\n%s\n", dirJ, directiveList[dirJ])
				for reqJ := 0; reqJ < len(requestList) && err == nil; reqJ++ {
					var res *http.Response
					fmt.Fprintf(&buf, "--- Request %s ---\n", requestList[reqJ])
					res, err = http.Get(srv.URL + requestList[reqJ])
					if err == nil {
						_, err = buf.ReadFrom(res.Body)
						res.Body.Close()
					}
				}
				srv.Close()
			}
		}
		if err == nil {
			gotStr := buf.String()
			if expectStr != gotStr {
				err = errorf("expected %s, got %s\n", expectStr, gotStr)
			}
		}
		if err != nil {
			t.Fatalf("%s", err)
		}
	}
}

func checkEnv(envStr string) (err error) {
	// envStr is reported by CGI program invoked with pass_all_env. It looks like
	// "key1=val1\nkey2=val2..." Place keys into map and make sure all actual
	// environment variables are included in this map. Some environment values get
	// legitimately changed for spawned executable, so verify keys only.
	list := strings.Split(envStr, "\n")
	mp := make(map[string]bool)
	for _, pr := range list {
		pos := strings.Index(pr, "=")
		if pos > 0 {
			mp[pr[:pos]] = true
		}
	}
	actualList := os.Environ()
	actualLen := len(actualList)
	for j := 0; j < actualLen && err == nil; j++ {
		actualStr := actualList[j]
		pos := strings.Index(actualStr, "=")
		if pos > 0 {
			k := actualStr[:pos]
			_, ok := mp[k]
			if !ok {
				// err = fmt.Errorf("environment key \"%s\" not found in CGI environment", k)
				fmt.Printf("environment key \"%s\" not found in CGI environment", k)
			}
		}
	}
	return
}

func TestPassAll(t *testing.T) {
	var err error
	var code int
	var hnd handlerType
	var srv *httptest.Server
	request := `/full`
	directive := `cgi {
match /full
exec {.}/test/fullenv
pass_all_env
}`

	// Testing the ServeHTTP method requires OS-specific CGI scripts, because a
	// system call is made to respond to the request.
	if runtime.GOOS == "linux" {
		var buf bytes.Buffer
		hnd, err = handlerGet(directive, "./test")
		if err == nil {
			srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				code, err = hnd.ServeHTTP(w, r)
				if err != nil {
					fmt.Fprintf(&buf, "code [%d], error [%s]\n", code, err)
				}
			}))
			fmt.Fprintf(&buf, "=== Directive ===\n%s\n", directive)
			var res *http.Response
			fmt.Fprintf(&buf, "--- Request %s ---\n", request)
			res, err = http.Get(srv.URL + request)
			if err == nil {
				_, err = buf.ReadFrom(res.Body)
				res.Body.Close()
			}
			srv.Close()
		}
		if err == nil {
			err = checkEnv(buf.String())
		}
		if err != nil {
			t.Fatalf("%s", err)
		}
	}
}

func TestMatches(t *testing.T) {
	var ok bool
	var prefixStr, suffixStr string
	// [request, pattern, expected success:1/expected error:0, prefix, suffix]
	list := [][]string{
		{"/foo/bar/baz", "/foo", "1", "/foo", "/bar/baz"},
		{"/foo/bar/baz", "/foo/*/baz", "1", "/foo/bar/baz", ""},
		{"/foo/bar/baz", "/foo/bar", "1", "/foo/bar", "/baz"},
		{"/foo/bar/baz", "foo/bar", "0", "", ""},
	}

	for _, rec := range list {
		ok, prefixStr, suffixStr = match(rec[0], []string{rec[1]})
		if ok {
			if rec[2] == "0" || rec[3] != prefixStr || rec[4] != suffixStr {
				t.Fatalf("expected mismatch for \"%s\" and \"%s\"", rec[0], rec[1])
			}
		} else {
			if rec[2] == "1" {
				t.Fatalf("expected match for \"%s\" and \"%s\"", rec[0], rec[1])
			}
		}
	}
}

func TestExceptions(t *testing.T) {
	// [request, except pattern, expected success:1/expected error:0]
	list := [][]string{
		{"/foo/bar/baz.png", "/*/*/*.png", "1"},
		{"/foo/bar/baz.png", "/foo/*/baz*", "1"},
		{"/foo/bar/baz.png", "/foo/bar/baz.jpg", "0"},
		{"/foo/bar/baz.png", "foo/bar", "0"},
	}

	for _, rec := range list {
		ok := excluded(rec[0], []string{rec[1]})
		if ok && rec[2] == "0" {
			t.Fatalf("unexpected exception for \"%s\" and \"%s\"", rec[0], rec[1])
		} else if !ok && rec[2] == "1" {
			t.Fatalf("expected exception for \"%s\" and \"%s\"", rec[0], rec[1])
		}
	}
}

func TestInspect(t *testing.T) {
	var err error
	var hnd handlerType
	var srv *httptest.Server
	var buf bytes.Buffer

	block := `cgi {
  match /foo/*
  exec bar --baz --quux
  pass_env HOME
  env VERY_LONG_KEY_INTENDED_TO_TEST_INSPECTION_REPORT=foo
  inspect
}`

	hnd, err = handlerGet(block, "./test")
	if err == nil {
		srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			_, hndErr := hnd.ServeHTTP(w, r)
			if err == nil && hndErr != nil {
				err = hndErr
			}
		}))
		var res *http.Response
		res, err = http.Get(srv.URL + "/foo/bar.tcl")
		if err == nil {
			_, err = buf.ReadFrom(res.Body)
			if err == nil {
				str := buf.String()
				if !strings.Contains(str, "CGI for Caddy") {
					err = fmt.Errorf("unexpected response for \"inspect\" request")
				}
			}
			res.Body.Close()
		}
		srv.Close()
	}
	if err != nil {
		t.Fatalf("%s", err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"
	"syscall"
)

const gitUser = "git"
const gitHome = "/home/git"

const prereceiveScript = `
#!/bin/bash
cat | %s hook
`

func getExitCode(err error) (int, error) {
	exitCode := 0
	if exiterr, ok := err.(*exec.ExitError); ok {
		if procExit := exiterr.Sys().(syscall.WaitStatus); ok {
			return procExit.ExitStatus(), nil
		}
	}
	return exitCode, fmt.Errorf("failed to get exit code")
}

func runCommandWithOutput(cmd *exec.Cmd) (output string, exitCode int, err error) {
	exitCode = 0
	out, err := cmd.CombinedOutput()
	if err != nil {
		var exiterr error
		if exitCode, exiterr = getExitCode(err); exiterr != nil {
			// TODO: Fix this so we check the error's text.
			// we've failed to retrieve exit code, so we set it to 127
			exitCode = 127
		}
	}
	output = string(out)
	return
}

func runCommand(cmd *exec.Cmd) (exitCode int, err error) {
	exitCode = 0
	err = cmd.Run()
	if err != nil {
		var exiterr error
		if exitCode, exiterr = getExitCode(err); exiterr != nil {
			// TODO: Fix this so we check the error's text.
			// we've failed to retrieve exit code, so we set it to 127
			exitCode = 127
		}
	}
	return
}

func addGitUser(homeDirectory, gitUsername string) {
	userAddCmd := exec.Command("useradd", "-d", homeDirectory, gitUsername)
	if out, _, err := runCommandWithOutput(userAddCmd); err != nil {
		fmt.Printf("failed to execute add user %s\n", out)
		os.Exit(1)
	}

	sshDir := fmt.Sprintf("%s/.ssh", homeDirectory)
	addSshDirCmd := exec.Command("mkdir", "-p", sshDir)
	if _, _, err := runCommandWithOutput(addSshDirCmd); err != nil {
		fmt.Printf("failed to create the .ssh directory\n")
		os.Exit(1)
	}

	authorizedKeysFilename := fmt.Sprintf("%s/.ssh/authorized_keys", homeDirectory)
	authorizedKeys, err := os.OpenFile(authorizedKeysFilename, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0600)
	if err != nil {
		fmt.Printf("failed to open authorized_keys %s\n", authorizedKeysFilename)
		os.Exit(1)
	}
	authorizedKeys.Close()

	changeOWnership := exec.Command("chown", "-R", gitUsername, homeDirectory)
	if _, _, err := runCommandWithOutput(changeOWnership); err != nil {
		fmt.Printf("failed to change ownership\n")
		os.Exit(1)
	}
	fmt.Printf("Created receiver script in %s for user '%s'.\n", homeDirectory, gitUsername)
}

func uploadKey(homeDirectory, gitreceivePath, username string) {
	inputRawKey, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
		fmt.Printf("failed to read key from stdin\n")
		os.Exit(1)
	}
	key := string(inputRawKey)

	// ssh-keygen doesn't read from pipes and sometimes /dev/stdin doesn't work
	// create a temporary file to write the key to it
	createTmpFile := exec.Command("mktemp")
	tmpFilename, _, err := runCommandWithOutput(createTmpFile)
	if err != nil {
		fmt.Printf("failed to create a temporary file\n")
		os.Exit(1)
	}

	tmpFile, err := os.OpenFile(tmpFilename, os.O_RDWR|os.O_CREATE, 0770)
	if err != nil {
		fmt.Printf("failed to open temporary file %s\n", tmpFilename)
		os.Exit(1)
	}

	if _, err := tmpFile.WriteString(key); err != nil {
		fmt.Printf("failed to write key to temporary file %s\n", tmpFilename)
		tmpFile.Close()
		os.Exit(1)
	}
	tmpFile.Close()

	getFingerprint := exec.Command("ssh-keygen", "-lf", tmpFilename)
	rawFingerprint, _, err := runCommandWithOutput(getFingerprint)
	if err != nil {
		fmt.Printf("failed to read key %s %s\n", err, rawFingerprint)
		os.Exit(1)
	}

	splitFingerprint := strings.Split(rawFingerprint, " ")
	if len(splitFingerprint) < 2 {
		fmt.Printf("fingerprint seems invalid: %s\n", rawFingerprint)
		os.Exit(1)
	}

	if err := os.Remove(tmpFilename); err != nil {
		fmt.Printf("failed to remove the temporary file %s\n", tmpFilename)
		os.Exit(1)
	}

	authorizedKeysFilename := fmt.Sprintf("%s/.ssh/authorized_keys", homeDirectory)
	authorizedKeys, err := os.OpenFile(authorizedKeysFilename, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0600)
	if err != nil {
		fmt.Printf("failed to open authorized_keys %s\n", authorizedKeysFilename)
		os.Exit(1)
	}
	fingerprint := splitFingerprint[1]

	keyPrefixTemplate := `command=%s run %s %s,no-agent-forwarding,no-pty,no-user-rc,no-X11-forwarding,no-port-forwarding`
	keyPrefix := fmt.Sprintf(keyPrefixTemplate, gitreceivePath, username, fingerprint)
	authorizedKeyEntry := fmt.Sprintf("%s %s", keyPrefix, key)

	if _, err := authorizedKeys.WriteString(authorizedKeyEntry); err != nil {
		fmt.Printf("failed to add key to authorized_keys")
		authorizedKeys.Close()
		os.Exit(1)
	}
	authorizedKeys.Close()

	fmt.Printf("%s\n", fingerprint)
}

func run(gitHome, receiveUser, receiveFingerprint, gitreceivePath string) {
	originalSSHCommand := os.Getenv("SSH_ORIGINAL_COMMAND")
	if len(originalSSHCommand) == 0 {
		fmt.Printf("SSH_ORIGINAL_COMMAND is undefined\n")
		os.Exit(1)
	}

	splitOriginalSSHCommand := strings.Split(originalSSHCommand, " ")
	if len(splitOriginalSSHCommand) < 2 {
		fmt.Printf("SSH_ORIGINAL_COMMAND is too short %s\n", originalSSHCommand)
		os.Exit(1)
	}

	repoRaw := splitOriginalSSHCommand[1]
	for key, value := range splitOriginalSSHCommand {
		splitOriginalSSHCommand[key] = strings.Trim(value, "'")
	}

	repo := strings.Trim(repoRaw, "'")

	repoPath := fmt.Sprintf("%s/%s", gitHome, repo)

	if _, err := os.Stat(repoPath); os.IsNotExist(err) {
		if err := os.Mkdir(repoPath, 0770); err != nil {
			fmt.Printf("failed to create repo directory\n")
			os.Exit(1)
		}
		initRepo := exec.Command("git", "init", "--bare")
		initRepo.Dir = repoPath
		if _, _, err := runCommandWithOutput(initRepo); err != nil {
			fmt.Printf("failed to initialize repository\n")
			os.Exit(1)
		}
	}

	prereceiveHookPath := fmt.Sprintf("%s/hooks/pre-receive", repoPath)
	prereceiveHook, err := os.OpenFile(prereceiveHookPath, os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0770)
	if err != nil {
		fmt.Printf("failed to open repo pre-receive hook script\n")
		os.Exit(1)
	}

	renderedPrereceiveScript := fmt.Sprintf(prereceiveScript, gitreceivePath)
	if _, err := prereceiveHook.WriteString(renderedPrereceiveScript); err != nil {
		prereceiveHook.Close()
		fmt.Printf("failed to write repo pre-receive hook script\n")
		os.Exit(1)
	}
	prereceiveHook.Close()
	env := os.Environ()

	receiveUserEnv := fmt.Sprintf("RECEIVE_USER=%s", receiveUser)
	receiveFingerprintEnv := fmt.Sprintf("RECEIVE_FINGERPRINT=%s", receiveFingerprint)
	receiveRepo := fmt.Sprintf("RECEIVE_REPO=%s", repo)
	githomeEnv := fmt.Sprintf("GITHOME=%s", gitHome)

	originalSSHCmd := exec.Command(splitOriginalSSHCommand[0], splitOriginalSSHCommand[1:]...)
	originalSSHCmd.Dir = gitHome
	originalSSHCmd.Env = append(env, receiveUserEnv, receiveFingerprintEnv, receiveRepo, githomeEnv)
	originalSSHCmd.Stdout = os.Stdout
	originalSSHCmd.Stdin = os.Stdin
	originalSSHCmd.Stderr = os.Stderr

	if exitCode, err := runCommand(originalSSHCmd); err != nil {
		fmt.Println(err)
		os.Exit(exitCode)
	}
}

func hook() {
	lineReader := bufio.NewScanner(os.Stdin)

	receiveUser := os.Getenv("RECEIVE_USER")
	receiveFingerprint := os.Getenv("RECEIVE_FINGERPRINT")
	receiveRepo := os.Getenv("RECEIVE_REPO")
	githomeEnv := os.Getenv("GITHOME")

	receiverPath := fmt.Sprintf("%s/receiver", githomeEnv)

	for lineReader.Scan() {
		line := lineReader.Text()
		args := strings.Split(line, " ")
		//oldRev := args[0]
		newRev := args[1]
		refName := args[2]

		if refName != "refs/heads/master" {
			continue
		}

		gitArchiver := exec.Command("git", "archive", newRev)
		receiver := exec.Command(receiverPath, receiveRepo, newRev, receiveUser, receiveFingerprint)
		receiver.Stdin, _ = gitArchiver.StdoutPipe()
		receiver.Stdout = os.Stdout
		err := receiver.Start()
		if err != nil {
			fmt.Printf("push denied - failed to start receiver for %s %s", newRev, err)
			os.Exit(1)
		}
		err = gitArchiver.Run()
		if err != nil {
			fmt.Printf("push denied - failed to run git archiver for %s %s", newRev, err)
			os.Exit(1)
		}
		err = receiver.Wait()
		if err != nil {
			fmt.Printf("push denied - receiver failed to exit cleanly for %s %s", newRev, err)
			os.Exit(1)
		}
	}
}

func main() {
	if len(os.Args) == 1 {
		return
	}

	gitreceivePath := os.Args[0]

	switch os.Args[1] {
	case "init":
		addGitUser(gitHome, gitUser)
	case "upload-key":
		uploadKey(gitHome, gitreceivePath, os.Args[2])
	case "run":
		run(gitHome, os.Args[2], os.Args[3], gitreceivePath)
	case "hook":
		hook()
	}

}
<commit_msg>wrap the ssh command in quotes<commit_after>package main

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"
	"syscall"
)

const gitUser = "git"
const gitHome = "/home/git"

const prereceiveScript = `
#!/bin/bash
cat | %s hook
`

func getExitCode(err error) (int, error) {
	exitCode := 0
	if exiterr, ok := err.(*exec.ExitError); ok {
		if procExit := exiterr.Sys().(syscall.WaitStatus); ok {
			return procExit.ExitStatus(), nil
		}
	}
	return exitCode, fmt.Errorf("failed to get exit code")
}

func runCommandWithOutput(cmd *exec.Cmd) (output string, exitCode int, err error) {
	exitCode = 0
	out, err := cmd.CombinedOutput()
	if err != nil {
		var exiterr error
		if exitCode, exiterr = getExitCode(err); exiterr != nil {
			// TODO: Fix this so we check the error's text.
			// we've failed to retrieve exit code, so we set it to 127
			exitCode = 127
		}
	}
	output = string(out)
	return
}

func runCommand(cmd *exec.Cmd) (exitCode int, err error) {
	exitCode = 0
	err = cmd.Run()
	if err != nil {
		var exiterr error
		if exitCode, exiterr = getExitCode(err); exiterr != nil {
			// TODO: Fix this so we check the error's text.
			// we've failed to retrieve exit code, so we set it to 127
			exitCode = 127
		}
	}
	return
}

func addGitUser(homeDirectory, gitUsername string) {
	userAddCmd := exec.Command("useradd", "-d", homeDirectory, gitUsername)
	if out, _, err := runCommandWithOutput(userAddCmd); err != nil {
		fmt.Printf("failed to execute add user %s\n", out)
		os.Exit(1)
	}

	sshDir := fmt.Sprintf("%s/.ssh", homeDirectory)
	addSshDirCmd := exec.Command("mkdir", "-p", sshDir)
	if _, _, err := runCommandWithOutput(addSshDirCmd); err != nil {
		fmt.Printf("failed to create the .ssh directory\n")
		os.Exit(1)
	}

	authorizedKeysFilename := fmt.Sprintf("%s/.ssh/authorized_keys", homeDirectory)
	authorizedKeys, err := os.OpenFile(authorizedKeysFilename, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0600)
	if err != nil {
		fmt.Printf("failed to open authorized_keys %s\n", authorizedKeysFilename)
		os.Exit(1)
	}
	authorizedKeys.Close()

	changeOWnership := exec.Command("chown", "-R", gitUsername, homeDirectory)
	if _, _, err := runCommandWithOutput(changeOWnership); err != nil {
		fmt.Printf("failed to change ownership\n")
		os.Exit(1)
	}
	fmt.Printf("Created receiver script in %s for user '%s'.\n", homeDirectory, gitUsername)
}

func uploadKey(homeDirectory, gitreceivePath, username string) {
	inputRawKey, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
		fmt.Printf("failed to read key from stdin\n")
		os.Exit(1)
	}
	key := string(inputRawKey)

	// ssh-keygen doesn't read from pipes and sometimes /dev/stdin doesn't work
	// create a temporary file to write the key to it
	createTmpFile := exec.Command("mktemp")
	tmpFilename, _, err := runCommandWithOutput(createTmpFile)
	if err != nil {
		fmt.Printf("failed to create a temporary file\n")
		os.Exit(1)
	}

	tmpFile, err := os.OpenFile(tmpFilename, os.O_RDWR|os.O_CREATE, 0770)
	if err != nil {
		fmt.Printf("failed to open temporary file %s\n", tmpFilename)
		os.Exit(1)
	}

	if _, err := tmpFile.WriteString(key); err != nil {
		fmt.Printf("failed to write key to temporary file %s\n", tmpFilename)
		tmpFile.Close()
		os.Exit(1)
	}
	tmpFile.Close()

	getFingerprint := exec.Command("ssh-keygen", "-lf", tmpFilename)
	rawFingerprint, _, err := runCommandWithOutput(getFingerprint)
	if err != nil {
		fmt.Printf("failed to read key %s %s\n", err, rawFingerprint)
		os.Exit(1)
	}

	splitFingerprint := strings.Split(rawFingerprint, " ")
	if len(splitFingerprint) < 2 {
		fmt.Printf("fingerprint seems invalid: %s\n", rawFingerprint)
		os.Exit(1)
	}

	if err := os.Remove(tmpFilename); err != nil {
		fmt.Printf("failed to remove the temporary file %s\n", tmpFilename)
		os.Exit(1)
	}

	authorizedKeysFilename := fmt.Sprintf("%s/.ssh/authorized_keys", homeDirectory)
	authorizedKeys, err := os.OpenFile(authorizedKeysFilename, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0600)
	if err != nil {
		fmt.Printf("failed to open authorized_keys %s\n", authorizedKeysFilename)
		os.Exit(1)
	}
	fingerprint := splitFingerprint[1]

	keyPrefixTemplate := `command="%s run %s %s",no-agent-forwarding,no-pty,no-user-rc,no-X11-forwarding,no-port-forwarding`
	keyPrefix := fmt.Sprintf(keyPrefixTemplate, gitreceivePath, username, fingerprint)
	authorizedKeyEntry := fmt.Sprintf("%s %s", keyPrefix, key)

	if _, err := authorizedKeys.WriteString(authorizedKeyEntry); err != nil {
		fmt.Printf("failed to add key to authorized_keys")
		authorizedKeys.Close()
		os.Exit(1)
	}
	authorizedKeys.Close()

	fmt.Printf("%s\n", fingerprint)
}

func run(gitHome, receiveUser, receiveFingerprint, gitreceivePath string) {
	originalSSHCommand := os.Getenv("SSH_ORIGINAL_COMMAND")
	if len(originalSSHCommand) == 0 {
		fmt.Printf("SSH_ORIGINAL_COMMAND is undefined\n")
		os.Exit(1)
	}

	splitOriginalSSHCommand := strings.Split(originalSSHCommand, " ")
	if len(splitOriginalSSHCommand) < 2 {
		fmt.Printf("SSH_ORIGINAL_COMMAND is too short %s\n", originalSSHCommand)
		os.Exit(1)
	}

	repoRaw := splitOriginalSSHCommand[1]
	for key, value := range splitOriginalSSHCommand {
		splitOriginalSSHCommand[key] = strings.Trim(value, "'")
	}

	repo := strings.Trim(repoRaw, "'")

	repoPath := fmt.Sprintf("%s/%s", gitHome, repo)

	if _, err := os.Stat(repoPath); os.IsNotExist(err) {
		if err := os.Mkdir(repoPath, 0770); err != nil {
			fmt.Printf("failed to create repo directory\n")
			os.Exit(1)
		}
		initRepo := exec.Command("git", "init", "--bare")
		initRepo.Dir = repoPath
		if _, _, err := runCommandWithOutput(initRepo); err != nil {
			fmt.Printf("failed to initialize repository\n")
			os.Exit(1)
		}
	}

	prereceiveHookPath := fmt.Sprintf("%s/hooks/pre-receive", repoPath)
	prereceiveHook, err := os.OpenFile(prereceiveHookPath, os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0770)
	if err != nil {
		fmt.Printf("failed to open repo pre-receive hook script\n")
		os.Exit(1)
	}

	renderedPrereceiveScript := fmt.Sprintf(prereceiveScript, gitreceivePath)
	if _, err := prereceiveHook.WriteString(renderedPrereceiveScript); err != nil {
		prereceiveHook.Close()
		fmt.Printf("failed to write repo pre-receive hook script\n")
		os.Exit(1)
	}
	prereceiveHook.Close()
	env := os.Environ()

	receiveUserEnv := fmt.Sprintf("RECEIVE_USER=%s", receiveUser)
	receiveFingerprintEnv := fmt.Sprintf("RECEIVE_FINGERPRINT=%s", receiveFingerprint)
	receiveRepo := fmt.Sprintf("RECEIVE_REPO=%s", repo)
	githomeEnv := fmt.Sprintf("GITHOME=%s", gitHome)

	originalSSHCmd := exec.Command(splitOriginalSSHCommand[0], splitOriginalSSHCommand[1:]...)
	originalSSHCmd.Dir = gitHome
	originalSSHCmd.Env = append(env, receiveUserEnv, receiveFingerprintEnv, receiveRepo, githomeEnv)
	originalSSHCmd.Stdout = os.Stdout
	originalSSHCmd.Stdin = os.Stdin
	originalSSHCmd.Stderr = os.Stderr

	if exitCode, err := runCommand(originalSSHCmd); err != nil {
		fmt.Println(err)
		os.Exit(exitCode)
	}
}

func hook() {
	lineReader := bufio.NewScanner(os.Stdin)

	receiveUser := os.Getenv("RECEIVE_USER")
	receiveFingerprint := os.Getenv("RECEIVE_FINGERPRINT")
	receiveRepo := os.Getenv("RECEIVE_REPO")
	githomeEnv := os.Getenv("GITHOME")

	receiverPath := fmt.Sprintf("%s/receiver", githomeEnv)

	for lineReader.Scan() {
		line := lineReader.Text()
		args := strings.Split(line, " ")
		//oldRev := args[0]
		newRev := args[1]
		refName := args[2]

		if refName != "refs/heads/master" {
			continue
		}

		gitArchiver := exec.Command("git", "archive", newRev)
		receiver := exec.Command(receiverPath, receiveRepo, newRev, receiveUser, receiveFingerprint)
		receiver.Stdin, _ = gitArchiver.StdoutPipe()
		receiver.Stdout = os.Stdout
		err := receiver.Start()
		if err != nil {
			fmt.Printf("push denied - failed to start receiver for %s %s", newRev, err)
			os.Exit(1)
		}
		err = gitArchiver.Run()
		if err != nil {
			fmt.Printf("push denied - failed to run git archiver for %s %s", newRev, err)
			os.Exit(1)
		}
		err = receiver.Wait()
		if err != nil {
			fmt.Printf("push denied - receiver failed to exit cleanly for %s %s", newRev, err)
			os.Exit(1)
		}
	}
}

func main() {
	if len(os.Args) == 1 {
		return
	}

	gitreceivePath := os.Args[0]

	switch os.Args[1] {
	case "init":
		addGitUser(gitHome, gitUser)
	case "upload-key":
		uploadKey(gitHome, gitreceivePath, os.Args[2])
	case "run":
		run(gitHome, os.Args[2], os.Args[3], gitreceivePath)
	case "hook":
		hook()
	}

}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"strconv"

	"github.com/deis/deisctl/client"
	"github.com/deis/deisctl/cmd"

	docopt "github.com/docopt/docopt-go"
)

const (
	// Version of deisctl client
	Version string = "0.11.0"
)

func exit(err error, code int) {
	fmt.Printf("Error: %v\n", err)
	os.Exit(code)
}

func setGlobalFlags(args map[string]interface{}) {
	client.Flags.Debug = args["--debug"].(bool)
	client.Flags.Version = args["--version"].(bool)
	client.Flags.Endpoint = args["--endpoint"].(string)
	client.Flags.EtcdKeyPrefix = args["--etcd-key-prefix"].(string)
	client.Flags.EtcdKeyFile = args["--etcd-keyfile"].(string)
	client.Flags.EtcdCertFile = args["--etcd-certfile"].(string)
	client.Flags.EtcdCAFile = args["--etcd-cafile"].(string)
	//client.Flags.UseAPI = args["--experimental-api"].(bool)
	client.Flags.KnownHostsFile = args["--known-hosts-file"].(string)
	client.Flags.StrictHostKeyChecking = args["--strict-host-key-checking"].(bool)
	timeout, _ := strconv.ParseFloat(args["--request-timeout"].(string), 64)
	client.Flags.RequestTimeout = timeout
	tunnel := args["--tunnel"].(string)
	if tunnel != "" {
		client.Flags.Tunnel = tunnel
	} else {
		client.Flags.Tunnel = os.Getenv("DEISCTL_TUNNEL")
	}
}

func main() {
	usage := `Deis Control Utility

Usage:
  deisctl <command> [<target>...] [options]

Example Commands:

  deisctl install platform
  deisctl uninstall builder@1
  deisctl list
  deisctl scale router=2
  deisctl start router@2
  deisctl stop router builder
  deisctl status controller
  deisctl journal controller

Options:
  --debug                     print debug information to stderr
  --version                   print version and exit
  --endpoint=<url>            etcd endpoint for fleet [default: http://127.0.0.1:4001]
  --etcd-key-prefix=<path>    keyspace for fleet data in etcd [default: /_coreos.com/fleet/]
  --etcd-keyfile=<path>       etcd key file authentication [default: ]
  --etcd-certfile=<path>      etcd cert file authentication [default: ]
  --etcd-cafile=<path>        etcd CA file authentication [default: ]
  --known-hosts-file=<path>   file used to store remote machine fingerprints [default: ~/.ssh/known_hosts]
  --strict-host-key-checking  verify SSH host keys [default: true]
  --tunnel=<host>             establish an SSH tunnel for communication with fleet and etcd [default: ]
  --request-timeout=<secs>    amount of time to allow a single request before considering it failed. [default: 3.0]
`
	// special handling for version
	if len(os.Args) == 2 && os.Args[1] == "--version" {
		fmt.Println(Version)
		os.Exit(0)
	}
	// parse command-line arguments
	args, err := docopt.Parse(usage, nil, true, "", true)
	if err != nil {
		exit(err, 2)
	}
	command := args["<command>"]
	targets := args["<target>"].([]string)
	setGlobalFlags(args)
	// construct a client
	c, err := client.NewClient()
	if err != nil {
		exit(err, 1)
	}
	// dispatch the command
	switch command {
	case "list":
		err = cmd.ListUnits(c)
	case "list-units":
		err = cmd.ListUnits(c)
	case "list-unit-files":
		err = cmd.ListUnitFiles(c)
	case "scale":
		err = cmd.Scale(c, targets)
	case "start":
		err = cmd.Start(c, targets)
	case "restart":
		err = cmd.Restart(c, targets)
	case "stop":
		err = cmd.Stop(c, targets)
	case "status":
		err = cmd.Status(c, targets)
	case "journal":
		err = cmd.Journal(c, targets)
	case "install":
		err = cmd.Install(c, targets)
	case "uninstall":
		err = cmd.Uninstall(c, targets)
	case "config":
		err = cmd.Config()
	case "update":
		err = cmd.Update()
	case "refresh-units":
		err = cmd.RefreshUnits()
	default:
		fmt.Printf(usage)
		os.Exit(2)
	}
	if err != nil {
		exit(err, 1)
	}
}
<commit_msg>fix(debug): remove unused --debug option<commit_after>package main

import (
	"fmt"
	"os"
	"strconv"

	"github.com/deis/deisctl/client"
	"github.com/deis/deisctl/cmd"

	docopt "github.com/docopt/docopt-go"
)

const (
	// Version of deisctl client
	Version string = "0.11.0"
)

func exit(err error, code int) {
	fmt.Printf("Error: %v\n", err)
	os.Exit(code)
}

func setGlobalFlags(args map[string]interface{}) {
	client.Flags.Debug = args["--debug"].(bool)
	client.Flags.Version = args["--version"].(bool)
	client.Flags.Endpoint = args["--endpoint"].(string)
	client.Flags.EtcdKeyPrefix = args["--etcd-key-prefix"].(string)
	client.Flags.EtcdKeyFile = args["--etcd-keyfile"].(string)
	client.Flags.EtcdCertFile = args["--etcd-certfile"].(string)
	client.Flags.EtcdCAFile = args["--etcd-cafile"].(string)
	//client.Flags.UseAPI = args["--experimental-api"].(bool)
	client.Flags.KnownHostsFile = args["--known-hosts-file"].(string)
	client.Flags.StrictHostKeyChecking = args["--strict-host-key-checking"].(bool)
	timeout, _ := strconv.ParseFloat(args["--request-timeout"].(string), 64)
	client.Flags.RequestTimeout = timeout
	tunnel := args["--tunnel"].(string)
	if tunnel != "" {
		client.Flags.Tunnel = tunnel
	} else {
		client.Flags.Tunnel = os.Getenv("DEISCTL_TUNNEL")
	}
}

func main() {
	usage := `Deis Control Utility

Usage:
  deisctl <command> [<target>...] [options]

Example Commands:

  deisctl install platform
  deisctl uninstall builder@1
  deisctl list
  deisctl scale router=2
  deisctl start router@2
  deisctl stop router builder
  deisctl status controller
  deisctl journal controller

Options:
  --version                   print version and exit
  --endpoint=<url>            etcd endpoint for fleet [default: http://127.0.0.1:4001]
  --etcd-key-prefix=<path>    keyspace for fleet data in etcd [default: /_coreos.com/fleet/]
  --etcd-keyfile=<path>       etcd key file authentication [default: ]
  --etcd-certfile=<path>      etcd cert file authentication [default: ]
  --etcd-cafile=<path>        etcd CA file authentication [default: ]
  --known-hosts-file=<path>   file used to store remote machine fingerprints [default: ~/.ssh/known_hosts]
  --strict-host-key-checking  verify SSH host keys [default: true]
  --tunnel=<host>             establish an SSH tunnel for communication with fleet and etcd [default: ]
  --request-timeout=<secs>    amount of time to allow a single request before considering it failed. [default: 3.0]
`
	// special handling for version
	if len(os.Args) == 2 && os.Args[1] == "--version" {
		fmt.Println(Version)
		os.Exit(0)
	}
	// parse command-line arguments
	args, err := docopt.Parse(usage, nil, true, "", true)
	if err != nil {
		exit(err, 2)
	}
	command := args["<command>"]
	targets := args["<target>"].([]string)
	setGlobalFlags(args)
	// construct a client
	c, err := client.NewClient()
	if err != nil {
		exit(err, 1)
	}
	// dispatch the command
	switch command {
	case "list":
		err = cmd.ListUnits(c)
	case "list-units":
		err = cmd.ListUnits(c)
	case "list-unit-files":
		err = cmd.ListUnitFiles(c)
	case "scale":
		err = cmd.Scale(c, targets)
	case "start":
		err = cmd.Start(c, targets)
	case "restart":
		err = cmd.Restart(c, targets)
	case "stop":
		err = cmd.Stop(c, targets)
	case "status":
		err = cmd.Status(c, targets)
	case "journal":
		err = cmd.Journal(c, targets)
	case "install":
		err = cmd.Install(c, targets)
	case "uninstall":
		err = cmd.Uninstall(c, targets)
	case "config":
		err = cmd.Config()
	case "update":
		err = cmd.Update()
	case "refresh-units":
		err = cmd.RefreshUnits()
	default:
		fmt.Printf(usage)
		os.Exit(2)
	}
	if err != nil {
		exit(err, 1)
	}
}
<|endoftext|>


<commit_before>package cu

// This file provides CGO flags to find CUDA libraries and headers.

//#cgo LDFLAGS:-lcuda
//
////default location:
//#cgo linux,windows LDFLAGS:-L/usr/local/cuda/lib64 -L/usr/local/cuda/lib
//#cgo linux,windows CFLAGS: -I/usr/local/cuda/include/
//
////default location if not properly symlinked:
//#cgo linux LDFLAGS:-L/usr/local/cuda-10.1/lib64 -L/usr/local/cuda-10.1/lib
//#cgo linux LDFLAGS:-L/usr/local/cuda-6.0/lib64 -L/usr/local/cuda-6.0/lib
//#cgo linux LDFLAGS:-L/usr/local/cuda-5.5/lib64 -L/usr/local/cuda-5.5/lib
//#cgo linux LDFLAGS:-L/usr/local/cuda-5.0/lib64 -L/usr/local/cuda-5.0/lib
//#cgo linux CFLAGS: -I/usr/local/cuda-10.1/include/
//#cgo linux CFLAGS: -I/usr/local/cuda-6.0/include/
//#cgo linux CFLAGS: -I/usr/local/cuda-5.5/include/
//#cgo linux CFLAGS: -I/usr/local/cuda-5.0/include/
//
////Ubuntu 15.04:
//#cgo linux LDFLAGS:-L/usr/lib/x86_64-linux-gnu/
//#cgo linux CFLAGS: -I/usr/include
//
////arch linux:
//#cgo linux LDFLAGS:-L/opt/cuda/lib64 -L/opt/cuda/lib
//#cgo linux CFLAGS: -I/opt/cuda/include
//
////Darwin:
//#cgo darwin LDFLAGS:-L/usr/local/cuda/lib
//#cgo darwin CFLAGS: -I/usr/local/cuda/include/
//
////WINDOWS:
//#cgo windows LDFLAGS:-LC:/cuda/v5.0/lib/x64 -LC:/cuda/v5.5/lib/x64 -LC:/cuda/v6.0/lib/x64 -LC:/cuda/v6.5/lib/x64 -LC:/cuda/v7.0/lib/x64 -LC:/cuda/v8.0/lib/x64 -LC:/cuda/v9.0/x64
//#cgo windows CFLAGS: -IC:/cuda/v5.0/include -IC:/cuda/v5.5/include -IC:/cuda/v6.0/include -IC:/cuda/v6.5/include -IC:/cuda/v7.0/include -IC:/cuda/v8.0/include -IC:/cuda/v9.0/include
import "C"
<commit_msg>Add cuda 10.2 CFLAGS path<commit_after>package cu

// This file provides CGO flags to find CUDA libraries and headers.

//#cgo LDFLAGS:-lcuda
//
////default location:
//#cgo linux,windows LDFLAGS:-L/usr/local/cuda/lib64 -L/usr/local/cuda/lib
//#cgo linux,windows CFLAGS: -I/usr/local/cuda/include/
//
////default location if not properly symlinked:
//#cgo linux LDFLAGS:-L/usr/local/cuda-10.1/lib64 -L/usr/local/cuda-10.1/lib
//#cgo linux LDFLAGS:-L/usr/local/cuda-6.0/lib64 -L/usr/local/cuda-6.0/lib
//#cgo linux LDFLAGS:-L/usr/local/cuda-5.5/lib64 -L/usr/local/cuda-5.5/lib
//#cgo linux LDFLAGS:-L/usr/local/cuda-5.0/lib64 -L/usr/local/cuda-5.0/lib
//#cgo linux CFLAGS: -I/usr/local/cuda-10.2/include/
//#cgo linux CFLAGS: -I/usr/local/cuda-10.1/include/
//#cgo linux CFLAGS: -I/usr/local/cuda-6.0/include/
//#cgo linux CFLAGS: -I/usr/local/cuda-5.5/include/
//#cgo linux CFLAGS: -I/usr/local/cuda-5.0/include/
//
////Ubuntu 15.04:
//#cgo linux LDFLAGS:-L/usr/lib/x86_64-linux-gnu/
//#cgo linux CFLAGS: -I/usr/include
//
////arch linux:
//#cgo linux LDFLAGS:-L/opt/cuda/lib64 -L/opt/cuda/lib
//#cgo linux CFLAGS: -I/opt/cuda/include
//
////Darwin:
//#cgo darwin LDFLAGS:-L/usr/local/cuda/lib
//#cgo darwin CFLAGS: -I/usr/local/cuda/include/
//
////WINDOWS:
//#cgo windows LDFLAGS:-LC:/cuda/v5.0/lib/x64 -LC:/cuda/v5.5/lib/x64 -LC:/cuda/v6.0/lib/x64 -LC:/cuda/v6.5/lib/x64 -LC:/cuda/v7.0/lib/x64 -LC:/cuda/v8.0/lib/x64 -LC:/cuda/v9.0/x64
//#cgo windows CFLAGS: -IC:/cuda/v5.0/include -IC:/cuda/v5.5/include -IC:/cuda/v6.0/include -IC:/cuda/v6.5/include -IC:/cuda/v7.0/include -IC:/cuda/v8.0/include -IC:/cuda/v9.0/include
import "C"
<|endoftext|>


<commit_before>package kindergarten

import (
	"fmt"
	"sort"
	"strings"
)

// Define the Garden type here.
type Garden struct {
	diagram  []string
	children []string
}

var symbolToPlant = map[string]string{
	"R": "radishes",
	"C": "clover",
	"G": "grass",
	"V": "violets",
}

// The diagram argument starts each row with a '\n'.  This allows Go's
// raw string literals to present diagrams in source code nicely as two
// rows flush left, for example,
//
//     diagram := `
//     VVCCGG
//     VVCCGG`

func NewGarden(diagram string, children []string) (*Garden, error) {
	if !isValidDiagram(diagram) {
		return &Garden{}, fmt.Errorf("invalid diagram")
	}
	trimmed := strings.Trim(diagram, "\n")
	rows := strings.Split(trimmed, "\n")
	sort.Strings(children)
	return &Garden{diagram: rows, children: children}, nil
}

func (g *Garden) Plants(child string) (plants []string, ok bool) {
	fmt.Printf("diagrams %v\n", g.diagram)
	index := indexOf(g.children, child)
	column := index * 2
	cups := []string{
		string(g.diagram[0][column]),
		string(g.diagram[0][column+1]),
		string(g.diagram[1][column]),
		string(g.diagram[1][column+1]),
	}
	for _, cup := range cups {
		plants = append(plants, symbolToPlant[cup])
	}
	return plants, true
}

func isValidDiagram(diagram string) bool {
	return strings.HasPrefix(diagram, "\n")
}

func indexOf(slice []string, element string) int {
	for i, v := range slice {
		if v == element {
			return i
		}
	}
	return -1
}
<commit_msg>Pass test 8 by checking for even rows<commit_after>package kindergarten

import (
	"fmt"
	"sort"
	"strings"
)

// Define the Garden type here.
type Garden struct {
	diagram  []string
	children []string
}

var symbolToPlant = map[string]string{
	"R": "radishes",
	"C": "clover",
	"G": "grass",
	"V": "violets",
}

// The diagram argument starts each row with a '\n'.  This allows Go's
// raw string literals to present diagrams in source code nicely as two
// rows flush left, for example,
//
//     diagram := `
//     VVCCGG
//     VVCCGG`

func NewGarden(diagram string, children []string) (*Garden, error) {
	if !isValidDiagram(diagram) {
		return &Garden{}, fmt.Errorf("invalid diagram")
	}
	sort.Strings(children)
	return &Garden{diagram: getDiagramRows(diagram), children: children}, nil
}

func (g *Garden) Plants(child string) (plants []string, ok bool) {
	fmt.Printf("diagrams %v\n", g.diagram)
	index := indexOf(g.children, child)
	column := index * 2
	cups := []string{
		string(g.diagram[0][column]),
		string(g.diagram[0][column+1]),
		string(g.diagram[1][column]),
		string(g.diagram[1][column+1]),
	}
	for _, cup := range cups {
		plants = append(plants, symbolToPlant[cup])
	}
	return plants, true
}

func isValidDiagram(diagram string) bool {
	return strings.HasPrefix(diagram, "\n") && isEvenRows(diagram)
}

func isEvenRows(diagram string) bool {
	rows := getDiagramRows(diagram)
	return len(rows[0]) == len(rows[1])
}

func getDiagramRows(diagram string) (rows []string) {
	trimmed := strings.Trim(diagram, "\n")
	return strings.Split(trimmed, "\n")
}

func indexOf(slice []string, element string) int {
	for i, v := range slice {
		if v == element {
			return i
		}
	}
	return -1
}
<|endoftext|>


<commit_before>package glut

import (
	"time"

	"github.com/256dpi/fire/coal"
)

// Value stores an arbitrary value.
type Value struct {
	coal.Base `json:"-" bson:",inline" coal:"values"`

	// The component managing the value.
	Component string `json:"component"`

	// The name of the value e.g. "my-value".
	Name string `json:"name"`

	// The content of the value.
	Data []byte `json:"data"`

	// The time after the value can be deleted.
	Deadline *time.Time

	// The time until the value is locked.
	Locked *time.Time `json:"locked"`

	// The token used to lock the value.
	Token *coal.ID `json:"token"`
}

// AddValueIndexes will add value indexes to the specified indexer. If
// removeAfter is values are automatically removed when their TTK timestamp
// falls behind the specified duration.
func AddValueIndexes(indexer *coal.Indexer, removeAfter time.Duration) {
	// index and require name to be unique among components
	indexer.Add(&Value{}, true, 0, "Component", "Name")

	// add ttl index
	indexer.Add(&Value{}, false, removeAfter, "Deadline")
}
<commit_msg>added missing tag<commit_after>package glut

import (
	"time"

	"github.com/256dpi/fire/coal"
)

// Value stores an arbitrary value.
type Value struct {
	coal.Base `json:"-" bson:",inline" coal:"values"`

	// The component managing the value.
	Component string `json:"component"`

	// The name of the value e.g. "my-value".
	Name string `json:"name"`

	// The content of the value.
	Data []byte `json:"data"`

	// The time after the value can be deleted.
	Deadline *time.Time `json:"deadline"`

	// The time until the value is locked.
	Locked *time.Time `json:"locked"`

	// The token used to lock the value.
	Token *coal.ID `json:"token"`
}

// AddValueIndexes will add value indexes to the specified indexer. If
// removeAfter is values are automatically removed when their TTK timestamp
// falls behind the specified duration.
func AddValueIndexes(indexer *coal.Indexer, removeAfter time.Duration) {
	// index and require name to be unique among components
	indexer.Add(&Value{}, true, 0, "Component", "Name")

	// add ttl index
	indexer.Add(&Value{}, false, removeAfter, "Deadline")
}
<|endoftext|>


<commit_before>// Copyright 2014 The oauth2 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 oauth2 provides support for making
// OAuth2 authorized and authenticated HTTP requests.
// It can additionally grant authorization with Bearer JWT.
package oauth2

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"mime"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
)

type tokenRespBody struct {
	AccessToken  string `json:"access_token"`
	TokenType    string `json:"token_type"`
	RefreshToken string `json:"refresh_token"`
	ExpiresIn    int64  `json:"expires_in"` // in seconds
	IdToken      string `json:"id_token"`
}

// TokenFetcher refreshes or fetches a new access token from the
// provider. It should return an error if it's not capable of
// retrieving a token.
type TokenFetcher interface {
	// FetchToken retrieves a new access token for the provider.
	// If the implementation doesn't know how to retrieve a new token,
	// it returns an error.
	FetchToken(existing *Token) (*Token, error)
}

// Options represents options to provide OAuth 2.0 client credentials
// and access level. A sample configuration:
//
//    opts := &oauth2.Options{
//        ClientID: "<clientID>",
//        ClientSecret: "ad4364309eff",
//        RedirectURL: "https://homepage/oauth2callback",
//        Scopes: []string{"scope1", "scope2"},
//        AccessType: "offline", // retrieves a refresh token
//    }
//
type Options struct {
	// ClientID is the OAuth client identifier used when communicating with
	// the configured OAuth provider.
	ClientID string `json:"client_id"`

	// ClientSecret is the OAuth client secret used when communicating with
	// the configured OAuth provider.
	ClientSecret string `json:"client_secret"`

	// RedirectURL is the URL to which the user will be returned after
	// granting (or denying) access.
	RedirectURL string `json:"redirect_url"`

	// Optional, identifies the level of access being requested.
	Scopes []string `json:"scopes"`

	// AccessType is an OAuth extension that gets sent as the
	// "access_type" field in the URL from AuthCodeURL.
	// See https://developers.google.com/accounts/docs/OAuth2WebServer.
	// It may be "online" (the default) or "offline".
	// If your application needs to refresh access tokens when the
	// user is not present at the browser, then use offline. This
	// will result in your application obtaining a refresh token
	// the first time your application exchanges an authorization
	// code for a user.
	AccessType string `json:"omit"`

	// ApprovalPrompt indicates whether the user should be
	// re-prompted for consent. If set to "auto" (default) the
	// user will be prompted only if they haven't previously
	// granted consent and the code can only be exchanged for an
	// access token.
	// If set to "force" the user will always be prompted, and the
	// code can be exchanged for a refresh token.
	ApprovalPrompt string `json:"omit"`
}

// NewConfig creates a generic OAuth 2.0 configuration that talks
// to an OAuth 2.0 provider specified with authURL and tokenURL.
func NewConfig(opts *Options, authURL, tokenURL string) (*Config, error) {
	aURL, err := url.Parse(authURL)
	if err != nil {
		return nil, err
	}
	tURL, err := url.Parse(tokenURL)
	if err != nil {
		return nil, err
	}
	conf := &Config{opts: opts, authURL: aURL, tokenURL: tURL}
	if err = conf.validate(); err != nil {
		return nil, err
	}
	return conf, nil
}

// Config represents the configuration of an OAuth 2.0 consumer client.
type Config struct {
	opts *Options
	// AuthURL is the URL the user will be directed to
	// in order to grant access.
	authURL *url.URL
	// TokenURL is the URL used to retrieve OAuth tokens.
	tokenURL *url.URL
}

// AuthCodeURL returns a URL to OAuth 2.0 provider's consent page
// that asks for permissions for the required scopes explicitly.
func (c *Config) AuthCodeURL(state string) (authURL string) {
	u := *c.authURL
	vals := url.Values{
		"response_type": {"code"},
		"client_id":     {c.opts.ClientID},
		"scope":         {strings.Join(c.opts.Scopes, " ")},
		"state":         {state},
	}
	if c.opts.AccessType != "" {
		vals.Set("access_type", c.opts.AccessType)
	}
	if c.opts.ApprovalPrompt != "" {
		vals.Set("approval_prompt", c.opts.ApprovalPrompt)
	}
	if c.opts.RedirectURL != "" {
		vals.Set("redirect_uri", c.opts.RedirectURL)
	}
	q := vals.Encode()
	if u.RawQuery == "" {
		u.RawQuery = q
	} else {
		u.RawQuery += "&" + q
	}
	return u.String()
}

// NewTransport creates a new authorizable transport. It doesn't
// initialize the new transport with a token, so after creation,
// you need to set a valid token (or an expired token with a valid
// refresh token) in order to be able to do authorized requests.
//
// Example:
//     t, _ := c.NewTransport()
//     t.SetToken(validToken)
//
func (c *Config) NewTransport() Transport {
	return NewAuthorizedTransport(http.DefaultTransport, c, nil)
}

// NewTransportWithCode exchanges the OAuth 2.0 exchange code with
// the provider to fetch a new access token (and refresh token). Once
// it succesffully retrieves a new token, creates a new transport
// authorized with it.
func (c *Config) NewTransportWithCode(exchangeCode string) (Transport, error) {
	token, err := c.Exchange(exchangeCode)
	if err != nil {
		return nil, err
	}
	return NewAuthorizedTransport(http.DefaultTransport, c, token), nil
}

// FetchToken retrieves a new access token and updates the existing token
// with the newly fetched credentials. If existing token doesn't
// contain a refresh token, it returns an error.
func (c *Config) FetchToken(existing *Token) (*Token, error) {
	if existing == nil || existing.RefreshToken == "" {
		return nil, errors.New("cannot fetch access token without refresh token.")
	}
	err := c.updateToken(existing, url.Values{
		"grant_type":    {"refresh_token"},
		"refresh_token": {existing.RefreshToken},
	})
	return existing, err
}

// Checks if all required configuration fields have non-zero values.
func (c *Config) validate() error {
	if c.opts.ClientID == "" {
		return errors.New("A client ID should be provided.")
	}
	if c.opts.ClientSecret == "" {
		return errors.New("A client secret should be provided.")
	}
	return nil
}

// Exchange exchanges the exchange code with the OAuth 2.0 provider
// to retrieve a new access token.
func (c *Config) Exchange(exchangeCode string) (*Token, error) {
	token := &Token{}
	vals := url.Values{
		"grant_type":    {"authorization_code"},
		"client_secret": {c.opts.ClientSecret},
		"code":          {exchangeCode},
	}
	if len(c.opts.Scopes) != 0 {
		vals.Set("scope", strings.Join(c.opts.Scopes, " "))
	}
	if c.opts.RedirectURL != "" {
		vals.Set("redirect_uri", c.opts.RedirectURL)
	}
	err := c.updateToken(token, vals)
	if err != nil {
		return nil, err
	}
	return token, nil
}

// updateToken mutates both tok and v.
func (c *Config) updateToken(tok *Token, v url.Values) error {
	v.Set("client_id", c.opts.ClientID)
	// Note that we're not setting v's client_secret to t.ClientSecret, due
	// to https://code.google.com/p/goauth2/issues/detail?id=31
	// Reddit only accepts client_secret in Authorization header.
	// Dropbox accepts either, but not both.
	// The spec requires servers to always support the Authorization header,
	// so that's all we use.
	r, err := http.DefaultClient.PostForm(c.tokenURL.String(), v)
	if err != nil {
		return err
	}
	defer r.Body.Close()
	if r.StatusCode != 200 {
		// TODO(jbd): Add status code or error message
		return errors.New("Error during updating token.")
	}

	resp := &tokenRespBody{}
	content, _, _ := mime.ParseMediaType(r.Header.Get("Content-Type"))
	switch content {
	case "application/x-www-form-urlencoded", "text/plain":
		body, err := ioutil.ReadAll(r.Body)
		if err != nil {
			return err
		}
		vals, err := url.ParseQuery(string(body))
		if err != nil {
			return err
		}
		resp.AccessToken = vals.Get("access_token")
		resp.TokenType = vals.Get("token_type")
		resp.RefreshToken = vals.Get("refresh_token")
		resp.ExpiresIn, _ = strconv.ParseInt(vals.Get("expires_in"), 10, 64)
		resp.IdToken = vals.Get("id_token")
	default:
		if err = json.NewDecoder(r.Body).Decode(&resp); err != nil {
			return err
		}
	}
	tok.AccessToken = resp.AccessToken
	tok.TokenType = resp.TokenType
	// Don't overwrite `RefreshToken` with an empty value
	if resp.RefreshToken != "" {
		tok.RefreshToken = resp.RefreshToken
	}
	if resp.ExpiresIn == 0 {
		tok.Expiry = time.Time{}
	} else {
		tok.Expiry = time.Now().Add(time.Duration(resp.ExpiresIn) * time.Second)
	}
	if resp.IdToken != "" {
		if tok.Extra == nil {
			tok.Extra = make(map[string]string)
		}
		tok.Extra["id_token"] = resp.IdToken
	}
	return nil
}
<commit_msg>Fixing json tags.<commit_after>// Copyright 2014 The oauth2 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 oauth2 provides support for making
// OAuth2 authorized and authenticated HTTP requests.
// It can additionally grant authorization with Bearer JWT.
package oauth2

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"mime"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
)

type tokenRespBody struct {
	AccessToken  string `json:"access_token"`
	TokenType    string `json:"token_type"`
	RefreshToken string `json:"refresh_token"`
	ExpiresIn    int64  `json:"expires_in"` // in seconds
	IdToken      string `json:"id_token"`
}

// TokenFetcher refreshes or fetches a new access token from the
// provider. It should return an error if it's not capable of
// retrieving a token.
type TokenFetcher interface {
	// FetchToken retrieves a new access token for the provider.
	// If the implementation doesn't know how to retrieve a new token,
	// it returns an error.
	FetchToken(existing *Token) (*Token, error)
}

// Options represents options to provide OAuth 2.0 client credentials
// and access level. A sample configuration:
//
//    opts := &oauth2.Options{
//        ClientID: "<clientID>",
//        ClientSecret: "ad4364309eff",
//        RedirectURL: "https://homepage/oauth2callback",
//        Scopes: []string{"scope1", "scope2"},
//        AccessType: "offline", // retrieves a refresh token
//    }
//
type Options struct {
	// ClientID is the OAuth client identifier used when communicating with
	// the configured OAuth provider.
	ClientID string `json:"client_id"`

	// ClientSecret is the OAuth client secret used when communicating with
	// the configured OAuth provider.
	ClientSecret string `json:"client_secret"`

	// RedirectURL is the URL to which the user will be returned after
	// granting (or denying) access.
	RedirectURL string `json:"redirect_url"`

	// Optional, identifies the level of access being requested.
	Scopes []string `json:"scopes"`

	// AccessType is an OAuth extension that gets sent as the
	// "access_type" field in the URL from AuthCodeURL.
	// See https://developers.google.com/accounts/docs/OAuth2WebServer.
	// It may be "online" (the default) or "offline".
	// If your application needs to refresh access tokens when the
	// user is not present at the browser, then use offline. This
	// will result in your application obtaining a refresh token
	// the first time your application exchanges an authorization
	// code for a user.
	AccessType string `json:"access_type,omitempty"`

	// ApprovalPrompt indicates whether the user should be
	// re-prompted for consent. If set to "auto" (default) the
	// user will be prompted only if they haven't previously
	// granted consent and the code can only be exchanged for an
	// access token.
	// If set to "force" the user will always be prompted, and the
	// code can be exchanged for a refresh token.
	ApprovalPrompt string `json:"-"`
}

// NewConfig creates a generic OAuth 2.0 configuration that talks
// to an OAuth 2.0 provider specified with authURL and tokenURL.
func NewConfig(opts *Options, authURL, tokenURL string) (*Config, error) {
	aURL, err := url.Parse(authURL)
	if err != nil {
		return nil, err
	}
	tURL, err := url.Parse(tokenURL)
	if err != nil {
		return nil, err
	}
	conf := &Config{opts: opts, authURL: aURL, tokenURL: tURL}
	if err = conf.validate(); err != nil {
		return nil, err
	}
	return conf, nil
}

// Config represents the configuration of an OAuth 2.0 consumer client.
type Config struct {
	opts *Options
	// AuthURL is the URL the user will be directed to
	// in order to grant access.
	authURL *url.URL
	// TokenURL is the URL used to retrieve OAuth tokens.
	tokenURL *url.URL
}

// AuthCodeURL returns a URL to OAuth 2.0 provider's consent page
// that asks for permissions for the required scopes explicitly.
func (c *Config) AuthCodeURL(state string) (authURL string) {
	u := *c.authURL
	vals := url.Values{
		"response_type": {"code"},
		"client_id":     {c.opts.ClientID},
		"scope":         {strings.Join(c.opts.Scopes, " ")},
		"state":         {state},
	}
	if c.opts.AccessType != "" {
		vals.Set("access_type", c.opts.AccessType)
	}
	if c.opts.ApprovalPrompt != "" {
		vals.Set("approval_prompt", c.opts.ApprovalPrompt)
	}
	if c.opts.RedirectURL != "" {
		vals.Set("redirect_uri", c.opts.RedirectURL)
	}
	q := vals.Encode()
	if u.RawQuery == "" {
		u.RawQuery = q
	} else {
		u.RawQuery += "&" + q
	}
	return u.String()
}

// NewTransport creates a new authorizable transport. It doesn't
// initialize the new transport with a token, so after creation,
// you need to set a valid token (or an expired token with a valid
// refresh token) in order to be able to do authorized requests.
//
// Example:
//     t, _ := c.NewTransport()
//     t.SetToken(validToken)
//
func (c *Config) NewTransport() Transport {
	return NewAuthorizedTransport(http.DefaultTransport, c, nil)
}

// NewTransportWithCode exchanges the OAuth 2.0 exchange code with
// the provider to fetch a new access token (and refresh token). Once
// it succesffully retrieves a new token, creates a new transport
// authorized with it.
func (c *Config) NewTransportWithCode(exchangeCode string) (Transport, error) {
	token, err := c.Exchange(exchangeCode)
	if err != nil {
		return nil, err
	}
	return NewAuthorizedTransport(http.DefaultTransport, c, token), nil
}

// FetchToken retrieves a new access token and updates the existing token
// with the newly fetched credentials. If existing token doesn't
// contain a refresh token, it returns an error.
func (c *Config) FetchToken(existing *Token) (*Token, error) {
	if existing == nil || existing.RefreshToken == "" {
		return nil, errors.New("cannot fetch access token without refresh token.")
	}
	err := c.updateToken(existing, url.Values{
		"grant_type":    {"refresh_token"},
		"refresh_token": {existing.RefreshToken},
	})
	return existing, err
}

// Checks if all required configuration fields have non-zero values.
func (c *Config) validate() error {
	if c.opts.ClientID == "" {
		return errors.New("A client ID should be provided.")
	}
	if c.opts.ClientSecret == "" {
		return errors.New("A client secret should be provided.")
	}
	return nil
}

// Exchange exchanges the exchange code with the OAuth 2.0 provider
// to retrieve a new access token.
func (c *Config) Exchange(exchangeCode string) (*Token, error) {
	token := &Token{}
	vals := url.Values{
		"grant_type":    {"authorization_code"},
		"client_secret": {c.opts.ClientSecret},
		"code":          {exchangeCode},
	}
	if len(c.opts.Scopes) != 0 {
		vals.Set("scope", strings.Join(c.opts.Scopes, " "))
	}
	if c.opts.RedirectURL != "" {
		vals.Set("redirect_uri", c.opts.RedirectURL)
	}
	err := c.updateToken(token, vals)
	if err != nil {
		return nil, err
	}
	return token, nil
}

// updateToken mutates both tok and v.
func (c *Config) updateToken(tok *Token, v url.Values) error {
	v.Set("client_id", c.opts.ClientID)
	// Note that we're not setting v's client_secret to t.ClientSecret, due
	// to https://code.google.com/p/goauth2/issues/detail?id=31
	// Reddit only accepts client_secret in Authorization header.
	// Dropbox accepts either, but not both.
	// The spec requires servers to always support the Authorization header,
	// so that's all we use.
	r, err := http.DefaultClient.PostForm(c.tokenURL.String(), v)
	if err != nil {
		return err
	}
	defer r.Body.Close()
	if r.StatusCode != 200 {
		// TODO(jbd): Add status code or error message
		return errors.New("Error during updating token.")
	}

	resp := &tokenRespBody{}
	content, _, _ := mime.ParseMediaType(r.Header.Get("Content-Type"))
	switch content {
	case "application/x-www-form-urlencoded", "text/plain":
		body, err := ioutil.ReadAll(r.Body)
		if err != nil {
			return err
		}
		vals, err := url.ParseQuery(string(body))
		if err != nil {
			return err
		}
		resp.AccessToken = vals.Get("access_token")
		resp.TokenType = vals.Get("token_type")
		resp.RefreshToken = vals.Get("refresh_token")
		resp.ExpiresIn, _ = strconv.ParseInt(vals.Get("expires_in"), 10, 64)
		resp.IdToken = vals.Get("id_token")
	default:
		if err = json.NewDecoder(r.Body).Decode(&resp); err != nil {
			return err
		}
	}
	tok.AccessToken = resp.AccessToken
	tok.TokenType = resp.TokenType
	// Don't overwrite `RefreshToken` with an empty value
	if resp.RefreshToken != "" {
		tok.RefreshToken = resp.RefreshToken
	}
	if resp.ExpiresIn == 0 {
		tok.Expiry = time.Time{}
	} else {
		tok.Expiry = time.Now().Add(time.Duration(resp.ExpiresIn) * time.Second)
	}
	if resp.IdToken != "" {
		if tok.Extra == nil {
			tok.Extra = make(map[string]string)
		}
		tok.Extra["id_token"] = resp.IdToken
	}
	return nil
}
<|endoftext|>