<commit_before>// Package vcard implements the vCard format, defined in RFC 6350.
package vcard

import (
	"strconv"
	"strings"
	"time"
)

// MIME type and file extension for VCard, defined in RFC 6350 section 10.1.
const (
	MIMEType  = "text/vcard"
	Extension = "vcf"
)

const timestampLayout = "20060102T150405Z"

// Card property parameters.
const (
	ParamLanguage      = "LANGUAGE"
	ParamValue         = "VALUE"
	ParamPreferred     = "PREF"
	ParamAltID         = "ALTID"
	ParamPID           = "PID"
	ParamType          = "TYPE"
	ParamMediaType     = "MEDIATYPE"
	ParamCalendarScale = "CALSCALE"
	ParamSortAs        = "SORT-AS"
	ParamGeolocation   = "GEO"
	ParamTimezone      = "TZ"
)

// Card properties.
const (
	// General Properties
	FieldSource = "SOURCE"
	FieldKind   = "KIND"
	FieldXML    = "XML"

	// Identification Properties
	FieldFormattedName = "FN"
	FieldName          = "N"
	FieldNickname      = "NICKNAME"
	FieldPhoto         = "PHOTO"
	FieldBirthday      = "BDAY"
	FieldAnniversary   = "ANNIVERSARY"
	FieldGender        = "GENDER"

	// Delivery Addressing Properties
	FieldAddress = "ADR"

	// Communications Properties
	FieldTelephone = "TEL"
	FieldEmail     = "EMAIL"
	FieldIMPP      = "IMPP" // Instant Messaging and Presence Protocol
	FieldLanguage  = "LANG"

	// Geographical Properties
	FieldTimezone    = "TZ"
	FieldGeolocation = "GEO"

	// Organizational Properties
	FieldTitle        = "TITLE"
	FieldRole         = "ROLE"
	FieldLogo         = "LOGO"
	FieldOrganization = "ORG"
	FieldMember       = "MEMBER"
	FieldRelated      = "RELATED"

	// Explanatory Properties
	FieldCategories   = "CATEGORIES"
	FieldNote         = "NOTE"
	FieldProductID    = "PRODID"
	FieldRevision     = "REV"
	FieldSound        = "SOUND"
	FieldUID          = "UID"
	FieldClientPIDMap = "CLIENTPIDMAP"
	FieldURL          = "URL"
	FieldVersion      = "VERSION"

	// Security Properties
	FieldKey = "KEY"

	// Calendar Properties
	FieldFreeOrBusyURL      = "FBURL"
	FieldCalendarAddressURI = "CALADRURI"
	FieldCalendarURI        = "CALURI"
)

func maybeGet(l []string, i int) string {
	if i < len(l) {
		return l[i]
	}
	return ""
}

// A Card is an address book entry.
type Card map[string][]*Field

// Get returns the first field of the card for the given property. If there is
// no such field, it returns nil.
func (c Card) Get(k string) *Field {
	fields := c[k]
	if len(fields) == 0 {
		return nil
	}
	return fields[0]
}

// Add adds the k, f pair to the list of fields. It appends to any existing
// fields.
func (c Card) Add(k string, f *Field) {
	c[k] = append(c[k], f)
}

// Set sets the key k to the single field f. It replaces any existing field.
func (c Card) Set(k string, f *Field) {
	c[k] = []*Field{f}
}

// Preferred returns the preferred field of the card for the given property.
func (c Card) Preferred(k string) *Field {
	fields := c[k]
	if len(fields) == 0 {
		return nil
	}

	field := fields[0]
	max := 0
	for _, f := range fields {
		n := 0
		if pref := f.Params.Get(ParamPreferred); pref != "" {
			n, _ = strconv.Atoi(pref)
		} else if f.Params.HasType("pref") {
			// Apple Contacts adds "pref" to the TYPE param
			n = 1
		}

		if n > max {
			max = n
			field = f
		}
	}
	return field
}

// Value returns the first field value of the card for the given property. If
// there is no such field, it returns an empty string.
func (c Card) Value(k string) string {
	f := c.Get(k)
	if f == nil {
		return ""
	}
	return f.Value
}

// AddValue adds the k, v pair to the list of field values. It appends to any
// existing values.
func (c Card) AddValue(k, v string) {
	c.Add(k, &Field{Value: v})
}

// SetValue sets the field k to the single value v. It replaces any existing
// value.
func (c Card) SetValue(k, v string) {
	c.Set(k, &Field{Value: v})
}

// PreferredValue returns the preferred field value of the card.
func (c Card) PreferredValue(k string) string {
	f := c.Preferred(k)
	if f == nil {
		return ""
	}
	return f.Value
}

// Values returns a list of values for a given property.
func (c Card) Values(k string) []string {
	fields := c[k]
	if fields == nil {
		return nil
	}

	values := make([]string, len(fields))
	for i, f := range fields {
		values[i] = f.Value
	}
	return values
}

// Kind returns the kind of the object represented by this card. If it isn't
// specified, it returns the default: KindIndividual.
func (c Card) Kind() Kind {
	kind := strings.ToLower(c.Value(FieldKind))
	if kind == "" {
		return KindIndividual
	}
	return Kind(kind)
}

// SetKind sets the kind of the object represented by this card.
func (c Card) SetKind(kind Kind) {
	c.SetValue(FieldKind, string(kind))
}

// FormattedNames returns formatted names of the card. The length of the result
// is always greater or equal to 1.
func (c Card) FormattedNames() []*Field {
	fns := c[FieldFormattedName]
	if len(fns) == 0 {
		return []*Field{{Value: ""}}
	}
	return fns
}

// Names returns names of the card.
func (c Card) Names() []*Name {
	ns := c[FieldName]
	if ns == nil {
		return nil
	}

	names := make([]*Name, len(ns))
	for i, n := range ns {
		names[i] = newName(n)
	}
	return names
}

// Name returns the preferred name of the card. If it isn't specified, it
// returns nil.
func (c Card) Name() *Name {
	n := c.Preferred(FieldName)
	if n == nil {
		return nil
	}
	return newName(n)
}

// AddName adds the specified name to the list of names.
func (c Card) AddName(name *Name) {
	c.Add(FieldName, name.field())
}

// Gender returns this card's gender.
func (c Card) Gender() (sex Sex, identity string) {
	v := c.Value(FieldGender)
	parts := strings.SplitN(v, ";", 2)
	return Sex(strings.ToUpper(parts[0])), maybeGet(parts, 1)
}

// SetGender sets this card's gender.
func (c Card) SetGender(sex Sex, identity string) {
	v := string(sex)
	if identity != "" {
		v += ";" + identity
	}
	c.SetValue(FieldGender, v)
}

// Addresses returns addresses of the card.
func (c Card) Addresses() []*Address {
	adrs := c[FieldAddress]
	if adrs == nil {
		return nil
	}

	addresses := make([]*Address, len(adrs))
	for i, adr := range adrs {
		addresses[i] = newAddress(adr)
	}
	return addresses
}

// Address returns the preferred address of the card. If it isn't specified, it
// returns nil.
func (c Card) Address() *Address {
	adr := c.Preferred(FieldAddress)
	if adr == nil {
		return nil
	}
	return newAddress(adr)
}

// AddAddress adds an address to the list of addresses.
func (c Card) AddAddress(address *Address) {
	c.Add(FieldAddress, address.field())
}

// Categories returns category information about the card, also known as "tags".
func (c Card) Categories() []string {
	return strings.Split(c.PreferredValue(FieldCategories), ",")
}

// SetCategories sets category information about the card.
func (c Card) SetCategories(categories []string) {
	c.SetValue(FieldCategories, strings.Join(categories, ","))
}

// Revision returns revision information about the current card.
func (c Card) Revision() (time.Time, error) {
	rev := c.Value(FieldRevision)
	if rev == "" {
		return time.Time{}, nil
	}
	return time.Parse(timestampLayout, rev)
}

// SetRevision sets revision information about the current card.
func (c Card) SetRevision(t time.Time) {
	c.SetValue(FieldRevision, t.Format(timestampLayout))
}

// A field contains a value and some parameters.
type Field struct {
	Value  string
	Params Params
	Group  string
}

// Params is a set of field parameters.
type Params map[string][]string

// Get returns the first value with the key k. It returns an empty string if
// there is no such value.
func (p Params) Get(k string) string {
	values := p[k]
	if len(values) == 0 {
		return ""
	}
	return values[0]
}

// Add adds the k, v pair to the list of parameters. It appends to any existing
// values.
func (p Params) Add(k, v string) {
	p[k] = append(p[k], v)
}

// Set sets the parameter k to the single value v. It replaces any existing
// value.
func (p Params) Set(k, v string) {
	p[k] = []string{v}
}

// Types returns the field types.
func (p Params) Types() []string {
	types := p[ParamType]
	list := make([]string, len(types))
	for i, t := range types {
		list[i] = strings.ToLower(t)
	}
	return list
}

// HasType returns true if and only if the field have the provided type.
func (p Params) HasType(t string) bool {
	for _, tt := range p[ParamType] {
		if strings.EqualFold(t, tt) {
			return true
		}
	}
	return false
}

// Kind is an object's kind.
type Kind string

// Values for FieldKind.
const (
	KindIndividual   Kind = "individual"
	KindGroup             = "group"
	KindOrganization      = "org"
	KindLocation          = "location"
)

// Values for ParamType.
const (
	// Generic
	TypeHome = "home"
	TypeWork = "work"

	// For FieldTelephone
	TypeText      = "text"
	TypeVoice     = "voice" // Default
	TypeFax       = "fax"
	TypeCell      = "cell"
	TypeVideo     = "video"
	TypePager     = "pager"
	TypeTextPhone = "textphone"

	// For FieldRelated
	TypeContact      = "contact"
	TypeAcquaintance = "acquaintance"
	TypeFriend       = "friend"
	TypeMet          = "met"
	TypeCoWorker     = "co-worker"
	TypeColleague    = "colleague"
	TypeCoResident   = "co-resident"
	TypeNeighbor     = "neighbor"
	TypeChild        = "child"
	TypeParent       = "parent"
	TypeSibling      = "sibling"
	TypeSpouse       = "spouse"
	TypeKin          = "kin"
	TypeMuse         = "muse"
	TypeCrush        = "crush"
	TypeDate         = "date"
	TypeSweetheart   = "sweetheart"
	TypeMe           = "me"
	TypeAgent        = "agent"
	TypeEmergency    = "emergency"
)

// Name contains an object's name components.
type Name struct {
	*Field

	FamilyName      string
	GivenName       string
	AdditionalName  string
	HonorificPrefix string
	HonorificSuffix string
}

func newName(field *Field) *Name {
	components := strings.Split(field.Value, ";")
	return &Name{
		field,
		maybeGet(components, 0),
		maybeGet(components, 1),
		maybeGet(components, 2),
		maybeGet(components, 3),
		maybeGet(components, 4),
	}
}

func (n *Name) field() *Field {
	if n.Field == nil {
		n.Field = new(Field)
	}
	n.Field.Value = strings.Join([]string{
		n.FamilyName,
		n.GivenName,
		n.AdditionalName,
		n.HonorificPrefix,
		n.HonorificSuffix,
	}, ";")
	return n.Field
}

// Sex is an object's biological sex.
type Sex string

const (
	SexUnspecified Sex = ""
	SexFemale          = "F"
	SexMale            = "M"
	SexOther           = "O"
	SexNone            = "N"
	SexUnknown         = "U"
)

// An Address is a delivery address.
type Address struct {
	*Field

	PostOfficeBox   string
	ExtendedAddress string // e.g., apartment or suite number
	StreetAddress   string
	Locality        string // e.g., city
	Region          string // e.g., state or province
	PostalCode      string
	Country         string
}

func newAddress(field *Field) *Address {
	components := strings.Split(field.Value, ";")
	return &Address{
		field,
		maybeGet(components, 0),
		maybeGet(components, 1),
		maybeGet(components, 2),
		maybeGet(components, 3),
		maybeGet(components, 4),
		maybeGet(components, 5),
		maybeGet(components, 6),
	}
}

func (a *Address) field() *Field {
	if a.Field == nil {
		a.Field = new(Field)
	}
	a.Field.Value = strings.Join([]string{
		a.PostOfficeBox,
		a.ExtendedAddress,
		a.StreetAddress,
		a.Locality,
		a.Region,
		a.PostalCode,
		a.Country,
	}, ";")
	return a.Field
}
<commit_msg>Fix constants types for Sex and Kind<commit_after>// Package vcard implements the vCard format, defined in RFC 6350.
package vcard

import (
	"strconv"
	"strings"
	"time"
)

// MIME type and file extension for VCard, defined in RFC 6350 section 10.1.
const (
	MIMEType  = "text/vcard"
	Extension = "vcf"
)

const timestampLayout = "20060102T150405Z"

// Card property parameters.
const (
	ParamLanguage      = "LANGUAGE"
	ParamValue         = "VALUE"
	ParamPreferred     = "PREF"
	ParamAltID         = "ALTID"
	ParamPID           = "PID"
	ParamType          = "TYPE"
	ParamMediaType     = "MEDIATYPE"
	ParamCalendarScale = "CALSCALE"
	ParamSortAs        = "SORT-AS"
	ParamGeolocation   = "GEO"
	ParamTimezone      = "TZ"
)

// Card properties.
const (
	// General Properties
	FieldSource = "SOURCE"
	FieldKind   = "KIND"
	FieldXML    = "XML"

	// Identification Properties
	FieldFormattedName = "FN"
	FieldName          = "N"
	FieldNickname      = "NICKNAME"
	FieldPhoto         = "PHOTO"
	FieldBirthday      = "BDAY"
	FieldAnniversary   = "ANNIVERSARY"
	FieldGender        = "GENDER"

	// Delivery Addressing Properties
	FieldAddress = "ADR"

	// Communications Properties
	FieldTelephone = "TEL"
	FieldEmail     = "EMAIL"
	FieldIMPP      = "IMPP" // Instant Messaging and Presence Protocol
	FieldLanguage  = "LANG"

	// Geographical Properties
	FieldTimezone    = "TZ"
	FieldGeolocation = "GEO"

	// Organizational Properties
	FieldTitle        = "TITLE"
	FieldRole         = "ROLE"
	FieldLogo         = "LOGO"
	FieldOrganization = "ORG"
	FieldMember       = "MEMBER"
	FieldRelated      = "RELATED"

	// Explanatory Properties
	FieldCategories   = "CATEGORIES"
	FieldNote         = "NOTE"
	FieldProductID    = "PRODID"
	FieldRevision     = "REV"
	FieldSound        = "SOUND"
	FieldUID          = "UID"
	FieldClientPIDMap = "CLIENTPIDMAP"
	FieldURL          = "URL"
	FieldVersion      = "VERSION"

	// Security Properties
	FieldKey = "KEY"

	// Calendar Properties
	FieldFreeOrBusyURL      = "FBURL"
	FieldCalendarAddressURI = "CALADRURI"
	FieldCalendarURI        = "CALURI"
)

func maybeGet(l []string, i int) string {
	if i < len(l) {
		return l[i]
	}
	return ""
}

// A Card is an address book entry.
type Card map[string][]*Field

// Get returns the first field of the card for the given property. If there is
// no such field, it returns nil.
func (c Card) Get(k string) *Field {
	fields := c[k]
	if len(fields) == 0 {
		return nil
	}
	return fields[0]
}

// Add adds the k, f pair to the list of fields. It appends to any existing
// fields.
func (c Card) Add(k string, f *Field) {
	c[k] = append(c[k], f)
}

// Set sets the key k to the single field f. It replaces any existing field.
func (c Card) Set(k string, f *Field) {
	c[k] = []*Field{f}
}

// Preferred returns the preferred field of the card for the given property.
func (c Card) Preferred(k string) *Field {
	fields := c[k]
	if len(fields) == 0 {
		return nil
	}

	field := fields[0]
	max := 0
	for _, f := range fields {
		n := 0
		if pref := f.Params.Get(ParamPreferred); pref != "" {
			n, _ = strconv.Atoi(pref)
		} else if f.Params.HasType("pref") {
			// Apple Contacts adds "pref" to the TYPE param
			n = 1
		}

		if n > max {
			max = n
			field = f
		}
	}
	return field
}

// Value returns the first field value of the card for the given property. If
// there is no such field, it returns an empty string.
func (c Card) Value(k string) string {
	f := c.Get(k)
	if f == nil {
		return ""
	}
	return f.Value
}

// AddValue adds the k, v pair to the list of field values. It appends to any
// existing values.
func (c Card) AddValue(k, v string) {
	c.Add(k, &Field{Value: v})
}

// SetValue sets the field k to the single value v. It replaces any existing
// value.
func (c Card) SetValue(k, v string) {
	c.Set(k, &Field{Value: v})
}

// PreferredValue returns the preferred field value of the card.
func (c Card) PreferredValue(k string) string {
	f := c.Preferred(k)
	if f == nil {
		return ""
	}
	return f.Value
}

// Values returns a list of values for a given property.
func (c Card) Values(k string) []string {
	fields := c[k]
	if fields == nil {
		return nil
	}

	values := make([]string, len(fields))
	for i, f := range fields {
		values[i] = f.Value
	}
	return values
}

// Kind returns the kind of the object represented by this card. If it isn't
// specified, it returns the default: KindIndividual.
func (c Card) Kind() Kind {
	kind := strings.ToLower(c.Value(FieldKind))
	if kind == "" {
		return KindIndividual
	}
	return Kind(kind)
}

// SetKind sets the kind of the object represented by this card.
func (c Card) SetKind(kind Kind) {
	c.SetValue(FieldKind, string(kind))
}

// FormattedNames returns formatted names of the card. The length of the result
// is always greater or equal to 1.
func (c Card) FormattedNames() []*Field {
	fns := c[FieldFormattedName]
	if len(fns) == 0 {
		return []*Field{{Value: ""}}
	}
	return fns
}

// Names returns names of the card.
func (c Card) Names() []*Name {
	ns := c[FieldName]
	if ns == nil {
		return nil
	}

	names := make([]*Name, len(ns))
	for i, n := range ns {
		names[i] = newName(n)
	}
	return names
}

// Name returns the preferred name of the card. If it isn't specified, it
// returns nil.
func (c Card) Name() *Name {
	n := c.Preferred(FieldName)
	if n == nil {
		return nil
	}
	return newName(n)
}

// AddName adds the specified name to the list of names.
func (c Card) AddName(name *Name) {
	c.Add(FieldName, name.field())
}

// Gender returns this card's gender.
func (c Card) Gender() (sex Sex, identity string) {
	v := c.Value(FieldGender)
	parts := strings.SplitN(v, ";", 2)
	return Sex(strings.ToUpper(parts[0])), maybeGet(parts, 1)
}

// SetGender sets this card's gender.
func (c Card) SetGender(sex Sex, identity string) {
	v := string(sex)
	if identity != "" {
		v += ";" + identity
	}
	c.SetValue(FieldGender, v)
}

// Addresses returns addresses of the card.
func (c Card) Addresses() []*Address {
	adrs := c[FieldAddress]
	if adrs == nil {
		return nil
	}

	addresses := make([]*Address, len(adrs))
	for i, adr := range adrs {
		addresses[i] = newAddress(adr)
	}
	return addresses
}

// Address returns the preferred address of the card. If it isn't specified, it
// returns nil.
func (c Card) Address() *Address {
	adr := c.Preferred(FieldAddress)
	if adr == nil {
		return nil
	}
	return newAddress(adr)
}

// AddAddress adds an address to the list of addresses.
func (c Card) AddAddress(address *Address) {
	c.Add(FieldAddress, address.field())
}

// Categories returns category information about the card, also known as "tags".
func (c Card) Categories() []string {
	return strings.Split(c.PreferredValue(FieldCategories), ",")
}

// SetCategories sets category information about the card.
func (c Card) SetCategories(categories []string) {
	c.SetValue(FieldCategories, strings.Join(categories, ","))
}

// Revision returns revision information about the current card.
func (c Card) Revision() (time.Time, error) {
	rev := c.Value(FieldRevision)
	if rev == "" {
		return time.Time{}, nil
	}
	return time.Parse(timestampLayout, rev)
}

// SetRevision sets revision information about the current card.
func (c Card) SetRevision(t time.Time) {
	c.SetValue(FieldRevision, t.Format(timestampLayout))
}

// A field contains a value and some parameters.
type Field struct {
	Value  string
	Params Params
	Group  string
}

// Params is a set of field parameters.
type Params map[string][]string

// Get returns the first value with the key k. It returns an empty string if
// there is no such value.
func (p Params) Get(k string) string {
	values := p[k]
	if len(values) == 0 {
		return ""
	}
	return values[0]
}

// Add adds the k, v pair to the list of parameters. It appends to any existing
// values.
func (p Params) Add(k, v string) {
	p[k] = append(p[k], v)
}

// Set sets the parameter k to the single value v. It replaces any existing
// value.
func (p Params) Set(k, v string) {
	p[k] = []string{v}
}

// Types returns the field types.
func (p Params) Types() []string {
	types := p[ParamType]
	list := make([]string, len(types))
	for i, t := range types {
		list[i] = strings.ToLower(t)
	}
	return list
}

// HasType returns true if and only if the field have the provided type.
func (p Params) HasType(t string) bool {
	for _, tt := range p[ParamType] {
		if strings.EqualFold(t, tt) {
			return true
		}
	}
	return false
}

// Kind is an object's kind.
type Kind string

// Values for FieldKind.
const (
	KindIndividual   Kind = "individual"
	KindGroup        Kind = "group"
	KindOrganization Kind = "org"
	KindLocation     Kind = "location"
)

// Values for ParamType.
const (
	// Generic
	TypeHome = "home"
	TypeWork = "work"

	// For FieldTelephone
	TypeText      = "text"
	TypeVoice     = "voice" // Default
	TypeFax       = "fax"
	TypeCell      = "cell"
	TypeVideo     = "video"
	TypePager     = "pager"
	TypeTextPhone = "textphone"

	// For FieldRelated
	TypeContact      = "contact"
	TypeAcquaintance = "acquaintance"
	TypeFriend       = "friend"
	TypeMet          = "met"
	TypeCoWorker     = "co-worker"
	TypeColleague    = "colleague"
	TypeCoResident   = "co-resident"
	TypeNeighbor     = "neighbor"
	TypeChild        = "child"
	TypeParent       = "parent"
	TypeSibling      = "sibling"
	TypeSpouse       = "spouse"
	TypeKin          = "kin"
	TypeMuse         = "muse"
	TypeCrush        = "crush"
	TypeDate         = "date"
	TypeSweetheart   = "sweetheart"
	TypeMe           = "me"
	TypeAgent        = "agent"
	TypeEmergency    = "emergency"
)

// Name contains an object's name components.
type Name struct {
	*Field

	FamilyName      string
	GivenName       string
	AdditionalName  string
	HonorificPrefix string
	HonorificSuffix string
}

func newName(field *Field) *Name {
	components := strings.Split(field.Value, ";")
	return &Name{
		field,
		maybeGet(components, 0),
		maybeGet(components, 1),
		maybeGet(components, 2),
		maybeGet(components, 3),
		maybeGet(components, 4),
	}
}

func (n *Name) field() *Field {
	if n.Field == nil {
		n.Field = new(Field)
	}
	n.Field.Value = strings.Join([]string{
		n.FamilyName,
		n.GivenName,
		n.AdditionalName,
		n.HonorificPrefix,
		n.HonorificSuffix,
	}, ";")
	return n.Field
}

// Sex is an object's biological sex.
type Sex string

const (
	SexUnspecified Sex = ""
	SexFemale      Sex = "F"
	SexMale        Sex = "M"
	SexOther       Sex = "O"
	SexNone        Sex = "N"
	SexUnknown     Sex = "U"
)

// An Address is a delivery address.
type Address struct {
	*Field

	PostOfficeBox   string
	ExtendedAddress string // e.g., apartment or suite number
	StreetAddress   string
	Locality        string // e.g., city
	Region          string // e.g., state or province
	PostalCode      string
	Country         string
}

func newAddress(field *Field) *Address {
	components := strings.Split(field.Value, ";")
	return &Address{
		field,
		maybeGet(components, 0),
		maybeGet(components, 1),
		maybeGet(components, 2),
		maybeGet(components, 3),
		maybeGet(components, 4),
		maybeGet(components, 5),
		maybeGet(components, 6),
	}
}

func (a *Address) field() *Field {
	if a.Field == nil {
		a.Field = new(Field)
	}
	a.Field.Value = strings.Join([]string{
		a.PostOfficeBox,
		a.ExtendedAddress,
		a.StreetAddress,
		a.Locality,
		a.Region,
		a.PostalCode,
		a.Country,
	}, ";")
	return a.Field
}
<|endoftext|>


<commit_before>package ethminer

import (
	"bytes"
	"github.com/ethereum/eth-go/ethchain"
	"github.com/ethereum/eth-go/ethutil"
	"github.com/ethereum/eth-go/ethwire"
	"github.com/ethereum/eth-go/ethlog"
	"sort"
)

var logger = ethlog.NewLogger("MINER")

type Miner struct {
	pow         ethchain.PoW
	ethereum    ethchain.EthManager
	coinbase    []byte
	reactChan   chan ethutil.React
	txs         ethchain.Transactions
	uncles      []*ethchain.Block
	block       *ethchain.Block
	powChan     chan []byte
	powQuitChan chan ethutil.React
	quitChan    chan bool
}

func NewDefaultMiner(coinbase []byte, ethereum ethchain.EthManager) Miner {
	reactChan := make(chan ethutil.React, 1)   // This is the channel that receives 'updates' when ever a new transaction or block comes in
	powChan := make(chan []byte, 1)            // This is the channel that receives valid sha hases for a given block
	powQuitChan := make(chan ethutil.React, 1) // This is the channel that can exit the miner thread
	quitChan := make(chan bool, 1)

	ethereum.Reactor().Subscribe("newBlock", reactChan)
	ethereum.Reactor().Subscribe("newTx:pre", reactChan)

	// We need the quit chan to be a Reactor event.
	// The POW search method is actually blocking and if we don't
	// listen to the reactor events inside of the pow itself
	// The miner overseer will never get the reactor events themselves
	// Only after the miner will find the sha
	ethereum.Reactor().Subscribe("newBlock", powQuitChan)
	ethereum.Reactor().Subscribe("newTx:pre", powQuitChan)

	miner := Miner{
		pow:         &ethchain.EasyPow{},
		ethereum:    ethereum,
		coinbase:    coinbase,
		reactChan:   reactChan,
		powChan:     powChan,
		powQuitChan: powQuitChan,
		quitChan:    quitChan,
	}

	// Insert initial TXs in our little miner 'pool'
	miner.txs = ethereum.TxPool().Flush()
	miner.block = ethereum.BlockChain().NewBlock(miner.coinbase)

	return miner
}
func (miner *Miner) Start() {
	// Prepare inital block
	//miner.ethereum.StateManager().Prepare(miner.block.State(), miner.block.State())
	go miner.listener()
}
func (miner *Miner) listener() {
out:
	for {
		select {
		case <-miner.quitChan:
			break out
		case chanMessage := <-miner.reactChan:
			if block, ok := chanMessage.Resource.(*ethchain.Block); ok {
				//logger.Infoln("Got new block via Reactor")
				if bytes.Compare(miner.ethereum.BlockChain().CurrentBlock.Hash(), block.Hash()) == 0 {
					// TODO: Perhaps continue mining to get some uncle rewards
					//logger.Infoln("New top block found resetting state")

					// Filter out which Transactions we have that were not in this block
					var newtxs []*ethchain.Transaction
					for _, tx := range miner.txs {
						found := false
						for _, othertx := range block.Transactions() {
							if bytes.Compare(tx.Hash(), othertx.Hash()) == 0 {
								found = true
							}
						}
						if found == false {
							newtxs = append(newtxs, tx)
						}
					}
					miner.txs = newtxs

					// Setup a fresh state to mine on
					//miner.block = miner.ethereum.BlockChain().NewBlock(miner.coinbase, miner.txs)

				} else {
					if bytes.Compare(block.PrevHash, miner.ethereum.BlockChain().CurrentBlock.PrevHash) == 0 {
						logger.Infoln("Adding uncle block")
						miner.uncles = append(miner.uncles, block)
					}
				}
			}

			if tx, ok := chanMessage.Resource.(*ethchain.Transaction); ok {
				found := false
				for _, ctx := range miner.txs {
					if found = bytes.Compare(ctx.Hash(), tx.Hash()) == 0; found {
						break
					}

				}
				if found == false {
					// Undo all previous commits
					miner.block.Undo()
					// Apply new transactions
					miner.txs = append(miner.txs, tx)
				}
			}
		default:
			miner.mineNewBlock()
		}
	}
}

func (self *Miner) Stop() {
	self.powQuitChan <- ethutil.React{}
	self.quitChan <- true
}

func (self *Miner) mineNewBlock() {
	stateManager := self.ethereum.StateManager()

	self.block = self.ethereum.BlockChain().NewBlock(self.coinbase)

	// Apply uncles
	if len(self.uncles) > 0 {
		self.block.SetUncles(self.uncles)
	}

	// Sort the transactions by nonce in case of odd network propagation
	sort.Sort(ethchain.TxByNonce{self.txs})

	// Accumulate all valid transactions and apply them to the new state
	// Error may be ignored. It's not important during mining
	parent := self.ethereum.BlockChain().GetBlock(self.block.PrevHash)
	coinbase := self.block.State().GetOrNewStateObject(self.block.Coinbase)
	coinbase.SetGasPool(self.block.CalcGasLimit(parent))
	receipts, txs, unhandledTxs, err := stateManager.ProcessTransactions(coinbase, self.block.State(), self.block, self.block, self.txs)
	if err != nil {
		logger.Debugln(err)
	}
	self.txs = append(txs, unhandledTxs...)

	// Set the transactions to the block so the new SHA3 can be calculated
	self.block.SetReceipts(receipts, txs)

	// Accumulate the rewards included for this block
	stateManager.AccumelateRewards(self.block.State(), self.block)

	self.block.State().Update()

	logger.Infoln("Mining on block. Includes", len(self.txs), "transactions")

	// Find a valid nonce
	self.block.Nonce = self.pow.Search(self.block, self.powQuitChan)
	if self.block.Nonce != nil {
		err := self.ethereum.StateManager().Process(self.block, false)
		if err != nil {
			logger.Infoln(err)
		} else {
			self.ethereum.Broadcast(ethwire.MsgBlockTy, []interface{}{self.block.Value().Val})
			logger.Infof("🔨  Mined block %x\n", self.block.Hash())
			logger.Infoln(self.block)
			// Gather the new batch of transactions currently in the tx pool
			self.txs = self.ethereum.TxPool().CurrentTransactions()
		}
	}
}
<commit_msg>space in miner logging message<commit_after>package ethminer

import (
	"bytes"
	"github.com/ethereum/eth-go/ethchain"
	"github.com/ethereum/eth-go/ethutil"
	"github.com/ethereum/eth-go/ethwire"
	"github.com/ethereum/eth-go/ethlog"
	"sort"
)

var logger = ethlog.NewLogger("MINER")

type Miner struct {
	pow         ethchain.PoW
	ethereum    ethchain.EthManager
	coinbase    []byte
	reactChan   chan ethutil.React
	txs         ethchain.Transactions
	uncles      []*ethchain.Block
	block       *ethchain.Block
	powChan     chan []byte
	powQuitChan chan ethutil.React
	quitChan    chan bool
}

func NewDefaultMiner(coinbase []byte, ethereum ethchain.EthManager) Miner {
	reactChan := make(chan ethutil.React, 1)   // This is the channel that receives 'updates' when ever a new transaction or block comes in
	powChan := make(chan []byte, 1)            // This is the channel that receives valid sha hases for a given block
	powQuitChan := make(chan ethutil.React, 1) // This is the channel that can exit the miner thread
	quitChan := make(chan bool, 1)

	ethereum.Reactor().Subscribe("newBlock", reactChan)
	ethereum.Reactor().Subscribe("newTx:pre", reactChan)

	// We need the quit chan to be a Reactor event.
	// The POW search method is actually blocking and if we don't
	// listen to the reactor events inside of the pow itself
	// The miner overseer will never get the reactor events themselves
	// Only after the miner will find the sha
	ethereum.Reactor().Subscribe("newBlock", powQuitChan)
	ethereum.Reactor().Subscribe("newTx:pre", powQuitChan)

	miner := Miner{
		pow:         &ethchain.EasyPow{},
		ethereum:    ethereum,
		coinbase:    coinbase,
		reactChan:   reactChan,
		powChan:     powChan,
		powQuitChan: powQuitChan,
		quitChan:    quitChan,
	}

	// Insert initial TXs in our little miner 'pool'
	miner.txs = ethereum.TxPool().Flush()
	miner.block = ethereum.BlockChain().NewBlock(miner.coinbase)

	return miner
}
func (miner *Miner) Start() {
	// Prepare inital block
	//miner.ethereum.StateManager().Prepare(miner.block.State(), miner.block.State())
	go miner.listener()
}
func (miner *Miner) listener() {
out:
	for {
		select {
		case <-miner.quitChan:
			break out
		case chanMessage := <-miner.reactChan:
			if block, ok := chanMessage.Resource.(*ethchain.Block); ok {
				//logger.Infoln("Got new block via Reactor")
				if bytes.Compare(miner.ethereum.BlockChain().CurrentBlock.Hash(), block.Hash()) == 0 {
					// TODO: Perhaps continue mining to get some uncle rewards
					//logger.Infoln("New top block found resetting state")

					// Filter out which Transactions we have that were not in this block
					var newtxs []*ethchain.Transaction
					for _, tx := range miner.txs {
						found := false
						for _, othertx := range block.Transactions() {
							if bytes.Compare(tx.Hash(), othertx.Hash()) == 0 {
								found = true
							}
						}
						if found == false {
							newtxs = append(newtxs, tx)
						}
					}
					miner.txs = newtxs

					// Setup a fresh state to mine on
					//miner.block = miner.ethereum.BlockChain().NewBlock(miner.coinbase, miner.txs)

				} else {
					if bytes.Compare(block.PrevHash, miner.ethereum.BlockChain().CurrentBlock.PrevHash) == 0 {
						logger.Infoln("Adding uncle block")
						miner.uncles = append(miner.uncles, block)
					}
				}
			}

			if tx, ok := chanMessage.Resource.(*ethchain.Transaction); ok {
				found := false
				for _, ctx := range miner.txs {
					if found = bytes.Compare(ctx.Hash(), tx.Hash()) == 0; found {
						break
					}

				}
				if found == false {
					// Undo all previous commits
					miner.block.Undo()
					// Apply new transactions
					miner.txs = append(miner.txs, tx)
				}
			}
		default:
			miner.mineNewBlock()
		}
	}
}

func (self *Miner) Stop() {
	self.powQuitChan <- ethutil.React{}
	self.quitChan <- true
}

func (self *Miner) mineNewBlock() {
	stateManager := self.ethereum.StateManager()

	self.block = self.ethereum.BlockChain().NewBlock(self.coinbase)

	// Apply uncles
	if len(self.uncles) > 0 {
		self.block.SetUncles(self.uncles)
	}

	// Sort the transactions by nonce in case of odd network propagation
	sort.Sort(ethchain.TxByNonce{self.txs})

	// Accumulate all valid transactions and apply them to the new state
	// Error may be ignored. It's not important during mining
	parent := self.ethereum.BlockChain().GetBlock(self.block.PrevHash)
	coinbase := self.block.State().GetOrNewStateObject(self.block.Coinbase)
	coinbase.SetGasPool(self.block.CalcGasLimit(parent))
	receipts, txs, unhandledTxs, err := stateManager.ProcessTransactions(coinbase, self.block.State(), self.block, self.block, self.txs)
	if err != nil {
		logger.Debugln(err)
	}
	self.txs = append(txs, unhandledTxs...)

	// Set the transactions to the block so the new SHA3 can be calculated
	self.block.SetReceipts(receipts, txs)

	// Accumulate the rewards included for this block
	stateManager.AccumelateRewards(self.block.State(), self.block)

	self.block.State().Update()

	logger.Infof("Mining on block. Includes %v transactions", len(self.txs))

	// Find a valid nonce
	self.block.Nonce = self.pow.Search(self.block, self.powQuitChan)
	if self.block.Nonce != nil {
		err := self.ethereum.StateManager().Process(self.block, false)
		if err != nil {
			logger.Infoln(err)
		} else {
			self.ethereum.Broadcast(ethwire.MsgBlockTy, []interface{}{self.block.Value().Val})
			logger.Infof("🔨  Mined block %x\n", self.block.Hash())
			logger.Infoln(self.block)
			// Gather the new batch of transactions currently in the tx pool
			self.txs = self.ethereum.TxPool().CurrentTransactions()
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
)

const (
	// API v1.1 : <https://circleci.com/docs/api/v1-reference/>
	// but beware that the summary is missing some method/URL pairs which are
	// described further down in the page.

	buildListURL = "https://circleci.com/api/v1.1/project/github/${project}/tree/${branch}?limit=${retrieve_count}&filter=successful&circle-token=${circle_token}"
	artifactsURL = "https://circleci.com/api/v1.1/project/github/${project}/${build_num}/artifacts?circle-token=${circle_token}"

	// We need to account for multiple workflows, and multiple builds within workflows
	defaultRetrieveCount = 10
)

type workflow struct {
	JobName      string `json:"job_name"`
	JobID        string `json:"job_id"`
	WorkflowName string `json:"workflow_name"`
	WorkflowID   string `json:"workflow_id"`
}

type build struct {
	BuildNum  int       `json:"build_num"`
	Revision  string    `json:"vcs_revision"`
	Workflows *workflow `json:"workflows"` // plural name but singleton struct

	// We want to skip bad builds, and perhaps print the others so that if
	// there's a mismatch from expectations, folks might notice.
	Status   string `json:"status"`
	Subject  string `json:"subject"`
	StopTime string `json:"stop_time"`
}

type artifact struct {
	URL string `json:"url"`
}

// FilterSet is the collection of attributes upon which we filter the results
// from Circle CI (or provide in URL to pre-filter).
type FilterSet struct {
	branch    string
	workflow  string
	jobname   string
	anyFlowID bool
}

// Expander is used to take strings containing ${var} and interpolate them,
// so that we don't have URLs which have %s/%s/%s and cross-referencing across
// places to figure out which those fields are.
type Expander map[string]string

// Get is just a map lookup which panics, as a function for use with os.Expand
func (e Expander) Get(key string) string {
	if val, ok := e[key]; ok {
		return val
	}
	// There is no recovery, we don't want to pass a bad URL out, we're
	// a client tool and we'll need to fix the hardcoded template strings.
	panic("bad key " + key)
}

// Expand converts "${foo}/${bar}" into "football/goal".
// It also handles some $foo without parens, but we avoid using that.
func (e *Expander) Expand(src string) string {
	return os.Expand(src, e.Get)
}

var (
	circleToken     string
	filter          FilterSet
	verbose, dryRun bool
)

func main() {
	var (
		project             string
		buildNum            int
		outputPath          string
		retrieveBuildsCount int
	)

	log.SetFlags(log.Lshortfile)
	log.SetOutput(os.Stderr)

	flag.StringVar(&circleToken, "token", "", "CircleCI auth token")
	flag.StringVar(&outputPath, "o", "", "output file `path`")
	flag.BoolVar(&verbose, "v", false, "verbose output")
	flag.BoolVar(&dryRun, "n", false, "skip artifact download")

	flag.StringVar(&project, "repo", "", "github `username/repo`")
	flag.IntVar(&buildNum, "build", 0, "get artifact for build number, ignoring branch")
	flag.StringVar(&filter.branch, "branch", "master", "search builds for branch `name`")

	// Workflows:
	// If there are multiple workflows, then the latest "build" is perhaps unrelated to building,
	// not even a later step in a workflow where an earlier step did build.  Eg, we have
	// stuff to automate dependencies checking, scheduled from cron.
	// So to retrieve an artifact, we want to only consider specific workflow names.
	// HOWEVER: those are config items in `.circleci/config.yml` and we should avoid hardcoding
	// such arbitrary choices across more than one repo, so our default for now is empty,
	// thus not filtered.
	//
	// Within a workflow, the build might not be the last step in the flow; it usually won't be.
	// Later steps might be "deploy", "stash image somewhere", etc.
	// So we need to step back from the last step within a workflow until we find the specific
	// step we're told.
	//
	// Eg, for one project, at this time, we use "commit_workflow" as the workflow to search for
	// and "build" as the job within that workflow.

	flag.StringVar(&filter.workflow, "workflow", "", "only consider builds which are part of this workflow")
	flag.StringVar(&filter.jobname, "jobname", "", "look within workflow for artifacts from this job's name")
	flag.IntVar(&retrieveBuildsCount, "retrieve-count", defaultRetrieveCount, "how many builds to retrieve")
	// This description is too long; how to make it shorter?
	flag.BoolVar(&filter.anyFlowID, "ignore-later-workflows", false, "get the last successful workflow/job build, even if of a previous flow-id than the latest we see for that workflow")

	// when the workflow-jobname functionality was first added, I (pdp) named it badly; for compatibility,
	// continue taking the confusingly named option, but map it to the fixed variable.  Similarly for
	// how the presence of multiple workflows means "workflow-depth" was now a misnomer, and "retrieve-count"
	// is more accurate.
	flag.StringVar(&filter.jobname, "workflow-artifact-build", "", "(alias for -workflow-jobname)")
	flag.IntVar(&retrieveBuildsCount, "workflow-depth", defaultRetrieveCount, "(alias for -retrieve-count)")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s [flags] <artifact>\n\n", filepath.Base(os.Args[0]))
		flag.PrintDefaults()
	}

	flag.Parse()

	if project == "" {
		out, err := exec.Command("git", "remote", "get-url", "origin").Output()
		if err != nil {
			log.Fatalf("exec git: %s", err)
		}
		project = gitProject(string(out))
	}

	artifactName := flag.Arg(0)
	if circleToken == "" {
		circleToken = os.Getenv("CIRCLE_TOKEN")
	}

	// for URL expansion with sane named parameters, and put in everything
	// we might want too, including filters, in case there are better
	// URLs we can switch to in future.
	expansions := Expander{
		"project":        project,
		"artifact":       artifactName,
		"retrieve_count": strconv.Itoa(retrieveBuildsCount),
		"build_num":      strconv.Itoa(buildNum),
		"circle_token":   circleToken,
		"branch":         filter.branch,
		"workflow":       filter.workflow,
		"jobname":        filter.jobname,
	}

	switch {
	case project == "":
		flag.Usage()
		log.Fatal("no <username>/<project> provided")
	case filter.branch == "":
		flag.Usage()
		log.Fatal("no <branch> provided")
	case artifactName == "":
		flag.Usage()
		log.Fatal("no <artifact> provided")
	case circleToken == "":
		flag.Usage()
		log.Fatal("no auth token set: use $CIRCLE_TOKEN or flag -token")
	case retrieveBuildsCount < 1:
		flag.Usage()
		log.Fatal("workflow depth must be a positive (smallish) integer")
	case buildNum > 0:
		// Don't look for a green build.
		fmt.Printf("Build: %d\n", buildNum)
	default:
		buildNum = circleFindBuild(expansions, filter)
		expansions["build_num"] = strconv.Itoa(buildNum)
	}

	// Get artifact from buildNum
	u := expansions.Expand(artifactsURL)
	if verbose {
		fmt.Println("Artifact list:", u)
	}
	req, err := http.NewRequest("GET", u, nil)
	if err != nil {
		log.Fatal(err)
	}
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer res.Body.Close()
	var artifacts []artifact
	if err := json.NewDecoder(res.Body).Decode(&artifacts); err != nil {
		log.Fatal(err)
	}
	if outputPath == "" {
		outputPath = filepath.Base(artifactName)
	}
	n, err := downloadArtifact(artifacts, artifactName, outputPath)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Wrote %s (%d bytes) to %s\n", artifactName, n, outputPath)
}

func circleFindBuild(expansions Expander, filter FilterSet) (buildNum int) {
	u := expansions.Expand(buildListURL)
	if verbose {
		fmt.Println("Build list:", u)
	}
	req, err := http.NewRequest("GET", u, nil)
	if err != nil {
		log.Fatal(err)
	}
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer res.Body.Close()
	body := new(bytes.Buffer)
	if _, err := io.Copy(body, res.Body); err != nil {
		log.Fatal(err)
	}

	var builds []build
	if err := json.Unmarshal(body.Bytes(), &builds); err != nil {
		log.Fatalf("%s: %s", err, body.String())
	}
	if len(builds) == 0 {
		log.Fatalf("no builds found for branch: %s", filter.branch)
	}

	// We _want_ to find the last successful workflow; as of APIv1.1 there's
	// nothing to filter directly by workflow, nor to tell if a workflow has
	// completed successfully, to know if we're grabbing something which later
	// failed, etc.
	//
	// So we just look for the last green build within a workflow and rely upon
	// the build we want being either that one, or earlier, with no prep steps
	// pre-build.  Unless the caller told us they don't care about matching
	// workflow ID to the latest workflow for which we see any builds.

	foundBuild := -1
	onlyWorkflowID := ""
	for i := 0; i < len(builds); i++ {
		headOfWorkflow := false
		if builds[i].Workflows == nil && (filter.workflow != "" || filter.jobname != "") {
			// fmt.Printf("skipping %d, no workflow: %+v\n", i, builds[i])
			// -- these happen, they show in the UI, I wonder if it's a manual trigger?
			continue
		}
		if builds[i].Status != "success" {
			continue
		}
		if onlyWorkflowID != "" && builds[i].Workflows.WorkflowID != onlyWorkflowID {
			continue
		}
		if filter.workflow != "" && builds[i].Workflows.WorkflowName != filter.workflow {
			continue
		}
		if onlyWorkflowID == "" && filter.workflow != "" && !filter.anyFlowID {
			onlyWorkflowID = builds[i].Workflows.WorkflowID
			headOfWorkflow = true
		}
		if filter.jobname != "" && builds[i].Workflows.JobName != filter.jobname {
			if headOfWorkflow {
				fmt.Printf("build: branch %q build %d is a %q, part of workflow %q, searching for build %q\n",
					filter.branch, builds[i].BuildNum,
					builds[i].Workflows.JobName, builds[0].Workflows.WorkflowName,
					filter.jobname)
			}
			continue
		}
		if builds[i].Workflows == nil {
			// must mean no filters, so i == 0
			fmt.Printf("build: workflow-less on branch %q found a build at offset %d\n",
				filter.branch, i)
		} else {
			fmt.Printf("build: workflow %q branch %q found build %q at offset %d\n",
				builds[i].Workflows.WorkflowName, filter.branch, builds[i].Workflows.JobName, i)
		}

		foundBuild = i
		break
	}

	if foundBuild < 0 {
		labelFlow := filter.workflow
		labelName := filter.jobname
		if labelFlow == "" {
			labelFlow = "*"
		}
		if labelName == "" {
			labelName = "*"
		}
		log.Fatalf("build: failed to find a build matching workflow=%q jobname=%q in branch %q",
			labelFlow, labelName, filter.branch)
	}

	if verbose {
		fmt.Printf("\nBuild Subject  : %s\nBuild Finished : %s\n",
			builds[foundBuild].Subject, builds[foundBuild].StopTime)
	}

	fmt.Printf("build: %d branch: %s rev: %s\n",
		builds[foundBuild].BuildNum, filter.branch, builds[foundBuild].Revision[:8])
	return builds[foundBuild].BuildNum
}

func downloadArtifact(artifacts []artifact, name, outputPath string) (int64, error) {
	for _, a := range artifacts {
		if verbose {
			fmt.Println("Artifact URL:", a.URL)
		}
		if !strings.HasSuffix(a.URL, name) {
			continue
		}
		u, err := url.Parse(a.URL)
		if err != nil {
			return 0, err
		}
		q := u.Query()
		q.Add("circle-token", circleToken)
		u.RawQuery = q.Encode()
		if verbose {
			fmt.Println("Artifact found:", name)
		}
		if dryRun {
			fmt.Println("Dry run: skipped download")
			os.Exit(0)
		}
		fmt.Printf("Downloading %s...\n", name)
		res, err := http.Get(u.String())
		if err != nil {
			return 0, err
		}
		defer res.Body.Close()
		if res.StatusCode != 200 {
			return 0, fmt.Errorf("http: remote server responded %s (check http://status.circleci.com)", res.Status)
		}
		f, err := os.Create(outputPath)
		if err != nil {
			return 0, err
		}
		return io.Copy(f, res.Body)
	}
	return 0, fmt.Errorf("unable to find artifact: %s", name)
}

var ghURL = regexp.MustCompile(`github\.com(?:/|:)(\w+/\w+)`)

func gitProject(url string) string {
	remote := ghURL.FindStringSubmatch(url)
	if len(remote) > 1 {
		return strings.Replace(remote[1], ".git", "", 1)
	}
	return ""
}
<commit_msg>Address most review feedback<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
)

const (
	// API v1.1 : <https://circleci.com/docs/api/v1-reference/>
	// but beware that the summary is missing some method/URL pairs which are
	// described further down in the page.

	buildListURL = "https://circleci.com/api/v1.1/project/github/${project}/tree/${branch}?limit=${retrieve_count}&filter=successful&circle-token=${circle_token}"
	artifactsURL = "https://circleci.com/api/v1.1/project/github/${project}/${build_num}/artifacts?circle-token=${circle_token}"

	// We need to account for multiple workflows, and multiple builds within workflows
	defaultRetrieveCount = 10
)

type workflow struct {
	JobName      string `json:"job_name"`
	JobID        string `json:"job_id"`
	WorkflowName string `json:"workflow_name"`
	WorkflowID   string `json:"workflow_id"`
}

type build struct {
	BuildNum  int       `json:"build_num"`
	Revision  string    `json:"vcs_revision"`
	Workflows *workflow `json:"workflows"` // plural name but singleton struct

	// We want to skip bad builds, and perhaps print the others so that if
	// there's a mismatch from expectations, folks might notice.
	Status   string `json:"status"`
	Subject  string `json:"subject"`
	StopTime string `json:"stop_time"`
}

type artifact struct {
	URL string `json:"url"`
}

// FilterSet is the collection of attributes upon which we filter the results
// from Circle CI (or provide in URL to pre-filter).
type FilterSet struct {
	branch    string
	workflow  string
	jobname   string
	anyFlowID bool
}

// Expander is used to take strings containing ${var} and interpolate them,
// so that we don't have URLs which have %s/%s/%s and cross-referencing across
// places to figure out which those fields are.
type Expander map[string]string

// Get is just a map lookup which panics, as a function for use with os.Expand
func (e Expander) Get(key string) string {
	if val, ok := e[key]; ok {
		return val
	}
	// There is no recovery, we don't want to pass a bad URL out, we're
	// a client tool and we'll need to fix the hardcoded template strings.
	panic("bad key " + key)
}

// Expand converts "${foo}/${bar}" into "football/goal".
// It also handles some $foo without parens, but we avoid using that.
func (e *Expander) Expand(src string) string {
	return os.Expand(src, e.Get)
}

var (
	circleToken     string
	filter          FilterSet
	verbose, dryRun bool
)

func main() {
	var (
		project             string
		buildNum            int
		outputPath          string
		retrieveBuildsCount int
	)

	log.SetFlags(log.Lshortfile)
	log.SetOutput(os.Stderr)

	flag.StringVar(&circleToken, "token", "", "CircleCI auth token")
	flag.StringVar(&outputPath, "o", "", "output file `path`")
	flag.BoolVar(&verbose, "v", false, "verbose output")
	flag.BoolVar(&dryRun, "dry-run", false, "skip artifact download")
	flag.BoolVar(&dryRun, "n", false, "(short for -dry-run)")

	flag.StringVar(&project, "repo", "", "github `username/repo`")
	flag.IntVar(&buildNum, "build", 0, "get artifact for build number, ignoring branch")
	flag.StringVar(&filter.branch, "branch", "master", "search builds for branch `name`")

	// Workflows:
	// If there are multiple workflows, then the latest "build" is perhaps unrelated to building,
	// not even a later step in a workflow where an earlier step did build.  Eg, we have
	// stuff to automate dependencies checking, scheduled from cron.
	// So to retrieve an artifact, we want to only consider specific workflow names.
	// However, those are config items in `.circleci/config.yml` and we should avoid hardcoding
	// such arbitrary choices across more than one repo, so our default for now is empty,
	// thus not filtered.
	//
	// Within a workflow, the build might not be the last step in the flow; it usually won't be.
	// Later steps might be "deploy", "stash image somewhere", etc.
	// So we need to step back from the last step within a workflow until we find the specific
	// step we're told.
	//
	// Eg, for one project, at this time, we use "commit_workflow" as the workflow to search for
	// and "build" as the job within that workflow.
	//
	// By default, we want the build found for a workflow to be part of the
	// same workflow invocation as the latest build seen for that workflow, so
	// that we don't skip back to an older generation. If instead you just want
	// "the latest build of that name, in any workflow matching this name",
	// then use -ignore-later-workflows.

	flag.StringVar(&filter.workflow, "workflow", "", "only consider builds which are part of this workflow")
	flag.StringVar(&filter.workflow, "w", "", "(short for -workflow)")
	flag.StringVar(&filter.jobname, "job", "", "look within workflow for artifacts from this build/step/job")
	flag.StringVar(&filter.jobname, "j", "", "(short for -job)")
	flag.IntVar(&retrieveBuildsCount, "search-depth", defaultRetrieveCount, "how far back to search in build history")
	flag.BoolVar(&filter.anyFlowID, "ignore-later-workflows", false, "latest build of any matching workflow will do")

	// DELETE AFTER 2018-04-01 {{{
	// when the workflow-jobname functionality was first added, I (pdp) named it badly; for compatibility,
	// continue taking the confusingly named option, but map it to the fixed variable.  Similarly for
	// how the presence of multiple workflows means "workflow-depth" was now a misnomer, and "retrieve-count"
	// is more accurate.
	flag.StringVar(&filter.jobname, "workflow-artifact-build", "", "(deprecated alias for -workflow-jobname)")
	flag.IntVar(&retrieveBuildsCount, "workflow-depth", defaultRetrieveCount, "(deprecated alias for -search-depth)")
	// DELETE AFTER 2018-04-01 }}}

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s [flags] <artifact>\n\n", filepath.Base(os.Args[0]))
		flag.PrintDefaults()
	}

	flag.Parse()

	if len(flag.Args()) != 1 {
		flag.Usage()
		log.Fatal("stray unparsed parameters left in command-line")
	}

	if project == "" {
		out, err := exec.Command("git", "remote", "get-url", "origin").Output()
		if err != nil {
			log.Fatalf("exec git: %s", err)
		}
		project = gitProject(string(out))
	}

	artifactName := flag.Arg(0)
	if circleToken == "" {
		circleToken = os.Getenv("CIRCLE_TOKEN")
	}

	// for URL expansion with sane named parameters, and put in everything
	// we might want too, including filters, in case there are better
	// URLs we can switch to in future.
	expansions := Expander{
		"project":        project,
		"artifact":       artifactName,
		"retrieve_count": strconv.Itoa(retrieveBuildsCount),
		"build_num":      strconv.Itoa(buildNum),
		"circle_token":   circleToken,
		"branch":         filter.branch,
		"workflow":       filter.workflow,
		"jobname":        filter.jobname,
	}

	switch {
	case project == "":
		flag.Usage()
		log.Fatal("no <username>/<project> provided")
	case filter.branch == "":
		flag.Usage()
		log.Fatal("no <branch> provided")
	case artifactName == "":
		flag.Usage()
		log.Fatal("no <artifact> provided")
	case circleToken == "":
		flag.Usage()
		log.Fatal("no auth token set: use $CIRCLE_TOKEN or flag -token")
	case retrieveBuildsCount < 1:
		flag.Usage()
		log.Fatal("workflow depth must be a positive (smallish) integer")
	case buildNum > 0:
		// Don't look for a green build.
		fmt.Printf("Build: %d\n", buildNum)
	default:
		buildNum = circleFindBuild(expansions, filter)
		expansions["build_num"] = strconv.Itoa(buildNum)
	}

	// Get artifact from buildNum
	u := expansions.Expand(artifactsURL)
	if verbose {
		fmt.Println("Artifact list:", u)
	}
	req, err := http.NewRequest("GET", u, nil)
	if err != nil {
		log.Fatal(err)
	}
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer res.Body.Close()
	var artifacts []artifact
	if err := json.NewDecoder(res.Body).Decode(&artifacts); err != nil {
		log.Fatal(err)
	}
	if outputPath == "" {
		outputPath = filepath.Base(artifactName)
	}
	n, err := downloadArtifact(artifacts, artifactName, outputPath)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Wrote %s (%d bytes) to %s\n", artifactName, n, outputPath)
}

func circleFindBuild(expansions Expander, filter FilterSet) (buildNum int) {
	u := expansions.Expand(buildListURL)
	if verbose {
		fmt.Println("Build list:", u)
	}
	req, err := http.NewRequest("GET", u, nil)
	if err != nil {
		log.Fatal(err)
	}
	req.Header.Set("Accept", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer res.Body.Close()
	body := new(bytes.Buffer)
	if _, err := io.Copy(body, res.Body); err != nil {
		log.Fatal(err)
	}

	var builds []build
	if err := json.Unmarshal(body.Bytes(), &builds); err != nil {
		log.Fatalf("%s: %s", err, body.String())
	}
	if len(builds) == 0 {
		log.Fatalf("no builds found for branch: %s", filter.branch)
	}

	// We _want_ to find the last successful workflow; as of APIv1.1 there's
	// nothing to filter directly by workflow, nor to tell if a workflow has
	// completed successfully, to know if we're grabbing something which later
	// failed, etc.
	//
	// So we just look for the last green build within a workflow and rely upon
	// the build we want being either that one, or earlier, with no prep steps
	// pre-build.  Unless the caller told us they don't care about matching
	// workflow ID to the latest workflow for which we see any builds.

	foundBuild := -1
	onlyWorkflowID := ""
	for i := 0; i < len(builds); i++ {
		headOfWorkflow := false
		if builds[i].Workflows == nil && (filter.workflow != "" || filter.jobname != "") {
			// fmt.Printf("skipping %d, no workflow: %+v\n", i, builds[i])
			// -- these happen, they show in the UI, I wonder if it's a manual trigger?
			continue
		}
		if builds[i].Status != "success" {
			continue
		}
		if onlyWorkflowID != "" && builds[i].Workflows.WorkflowID != onlyWorkflowID {
			continue
		}
		if filter.workflow != "" && builds[i].Workflows.WorkflowName != filter.workflow {
			continue
		}
		if onlyWorkflowID == "" && filter.workflow != "" && !filter.anyFlowID {
			onlyWorkflowID = builds[i].Workflows.WorkflowID
			headOfWorkflow = true
		}
		if filter.jobname != "" && builds[i].Workflows.JobName != filter.jobname {
			if headOfWorkflow {
				fmt.Printf("build: branch %q build %d is a %q, part of workflow %q, searching for build %q\n",
					filter.branch, builds[i].BuildNum,
					builds[i].Workflows.JobName, builds[0].Workflows.WorkflowName,
					filter.jobname)
			}
			continue
		}
		if builds[i].Workflows == nil {
			// must mean no filters, so i == 0
			fmt.Printf("build: workflow-less on branch %q found a build at offset %d\n",
				filter.branch, i)
		} else {
			fmt.Printf("build: workflow %q branch %q found build %q at offset %d\n",
				builds[i].Workflows.WorkflowName, filter.branch, builds[i].Workflows.JobName, i)
		}

		foundBuild = i
		break
	}

	if foundBuild < 0 {
		labelFlow := filter.workflow
		labelName := filter.jobname
		if labelFlow == "" {
			labelFlow = "*"
		}
		if labelName == "" {
			labelName = "*"
		}
		log.Fatalf("build: failed to find a build matching workflow=%q jobname=%q in branch %q",
			labelFlow, labelName, filter.branch)
	}

	if verbose {
		fmt.Printf("\nBuild Subject  : %s\nBuild Finished : %s\n",
			builds[foundBuild].Subject, builds[foundBuild].StopTime)
	}

	fmt.Printf("build: %d branch: %s rev: %s\n",
		builds[foundBuild].BuildNum, filter.branch, builds[foundBuild].Revision[:8])
	return builds[foundBuild].BuildNum
}

func downloadArtifact(artifacts []artifact, name, outputPath string) (int64, error) {
	for _, a := range artifacts {
		if verbose {
			fmt.Println("Artifact URL:", a.URL)
		}
		if !strings.HasSuffix(a.URL, name) {
			continue
		}
		u, err := url.Parse(a.URL)
		if err != nil {
			return 0, err
		}
		q := u.Query()
		q.Add("circle-token", circleToken)
		u.RawQuery = q.Encode()
		if verbose {
			fmt.Println("Artifact found:", name)
		}
		if dryRun {
			fmt.Println("Dry run: skipped download")
			os.Exit(0)
		}
		fmt.Printf("Downloading %s...\n", name)
		res, err := http.Get(u.String())
		if err != nil {
			return 0, err
		}
		defer res.Body.Close()
		if res.StatusCode != 200 {
			return 0, fmt.Errorf("http: remote server responded %s (check http://status.circleci.com)", res.Status)
		}
		f, err := os.Create(outputPath)
		if err != nil {
			return 0, err
		}
		return io.Copy(f, res.Body)
	}
	return 0, fmt.Errorf("unable to find artifact: %s", name)
}

var ghURL = regexp.MustCompile(`github\.com(?:/|:)(\w+/\w+)`)

func gitProject(url string) string {
	remote := ghURL.FindStringSubmatch(url)
	if len(remote) > 1 {
		return strings.Replace(remote[1], ".git", "", 1)
	}
	return ""
}
<|endoftext|>


<commit_before>package main

import (
    "log"
    "bytes"
    "crypto/x509"
    "crypto/x509/pkix"
    "encoding/pem"
    "encoding/asn1"
    "syscall/js"
    "crypto/rsa"
    "crypto/ecdsa"
    "crypto/rand"
    "math/big"
    "time"
    "net"
    "crypto/sha1"
    "errors"

    "github.com/pavel-v-chernykh/keystore-go"
)

var (
    ch = make(chan struct{}, 0)
)

func der2pem(args []js.Value) {
    input := args[0]
    ty := args[1].String()
    buf := make([]byte, input.Length())
    for i := 0; i < input.Length(); i++ {
        buf[i] = byte(input.Index(i).Int())
    }

    if ty == "cert" {
        b := &pem.Block{
            Type: "CERTIFICATE",
            Bytes: buf,
        }
        pemCert := pem.EncodeToMemory(b)
        args[2].Invoke(string(pemCert))
     } else if ty == "pkey" {
        b := &pem.Block{
            Type: "PRIVATE KEY",
            Bytes: buf,
        }
        pemPkey := pem.EncodeToMemory(b)
        args[2].Invoke(js.Undefined(), string(pemPkey))
    }
}

func jks2pem(args []js.Value) {
    input := args[0]
    passwd := args[1].String()

    buf := make([]byte, input.Length())
    for i := 0; i < input.Length(); i++ {
        buf[i] = byte(input.Index(i).Int())
    }

    reader := bytes.NewReader(buf)
    ks, err := keystore.Decode(reader, []byte(passwd))
    if err != nil {
        log.Fatal(err)
    }

    for _, v := range ks {
        val, ok := v.(*keystore.PrivateKeyEntry)
        if ok {

            certchain := ""
            for _, cert := range val.CertChain {
                _,  err := x509.ParseCertificate(cert.Content)
                if err != nil {
                    log.Fatal(err)
                }

                block := &pem.Block{
                    Type: "CERTIFICATE",
                    Bytes: val.CertChain[0].Content,
                }

                certchain = certchain + "\n" + string(pem.EncodeToMemory(block))
            }

            block := &pem.Block {
                Type: "PRIVATE KEY",
                Bytes: val.PrivKey,
            }
            pkey := string(pem.EncodeToMemory(block))
            args[2].Invoke(certchain, pkey)
            return
        }else {
            log.Fatal("unsupported keystore entry")
        }
    }

    return
}
/*
func generateKeyId(pubkey interface{}) []byte {
    switch key := pubkey.(type) {
    case *rsa.PublicKey:
        encoded := x509.MarshalPKCS1PublicKey(pubkey)
        skid := sha1.Sum(encoded)
        return skid[:]
    default:
        return nil
    }
}
*/
func processPrivateKey(key interface{}) (pub, priv interface{}, keyid []byte, err error) {
    switch key := key.(type) {
    case *rsa.PrivateKey:
        encoded := x509.MarshalPKCS1PublicKey(&key.PublicKey)
        skid := sha1.Sum(encoded)
        return key, &key.PublicKey, skid[:], nil
    case *ecdsa.PrivateKey:
        spkiASN1, err := x509.MarshalPKIXPublicKey(key.PublicKey)
        if err != nil {
            log.Fatal(err)
        }
        var spki struct {
            Algorithm        pkix.AlgorithmIdentifier
            SubjectPublicKey asn1.BitString
        }
        _, err = asn1.Unmarshal(spkiASN1, &spki)
        if err != nil {
            log.Fatal(err)
        }
        skid := sha1.Sum(spki.SubjectPublicKey.Bytes)
        return key, &key.PublicKey, skid[:], nil
    default:
        return nil, nil, nil, errors.New("unsupported algorithm")
    }
}

func newCert(args[]js.Value) (derCert, derPriv []byte){
    jsPKey := args[0]
    buf := make([]byte, jsPKey.Length())
    for i := 0; i < jsPKey.Length(); i++ {
        buf[i] = byte(jsPKey.Index(i).Int())
    }
    key, err := x509.ParsePKCS8PrivateKey(buf)
    if err != nil {
        log.Fatal(err)
    }

    privkey, pubkey, keyid, err := processPrivateKey(key)
    if err != nil {
        log.Fatal(err)
    }

    certinfo := args[1]

    names := pkix.Name{}
    subject := certinfo.Get("subject")
    if subject != js.Undefined() {
        if subject.Get("commonName") != js.Undefined() {
            names.CommonName= subject.Get("commonName").String();
        }
        if subject.Get("organizationName") != js.Undefined() {
            names.Organization = []string{subject.Get("organizationName").String()};
        }
        if subject.Get("organizationUnitName") != js.Undefined() {
            names.OrganizationalUnit = []string{subject.Get("organizationUnitName").String()};
        }
        if subject.Get("countryCode") != js.Undefined() {
            names.Country = []string{subject.Get("countryCode").String()};
        }
        if subject.Get("stasteOrProvinceName") != js.Undefined() {
            names.Province = []string{subject.Get("stasteOrProvinceName").String()};
        }
        if subject.Get("localityName") != js.Undefined() {
            names.Locality = []string{subject.Get("localityName").String()};
        }
    }

    days := 365
    if certinfo.Get("expiryDate") != js.Undefined() {
        days = certinfo.Get("expiryData").Int()
    }
    stime := time.Now()
    etime := time.Now().AddDate(0, 0, days)
    timefmt := "2006-01-02 15:04:05"
    if certinfo.Get("not before") != js.Undefined() {
        if stime, err = time.Parse(timefmt,certinfo.Get("not before").String()); err != nil {
            log.Fatal(err)
        }
    }
    if certinfo.Get("not after") != js.Undefined() {
        if etime, err = time.Parse(timefmt, certinfo.Get("not after").String()); err != nil {
            log.Fatal(err)
        }
    }

    isCA := false
    if certinfo.Get("isCA") != js.Undefined() {
        isCA = certinfo.Get("isCA").Bool()
    }

    eku := make([]x509.ExtKeyUsage, 0)
    jseku := certinfo.Get("extendkeyusage")
    if jseku != js.Undefined() {
        m := map[string]x509.ExtKeyUsage{
            "any":x509.ExtKeyUsageAny,
	    "serverauth":x509.ExtKeyUsageServerAuth,
            "clientauth":x509.ExtKeyUsageClientAuth,
            "codesigning":x509.ExtKeyUsageCodeSigning,
            "emailprotection":x509.ExtKeyUsageEmailProtection,
        }
        for i := 0; i < jseku.Length(); i++ {
            value := jseku.Index(i).String()
            if val, ok := m[value]; ok {
                eku = append(eku, val)
            }
        }
    }

    var ku x509.KeyUsage
    jsku := certinfo.Get("keyusage")
    if jsku != js.Undefined() {
        m := map[string]x509.KeyUsage {
          "digitalsignature": x509.KeyUsageDigitalSignature,
          "contentcommitment": x509.KeyUsageContentCommitment,
          "keyencipherment": x509.KeyUsageKeyEncipherment,
          "dataencipherment": x509.KeyUsageDataEncipherment,
          "keyagreement": x509. KeyUsageKeyAgreement,
          "certsign": x509.KeyUsageCertSign,
          "crlsign": x509.KeyUsageCRLSign,
          "encipheronly": x509.KeyUsageEncipherOnly,
          "decipheronly": x509.KeyUsageDecipherOnly,
        }
        for i := 0; i < jsku.Length(); i++ {
            value := jsku.Index(i).String()
            if val, ok := m[value]; ok {
                ku = ku | val
            }
        }
    }

    if isCA {
        ku = x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign | x509.KeyUsageCRLSign
        eku = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}
    }
    template := &x509.Certificate{
        SerialNumber: big.NewInt(time.Now().Unix()),
        Subject: names,
        NotBefore: stime,
        NotAfter: etime,
        KeyUsage: ku,
        ExtKeyUsage: eku,
        BasicConstraintsValid: true,
        IsCA: isCA,
        SubjectKeyId: keyid,
    }

    cacert := template
    capriv := interface{}(privkey)
    if len(args) >= 3 && args[2] != js.Undefined() {
        cainfo := args[2]
        pemCACert := cainfo.Get("cert").String()
        pemCAPkey := cainfo.Get("pkey").String()
        var b *pem.Block
        var err error
        b, _ = pem.Decode([]byte(pemCACert))
        cacert, err = x509.ParseCertificate(b.Bytes)
        if err != nil {
            log.Fatal(err)
        }
        b, _ = pem.Decode([]byte(pemCAPkey))
        pkeyinterface, err := x509.ParsePKCS8PrivateKey(b.Bytes)
        if err != nil {
            log.Fatal(err)
        }
        caprivkey, _, cakeyid, err := processPrivateKey(pkeyinterface)
        if err != nil {
            log.Fatal(err)
        }
        capriv = caprivkey
        template.AuthorityKeyId = cakeyid
    }

    altnames := certinfo.Get("subject-alt-name")
    if altnames != js.Undefined() {
        for i := 0; i < altnames.Length(); i++ {
            v := altnames.Index(i).String()
            if net.ParseIP(v) != nil {
                template.IPAddresses = append(template.IPAddresses, net.ParseIP(v))
            } else {
                template.DNSNames = append(template.DNSNames, v)
            }
        }
    }

    derBytes, err := x509.CreateCertificate(rand.Reader, template, cacert, pubkey, capriv)
    if err != nil {
        log.Fatal(err)
    }

    return derBytes, buf
}

func createCACertificate(args []js.Value) {
    n := len(args)
    if n != 3 {
        log.Fatal("invalid arguments")
    }

    derCert, derPriv := newCert(args[0:2])
    pemCert := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derCert})
    pemPkey := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes:derPriv})
    args[2].Invoke(string(pemCert), string(pemPkey))
    return
}

func createCertificate(args[] js.Value) {
    n := len(args)
    if n != 4 {
        log.Fatal("invalid arguments")
    }

    cb := args[n-1]
    derCert, derPriv := newCert(args[0:n-1])
    pemCert := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derCert})
    pemPkey := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes:derPriv})
    cb.Invoke(string(pemCert), string(pemPkey))
    return
}

func main() {

    js.Global().Set("wasmJKS2Pem", js.NewCallback(jks2pem))
    js.Global().Set("wasmDer2Pem", js.NewCallback(der2pem))
    js.Global().Set("wasmCreateCertificate", js.NewCallback(createCertificate))
    js.Global().Set("wasmCreateCACertificate", js.NewCallback(createCACertificate))
    <-ch
    log.Println("end")
}
<commit_msg>fix: x509.MarshalPKIXPublic need pointer value<commit_after>package main

import (
    "log"
    "bytes"
    "crypto/x509"
    "crypto/x509/pkix"
    "encoding/pem"
    "encoding/asn1"
    "syscall/js"
    "crypto/rsa"
    "crypto/ecdsa"
    "crypto/rand"
    "math/big"
    "time"
    "net"
    "crypto/sha1"
    "errors"

    "github.com/pavel-v-chernykh/keystore-go"
)

var (
    ch = make(chan struct{}, 0)
)

func der2pem(args []js.Value) {
    input := args[0]
    ty := args[1].String()
    buf := make([]byte, input.Length())
    for i := 0; i < input.Length(); i++ {
        buf[i] = byte(input.Index(i).Int())
    }

    if ty == "cert" {
        b := &pem.Block{
            Type: "CERTIFICATE",
            Bytes: buf,
        }
        pemCert := pem.EncodeToMemory(b)
        args[2].Invoke(string(pemCert))
     } else if ty == "pkey" {
        b := &pem.Block{
            Type: "PRIVATE KEY",
            Bytes: buf,
        }
        pemPkey := pem.EncodeToMemory(b)
        args[2].Invoke(js.Undefined(), string(pemPkey))
    }
}

func jks2pem(args []js.Value) {
    input := args[0]
    passwd := args[1].String()

    buf := make([]byte, input.Length())
    for i := 0; i < input.Length(); i++ {
        buf[i] = byte(input.Index(i).Int())
    }

    reader := bytes.NewReader(buf)
    ks, err := keystore.Decode(reader, []byte(passwd))
    if err != nil {
        log.Fatal(err)
    }

    for _, v := range ks {
        val, ok := v.(*keystore.PrivateKeyEntry)
        if ok {

            certchain := ""
            for _, cert := range val.CertChain {
                _,  err := x509.ParseCertificate(cert.Content)
                if err != nil {
                    log.Fatal(err)
                }

                block := &pem.Block{
                    Type: "CERTIFICATE",
                    Bytes: val.CertChain[0].Content,
                }

                certchain = certchain + "\n" + string(pem.EncodeToMemory(block))
            }

            block := &pem.Block {
                Type: "PRIVATE KEY",
                Bytes: val.PrivKey,
            }
            pkey := string(pem.EncodeToMemory(block))
            args[2].Invoke(certchain, pkey)
            return
        }else {
            log.Fatal("unsupported keystore entry")
        }
    }

    return
}
/*
func generateKeyId(pubkey interface{}) []byte {
    switch key := pubkey.(type) {
    case *rsa.PublicKey:
        encoded := x509.MarshalPKCS1PublicKey(pubkey)
        skid := sha1.Sum(encoded)
        return skid[:]
    default:
        return nil
    }
}
*/
func processPrivateKey(key interface{}) (pub, priv interface{}, keyid []byte, err error) {
    switch key := key.(type) {
    case *rsa.PrivateKey:
        encoded := x509.MarshalPKCS1PublicKey(&key.PublicKey)
        skid := sha1.Sum(encoded)
        return key, &key.PublicKey, skid[:], nil
    case *ecdsa.PrivateKey:
        spkiASN1, err := x509.MarshalPKIXPublicKey(&key.PublicKey)
        if err != nil {
            log.Fatal(err)
        }
        var spki struct {
            Algorithm        pkix.AlgorithmIdentifier
            SubjectPublicKey asn1.BitString
        }
        _, err = asn1.Unmarshal(spkiASN1, &spki)
        if err != nil {
            log.Fatal(err)
        }
        skid := sha1.Sum(spki.SubjectPublicKey.Bytes)
        return key, &key.PublicKey, skid[:], nil
    default:
        return nil, nil, nil, errors.New("unsupported algorithm")
    }
}

func newCert(args[]js.Value) (derCert, derPriv []byte){
    jsPKey := args[0]
    buf := make([]byte, jsPKey.Length())
    for i := 0; i < jsPKey.Length(); i++ {
        buf[i] = byte(jsPKey.Index(i).Int())
    }
    key, err := x509.ParsePKCS8PrivateKey(buf)
    if err != nil {
        log.Fatal(err)
    }
    log.Println("come here1")
    privkey, pubkey, keyid, err := processPrivateKey(key)
    if err != nil {
        log.Fatal(err)
    }

    log.Println("come here2")
    certinfo := args[1]

    names := pkix.Name{}
    subject := certinfo.Get("subject")
    if subject != js.Undefined() {
        if subject.Get("commonName") != js.Undefined() {
            names.CommonName= subject.Get("commonName").String();
        }
        if subject.Get("organizationName") != js.Undefined() {
            names.Organization = []string{subject.Get("organizationName").String()};
        }
        if subject.Get("organizationUnitName") != js.Undefined() {
            names.OrganizationalUnit = []string{subject.Get("organizationUnitName").String()};
        }
        if subject.Get("countryCode") != js.Undefined() {
            names.Country = []string{subject.Get("countryCode").String()};
        }
        if subject.Get("stasteOrProvinceName") != js.Undefined() {
            names.Province = []string{subject.Get("stasteOrProvinceName").String()};
        }
        if subject.Get("localityName") != js.Undefined() {
            names.Locality = []string{subject.Get("localityName").String()};
        }
    }

    days := 365
    if certinfo.Get("expiryDate") != js.Undefined() {
        days = certinfo.Get("expiryData").Int()
    }
    stime := time.Now()
    etime := time.Now().AddDate(0, 0, days)
    timefmt := "2006-01-02 15:04:05"
    if certinfo.Get("not before") != js.Undefined() {
        if stime, err = time.Parse(timefmt,certinfo.Get("not before").String()); err != nil {
            log.Fatal(err)
        }
    }
    if certinfo.Get("not after") != js.Undefined() {
        if etime, err = time.Parse(timefmt, certinfo.Get("not after").String()); err != nil {
            log.Fatal(err)
        }
    }

    isCA := false
    if certinfo.Get("isCA") != js.Undefined() {
        isCA = certinfo.Get("isCA").Bool()
    }

    eku := make([]x509.ExtKeyUsage, 0)
    jseku := certinfo.Get("extendkeyusage")
    if jseku != js.Undefined() {
        m := map[string]x509.ExtKeyUsage{
            "any":x509.ExtKeyUsageAny,
	    "serverauth":x509.ExtKeyUsageServerAuth,
            "clientauth":x509.ExtKeyUsageClientAuth,
            "codesigning":x509.ExtKeyUsageCodeSigning,
            "emailprotection":x509.ExtKeyUsageEmailProtection,
        }
        for i := 0; i < jseku.Length(); i++ {
            value := jseku.Index(i).String()
            if val, ok := m[value]; ok {
                eku = append(eku, val)
            }
        }
    }

    var ku x509.KeyUsage
    jsku := certinfo.Get("keyusage")
    if jsku != js.Undefined() {
        m := map[string]x509.KeyUsage {
          "digitalsignature": x509.KeyUsageDigitalSignature,
          "contentcommitment": x509.KeyUsageContentCommitment,
          "keyencipherment": x509.KeyUsageKeyEncipherment,
          "dataencipherment": x509.KeyUsageDataEncipherment,
          "keyagreement": x509. KeyUsageKeyAgreement,
          "certsign": x509.KeyUsageCertSign,
          "crlsign": x509.KeyUsageCRLSign,
          "encipheronly": x509.KeyUsageEncipherOnly,
          "decipheronly": x509.KeyUsageDecipherOnly,
        }
        for i := 0; i < jsku.Length(); i++ {
            value := jsku.Index(i).String()
            if val, ok := m[value]; ok {
                ku = ku | val
            }
        }
    }

    if isCA {
        ku = x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign | x509.KeyUsageCRLSign
        eku = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}
    }
    template := &x509.Certificate{
        SerialNumber: big.NewInt(time.Now().Unix()),
        Subject: names,
        NotBefore: stime,
        NotAfter: etime,
        KeyUsage: ku,
        ExtKeyUsage: eku,
        BasicConstraintsValid: true,
        IsCA: isCA,
        SubjectKeyId: keyid,
    }

    cacert := template
    capriv := interface{}(privkey)
    if len(args) >= 3 && args[2] != js.Undefined() {
    log.Println("come here3")
        cainfo := args[2]
        pemCACert := cainfo.Get("cert").String()
        pemCAPkey := cainfo.Get("pkey").String()
        var b *pem.Block
        var err error
        b, _ = pem.Decode([]byte(pemCACert))
        cacert, err = x509.ParseCertificate(b.Bytes)
        if err != nil {
            log.Fatal(err)
        }
        b, _ = pem.Decode([]byte(pemCAPkey))
        pkeyinterface, err := x509.ParsePKCS8PrivateKey(b.Bytes)
        if err != nil {
            log.Fatal(err)
        }
        caprivkey, _, cakeyid, err := processPrivateKey(pkeyinterface)
        if err != nil {
            log.Fatal(err)
        }
        capriv = caprivkey
        template.AuthorityKeyId = cakeyid
    }
    log.Println("come here4")

    altnames := certinfo.Get("subject-alt-name")
    if altnames != js.Undefined() {
        for i := 0; i < altnames.Length(); i++ {
            v := altnames.Index(i).String()
            if net.ParseIP(v) != nil {
                template.IPAddresses = append(template.IPAddresses, net.ParseIP(v))
            } else {
                template.DNSNames = append(template.DNSNames, v)
            }
        }
    }

    derBytes, err := x509.CreateCertificate(rand.Reader, template, cacert, pubkey, capriv)
    if err != nil {
        log.Fatal(err)
    }

    return derBytes, buf
}

func createCACertificate(args []js.Value) {
    n := len(args)
    if n != 3 {
        log.Fatal("invalid arguments")
    }

    derCert, derPriv := newCert(args[0:2])
    pemCert := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derCert})
    pemPkey := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes:derPriv})
    args[2].Invoke(string(pemCert), string(pemPkey))
    return
}

func createCertificate(args[] js.Value) {
    n := len(args)
    if n != 4 {
        log.Fatal("invalid arguments")
    }

    cb := args[n-1]
    derCert, derPriv := newCert(args[0:n-1])
    pemCert := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derCert})
    pemPkey := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes:derPriv})
    cb.Invoke(string(pemCert), string(pemPkey))
    return
}

func main() {

    js.Global().Set("wasmJKS2Pem", js.NewCallback(jks2pem))
    js.Global().Set("wasmDer2Pem", js.NewCallback(der2pem))
    js.Global().Set("wasmCreateCertificate", js.NewCallback(createCertificate))
    js.Global().Set("wasmCreateCACertificate", js.NewCallback(createCACertificate))
    <-ch
    log.Println("end")
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"net"
	"strings"
	"sync"
)

var outputChannel = make(chan chan string, 5)
var peers []Peer
var messagesReceivedAlready = make(map[string]bool)
var messagesReceivedAlreadyLock = &sync.Mutex{}
var peerChannel chan Peer

type Peer struct {
	conn     net.Conn
	username string
}
func createConnection(ip string){
	go func(){
		conn,_ := net.Dial("tcp",ip)
		handleConn(conn)
	}()
}
func broadcastMessage(message string){
	encrypted,err:=encrypt(message,[]string{"slaidan_lt","leijurv"})
	if err!=nil{
		panic(err)
	}
	for i:=range peers {
		fmt.Println("Sending "+message+" to "+peers[i].username)
		peers[i].conn.Write([]byte(encrypted+"\n"))
	}
}
func onMessageReceived(message string, peerFrom Peer) {
	messagesReceivedAlreadyLock.Lock()
	_, found := messagesReceivedAlready[message]
	if found {
		fmt.Println("Lol wait. " + peerFrom.username + " sent us something we already has. Ignoring...")
		messagesReceivedAlreadyLock.Unlock()
		return
	}
	messagesReceivedAlready[message] = true
	messagesReceivedAlreadyLock.Unlock()
	messageChannel := make(chan string, 100)
	outputChannel <- messageChannel
	go func() {
		defer close(messageChannel)
		processMessage(message, messageChannel, peerFrom)
	}()
}
func processMessage(message string, messageChannel chan string, peerFrom Peer) {
	messageChannel <- "Hey, a message from " + peerFrom.username + ". "
	messageChannel <- "Beginning decryption. "
	msg,err:=decrypt(message)
	if err!=nil{
		messageChannel<-"Unable to decrypt =("
		messageChannel<-err.Error()
		return
	}
	messageChannel <- "Done decrypting. "
	messageChannel <- "Here's the message: "
	messageChannel <- msg
}

func handleConn(conn net.Conn) {
	fmt.Println("CONNECTION BABE. Sending our name")
	conn.Write([]byte(config.Username + "\n"))
	username, err := bufio.NewReader(conn).ReadString('\n')
	if err != nil {
		return
	}
	username = strings.TrimSpace(username)
	fmt.Println("Received username: " + username)
	//here make sure that username is valid
	peerObj := Peer{conn: conn, username: username}
	peerChannel <- peerObj
}
func onConnClose(peer Peer) {
	//remove from list of peers, but idk how to do that in go =(
	fmt.Println("Disconnected from " + peer.username)
}
func peerListen(peer Peer) {
	defer peer.conn.Close()
	defer onConnClose(peer)
	conn := peer.conn
	username := peer.username
	fmt.Println("Beginning to listen to " + username)
	for {
		message, err := bufio.NewReader(conn).ReadString('\n')
		if err != nil {
			fmt.Println(err.Error())
			return
		}
		message = strings.TrimSpace(message)
		onMessageReceived(message, peer)
	}
}
func peerWithName(name string) int {
	for i := 0; i < len(peers); i++ {
		if peers[i].username == name {
			return i
		}
	}
	return -1
}
func listen() {
	ln, err := net.Listen("tcp", ":8081")
	if err != nil {
		panic(err)
	}
	defer ln.Close()
	peerChannel = make(chan Peer)
	defer close(peerChannel)
	go func() {
		for {
			peer, ok := <-peerChannel
			if ok {
				if peerWithName(peer.username) == -1 {
					peers = append(peers, peer)
					broadcastMessage("lol dank memes")
					go peerListen(peer)
				} else {
					peer.conn.Close()
					fmt.Println("Sadly we are already connected to " + peer.username + ". Disconnecting")
				}
			} else {
				fmt.Println("Peers over")
				return
			}
		}
	}()
	for {
		conn, err := ln.Accept()
		if err != nil {
			panic(err)
		}
		go handleConn(conn)
	}
}
<commit_msg>updated<commit_after>package main

import (
	"bufio"
	"fmt"
	"net"
	"strings"
	"sync"
)

var outputChannel = make(chan chan string, 5)
var peers []Peer
var messagesReceivedAlready = make(map[string]bool)
var messagesReceivedAlreadyLock = &sync.Mutex{}
var peerChannel chan Peer

type Peer struct {
	conn     net.Conn
	username string
}
func createConnection(ip string){
	go func(){
		conn,_ := net.Dial("tcp",ip)
		handleConn(conn)
	}()
}
func broadcastMessage(message string){
	encrypted,err:=encrypt(message,[]string{"slaidan_lt","leijurv"})
	if err!=nil{
		panic(err)
	}
	for i:=range peers {
		fmt.Println("Sending "+message+" to "+peers[i].username)
		peers[i].conn.Write([]byte(encrypted+"\n"))
	}
}
func onMessageReceived(message string, peerFrom Peer) {
	messagesReceivedAlreadyLock.Lock()
	_, found := messagesReceivedAlready[message]
	if found {
		fmt.Println("Lol wait. " + peerFrom.username + " sent us something we already has. Ignoring...")
		messagesReceivedAlreadyLock.Unlock()
		return
	}
	messagesReceivedAlready[message] = true
	messagesReceivedAlreadyLock.Unlock()
	messageChannel := make(chan string, 100)
	outputChannel <- messageChannel
	go func() {
		defer close(messageChannel)
		processMessage(message, messageChannel, peerFrom)
	}()
}
func processMessage(message string, messageChannel chan string, peerFrom Peer) {
	messageChannel <- "Hey, a message from " + peerFrom.username + ". "
	messageChannel <- "Beginning decryption. "
	msg,err:=decrypt(message)
	if err!=nil{
		messageChannel<-"Unable to decrypt =("
		messageChannel<-err.Error()
		return
	}
	messageChannel <- "Done decrypting. "
	messageChannel <- "Here's the message: "
	messageChannel <- msg
}

func handleConn(conn net.Conn) {
	fmt.Println("CONNECTION BABE. Sending our name")
	conn.Write([]byte(config.Username + "\n"))
	username, err := bufio.NewReader(conn).ReadString('\n')
	if err != nil {
		return
	}
	username = strings.TrimSpace(username)
	fmt.Println("Received username: " + username)
	//here make sure that username is valid
	peerObj := Peer{conn: conn, username: username}
	peerChannel <- peerObj
}
func onConnClose(peer Peer) {
	//remove from list of peers, but idk how to do that in go =(
	fmt.Println("Disconnected from " + peer.username)
}
func peerListen(peer Peer) {
	defer peer.conn.Close()
	defer onConnClose(peer)
	conn := peer.conn
	username := peer.username
	fmt.Println("Beginning to listen to " + username)
	for {
		message, err := bufio.NewReader(conn).ReadString('\n')
		if err != nil {
			fmt.Println(err.Error())
			return
		}
		message = strings.TrimSpace(message)
		onMessageReceived(message, peer)
	}
}
func peerWithName(name string) int {
	for i := 0; i < len(peers); i++ {
		if peers[i].username == name {
			return i
		}
	}
	return -1
}
func listen() {
	ln, err := net.Listen("tcp", ":8080")
	if err != nil {
		panic(err)
	}
	defer ln.Close()
	peerChannel = make(chan Peer)
	defer close(peerChannel)
	go func() {
		for {
			peer, ok := <-peerChannel
			if ok {
				if peerWithName(peer.username) == -1 {
					peers = append(peers, peer)
					broadcastMessage("lol dank memes")
					go peerListen(peer)
				} else {
					peer.conn.Close()
					fmt.Println("Sadly we are already connected to " + peer.username + ". Disconnecting")
				}
			} else {
				fmt.Println("Peers over")
				return
			}
		}
	}()
	for {
		conn, err := ln.Accept()
		if err != nil {
			panic(err)
		}
		go handleConn(conn)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"code.google.com/p/go.net/websocket"
	"html/template"
	"log"
	"net/http"
	"os"
)

const (
	listenAddr = "localhost:4000" // server address
)

var (
	pwd, _         = os.Getwd()
	rootTemp       = template.Must(template.ParseFiles(pwd + "/chat.html"))
	JSON           = websocket.JSON            // codec for JSON
	Message        = websocket.Message         // codec for string, []byte
	active_clients = make(map[client_sock]int) // map containing clients
)

// Initialize handlers and websocket handlers
func init() {
	http.HandleFunc("/", rootHandler)
	http.Handle("/sock", websocket.Handler(SockServer))
}

//
type client_sock struct {
	websocket *websocket.Conn
	client_ip string
}

func SockServer(ws *websocket.Conn) {
	var err error
	var client_msg string
	// use []byte if websocket binary type is blob or arraybuffer
	// var client_msg []byte

	// cleanup on server side
	defer func() {
		if err = ws.Close(); err != nil {
			log.Println("Websocket could not be closed", err.Error())
		}
	}()

	client := ws.Request().RemoteAddr
	log.Println("Client connected:", client)
	sock_cli := client_sock{ws, client}
	active_clients[sock_cli] = 0
	log.Println("Number of clients connected ...", len(active_clients))

	// for loop so the websocket stays open otherwise
	// it'll close after one Receieve and Send
	for {
		if err = Message.Receive(ws, &client_msg); err != nil {
			// If we cannot Read then the connection is closed
			log.Println("Websocket Disconnected waiting", err.Error())
			// remove the ws client conn from our active clients
			delete(active_clients, sock_cli)
			log.Println("Number of clients still connected ...", len(active_clients))
			return
		}

		client_msg = sock_cli.client_ip + " Said: " + client_msg
		for cs, _ := range active_clients {
			if err = Message.Send(cs.websocket, client_msg); err != nil {
				// we could not send the message to a peer
				log.Println("Could not send message to ", cs.client_ip, err.Error())
			}
		}
	}
}

func rootHandler(w http.ResponseWriter, req *http.Request) {
	err := rootTemp.Execute(w, listenAddr)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func main() {
	err := http.ListenAndServe(listenAddr, nil)
	if err != nil {
		panic("ListenAndServe: " + err.Error())
	}
}
<commit_msg>Documentation Changes<commit_after>package main

import (
	"code.google.com/p/go.net/websocket"
	"html/template"
	"log"
	"net/http"
	"os"
)

const (
	listenAddr = "localhost:4000" // server address
)

var (
	pwd, _        = os.Getwd()
	RootTemp      = template.Must(template.ParseFiles(pwd + "/chat.html"))
	JSON          = websocket.JSON           // codec for JSON
	Message       = websocket.Message        // codec for string, []byte
	ActiveClients = make(map[ClientConn]int) // map containing clients
)

// Initialize handlers and websocket handlers
func init() {
	http.HandleFunc("/", rootHandler)
	http.Handle("/sock", websocket.Handler(SockServer))
}

// Client connection consists of the websocket and the client ip
type ClientConn struct {
	websocket *websocket.Conn
	client_ip string
}

// WebSocket server to handle chat between clients
func SockServer(ws *websocket.Conn) {
	var err error
	var client_msg string
	// use []byte if websocket binary type is blob or arraybuffer
	// var client_msg []byte

	// cleanup on server side
	defer func() {
		if err = ws.Close(); err != nil {
			log.Println("Websocket could not be closed", err.Error())
		}
	}()

	client := ws.Request().RemoteAddr
	log.Println("Client connected:", client)
	sock_cli := ClientConn{ws, client}
	ActiveClients[sock_cli] = 0
	log.Println("Number of clients connected ...", len(ActiveClients))

	// for loop so the websocket stays open otherwise
	// it'll close after one Receieve and Send
	for {
		if err = Message.Receive(ws, &client_msg); err != nil {
			// If we cannot Read then the connection is closed
			log.Println("Websocket Disconnected waiting", err.Error())
			// remove the ws client conn from our active clients
			delete(ActiveClients, sock_cli)
			log.Println("Number of clients still connected ...", len(ActiveClients))
			return
		}

		client_msg = sock_cli.client_ip + " Said: " + client_msg
		for cs, _ := range ActiveClients {
			if err = Message.Send(cs.websocket, client_msg); err != nil {
				// we could not send the message to a peer
				log.Println("Could not send message to ", cs.client_ip, err.Error())
			}
		}
	}
}

// RootHandler renders the template for the root page
func RootHandler(w http.ResponseWriter, req *http.Request) {
	err := RootTemp.Execute(w, listenAddr)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func main() {
	err := http.ListenAndServe(listenAddr, nil)
	if err != nil {
		panic("ListenAndServe: " + err.Error())
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"os"

	"github.com/cloudfoundry-incubator/veritas/chug_commands"
)

func ChugCommand() Command {
	var (
		rel          string
		data         string
		hideNonLager bool
	)

	flagSet := flag.NewFlagSet("chug", flag.ExitOnError)
	flagSet.StringVar(&rel, "rel", "", "render timestamps as durations relative to: 'first', 'now', or a number interpreted as a unix timestamp")
	flagSet.StringVar(&data, "data", "short", "render data: 'none', 'short', 'long'")
	flagSet.BoolVar(&hideNonLager, "hide", false, "hide non-lager logs")

	return Command{
		Name:        "chug",
		Description: "[file] - Prettify lager logs",
		FlagSet:     flagSet,
		Run: func(args []string) {
			if len(args) == 0 {
				err := chug_commands.Prettify(rel, data, hideNonLager, os.Stdin)
				ExitIfError("Failed to chug", err)
			} else {
				f, err := os.Open(args[0])
				ExitIfError("Could not open file", err)

				err = chug_commands.Prettify(rel, data, hideNonLager, f)
				ExitIfError("Failed to chug", err)

				f.Close()
			}
		},
	}
}

func ServeChugCommand() Command {
	var (
		addr string
		dev  bool
	)

	flagSet := flag.NewFlagSet("chug-serve", flag.ExitOnError)
	flagSet.StringVar(&addr, "addr", ":", "address to serve chug")
	flagSet.BoolVar(&dev, "dev", false, "dev mode")

	return Command{
		Name:        "chug-serve",
		Description: "[file] - Serve up pretty lager logs",
		FlagSet:     flagSet,
		Run: func(args []string) {
			if len(args) == 0 {
				err := chug_commands.ServeLogs(addr, dev, os.Stdin)
				ExitIfError("Failed to serve chug", err)
			} else {
				f, err := os.Open(args[0])
				ExitIfError("Could not open file", err)

				err = chug_commands.ServeLogs(addr, dev, f)
				ExitIfError("Failed to serve chug", err)

				f.Close()
			}
		},
	}
}
<commit_msg>chug-serve picks a random address correctly<commit_after>package main

import (
	"flag"
	"os"

	"github.com/cloudfoundry-incubator/veritas/chug_commands"
)

func ChugCommand() Command {
	var (
		rel          string
		data         string
		hideNonLager bool
	)

	flagSet := flag.NewFlagSet("chug", flag.ExitOnError)
	flagSet.StringVar(&rel, "rel", "", "render timestamps as durations relative to: 'first', 'now', or a number interpreted as a unix timestamp")
	flagSet.StringVar(&data, "data", "short", "render data: 'none', 'short', 'long'")
	flagSet.BoolVar(&hideNonLager, "hide", false, "hide non-lager logs")

	return Command{
		Name:        "chug",
		Description: "[file] - Prettify lager logs",
		FlagSet:     flagSet,
		Run: func(args []string) {
			if len(args) == 0 {
				err := chug_commands.Prettify(rel, data, hideNonLager, os.Stdin)
				ExitIfError("Failed to chug", err)
			} else {
				f, err := os.Open(args[0])
				ExitIfError("Could not open file", err)

				err = chug_commands.Prettify(rel, data, hideNonLager, f)
				ExitIfError("Failed to chug", err)

				f.Close()
			}
		},
	}
}

func ServeChugCommand() Command {
	var (
		addr string
		dev  bool
	)

	flagSet := flag.NewFlagSet("chug-serve", flag.ExitOnError)
	flagSet.StringVar(&addr, "addr", "127.0.0.1:0", "address to serve chug")
	flagSet.BoolVar(&dev, "dev", false, "dev mode")

	return Command{
		Name:        "chug-serve",
		Description: "[file] - Serve up pretty lager logs",
		FlagSet:     flagSet,
		Run: func(args []string) {
			if len(args) == 0 {
				err := chug_commands.ServeLogs(addr, dev, os.Stdin)
				ExitIfError("Failed to serve chug", err)
			} else {
				f, err := os.Open(args[0])
				ExitIfError("Could not open file", err)

				err = chug_commands.ServeLogs(addr, dev, f)
				ExitIfError("Failed to serve chug", err)

				f.Close()
			}
		},
	}
}
<|endoftext|>


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

package connpool

import (
	"net"
	"time"
)

type pooledConn struct {
	conn net.Conn
	err  error
}

// Set the error if the error is not recoverable.
func (self *pooledConn) setErr(err error) {
	if err != nil {
		nerr, ok := err.(net.Error)
		if ok && nerr.Temporary() {
			return
		}
		self.err = err
	}
}

func (self *pooledConn) Read(b []byte) (n int, err error) {
	n, err = self.conn.Read(b)
	self.setErr(err)
	return
}

func (self *pooledConn) Write(b []byte) (n int, err error) {
	n, err = self.conn.Write(b)
	self.setErr(err)
	return
}

func (self *pooledConn) Close() error {
	err := self.conn.Close()
	self.setErr(err)
	return
}

func (self *pooledConn) LocalAddr() net.Addr {
	return self.conn.LocalAddr()
}

func (self *pooledConn) RemoteAddr() net.Addr {
	return self.conn.RemoteAddr()
}

func (self *pooledConn) SetDeadline(t time.Time) error {
	err := self.conn.SetDeadline(t)
	self.setErr(err)
	return
}

func (self *pooledConn) SetReadDeadline(t time.Time) error {
	err := self.conn.SetReadDeadline(t)
	self.setErr(err)
	return
}

func (self *pooledConn) SetWriteDeadline(t time.Time) error {
	err := self.conn.SetWriteDeadline(t)
	self.setErr(err)
	return
}
<commit_msg>pooledConn<commit_after>/*
 * Copyright 2013 Nan Deng
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package connpool

import (
	"net"
	"time"
)

type pooledConn struct {
	conn net.Conn
	err  error
}

// Set the error if the error is not recoverable.
func (self *pooledConn) setErr(err error) {
	if err != nil {
		nerr, ok := err.(net.Error)
		if ok && nerr.Temporary() {
			return
		}
		self.err = err
	}
}

func (self *pooledConn) Read(b []byte) (n int, err error) {
	n, err = self.conn.Read(b)
	self.setErr(err)
	return
}

func (self *pooledConn) Write(b []byte) (n int, err error) {
	n, err = self.conn.Write(b)
	self.setErr(err)
	return
}

func (self *pooledConn) Close() error {
	err := self.conn.Close()
	self.setErr(err)
	return err
}

func (self *pooledConn) LocalAddr() net.Addr {
	return self.conn.LocalAddr()
}

func (self *pooledConn) RemoteAddr() net.Addr {
	return self.conn.RemoteAddr()
}

func (self *pooledConn) SetDeadline(t time.Time) error {
	err := self.conn.SetDeadline(t)
	self.setErr(err)
	return err
}

func (self *pooledConn) SetReadDeadline(t time.Time) error {
	err := self.conn.SetReadDeadline(t)
	self.setErr(err)
	return err
}

func (self *pooledConn) SetWriteDeadline(t time.Time) error {
	err := self.conn.SetWriteDeadline(t)
	self.setErr(err)
	return err
}
<|endoftext|>