<commit_before>package scrobble

import (
	"log"
	"time"

	"github.com/hawx/mpdrobble/scrobble/lastfm"
)

type Scrobbler interface {
	Scrobble(artist, album, albumArtist, title string, timestamp time.Time) error
	NowPlaying(artist, album, albumArtist, title string) error
	Name() string
}

func New(db Database, name, apiKey, secret, username, password, uriBase string) (Scrobbler, error) {
	api := lastfm.New(apiKey, secret, uriBase)

	queue, err := db.Queue([]byte(name))
	if err != nil {
		return nil, err
	}

	scrobbler := &lastfmScrobbler{api, username, password, false, name}
	return &queuedScrobbler{scrobbler, queue}, nil
}

type queuedScrobbler struct {
	Scrobbler
	queue Queue
}

func (api *queuedScrobbler) Scrobble(artist, album, albumArtist, title string, timestamp time.Time) (err error) {
	track, err := Track{artist, album, albumArtist, title, timestamp}, nil
	for err == nil {
		err = api.Scrobbler.Scrobble(track.Artist, track.Album, track.AlbumArtist, track.Title, track.Timestamp)
		if err != nil {
			break
		}
		track, err = api.queue.Dequeue()
	}

	if err != nil && err != QUEUE_EMPTY {
		api.queue.Enqueue(track)
		log.Printf("[%s] Queued: %s by %s\n", api.Name(), title, artist)
	}

	return err
}

type lastfmScrobbler struct {
	api      *lastfm.Api
	username string
	password string
	loggedIn bool
	name     string
}

func (api *lastfmScrobbler) Name() string {
	return api.name
}

func (api *lastfmScrobbler) login() error {
	if !api.loggedIn {
		err := api.api.Login(api.username, api.password)
		if err == nil {
			log.Printf("[%s] Connected", api.Name())
		}
		return err
	}
	return nil
}

func (api *lastfmScrobbler) Scrobble(artist, album, albumArtist, title string, timestamp time.Time) error {
	if err := api.login(); err != nil {
		return err
	}

	err := api.api.Scrobble(lastfm.ScrobbleArgs{
		Artist:      artist,
		Album:       album,
		AlbumArtist: albumArtist,
		Track:       title,
		Timestamp:   timestamp.Unix(),
	})

	if err == nil {
		log.Printf("[%s] Submitted: %s by %s\n", api.Name(), title, artist)
	}

	return err
}

func (api *lastfmScrobbler) NowPlaying(artist, album, albumArtist, title string) error {
	if err := api.login(); err != nil {
		return err
	}

	err := api.api.UpdateNowPlaying(lastfm.UpdateNowPlayingArgs{
		Artist:      artist,
		Track:       title,
		Album:       album,
		AlbumArtist: albumArtist,
	})

	if err == nil {
		log.Printf("[%s] NowPlaying: %s by %s\n", api.Name(), title, artist)
	}

	return err
}
<commit_msg>Save whether loggedin to services; don't display QUEUE_EMPTYs<commit_after>package scrobble

import (
	"log"
	"time"

	"github.com/hawx/mpdrobble/scrobble/lastfm"
)

type Scrobbler interface {
	Scrobble(artist, album, albumArtist, title string, timestamp time.Time) error
	NowPlaying(artist, album, albumArtist, title string) error
	Name() string
}

func New(db Database, name, apiKey, secret, username, password, uriBase string) (Scrobbler, error) {
	api := lastfm.New(apiKey, secret, uriBase)

	queue, err := db.Queue([]byte(name))
	if err != nil {
		return nil, err
	}

	scrobbler := &lastfmScrobbler{api, username, password, false, name}
	return &queuedScrobbler{scrobbler, queue}, nil
}

type queuedScrobbler struct {
	Scrobbler
	queue Queue
}

func (api *queuedScrobbler) Scrobble(artist, album, albumArtist, title string, timestamp time.Time) (err error) {
	track, err := Track{artist, album, albumArtist, title, timestamp}, nil
	for err == nil {
		err = api.Scrobbler.Scrobble(track.Artist, track.Album, track.AlbumArtist, track.Title, track.Timestamp)
		if err != nil {
			break
		}
		track, err = api.queue.Dequeue()
	}

	if err != nil {
		if err == QUEUE_EMPTY {
			return nil
		} else {
			api.queue.Enqueue(track)
			log.Printf("[%s] Queued: %s by %s\n", api.Name(), title, artist)
		}
	}

	return err
}

type lastfmScrobbler struct {
	api      *lastfm.Api
	username string
	password string
	loggedIn bool
	name     string
}

func (api *lastfmScrobbler) Name() string {
	return api.name
}

func (api *lastfmScrobbler) login() error {
	if !api.loggedIn {
		err := api.api.Login(api.username, api.password)
		if err == nil {
			log.Printf("[%s] Connected", api.Name())
			api.loggedIn = true
		}
		return err
	}
	return nil
}

func (api *lastfmScrobbler) Scrobble(artist, album, albumArtist, title string, timestamp time.Time) error {
	if err := api.login(); err != nil {
		return err
	}

	err := api.api.Scrobble(lastfm.ScrobbleArgs{
		Artist:      artist,
		Album:       album,
		AlbumArtist: albumArtist,
		Track:       title,
		Timestamp:   timestamp.Unix(),
	})

	if err == nil {
		log.Printf("[%s] Submitted: %s by %s\n", api.Name(), title, artist)
	}

	return err
}

func (api *lastfmScrobbler) NowPlaying(artist, album, albumArtist, title string) error {
	if err := api.login(); err != nil {
		return err
	}

	err := api.api.UpdateNowPlaying(lastfm.UpdateNowPlayingArgs{
		Artist:      artist,
		Track:       title,
		Album:       album,
		AlbumArtist: albumArtist,
	})

	if err == nil {
		log.Printf("[%s] NowPlaying: %s by %s\n", api.Name(), title, artist)
	}

	return err
}
<|endoftext|>


<commit_before>package psl

import (
	"bytes"
	"math"
	"sort"
	"strconv"
)

var HeaderV2 = []string{
	"HRX (r+1)",
	"ΔHRX",
	"Xcisla",
	"ƩR OD-DO",
	"Ntice",
	"Xtice",
	"ƩSTL OD-DO (min)",
	"ƩSTL OD-DO (max)",
	"ƩSTL OD-DO (počet)",
	"ƩKombinacie (min)",
	"ƩKombinacie (max)",
	"Kombinacie (počet)",
	"HHrx (min)",
	"HHrx (max)",
	"HHrx (počet)",
	// "ΔHHrx (min)",
	// "ΔHHrx (max)",
	"ƩR 1-DO (min)",
	"ƩR 1-DO (max)",
	"ƩR 1-DO (počet)",
	"ƩSTL 1-DO (min)",
	"ƩSTL 1-DO (max)",
	"ƩSTL 1-DO (počet)",
	"P (min)", "P (max)",
	"N (min)", "N (max)",
	"Pr (min)", "Pr (max)",
	"Mc (min)", "Mc (max)",
	"Vc (min)", "Vc (max)",
	"C19 (min)", "C19 (max)",
	"C0 (min)", "C0 (max)",
	"cC (min)", "cC (max)",
	"Cc (min)", "Cc (max)",
	"CC (min)", "CC (max)",
	"Zh (min)", "Zh (max)",
}

// vystup filter
type V2 struct {
	n, m      int
	Hrx, HHrx *H
	r         Riadok
	p         Xcisla

	hrx              float64
	sucet            [2]int
	hhrx, r1, s1, s2 map[float64]int
	nKombi           int
	ntice, xtice     map[string]int
	cislovacky       []Cislovacky
	zhoda            [2]int
}

func NewV2(a *Archiv, sk Skupina) V2 {
	return V2{
		n:    a.n,
		m:    a.m,
		Hrx:  a.Hrx,
		HHrx: a.HHrx,
		r:    a.Riadok,
		p:    sk.Xcisla,

		hrx:   sk.Hrx,
		sucet: [2]int{math.MaxInt32, 0},
		hhrx:  make(map[float64]int),
		r1:    make(map[float64]int),
		s1:    make(map[float64]int),
		s2:    make(map[float64]int),
		ntice: make(map[string]int),
		xtice: make(map[string]int),
		zhoda: [2]int{math.MaxInt32, 0},
	}
}

func (v *V2) Add(k Kombinacia) {
	v.nKombi++

	// zhoda min, max
	zhoda := Zhoda(v.r.K, k)
	v.zhoda[0] = min(v.zhoda[0], zhoda)
	v.zhoda[1] = max(v.zhoda[1], zhoda)

	// sucet min, max
	sucet := k.Sucet()
	v.sucet[0] = min(v.sucet[0], sucet)
	v.sucet[1] = max(v.sucet[1], sucet)

	// STL2 min, max, pocet
	_, S2 := k.SucetRSNext(v.Hrx.Cisla)
	if _, ok := v.s2[S2]; !ok {
		v.s2[S2] = 1
	}

	// R1, STL2 min, max, pocet
	R1, S1 := k.SucetRSNext(v.HHrx.Cisla)
	if _, ok := v.r1[R1]; !ok {
		v.r1[R1] = 1
	}
	if _, ok := v.s1[S1]; !ok {
		v.s1[S1] = 1
	}

	// HHrx min, max, pocet
	hhrx := v.HHrx.ValueKombinacia(k)
	if _, ok := v.hhrx[hhrx]; !ok {
		v.hhrx[hhrx] = 1
	}

	//  pocet Ntic
	v.ntice[Ntica(k).String()]++

	// pocet Xtic
	v.xtice[Xtica(v.m, k).String()]++

	// cislovacky
	v.cislovacky = append(v.cislovacky, k.Cislovacky())
}

func (v V2) Riadok() []string {
	r := make([]string, 0, len(HeaderV2))
	r = append(r, ftoa(v.hrx))
	r = append(r, ftoa(v.hrx-v.r.Hrx))
	r = append(r, v.p.String())
	r = append(r, ftoa(v.r.R2))
	r = append(r, v.formatTica(v.ntice))
	r = append(r, v.formatTica(v.xtice))
	r = append(r, v.formatFloatMap(v.s2)...)
	r = append(r, itoa(v.sucet[0]), itoa(v.sucet[1]))
	r = append(r, itoa(v.nKombi))
	r = append(r, v.formatFloatMap(v.hhrx)...)
	r = append(r, v.formatFloatMap(v.r1)...)
	r = append(r, v.formatFloatMap(v.s1)...)
	r = append(r, v.formatCislovacky()...)
	r = append(r, itoa(v.zhoda[0]), itoa(v.zhoda[1]))
	return r
}

func (v *V2) formatCislovacky() []string {
	var cmin, cmax Cislovacky
	for i := range cmax {
		cmin[i] = byte(99)
	}
	for _, c := range v.cislovacky {
		for i := range c {
			cmin[i] = byte(min(int(c[i]), int(cmin[i])))
			cmax[i] = byte(max(int(c[i]), int(cmax[i])))
		}
	}
	s := make([]string, 20)
	for i := 0; i < 10; i++ {
		j := i * 2
		s[j] = itoa(int(cmin[i]))
		s[j+1] = itoa(int(cmax[i]))
	}
	return s
}

func (v *V2) formatFloatMap(m map[float64]int) []string {
	if len(m) == 0 {
		return []string{"0", "0", "0"}
	}
	var (
		n   int
		min = math.MaxFloat64
		max = math.SmallestNonzeroFloat64
	)
	for k, v := range m {
		n += v
		if k > max {
			max = k
		}
		if k < min {
			min = k
		}
	}
	return []string{ftoa(min), ftoa(max), itoa(n)}
}

func (v *V2) formatIntMap(m map[int]int) []string {
	if len(m) == 0 {
		return []string{"0", "0", "0"}
	}
	var (
		n   int
		min = math.MaxInt32
		max int
	)
	for k, v := range m {
		n += v
		if k > max {
			max = k
		}
		if k < min {
			min = k
		}
	}
	return []string{itoa(min), itoa(max), itoa(n)}
}

func (v *V2) formatTica(m map[string]int) string {
	if len(m) == 0 {
		return ""
	}
	var keys []string
	for k := range m {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	var buf bytes.Buffer
	for i, k := range keys {
		v := m[k]
		if i > 0 {
			buf.WriteString(", ")
		}
		buf.WriteString(k + ":(" + itoa(v) + ")")
	}
	return buf.String()
}

func (v V2) Empty() bool {
	return v.nKombi == 0
}

// vystup generator
type V1 struct {
	n, m      int
	hrx, hhrx *H
	riadok    Riadok
	Header    []string
}

func NewV1(a *Archiv) V1 {

	var header []string
	for i := 1; i <= a.n; i++ {
		header = append(header, strconv.Itoa(i))
	}
	header = append(header,
		"P",
		"N",
		"Sled PN",
		"PR",
		"Sled PNPr",
		"Mc",
		"Vc",
		"Sled McVc",
		"C19",
		"C0",
		"cC",
		"Cc",
		"CC",
		"Sled prirodzené kritéria",
		"ZH",
		"ZH presun (r/r+1)",
		"Sm",
		"Kk",
		"Ntica",
		"Ntica súčet",
		"Ntica súčin pozície a stĺpca",
		"Xtica",
		"ƩR 1-DO",
		"ΔƩR 1-DO",
		"ƩSTL 1-DO",
		"ΔƩSTL 1-DO",
		"Δ(ƩR1-DO-ƩSTL1-DO)",
		"HHrx",
		"ΔHHrx",
		"ƩR OD-DO",
		"ΔƩR OD-DO",
		"ƩSTL OD-DO",
		"ΔƩSTL OD-DO",
		"Δ(ƩROD-DO-ƩSTLOD-DO)",
		"Hrx",
		"ΔHrx",
		"ƩKombinacie",
		"Cifra 1", "Cifra 2", "Cifra 3", "Cifra 4", "Cifra 5",
		"Cifra 6", "Cifra 7", "Cifra 8", "Cifra 9", "Cifra 0",
	)
	return V1{
		n:      a.n,
		m:      a.m,
		hrx:    a.Hrx,
		hhrx:   a.HHrx,
		riadok: a.Riadok,
		Header: header,
	}
}

func (v V1) Riadok(k Kombinacia) []string {
	var (
		line   = make([]string, 0, len(v.Header)+v.n)
		r1, s1 = k.SucetRSNext(v.hhrx.Cisla)
		r2, s2 = k.SucetRSNext(v.hrx.Cisla)
		hrx    = v.hrx.ValueKombinacia(k)
		hhrx   = v.hhrx.ValueKombinacia(k)
	)
	for _, cislo := range k {
		line = append(line, strconv.Itoa(int(cislo)))
	}
	c := k.Cislovacky()
	cislovacky := c.Strings()
	line = append(line, cislovacky[0:2]...)
	line = append(line, k.SledPN())
	line = append(line, cislovacky[2])
	line = append(line, k.SledPNPr())
	line = append(line, cislovacky[3:5]...)
	line = append(line, k.SledMcVc())
	line = append(line, cislovacky[5:]...)
	line = append(line, k.SledPrirodzene())
	line = append(line,
		itoa(Zhoda(v.riadok.K, k)),
		NewZhodaPresun(v.riadok.K, k).String(),
		ftoa(Smernica(k, v.n, v.m)),
		ftoa(Korelacia(v.riadok.K, k, v.n, v.m)),
		Ntica(k).String(),
		NticaSucet(k).String(),
		NticaSucin(k).String(),
		Xtica(v.m, k).String(),

		ftoa(r1),
		ftoa(r1-v.riadok.R1), //dt
		ftoa(s1),
		ftoa(s1-v.riadok.S1), //dt
		ftoa(r1-s1),
		ftoa(hhrx),
		ftoa(hhrx-v.riadok.HHrx), //dt

		ftoa(r2),
		ftoa(r2-v.riadok.R2), //dt
		ftoa(s2),
		ftoa(s2-v.riadok.S2), //dt
		ftoa(r2-s2),
		ftoa(hrx),
		ftoa(hrx-v.riadok.Hrx), //dt

		itoa(k.Sucet()),
	)
	line = append(line, k.Cifrovacky().Strings()...)
	return line
}
<commit_msg>fix R2 sum<commit_after>package psl

import (
	"bytes"
	"math"
	"sort"
	"strconv"
)

var HeaderV2 = []string{
	"HRX (r+1)",
	"ΔHRX",
	"Xcisla",
	"ƩR OD-DO",
	"Ntice",
	"Xtice",
	"ƩSTL OD-DO (min)",
	"ƩSTL OD-DO (max)",
	"ƩSTL OD-DO (počet)",
	"ƩKombinacie (min)",
	"ƩKombinacie (max)",
	"Kombinacie (počet)",
	"HHrx (min)",
	"HHrx (max)",
	"HHrx (počet)",
	// "ΔHHrx (min)",
	// "ΔHHrx (max)",
	"ƩR 1-DO (min)",
	"ƩR 1-DO (max)",
	"ƩR 1-DO (počet)",
	"ƩSTL 1-DO (min)",
	"ƩSTL 1-DO (max)",
	"ƩSTL 1-DO (počet)",
	"P (min)", "P (max)",
	"N (min)", "N (max)",
	"Pr (min)", "Pr (max)",
	"Mc (min)", "Mc (max)",
	"Vc (min)", "Vc (max)",
	"C19 (min)", "C19 (max)",
	"C0 (min)", "C0 (max)",
	"cC (min)", "cC (max)",
	"Cc (min)", "Cc (max)",
	"CC (min)", "CC (max)",
	"Zh (min)", "Zh (max)",
}

// vystup filter
type V2 struct {
	n, m      int
	Hrx, HHrx *H
	// r         Riadok
	p Xcisla

	hrx              float64
	sucet            [2]int
	hhrx, r1, s1, s2 map[float64]int
	nKombi           int
	ntice, xtice     map[string]int
	cislovacky       []Cislovacky
	zhoda            [2]int

	K0   Kombinacia
	HRX0 float64
	R2   float64
}

func NewV2(a *Archiv, sk Skupina) V2 {
	return V2{
		n:    a.n,
		m:    a.m,
		Hrx:  a.Hrx,
		HHrx: a.HHrx,
		// r:    a.Riadok,
		p: sk.Xcisla,

		hrx:   sk.Hrx,
		sucet: [2]int{math.MaxInt32, 0},
		hhrx:  make(map[float64]int),
		r1:    make(map[float64]int),
		s1:    make(map[float64]int),
		s2:    make(map[float64]int),
		ntice: make(map[string]int),
		xtice: make(map[string]int),
		zhoda: [2]int{math.MaxInt32, 0},

		K0:   a.Riadok.K,
		HRX0: a.Riadok.Hrx,
	}
}

func (v *V2) Add(k Kombinacia) {
	v.nKombi++

	// zhoda min, max
	zhoda := Zhoda(v.K0, k)
	v.zhoda[0] = min(v.zhoda[0], zhoda)
	v.zhoda[1] = max(v.zhoda[1], zhoda)

	// sucet min, max
	sucet := k.Sucet()
	v.sucet[0] = min(v.sucet[0], sucet)
	v.sucet[1] = max(v.sucet[1], sucet)

	// STL2 min, max, pocet
	R2, S2 := k.SucetRSNext(v.Hrx.Cisla)
	if _, ok := v.s2[S2]; !ok {
		v.s2[S2] = 1
	}
	v.R2 = R2

	// R1, STL1 min, max, pocet
	R1, S1 := k.SucetRSNext(v.HHrx.Cisla)
	if _, ok := v.r1[R1]; !ok {
		v.r1[R1] = 1
	}
	if _, ok := v.s1[S1]; !ok {
		v.s1[S1] = 1
	}

	// HHrx min, max, pocet
	hhrx := v.HHrx.ValueKombinacia(k)
	if _, ok := v.hhrx[hhrx]; !ok {
		v.hhrx[hhrx] = 1
	}

	//  pocet Ntic
	v.ntice[Ntica(k).String()]++

	// pocet Xtic
	v.xtice[Xtica(v.m, k).String()]++

	// cislovacky
	v.cislovacky = append(v.cislovacky, k.Cislovacky())
}

func (v V2) Riadok() []string {
	r := make([]string, 0, len(HeaderV2))
	r = append(r, ftoa(v.hrx))
	r = append(r, ftoa(v.hrx-v.HRX0))
	r = append(r, v.p.String())
	r = append(r, ftoa(v.R2))
	r = append(r, v.formatTica(v.ntice))
	r = append(r, v.formatTica(v.xtice))
	r = append(r, v.formatFloatMap(v.s2)...)
	r = append(r, itoa(v.sucet[0]), itoa(v.sucet[1]))
	r = append(r, itoa(v.nKombi))
	r = append(r, v.formatFloatMap(v.hhrx)...)
	r = append(r, v.formatFloatMap(v.r1)...)
	r = append(r, v.formatFloatMap(v.s1)...)
	r = append(r, v.formatCislovacky()...)
	r = append(r, itoa(v.zhoda[0]), itoa(v.zhoda[1]))
	return r
}

func (v *V2) formatCislovacky() []string {
	var cmin, cmax Cislovacky
	for i := range cmax {
		cmin[i] = byte(99)
	}
	for _, c := range v.cislovacky {
		for i := range c {
			cmin[i] = byte(min(int(c[i]), int(cmin[i])))
			cmax[i] = byte(max(int(c[i]), int(cmax[i])))
		}
	}
	s := make([]string, 20)
	for i := 0; i < 10; i++ {
		j := i * 2
		s[j] = itoa(int(cmin[i]))
		s[j+1] = itoa(int(cmax[i]))
	}
	return s
}

func (v *V2) formatFloatMap(m map[float64]int) []string {
	if len(m) == 0 {
		return []string{"0", "0", "0"}
	}
	var (
		n   int
		min = math.MaxFloat64
		max = math.SmallestNonzeroFloat64
	)
	for k, v := range m {
		n += v
		if k > max {
			max = k
		}
		if k < min {
			min = k
		}
	}
	return []string{ftoa(min), ftoa(max), itoa(n)}
}

func (v *V2) formatIntMap(m map[int]int) []string {
	if len(m) == 0 {
		return []string{"0", "0", "0"}
	}
	var (
		n   int
		min = math.MaxInt32
		max int
	)
	for k, v := range m {
		n += v
		if k > max {
			max = k
		}
		if k < min {
			min = k
		}
	}
	return []string{itoa(min), itoa(max), itoa(n)}
}

func (v *V2) formatTica(m map[string]int) string {
	if len(m) == 0 {
		return ""
	}
	var keys []string
	for k := range m {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	var buf bytes.Buffer
	for i, k := range keys {
		v := m[k]
		if i > 0 {
			buf.WriteString(", ")
		}
		buf.WriteString(k + ":(" + itoa(v) + ")")
	}
	return buf.String()
}

func (v V2) Empty() bool {
	return v.nKombi == 0
}

// vystup generator
type V1 struct {
	n, m      int
	hrx, hhrx *H
	riadok    Riadok
	Header    []string
}

func NewV1(a *Archiv) V1 {

	var header []string
	for i := 1; i <= a.n; i++ {
		header = append(header, strconv.Itoa(i))
	}
	header = append(header,
		"P",
		"N",
		"Sled PN",
		"PR",
		"Sled PNPr",
		"Mc",
		"Vc",
		"Sled McVc",
		"C19",
		"C0",
		"cC",
		"Cc",
		"CC",
		"Sled prirodzené kritéria",
		"ZH",
		"ZH presun (r/r+1)",
		"Sm",
		"Kk",
		"Ntica",
		"Ntica súčet",
		"Ntica súčin pozície a stĺpca",
		"Xtica",
		"ƩR 1-DO",
		"ΔƩR 1-DO",
		"ƩSTL 1-DO",
		"ΔƩSTL 1-DO",
		"Δ(ƩR1-DO-ƩSTL1-DO)",
		"HHrx",
		"ΔHHrx",
		"ƩR OD-DO",
		"ΔƩR OD-DO",
		"ƩSTL OD-DO",
		"ΔƩSTL OD-DO",
		"Δ(ƩROD-DO-ƩSTLOD-DO)",
		"Hrx",
		"ΔHrx",
		"ƩKombinacie",
		"Cifra 1", "Cifra 2", "Cifra 3", "Cifra 4", "Cifra 5",
		"Cifra 6", "Cifra 7", "Cifra 8", "Cifra 9", "Cifra 0",
	)
	return V1{
		n:      a.n,
		m:      a.m,
		hrx:    a.Hrx,
		hhrx:   a.HHrx,
		riadok: a.Riadok,
		Header: header,
	}
}

func (v V1) Riadok(k Kombinacia) []string {
	var (
		line   = make([]string, 0, len(v.Header)+v.n)
		r1, s1 = k.SucetRSNext(v.hhrx.Cisla)
		r2, s2 = k.SucetRSNext(v.hrx.Cisla)
		hrx    = v.hrx.ValueKombinacia(k)
		hhrx   = v.hhrx.ValueKombinacia(k)
	)
	for _, cislo := range k {
		line = append(line, strconv.Itoa(int(cislo)))
	}
	c := k.Cislovacky()
	cislovacky := c.Strings()
	line = append(line, cislovacky[0:2]...)
	line = append(line, k.SledPN())
	line = append(line, cislovacky[2])
	line = append(line, k.SledPNPr())
	line = append(line, cislovacky[3:5]...)
	line = append(line, k.SledMcVc())
	line = append(line, cislovacky[5:]...)
	line = append(line, k.SledPrirodzene())
	line = append(line,
		itoa(Zhoda(v.riadok.K, k)),
		NewZhodaPresun(v.riadok.K, k).String(),
		ftoa(Smernica(k, v.n, v.m)),
		ftoa(Korelacia(v.riadok.K, k, v.n, v.m)),
		Ntica(k).String(),
		NticaSucet(k).String(),
		NticaSucin(k).String(),
		Xtica(v.m, k).String(),

		ftoa(r1),
		ftoa(r1-v.riadok.R1), //dt
		ftoa(s1),
		ftoa(s1-v.riadok.S1), //dt
		ftoa(r1-s1),
		ftoa(hhrx),
		ftoa(hhrx-v.riadok.HHrx), //dt

		ftoa(r2),
		ftoa(r2-v.riadok.R2), //dt
		ftoa(s2),
		ftoa(s2-v.riadok.S2), //dt
		ftoa(r2-s2),
		ftoa(hrx),
		ftoa(hrx-v.riadok.Hrx), //dt

		itoa(k.Sucet()),
	)
	line = append(line, k.Cifrovacky().Strings()...)
	return line
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/binary"
	"encoding/json"
	"log"
	"os"
	"os/user"
	"path"

	"github.com/robbiev/multipass"
)

type KeychainResponse struct {
	Success bool
	Items   []multipass.Item
}

func getKeychain(password []byte) KeychainResponse {
	usr, err := user.Current()
	if err != nil {
		log.Println(err)
		return KeychainResponse{Success: false}
	}
	home := usr.HomeDir
	onePasswordDir := path.Join(home, "/Dropbox/1password/1Password.agilekeychain/data/default")
	keyChain := multipass.NewAgileKeyChain(onePasswordDir)
	defer keyChain.Close()
	err = keyChain.Open(password)
	response := KeychainResponse{Success: err == nil}
	if err == nil {
		var items []multipass.Item
		keyChain.ForEachItem(func(p string, f []byte) error {
			item, err := multipass.DecryptFile(f, keyChain.Keys())
			if err == nil {
				items = append(items, item)
			}
			return nil
		})
		response.Items = items
	}
	return response
}

func main() {
	defer func() {
		if r := recover(); r != nil {
			log.Println("Recovered in f", r)
		}
	}()

	for {
		// get message length, 4 bytes
		var length uint32
		err := binary.Read(os.Stdin, binary.LittleEndian, &length)
		if err != nil {
			break
		}

		// read message
		message := make([]byte, length)
		_, err = os.Stdin.Read(message)
		if err != nil {
			break
		}

		log.Println("read message")

		type Command struct {
			Action  string
			Payload interface{}
		}

		var command Command
		json.Unmarshal(message, &command)
		payload := command.Payload.(map[string]interface{})

		// there's only one message type right now
		password := []byte(payload["Password"].(string))
		response := getKeychain(password)

		encoded, _ := json.Marshal(response)
		binary.Write(os.Stdout, binary.LittleEndian, uint32(len(encoded)))
		_, err = os.Stdout.Write(encoded)
		if err != nil {
			log.Println(err)
			break
		}
	}
}
<commit_msg>can't seem to get home dir from JS<commit_after>package main

import (
	"encoding/binary"
	"encoding/json"
	"log"
	"os"
	"os/user"
	"path"

	"github.com/robbiev/multipass"
)

type KeychainResponse struct {
	Success bool
	Items   []multipass.Item
}

type HomeResponse struct {
	Success bool
	Home    string
}

func getHome() (string, error) {
	usr, err := user.Current()
	if err != nil {
		return "", err
	}
	return usr.HomeDir, nil
}

func getHomeResponse() HomeResponse {
	home, err := getHome()
	if err != nil {
		log.Println(err)
		return HomeResponse{Success: false}
	}
	return HomeResponse{Success: true, Home: home}
}

func getKeychain(password []byte) KeychainResponse {
	home, err := getHome()
	if err != nil {
		log.Println(err)
		return KeychainResponse{Success: false}
	}
	onePasswordDir := path.Join(home, "/Dropbox/1password/1Password.agilekeychain/data/default")
	keyChain := multipass.NewAgileKeyChain(onePasswordDir)
	defer keyChain.Close()
	err = keyChain.Open(password)
	response := KeychainResponse{Success: err == nil}
	if err == nil {
		var items []multipass.Item
		keyChain.ForEachItem(func(p string, f []byte) error {
			item, err := multipass.DecryptFile(f, keyChain.Keys())
			if err == nil {
				items = append(items, item)
			}
			return nil
		})
		response.Items = items
	}
	return response
}

func main() {
	defer func() {
		if r := recover(); r != nil {
			log.Println("Recovered in f", r)
		}
	}()

	for {
		// get message length, 4 bytes
		var length uint32
		err := binary.Read(os.Stdin, binary.LittleEndian, &length)
		if err != nil {
			break
		}

		// read message
		message := make([]byte, length)
		_, err = os.Stdin.Read(message)
		if err != nil {
			break
		}

		log.Println("read message")

		type Command struct {
			Action  string
			Payload interface{}
		}

		var command Command
		json.Unmarshal(message, &command)
		payload := command.Payload.(map[string]interface{})

		// there's only one message type right now
		password := []byte(payload["Password"].(string))
		response := getKeychain(password)

		encoded, _ := json.Marshal(response)
		binary.Write(os.Stdout, binary.LittleEndian, uint32(len(encoded)))
		_, err = os.Stdout.Write(encoded)
		if err != nil {
			log.Println(err)
			break
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/davyxu/pbmeta"
	pbprotos "github.com/davyxu/pbmeta/proto"
	"strconv"
	"strings"
)

func fieldTypeString(fd *pbmeta.FieldDescriptor) string {

	var ret string

	switch fd.Type() {

	case pbprotos.FieldDescriptorProto_TYPE_INT32:
		ret = "int"
	case pbprotos.FieldDescriptorProto_TYPE_UINT32:
		ret = "uint"
	case pbprotos.FieldDescriptorProto_TYPE_BOOL:
		ret = "bool"
	case pbprotos.FieldDescriptorProto_TYPE_FLOAT:
		ret = "float"
	case pbprotos.FieldDescriptorProto_TYPE_DOUBLE:
		ret = "double"
	case pbprotos.FieldDescriptorProto_TYPE_STRING:
		ret = "string"
	case pbprotos.FieldDescriptorProto_TYPE_INT64:
		ret = "long"
	case pbprotos.FieldDescriptorProto_TYPE_ENUM,
		pbprotos.FieldDescriptorProto_TYPE_MESSAGE:
		ret = fd.FullTypeName()
	default:
		ret = "unknown"
	}

	if fd.IsRepeated() {
		return fmt.Sprintf("global::System.Collections.Generic.List<%s>", ret)
	}

	return ret
}

func getDataFormat(fd *pbmeta.FieldDescriptor) string {
	switch fd.Type() {
	case pbprotos.FieldDescriptorProto_TYPE_STRING,
		pbprotos.FieldDescriptorProto_TYPE_MESSAGE,
		pbprotos.FieldDescriptorProto_TYPE_BOOL:
		return "Default"
	case pbprotos.FieldDescriptorProto_TYPE_FLOAT:
		return "FixedSize"
	}

	return "TwosComplement"
}

func wrapDefaultValue(fd *pbmeta.FieldDescriptor, typestr string) string {
	v := strings.TrimSpace(fd.DefaultValue())
	if v != "" {
		return fmt.Sprintf("(%s)%s", typestr, v)
	}

	return fmt.Sprintf("default(%s)", typestr)
}

func getDefaultValue(fd *pbmeta.FieldDescriptor) string {
	switch fd.Type() {
	case pbprotos.FieldDescriptorProto_TYPE_INT32:
		return wrapDefaultValue(fd, "int")
	case pbprotos.FieldDescriptorProto_TYPE_UINT32:
		return wrapDefaultValue(fd, "uint")
	case pbprotos.FieldDescriptorProto_TYPE_BOOL:
		return wrapDefaultValue(fd, "bool")
	case pbprotos.FieldDescriptorProto_TYPE_FLOAT:
		return wrapDefaultValue(fd, "float")
	case pbprotos.FieldDescriptorProto_TYPE_DOUBLE:
		return wrapDefaultValue(fd, "double")
	case pbprotos.FieldDescriptorProto_TYPE_INT64:
		return wrapDefaultValue(fd, "long")
	case pbprotos.FieldDescriptorProto_TYPE_STRING:
		v := strings.TrimSpace(fd.DefaultValue())
		if v != "" {
			return "@" + strconv.Quote(fd.DefaultValue())
		}

		return strconv.Quote(fd.DefaultValue())
	case pbprotos.FieldDescriptorProto_TYPE_ENUM:
		ed := fd.EnumDesc()
		if ed.ValueCount() > 0 {

			var defaultValue string

			// 有defaultvalue, 直接取值, 否则取枚举第一个
			if v := strings.TrimSpace(fd.DefaultValue()); v != "" {
				defaultValue = v
			} else {
				defaultValue = ed.Value(0).Name()
			}

			return fmt.Sprintf("%s.%s", fd.FullTypeName(), defaultValue)
		}
	case pbprotos.FieldDescriptorProto_TYPE_MESSAGE:
		return "null"
	}

	return "unknown"
}

func isRequired(fd *pbmeta.FieldDescriptor) string {
	if fd.IsRequired() {
		return "true"
	}

	return "false"
}

func printField(gen *Generator, fd *pbmeta.FieldDescriptor, msg *pbmeta.Descriptor, file *pbmeta.FileDescriptor) {
	typeStr := fieldTypeString(fd)
	memberVar := "_" + fd.Name()

	//  private int _Age = default(int);

	if fd.IsRepeated() {
		gen.Println("readonly ", typeStr, " ", memberVar, " = new ", typeStr, "();")

	} else {

		gen.Println(typeStr, " ", memberVar, " = ", getDefaultValue(fd), ";")
		gen.Println("bool _has", fd.Name(), " = false;")

	}

	// [global::ProtoBuf.ProtoMember(10, IsRequired = false, Name=@"Age", DataFormat = global::ProtoBuf.DataFormat.TwosComplement)]
	gen.BeginLine()

	gen.Print("[global::ProtoBuf.ProtoMember(", fd.Define.GetNumber())

	if !fd.IsRepeated() {
		gen.Print(", IsRequired = ", isRequired(fd))
	}

	gen.Print(", Name=@\"", fd.Name(), "\", DataFormat = global::ProtoBuf.DataFormat.", getDataFormat(fd), ")]")

	gen.EndLine()

	if !fd.IsRepeated() {
		gen.Println("[global::System.ComponentModel.DefaultValue(", getDefaultValue(fd), ")]")
	}

	// 属性定义
	gen.Println("public ", typeStr, " ", fd.Name())
	gen.Println("{")
	gen.In()
	gen.Println("get { return ", memberVar, "; }")

	if !fd.IsRepeated() {
		gen.Println("set { ", memberVar, " = value; ")
		gen.Println("      _has", fd.Name(), " = true;")
		gen.Println("}")
	}

	gen.Out()
	gen.Println("}")

	gen.Println()

	if !fd.IsRepeated() {
		gen.Println("public bool Has", fd.Name())
		gen.Println("{")
		gen.In()
		gen.Println("get { return _has", fd.Name(), "; }")
		gen.Println("set { _has", fd.Name(), " = value; }")
		gen.Out()
		gen.Println("}")
	}

}
<commit_msg>修复导出descriptor.proto时的一个枚举默认值导致的崩溃<commit_after>package main

import (
	"fmt"
	"strconv"
	"strings"

	"github.com/davyxu/pbmeta"
	pbprotos "github.com/davyxu/pbmeta/proto"
)

func fieldTypeString(fd *pbmeta.FieldDescriptor) string {

	var ret string

	switch fd.Type() {

	case pbprotos.FieldDescriptorProto_TYPE_INT32:
		ret = "int"
	case pbprotos.FieldDescriptorProto_TYPE_UINT32:
		ret = "uint"
	case pbprotos.FieldDescriptorProto_TYPE_BOOL:
		ret = "bool"
	case pbprotos.FieldDescriptorProto_TYPE_FLOAT:
		ret = "float"
	case pbprotos.FieldDescriptorProto_TYPE_DOUBLE:
		ret = "double"
	case pbprotos.FieldDescriptorProto_TYPE_STRING:
		ret = "string"
	case pbprotos.FieldDescriptorProto_TYPE_INT64:
		ret = "long"
	case pbprotos.FieldDescriptorProto_TYPE_ENUM,
		pbprotos.FieldDescriptorProto_TYPE_MESSAGE:
		ret = fd.FullTypeName()
	default:
		ret = "unknown"
	}

	if fd.IsRepeated() {
		return fmt.Sprintf("global::System.Collections.Generic.List<%s>", ret)
	}

	return ret
}

func getDataFormat(fd *pbmeta.FieldDescriptor) string {
	switch fd.Type() {
	case pbprotos.FieldDescriptorProto_TYPE_STRING,
		pbprotos.FieldDescriptorProto_TYPE_MESSAGE,
		pbprotos.FieldDescriptorProto_TYPE_BOOL:
		return "Default"
	case pbprotos.FieldDescriptorProto_TYPE_FLOAT:
		return "FixedSize"
	}

	return "TwosComplement"
}

func wrapDefaultValue(fd *pbmeta.FieldDescriptor, typestr string) string {
	v := strings.TrimSpace(fd.DefaultValue())
	if v != "" {
		return fmt.Sprintf("(%s)%s", typestr, v)
	}

	return fmt.Sprintf("default(%s)", typestr)
}

func getDefaultValue(fd *pbmeta.FieldDescriptor) string {
	switch fd.Type() {
	case pbprotos.FieldDescriptorProto_TYPE_INT32:
		return wrapDefaultValue(fd, "int")
	case pbprotos.FieldDescriptorProto_TYPE_UINT32:
		return wrapDefaultValue(fd, "uint")
	case pbprotos.FieldDescriptorProto_TYPE_BOOL:
		return wrapDefaultValue(fd, "bool")
	case pbprotos.FieldDescriptorProto_TYPE_FLOAT:
		return wrapDefaultValue(fd, "float")
	case pbprotos.FieldDescriptorProto_TYPE_DOUBLE:
		return wrapDefaultValue(fd, "double")
	case pbprotos.FieldDescriptorProto_TYPE_INT64:
		return wrapDefaultValue(fd, "long")
	case pbprotos.FieldDescriptorProto_TYPE_STRING:
		v := strings.TrimSpace(fd.DefaultValue())
		if v != "" {
			return "@" + strconv.Quote(fd.DefaultValue())
		}

		return strconv.Quote(fd.DefaultValue())
	case pbprotos.FieldDescriptorProto_TYPE_ENUM:
		ed := fd.EnumDesc()

		if ed == nil {
			return fd.DefaultValue()
		}

		if ed.ValueCount() > 0 {

			var defaultValue string

			// 有defaultvalue, 直接取值, 否则取枚举第一个
			if v := strings.TrimSpace(fd.DefaultValue()); v != "" {
				defaultValue = v
			} else {
				defaultValue = ed.Value(0).Name()
			}

			return fmt.Sprintf("%s.%s", fd.FullTypeName(), defaultValue)
		}
	case pbprotos.FieldDescriptorProto_TYPE_MESSAGE:
		return "null"
	}

	return "unknown"
}

func isRequired(fd *pbmeta.FieldDescriptor) string {
	if fd.IsRequired() {
		return "true"
	}

	return "false"
}

func printField(gen *Generator, fd *pbmeta.FieldDescriptor, msg *pbmeta.Descriptor, file *pbmeta.FileDescriptor) {
	typeStr := fieldTypeString(fd)
	memberVar := "_" + fd.Name()

	//  private int _Age = default(int);

	if fd.IsRepeated() {
		gen.Println("readonly ", typeStr, " ", memberVar, " = new ", typeStr, "();")

	} else {

		gen.Println(typeStr, " ", memberVar, " = ", getDefaultValue(fd), ";")
		gen.Println("bool _has", fd.Name(), " = false;")

	}

	// [global::ProtoBuf.ProtoMember(10, IsRequired = false, Name=@"Age", DataFormat = global::ProtoBuf.DataFormat.TwosComplement)]
	gen.BeginLine()

	gen.Print("[global::ProtoBuf.ProtoMember(", fd.Define.GetNumber())

	if !fd.IsRepeated() {
		gen.Print(", IsRequired = ", isRequired(fd))
	}

	gen.Print(", Name=@\"", fd.Name(), "\", DataFormat = global::ProtoBuf.DataFormat.", getDataFormat(fd), ")]")

	gen.EndLine()

	if !fd.IsRepeated() {
		gen.Println("[global::System.ComponentModel.DefaultValue(", getDefaultValue(fd), ")]")
	}

	// 属性定义
	gen.Println("public ", typeStr, " ", fd.Name())
	gen.Println("{")
	gen.In()
	gen.Println("get { return ", memberVar, "; }")

	if !fd.IsRepeated() {
		gen.Println("set { ", memberVar, " = value; ")
		gen.Println("      _has", fd.Name(), " = true;")
		gen.Println("}")
	}

	gen.Out()
	gen.Println("}")

	gen.Println()

	if !fd.IsRepeated() {
		gen.Println("public bool Has", fd.Name())
		gen.Println("{")
		gen.In()
		gen.Println("get { return _has", fd.Name(), "; }")
		gen.Println("set { _has", fd.Name(), " = value; }")
		gen.Out()
		gen.Println("}")
	}

}
<|endoftext|>


<commit_before>package multipass

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/json"
	"encoding/pem"
	"errors"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"path"
	"strings"
	"time"

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

	jose "gopkg.in/square/go-jose.v1"
)

var ErrInvalidToken error = errors.New("invalid token")

type Auth struct {
	*Multipass
	Next httpserver.Handler
}

type Rule struct {
	Basepath  string
	Expires   time.Duration
	Resources []string
	Handles   []string

	SMTPAddr, SMTPUser, SMTPPass string
	MailFrom, MailTmpl           string
}

type Multipass struct {
	Resources []string
	Basepath  string
	SiteAddr  string
	Expires   time.Duration

	sender     Sender
	authorizer Authorizer
	signer     jose.Signer
	key        *rsa.PrivateKey
}

func NewMultipassFromRule(r Rule) (*Multipass, error) {
	m, err := NewMultipass()
	if err != nil {
		return nil, err
	}
	if len(r.Resources) > 0 {
		m.Resources = r.Resources
	}
	if len(r.Basepath) > 0 {
		m.Basepath = r.Basepath
	}
	if r.Expires > 0 {
		m.Expires = r.Expires
	}

	smtpAddr := "localhost:25"
	if len(r.SMTPAddr) > 0 {
		smtpAddr = r.SMTPAddr
	}
	mailTmpl := emailTemplate
	if len(r.MailTmpl) > 0 {
		mailTmpl = r.MailTmpl
	}
	m.sender = NewMailSender(smtpAddr, nil, r.MailFrom, mailTmpl)

	authorizer := &EmailAuthorizer{list: []string{}}
	for _, handle := range r.Handles {
		authorizer.Add(handle)
	}
	m.authorizer = authorizer

	return m, nil
}

func NewMultipass() (*Multipass, error) {
	pk, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return nil, err
	}
	signer, err := jose.NewSigner(jose.PS512, pk)
	if err != nil {
		return nil, err
	}
	return &Multipass{
		Resources: []string{"/"},
		Basepath:  "/",
		Expires:   time.Hour * 24,
		key:       pk,
		signer:    signer,
	}, nil
}

// Claims are part of the JSON web token
type Claims struct {
	Handle    string   `json:"handle"`
	Resources []string `json:"resources"`
	Expires   int64    `json:"exp"`
}

func (m *Multipass) AccessToken(handle string) (tokenStr string, err error) {
	exp := time.Now().Add(m.Expires)
	claims := &Claims{
		Handle:    handle,
		Resources: m.Resources,
		Expires:   exp.Unix(),
	}
	payload, err := json.Marshal(claims)
	if err != nil {
		return "", err
	}
	jws, err := m.signer.Sign(payload)
	if err != nil {
		return "", err
	}

	return jws.CompactSerialize()
}

func (m *Multipass) LoginURL(u url.URL, tokenStr string) url.URL {
	u.Path = path.Join(m.Basepath, "login")
	v := url.Values{}
	v.Set("token", tokenStr)
	u.RawQuery = v.Encode()

	return u
}

func loginHandler(w http.ResponseWriter, r *http.Request, m *Multipass) (int, error) {
	if r.Method == "POST" {
		r.ParseForm()
		handle := r.PostForm.Get("handle")
		if len(handle) == 0 {
			loc := path.Join(m.Basepath, "login")
			http.Redirect(w, r, loc, http.StatusSeeOther)
			return http.StatusSeeOther, nil
		}
		switch m.authorizer.IsAuthorized(handle) {
		case true:
			token, err := m.AccessToken(handle)
			if err != nil {
				log.Print(err)
			}
			siteURL, err := url.Parse(m.SiteAddr)
			if err != nil {
				log.Fatal(err)
			}
			loginURL := m.LoginURL(*siteURL, token)
			if err := m.sender.Send(handle, loginURL.String()); err != nil {
				log.Print(err)
			}
		}
		w.Header().Add("Content-Type", "text/html; charset=utf-8")
		w.Write([]byte("A login link has been sent to user with handle " + handle + " if your handle is authorized"))
		return http.StatusOK, nil
	}
	if r.Method == "GET" {
		if tokenStr := r.URL.Query().Get("token"); len(tokenStr) > 0 {
			cookie := &http.Cookie{
				Name:  "jwt_token",
				Value: tokenStr,
				Path:  "/",
			}
			http.SetCookie(w, cookie)
			r.URL.Path = ""
			r.URL.RawQuery = ""
			http.Redirect(w, r, r.URL.String(), http.StatusSeeOther)
			return http.StatusSeeOther, nil
		}
		w.Header().Add("Content-Type", "text/html; charset=utf-8")
		w.Write([]byte("<form action=" + r.URL.Path + " method=POST><input type=text name=handle /><input type=submit></form>"))
		return http.StatusOK, nil
	}
	return http.StatusMethodNotAllowed, nil
}

func loginformHandler(w http.ResponseWriter, r *http.Request, m *Multipass) (int, error) {
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	w.Write([]byte(`

<form action="` + path.Join(m.Basepath, "/login") + `" method=POST>
<input type=hidden name=url value="` + r.URL.String() + `"/>
<input type=text name=handle />
<input type=submit>
</form>
`))
	return http.StatusOK, nil
}

func signoutHandler(w http.ResponseWriter, r *http.Request, m *Multipass) (int, error) {
	if cookie, err := r.Cookie("jwt_token"); err == nil {
		cookie.Expires = time.Now().AddDate(-1, 0, 0)
		cookie.MaxAge = -1
		cookie.Path = "/"
		http.SetCookie(w, cookie)
	}
	loc := path.Join(m.Basepath, "login")
	http.Redirect(w, r, loc, http.StatusSeeOther)
	return http.StatusSeeOther, nil
}

func publickeyHandler(w http.ResponseWriter, r *http.Request, m *Multipass) (int, error) {
	data, err := x509.MarshalPKIXPublicKey(&m.key.PublicKey)
	if err != nil {
		return http.StatusInternalServerError, err
	}
	block := &pem.Block{
		Type:  "PUBLIC KEY",
		Bytes: data,
	}
	w.Header().Set("Content-Type", "application/pkix-cert")
	if err := pem.Encode(w, block); err != nil {
		return http.StatusInternalServerError, err
	}
	return http.StatusOK, nil
}

func tokenHandler(w http.ResponseWriter, r *http.Request, m *Multipass) (int, error) {
	// Extract token from HTTP header, query parameter or cookie
	tokenStr, err := extractToken(r)
	if err != nil {
		return http.StatusUnauthorized, ErrInvalidToken
	}
	var claims *Claims
	if claims, err = validateToken(tokenStr, m.key.PublicKey); err != nil {
		return http.StatusUnauthorized, ErrInvalidToken
	}
	// Authorize handle claim
	if ok := m.authorizer.IsAuthorized(claims.Handle); !ok {
		return http.StatusUnauthorized, ErrInvalidToken
	}
	// Verify path claim
	var match bool
	for _, path := range claims.Resources {
		if httpserver.Path(r.URL.Path).Matches(path) {
			match = true
			continue
		}
	}
	if !match {
		return http.StatusUnauthorized, ErrInvalidToken
	}
	return http.StatusOK, nil
}

func (a *Auth) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
	m := a.Multipass
	var pathMatch bool
	for _, path := range m.Resources {
		if httpserver.Path(r.URL.Path).Matches(path) {
			pathMatch = true
			continue
		}
	}
	if !pathMatch {
		return a.Next.ServeHTTP(w, r)
	}

	switch r.URL.Path {
	case path.Join(m.Basepath, "pub.cer"):
		return publickeyHandler(w, r, m)
	case path.Join(m.Basepath, "login"):
		return loginHandler(w, r, m)
	case path.Join(m.Basepath, "signout"):
		return signoutHandler(w, r, m)
	default:
		if code, err := tokenHandler(w, r, m); err != nil {
			w.WriteHeader(code)
			return loginformHandler(w, r, m)
		}
	}
	return a.Next.ServeHTTP(w, r)
}

// extractToken returns the JWT token embedded in the given request.
// JWT tokens can be embedded in the header prefixed with "Bearer ", with a
// "token" key query parameter or a cookie named "jwt_token".
func extractToken(r *http.Request) (string, error) {
	//from header
	if h := r.Header.Get("Authorization"); strings.HasPrefix(h, "Bearer ") {
		if len(h) > 7 {
			return h[7:], nil
		}
	}

	//from query parameter
	if token := r.URL.Query().Get("token"); len(token) > 0 {
		return token, nil
	}

	//from cookie
	if cookie, err := r.Cookie("jwt_token"); err == nil {
		return cookie.Value, nil
	}

	return "", fmt.Errorf("no token found")
}

func validateToken(token string, key rsa.PublicKey) (*Claims, error) {
	claims := &Claims{}

	// Verify token signature
	payload, err := verifyToken(token, key)
	if err != nil {
		return nil, err
	}
	// Unmarshal token claims
	if err := json.Unmarshal(payload, claims); err != nil {
		return nil, err
	}
	// Verify expire claim
	if time.Unix(claims.Expires, 0).Before(time.Now()) {
		return nil, errors.New("Token expired")
	}
	return claims, nil
}

func verifyToken(token string, key rsa.PublicKey) ([]byte, error) {
	var data []byte

	obj, err := jose.ParseSigned(token)
	if err != nil {
		return data, err
	}
	data, err = obj.Verify(&key)
	if err != nil {
		return data, err
	}
	return data, nil
}
<commit_msg>Remove type error declaration<commit_after>package multipass

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/json"
	"encoding/pem"
	"errors"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"path"
	"strings"
	"time"

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

	jose "gopkg.in/square/go-jose.v1"
)

var ErrInvalidToken = errors.New("invalid token")

type Auth struct {
	*Multipass
	Next httpserver.Handler
}

type Rule struct {
	Basepath  string
	Expires   time.Duration
	Resources []string
	Handles   []string

	SMTPAddr, SMTPUser, SMTPPass string
	MailFrom, MailTmpl           string
}

type Multipass struct {
	Resources []string
	Basepath  string
	SiteAddr  string
	Expires   time.Duration

	sender     Sender
	authorizer Authorizer
	signer     jose.Signer
	key        *rsa.PrivateKey
}

func NewMultipassFromRule(r Rule) (*Multipass, error) {
	m, err := NewMultipass()
	if err != nil {
		return nil, err
	}
	if len(r.Resources) > 0 {
		m.Resources = r.Resources
	}
	if len(r.Basepath) > 0 {
		m.Basepath = r.Basepath
	}
	if r.Expires > 0 {
		m.Expires = r.Expires
	}

	smtpAddr := "localhost:25"
	if len(r.SMTPAddr) > 0 {
		smtpAddr = r.SMTPAddr
	}
	mailTmpl := emailTemplate
	if len(r.MailTmpl) > 0 {
		mailTmpl = r.MailTmpl
	}
	m.sender = NewMailSender(smtpAddr, nil, r.MailFrom, mailTmpl)

	authorizer := &EmailAuthorizer{list: []string{}}
	for _, handle := range r.Handles {
		authorizer.Add(handle)
	}
	m.authorizer = authorizer

	return m, nil
}

func NewMultipass() (*Multipass, error) {
	pk, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return nil, err
	}
	signer, err := jose.NewSigner(jose.PS512, pk)
	if err != nil {
		return nil, err
	}
	return &Multipass{
		Resources: []string{"/"},
		Basepath:  "/",
		Expires:   time.Hour * 24,
		key:       pk,
		signer:    signer,
	}, nil
}

// Claims are part of the JSON web token
type Claims struct {
	Handle    string   `json:"handle"`
	Resources []string `json:"resources"`
	Expires   int64    `json:"exp"`
}

func (m *Multipass) AccessToken(handle string) (tokenStr string, err error) {
	exp := time.Now().Add(m.Expires)
	claims := &Claims{
		Handle:    handle,
		Resources: m.Resources,
		Expires:   exp.Unix(),
	}
	payload, err := json.Marshal(claims)
	if err != nil {
		return "", err
	}
	jws, err := m.signer.Sign(payload)
	if err != nil {
		return "", err
	}

	return jws.CompactSerialize()
}

func (m *Multipass) LoginURL(u url.URL, tokenStr string) url.URL {
	u.Path = path.Join(m.Basepath, "login")
	v := url.Values{}
	v.Set("token", tokenStr)
	u.RawQuery = v.Encode()

	return u
}

func loginHandler(w http.ResponseWriter, r *http.Request, m *Multipass) (int, error) {
	if r.Method == "POST" {
		r.ParseForm()
		handle := r.PostForm.Get("handle")
		if len(handle) == 0 {
			loc := path.Join(m.Basepath, "login")
			http.Redirect(w, r, loc, http.StatusSeeOther)
			return http.StatusSeeOther, nil
		}
		switch m.authorizer.IsAuthorized(handle) {
		case true:
			token, err := m.AccessToken(handle)
			if err != nil {
				log.Print(err)
			}
			siteURL, err := url.Parse(m.SiteAddr)
			if err != nil {
				log.Fatal(err)
			}
			loginURL := m.LoginURL(*siteURL, token)
			if err := m.sender.Send(handle, loginURL.String()); err != nil {
				log.Print(err)
			}
		}
		w.Header().Add("Content-Type", "text/html; charset=utf-8")
		w.Write([]byte("A login link has been sent to user with handle " + handle + " if your handle is authorized"))
		return http.StatusOK, nil
	}
	if r.Method == "GET" {
		if tokenStr := r.URL.Query().Get("token"); len(tokenStr) > 0 {
			cookie := &http.Cookie{
				Name:  "jwt_token",
				Value: tokenStr,
				Path:  "/",
			}
			http.SetCookie(w, cookie)
			r.URL.Path = ""
			r.URL.RawQuery = ""
			http.Redirect(w, r, r.URL.String(), http.StatusSeeOther)
			return http.StatusSeeOther, nil
		}
		w.Header().Add("Content-Type", "text/html; charset=utf-8")
		w.Write([]byte("<form action=" + r.URL.Path + " method=POST><input type=text name=handle /><input type=submit></form>"))
		return http.StatusOK, nil
	}
	return http.StatusMethodNotAllowed, nil
}

func loginformHandler(w http.ResponseWriter, r *http.Request, m *Multipass) (int, error) {
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	w.Write([]byte(`

<form action="` + path.Join(m.Basepath, "/login") + `" method=POST>
<input type=hidden name=url value="` + r.URL.String() + `"/>
<input type=text name=handle />
<input type=submit>
</form>
`))
	return http.StatusOK, nil
}

func signoutHandler(w http.ResponseWriter, r *http.Request, m *Multipass) (int, error) {
	if cookie, err := r.Cookie("jwt_token"); err == nil {
		cookie.Expires = time.Now().AddDate(-1, 0, 0)
		cookie.MaxAge = -1
		cookie.Path = "/"
		http.SetCookie(w, cookie)
	}
	loc := path.Join(m.Basepath, "login")
	http.Redirect(w, r, loc, http.StatusSeeOther)
	return http.StatusSeeOther, nil
}

func publickeyHandler(w http.ResponseWriter, r *http.Request, m *Multipass) (int, error) {
	data, err := x509.MarshalPKIXPublicKey(&m.key.PublicKey)
	if err != nil {
		return http.StatusInternalServerError, err
	}
	block := &pem.Block{
		Type:  "PUBLIC KEY",
		Bytes: data,
	}
	w.Header().Set("Content-Type", "application/pkix-cert")
	if err := pem.Encode(w, block); err != nil {
		return http.StatusInternalServerError, err
	}
	return http.StatusOK, nil
}

func tokenHandler(w http.ResponseWriter, r *http.Request, m *Multipass) (int, error) {
	// Extract token from HTTP header, query parameter or cookie
	tokenStr, err := extractToken(r)
	if err != nil {
		return http.StatusUnauthorized, ErrInvalidToken
	}
	var claims *Claims
	if claims, err = validateToken(tokenStr, m.key.PublicKey); err != nil {
		return http.StatusUnauthorized, ErrInvalidToken
	}
	// Authorize handle claim
	if ok := m.authorizer.IsAuthorized(claims.Handle); !ok {
		return http.StatusUnauthorized, ErrInvalidToken
	}
	// Verify path claim
	var match bool
	for _, path := range claims.Resources {
		if httpserver.Path(r.URL.Path).Matches(path) {
			match = true
			continue
		}
	}
	if !match {
		return http.StatusUnauthorized, ErrInvalidToken
	}
	return http.StatusOK, nil
}

func (a *Auth) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
	m := a.Multipass
	var pathMatch bool
	for _, path := range m.Resources {
		if httpserver.Path(r.URL.Path).Matches(path) {
			pathMatch = true
			continue
		}
	}
	if !pathMatch {
		return a.Next.ServeHTTP(w, r)
	}

	switch r.URL.Path {
	case path.Join(m.Basepath, "pub.cer"):
		return publickeyHandler(w, r, m)
	case path.Join(m.Basepath, "login"):
		return loginHandler(w, r, m)
	case path.Join(m.Basepath, "signout"):
		return signoutHandler(w, r, m)
	default:
		if code, err := tokenHandler(w, r, m); err != nil {
			w.WriteHeader(code)
			return loginformHandler(w, r, m)
		}
	}
	return a.Next.ServeHTTP(w, r)
}

// extractToken returns the JWT token embedded in the given request.
// JWT tokens can be embedded in the header prefixed with "Bearer ", with a
// "token" key query parameter or a cookie named "jwt_token".
func extractToken(r *http.Request) (string, error) {
	//from header
	if h := r.Header.Get("Authorization"); strings.HasPrefix(h, "Bearer ") {
		if len(h) > 7 {
			return h[7:], nil
		}
	}

	//from query parameter
	if token := r.URL.Query().Get("token"); len(token) > 0 {
		return token, nil
	}

	//from cookie
	if cookie, err := r.Cookie("jwt_token"); err == nil {
		return cookie.Value, nil
	}

	return "", fmt.Errorf("no token found")
}

func validateToken(token string, key rsa.PublicKey) (*Claims, error) {
	claims := &Claims{}

	// Verify token signature
	payload, err := verifyToken(token, key)
	if err != nil {
		return nil, err
	}
	// Unmarshal token claims
	if err := json.Unmarshal(payload, claims); err != nil {
		return nil, err
	}
	// Verify expire claim
	if time.Unix(claims.Expires, 0).Before(time.Now()) {
		return nil, errors.New("Token expired")
	}
	return claims, nil
}

func verifyToken(token string, key rsa.PublicKey) ([]byte, error) {
	var data []byte

	obj, err := jose.ParseSigned(token)
	if err != nil {
		return data, err
	}
	data, err = obj.Verify(&key)
	if err != nil {
		return data, err
	}
	return data, nil
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/iam"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAWSPolicyAttachment_basic(t *testing.T) {
	var out iam.ListEntitiesForPolicyOutput

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSPolicyAttachmentDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSPolicyAttachConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSPolicyAttachmentExists("aws_iam_policy_attachment.test-attach", 3, &out),
					testAccCheckAWSPolicyAttachmentAttributes([]string{"test-user"}, []string{"test-role"}, []string{"test-group"}, &out),
				),
			},
			resource.TestStep{
				Config: testAccAWSPolicyAttachConfigUpdate,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSPolicyAttachmentExists("aws_iam_policy_attachment.test-attach", 6, &out),
					testAccCheckAWSPolicyAttachmentAttributes([]string{"test-user3", "test-user3"}, []string{"test-role2", "test-role3"}, []string{"test-group2", "test-group3"}, &out),
				),
			},
		},
	})
}

func TestAccAWSPolicyAttachment_paginatedEntities(t *testing.T) {
	var out iam.ListEntitiesForPolicyOutput

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSPolicyAttachmentDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSPolicyAttachConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSPolicyAttachmentExists("aws_iam_policy_attachment.test-attach", 101, &out),
				),
			},
		},
	})
}

func testAccCheckAWSPolicyAttachmentDestroy(s *terraform.State) error {
	return nil
}

func testAccCheckAWSPolicyAttachmentExists(n string, c int64, out *iam.ListEntitiesForPolicyOutput) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No policy name is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).iamconn
		arn := rs.Primary.Attributes["policy_arn"]

		resp, err := conn.GetPolicy(&iam.GetPolicyInput{
			PolicyArn: aws.String(arn),
		})
		if err != nil {
			return fmt.Errorf("Error: Policy (%s) not found", n)
		}
		if c != *resp.Policy.AttachmentCount {
			return fmt.Errorf("Error: Policy (%s) has wrong number of entities attached on initial creation", n)
		}
		resp2, err := conn.ListEntitiesForPolicy(&iam.ListEntitiesForPolicyInput{
			PolicyArn: aws.String(arn),
		})
		if err != nil {
			return fmt.Errorf("Error: Failed to get entities for Policy (%s)", arn)
		}

		*out = *resp2
		return nil
	}
}

func testAccCheckAWSPolicyAttachmentAttributes(users []string, roles []string, groups []string, out *iam.ListEntitiesForPolicyOutput) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		uc := len(users)
		rc := len(roles)
		gc := len(groups)

		for _, u := range users {
			for _, pu := range out.PolicyUsers {
				if u == *pu.UserName {
					uc--
				}
			}
		}
		for _, r := range roles {
			for _, pr := range out.PolicyRoles {
				if r == *pr.RoleName {
					rc--
				}
			}
		}
		for _, g := range groups {
			for _, pg := range out.PolicyGroups {
				if g == *pg.GroupName {
					gc--
				}
			}
		}
		if uc != 0 || rc != 0 || gc != 0 {
			return fmt.Errorf("Error: Number of attached users, roles, or groups was incorrect:\n expected %d users and found %d\nexpected %d roles and found %d\nexpected %d groups and found %d", len(users), len(users)-uc, len(roles), len(roles)-rc, len(groups), len(groups)-gc)
		}
		return nil
	}
}

const testAccAWSPolicyAttachConfig = `
resource "aws_iam_user" "user" {
    name = "test-user"
}
resource "aws_iam_role" "role" {
    name = "test-role"
	  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}
resource "aws_iam_group" "group" {
    name = "test-group"
}

resource "aws_iam_policy" "policy" {
    name = "test-policy"
    description = "A test policy"
    policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "iam:ChangePassword"
      ],
      "Resource": "*",
      "Effect": "Allow"
    }
  ]
}
EOF
}

resource "aws_iam_policy_attachment" "test-attach" {
    name = "test-attachment"
    users = ["${aws_iam_user.user.name}"]
    roles = ["${aws_iam_role.role.name}"]
    groups = ["${aws_iam_group.group.name}"]
    policy_arn = "${aws_iam_policy.policy.arn}"
}
`

const testAccAWSPolicyAttachConfigUpdate = `
resource "aws_iam_user" "user" {
    name = "test-user"
}
resource "aws_iam_user" "user2" {
    name = "test-user2"
}
resource "aws_iam_user" "user3" {
    name = "test-user3"
}
resource "aws_iam_role" "role" {
    name = "test-role"
	  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}

resource "aws_iam_role" "role2" {
    name = "test-role2"
	  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF

}
resource "aws_iam_role" "role3" {
    name = "test-role3"
	  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF

}
resource "aws_iam_group" "group" {
    name = "test-group"
}
resource "aws_iam_group" "group2" {
    name = "test-group2"
}
resource "aws_iam_group" "group3" {
    name = "test-group3"
}

resource "aws_iam_policy" "policy" {
    name = "test-policy"
    description = "A test policy"
    policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "iam:ChangePassword"
      ],
      "Resource": "*",
      "Effect": "Allow"
    }
  ]
}
EOF
}

resource "aws_iam_policy_attachment" "test-attach" {
    name = "test-attachment"
    users = [
        "${aws_iam_user.user2.name}",
        "${aws_iam_user.user3.name}"
    ]
    roles = [
        "${aws_iam_role.role2.name}",
        "${aws_iam_role.role3.name}"
    ]
    groups = [
        "${aws_iam_group.group2.name}",
        "${aws_iam_group.group3.name}"
    ]
    policy_arn = "${aws_iam_policy.policy.arn}"
}
`

const testAccAWSPolicyPaginatedAttachConfig = `
resource "aws_iam_user" "user" {
    count = 101
    name = "${format("paged-test-user-%d", count.index + 1)}"
}

resource "aws_iam_policy" "policy" {
    name = "test-policy"
    description = "A test policy"
    policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "iam:ChangePassword"
      ],
      "Resource": "*",
      "Effect": "Allow"
    }
  ]
}
EOF
}

resource "aws_iam_policy_attachment" "test-paginated-attach" {
    name = "test-attachment"
    users = ["${aws_iam_user.user.*.name}"]
    policy_arn = "${aws_iam_policy.policy.arn}"
}
`
<commit_msg>provider/aws: Change  paginated test to use the correct configuration block<commit_after>package aws

import (
	"fmt"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/iam"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAWSPolicyAttachment_basic(t *testing.T) {
	var out iam.ListEntitiesForPolicyOutput

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSPolicyAttachmentDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSPolicyAttachConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSPolicyAttachmentExists("aws_iam_policy_attachment.test-attach", 3, &out),
					testAccCheckAWSPolicyAttachmentAttributes([]string{"test-user"}, []string{"test-role"}, []string{"test-group"}, &out),
				),
			},
			resource.TestStep{
				Config: testAccAWSPolicyAttachConfigUpdate,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSPolicyAttachmentExists("aws_iam_policy_attachment.test-attach", 6, &out),
					testAccCheckAWSPolicyAttachmentAttributes([]string{"test-user3", "test-user3"}, []string{"test-role2", "test-role3"}, []string{"test-group2", "test-group3"}, &out),
				),
			},
		},
	})
}

func TestAccAWSPolicyAttachment_paginatedEntities(t *testing.T) {
	var out iam.ListEntitiesForPolicyOutput

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSPolicyAttachmentDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSPolicyPaginatedAttachConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSPolicyAttachmentExists("aws_iam_policy_attachment.test-paginated-attach", 101, &out),
				),
			},
		},
	})
}

func testAccCheckAWSPolicyAttachmentDestroy(s *terraform.State) error {
	return nil
}

func testAccCheckAWSPolicyAttachmentExists(n string, c int64, out *iam.ListEntitiesForPolicyOutput) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No policy name is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).iamconn
		arn := rs.Primary.Attributes["policy_arn"]

		resp, err := conn.GetPolicy(&iam.GetPolicyInput{
			PolicyArn: aws.String(arn),
		})
		if err != nil {
			return fmt.Errorf("Error: Policy (%s) not found", n)
		}
		if c != *resp.Policy.AttachmentCount {
			return fmt.Errorf("Error: Policy (%s) has wrong number of entities attached on initial creation", n)
		}
		resp2, err := conn.ListEntitiesForPolicy(&iam.ListEntitiesForPolicyInput{
			PolicyArn: aws.String(arn),
		})
		if err != nil {
			return fmt.Errorf("Error: Failed to get entities for Policy (%s)", arn)
		}

		*out = *resp2
		return nil
	}
}

func testAccCheckAWSPolicyAttachmentAttributes(users []string, roles []string, groups []string, out *iam.ListEntitiesForPolicyOutput) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		uc := len(users)
		rc := len(roles)
		gc := len(groups)

		for _, u := range users {
			for _, pu := range out.PolicyUsers {
				if u == *pu.UserName {
					uc--
				}
			}
		}
		for _, r := range roles {
			for _, pr := range out.PolicyRoles {
				if r == *pr.RoleName {
					rc--
				}
			}
		}
		for _, g := range groups {
			for _, pg := range out.PolicyGroups {
				if g == *pg.GroupName {
					gc--
				}
			}
		}
		if uc != 0 || rc != 0 || gc != 0 {
			return fmt.Errorf("Error: Number of attached users, roles, or groups was incorrect:\n expected %d users and found %d\nexpected %d roles and found %d\nexpected %d groups and found %d", len(users), len(users)-uc, len(roles), len(roles)-rc, len(groups), len(groups)-gc)
		}
		return nil
	}
}

const testAccAWSPolicyAttachConfig = `
resource "aws_iam_user" "user" {
    name = "test-user"
}
resource "aws_iam_role" "role" {
    name = "test-role"
	  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}
resource "aws_iam_group" "group" {
    name = "test-group"
}

resource "aws_iam_policy" "policy" {
    name = "test-policy"
    description = "A test policy"
    policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "iam:ChangePassword"
      ],
      "Resource": "*",
      "Effect": "Allow"
    }
  ]
}
EOF
}

resource "aws_iam_policy_attachment" "test-attach" {
    name = "test-attachment"
    users = ["${aws_iam_user.user.name}"]
    roles = ["${aws_iam_role.role.name}"]
    groups = ["${aws_iam_group.group.name}"]
    policy_arn = "${aws_iam_policy.policy.arn}"
}
`

const testAccAWSPolicyAttachConfigUpdate = `
resource "aws_iam_user" "user" {
    name = "test-user"
}
resource "aws_iam_user" "user2" {
    name = "test-user2"
}
resource "aws_iam_user" "user3" {
    name = "test-user3"
}
resource "aws_iam_role" "role" {
    name = "test-role"
	  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}

resource "aws_iam_role" "role2" {
    name = "test-role2"
	  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF

}
resource "aws_iam_role" "role3" {
    name = "test-role3"
	  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF

}
resource "aws_iam_group" "group" {
    name = "test-group"
}
resource "aws_iam_group" "group2" {
    name = "test-group2"
}
resource "aws_iam_group" "group3" {
    name = "test-group3"
}

resource "aws_iam_policy" "policy" {
    name = "test-policy"
    description = "A test policy"
    policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "iam:ChangePassword"
      ],
      "Resource": "*",
      "Effect": "Allow"
    }
  ]
}
EOF
}

resource "aws_iam_policy_attachment" "test-attach" {
    name = "test-attachment"
    users = [
        "${aws_iam_user.user2.name}",
        "${aws_iam_user.user3.name}"
    ]
    roles = [
        "${aws_iam_role.role2.name}",
        "${aws_iam_role.role3.name}"
    ]
    groups = [
        "${aws_iam_group.group2.name}",
        "${aws_iam_group.group3.name}"
    ]
    policy_arn = "${aws_iam_policy.policy.arn}"
}
`

const testAccAWSPolicyPaginatedAttachConfig = `
resource "aws_iam_user" "user" {
    count = 101
    name = "${format("paged-test-user-%d", count.index + 1)}"
}

resource "aws_iam_policy" "policy" {
    name = "test-policy"
    description = "A test policy"
    policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "iam:ChangePassword"
      ],
      "Resource": "*",
      "Effect": "Allow"
    }
  ]
}
EOF
}

resource "aws_iam_policy_attachment" "test-paginated-attach" {
    name = "test-attachment"
    users = ["${aws_iam_user.user.*.name}"]
    policy_arn = "${aws_iam_policy.policy.arn}"
}
`
<|endoftext|>


<commit_before>package core

import (
	"errors"
	"fmt"
	"github.com/MG-RAST/AWE/lib/conf"
	"github.com/MG-RAST/AWE/lib/db"
	mgo "github.com/MG-RAST/AWE/vendor/gopkg.in/mgo.v2"
	"github.com/MG-RAST/AWE/vendor/gopkg.in/mgo.v2/bson"
)

// mongodb has hard limit of 16 MB docuemnt size
var DocumentMaxByte = 16777216

// indexed info fields for search
var JobInfoIndexes = []string{"submittime", "completedtime", "pipeline", "clientgroups", "project", "service", "user", "priority"}

func HasInfoField(a string) bool {
	for _, b := range JobInfoIndexes {
		if b == a {
			return true
		}
	}
	return false
}

func InitJobDB() {
	session := db.Connection.Session.Copy()
	defer session.Close()
	cj := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_JOBS)
	cj.EnsureIndex(mgo.Index{Key: []string{"acl.owner"}, Background: true})
	cj.EnsureIndex(mgo.Index{Key: []string{"acl.read"}, Background: true})
	cj.EnsureIndex(mgo.Index{Key: []string{"acl.write"}, Background: true})
	cj.EnsureIndex(mgo.Index{Key: []string{"acl.delete"}, Background: true})
	cj.EnsureIndex(mgo.Index{Key: []string{"id"}, Unique: true})
	cj.EnsureIndex(mgo.Index{Key: []string{"jid"}, Background: true})
	cj.EnsureIndex(mgo.Index{Key: []string{"state"}, Background: true})
	cj.EnsureIndex(mgo.Index{Key: []string{"expiration"}, Background: true})
	cj.EnsureIndex(mgo.Index{Key: []string{"updatetime"}, Background: true})
	for _, v := range JobInfoIndexes {
		cj.EnsureIndex(mgo.Index{Key: []string{"info." + v}, Background: true})
	}
	cp := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_PERF)
	cp.EnsureIndex(mgo.Index{Key: []string{"id"}, Unique: true})
}

func InitClientGroupDB() {
	session := db.Connection.Session.Copy()
	defer session.Close()
	cc := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_CGS)
	cc.EnsureIndex(mgo.Index{Key: []string{"id"}, Unique: true})
	cc.EnsureIndex(mgo.Index{Key: []string{"name"}, Unique: true})
	cc.EnsureIndex(mgo.Index{Key: []string{"token"}, Unique: true})
}

func dbDelete(q bson.M, coll string) (err error) {
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C(coll)
	_, err = c.RemoveAll(q)
	return
}

func dbUpsert(t interface{}) (err error) {
	// test that document not to large
	if nbson, err := bson.Marshal(t); err == nil {
		if len(nbson) >= DocumentMaxByte {
			return errors.New(fmt.Sprintf("bson document size is greater than limit of %d bytes", DocumentMaxByte))
		}
	}
	session := db.Connection.Session.Copy()
	defer session.Close()
	switch t := t.(type) {
	case *Job:
		c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_JOBS)
		_, err = c.Upsert(bson.M{"id": t.Id}, &t)
	case *JobPerf:
		c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_PERF)
		_, err = c.Upsert(bson.M{"id": t.Id}, &t)
	case *ClientGroup:
		c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_CGS)
		_, err = c.Upsert(bson.M{"id": t.Id}, &t)
	default:
		fmt.Printf("invalid database entry type\n")
	}
	return
}

func dbCount(q bson.M) (count int, err error) {
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_JOBS)
	if count, err = c.Find(q).Count(); err != nil {
		return 0, err
	} else {
		return count, nil
	}
}

func dbFind(q bson.M, results *Jobs, options map[string]int) (count int, err error) {
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_JOBS)
	query := c.Find(q)
	if count, err = query.Count(); err != nil {
		return 0, err
	}
	if limit, has := options["limit"]; has {
		if offset, has := options["offset"]; has {
			err = query.Limit(limit).Skip(offset).All(results)
			return
		} else {
			return 0, errors.New("store.db.Find options limit and offset must be used together")
		}
	}
	err = query.All(results)
	return
}

func dbFindSort(q bson.M, results *Jobs, options map[string]int, sortby string) (count int, err error) {
	if sortby == "" {
		return 0, errors.New("sortby must be an nonempty string")
	}
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_JOBS)
	query := c.Find(q)
	if count, err = query.Count(); err != nil {
		return 0, err
	}

	if limit, has := options["limit"]; has {
		if offset, has := options["offset"]; has {
			err = query.Sort(sortby).Limit(limit).Skip(offset).All(results)
			return
		}
	}
	err = query.Sort(sortby).All(results)
	return
}

func DbFindDistinct(q bson.M, d string) (results interface{}, err error) {
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_JOBS)
	query := c.Find(q)
	err = query.Distinct("info."+d, &results)
	return
}

func dbFindClientGroups(q bson.M, results *ClientGroups) (count int, err error) {
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_CGS)
	query := c.Find(q)
	if count, err = query.Count(); err != nil {
		return 0, err
	}
	err = query.All(results)
	return
}

func dbFindSortClientGroups(q bson.M, results *ClientGroups, options map[string]int, sortby string) (count int, err error) {
	if sortby == "" {
		return 0, errors.New("sortby must be an nonempty string")
	}
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_CGS)
	query := c.Find(q)
	if count, err = query.Count(); err != nil {
		return 0, err
	}

	if limit, has := options["limit"]; has {
		if offset, has := options["offset"]; has {
			err = query.Sort(sortby).Limit(limit).Skip(offset).All(results)
			return
		}
	}
	err = query.Sort(sortby).All(results)
	return
}

func LoadJob(id string) (job *Job, err error) {
	job = new(Job)
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_JOBS)
	if err = c.Find(bson.M{"id": id}).One(&job); err == nil {
		return job, nil
	}
	return nil, err
}

func LoadJobPerf(id string) (perf *JobPerf, err error) {
	perf = new(JobPerf)
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_PERF)
	if err = c.Find(bson.M{"id": id}).One(&perf); err == nil {
		return perf, nil
	}
	return nil, err
}

func LoadClientGroup(id string) (clientgroup *ClientGroup, err error) {
	clientgroup = new(ClientGroup)
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_CGS)
	if err = c.Find(bson.M{"id": id}).One(&clientgroup); err == nil {
		return clientgroup, nil
	}
	return nil, err
}

func LoadClientGroupByName(name string) (clientgroup *ClientGroup, err error) {
	clientgroup = new(ClientGroup)
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_CGS)
	if err = c.Find(bson.M{"name": name}).One(&clientgroup); err == nil {
		return clientgroup, nil
	}
	return nil, err
}

func LoadClientGroupByToken(token string) (clientgroup *ClientGroup, err error) {
	clientgroup = new(ClientGroup)
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_CGS)
	if err = c.Find(bson.M{"token": token}).One(&clientgroup); err == nil {
		return clientgroup, nil
	}
	return nil, err
}

func DeleteClientGroup(id string) (err error) {
	err = dbDelete(bson.M{"id": id}, conf.DB_COLL_CGS)
	return
}
<commit_msg>mgo query fix<commit_after>package core

import (
	"errors"
	"fmt"
	"github.com/MG-RAST/AWE/lib/conf"
	"github.com/MG-RAST/AWE/lib/db"
	mgo "github.com/MG-RAST/AWE/vendor/gopkg.in/mgo.v2"
	"github.com/MG-RAST/AWE/vendor/gopkg.in/mgo.v2/bson"
)

// mongodb has hard limit of 16 MB docuemnt size
var DocumentMaxByte = 16777216

// indexed info fields for search
var JobInfoIndexes = []string{"submittime", "completedtime", "pipeline", "clientgroups", "project", "service", "user", "priority"}

func HasInfoField(a string) bool {
	for _, b := range JobInfoIndexes {
		if b == a {
			return true
		}
	}
	return false
}

func InitJobDB() {
	session := db.Connection.Session.Copy()
	defer session.Close()
	cj := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_JOBS)
	cj.EnsureIndex(mgo.Index{Key: []string{"acl.owner"}, Background: true})
	cj.EnsureIndex(mgo.Index{Key: []string{"acl.read"}, Background: true})
	cj.EnsureIndex(mgo.Index{Key: []string{"acl.write"}, Background: true})
	cj.EnsureIndex(mgo.Index{Key: []string{"acl.delete"}, Background: true})
	cj.EnsureIndex(mgo.Index{Key: []string{"id"}, Unique: true})
	cj.EnsureIndex(mgo.Index{Key: []string{"jid"}, Background: true})
	cj.EnsureIndex(mgo.Index{Key: []string{"state"}, Background: true})
	cj.EnsureIndex(mgo.Index{Key: []string{"expiration"}, Background: true})
	cj.EnsureIndex(mgo.Index{Key: []string{"updatetime"}, Background: true})
	for _, v := range JobInfoIndexes {
		cj.EnsureIndex(mgo.Index{Key: []string{"info." + v}, Background: true})
	}
	cp := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_PERF)
	cp.EnsureIndex(mgo.Index{Key: []string{"id"}, Unique: true})
}

func InitClientGroupDB() {
	session := db.Connection.Session.Copy()
	defer session.Close()
	cc := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_CGS)
	cc.EnsureIndex(mgo.Index{Key: []string{"id"}, Unique: true})
	cc.EnsureIndex(mgo.Index{Key: []string{"name"}, Unique: true})
	cc.EnsureIndex(mgo.Index{Key: []string{"token"}, Unique: true})
}

func dbDelete(q bson.M, coll string) (err error) {
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C(coll)
	_, err = c.RemoveAll(q)
	return
}

func dbUpsert(t interface{}) (err error) {
	// test that document not to large
	if nbson, err := bson.Marshal(t); err == nil {
		if len(nbson) >= DocumentMaxByte {
			return errors.New(fmt.Sprintf("bson document size is greater than limit of %d bytes", DocumentMaxByte))
		}
	}
	session := db.Connection.Session.Copy()
	defer session.Close()
	switch t := t.(type) {
	case *Job:
		c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_JOBS)
		_, err = c.Upsert(bson.M{"id": t.Id}, &t)
	case *JobPerf:
		c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_PERF)
		_, err = c.Upsert(bson.M{"id": t.Id}, &t)
	case *ClientGroup:
		c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_CGS)
		_, err = c.Upsert(bson.M{"id": t.Id}, &t)
	default:
		fmt.Printf("invalid database entry type\n")
	}
	return
}

func dbCount(q bson.M) (count int, err error) {
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_JOBS)
	if count, err = c.Find(q).Count(); err != nil {
		return 0, err
	} else {
		return count, nil
	}
}

func dbFind(q bson.M, results *Jobs, options map[string]int) (count int, err error) {
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_JOBS)
	query := c.Find(q)
	if count, err = query.Count(); err != nil {
		return 0, err
	}
	if limit, has := options["limit"]; has {
		if offset, has := options["offset"]; has {
			err = query.Limit(limit).Skip(offset).All(results)
			return
		} else {
			return 0, errors.New("store.db.Find options limit and offset must be used together")
		}
	}
	err = query.All(results)
	return
}

func dbFindSort(q bson.M, results *Jobs, options map[string]int, sortby string) (count int, err error) {
	if sortby == "" {
		return 0, errors.New("sortby must be an nonempty string")
	}
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_JOBS)
	query := c.Find(q)
	if count, err = query.Count(); err != nil {
		return 0, err
	}

	if limit, has := options["limit"]; has {
		if offset, has := options["offset"]; has {
			err = query.Sort(sortby).Limit(limit).Skip(offset).All(results)
			return
		}
	}
	err = query.Sort(sortby).All(results)
	return
}

func DbFindDistinct(q bson.M, d string) (results interface{}, err error) {
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_JOBS)
	err = c.Find(q).Distinct("info."+d, &results)
	return
}

func dbFindClientGroups(q bson.M, results *ClientGroups) (count int, err error) {
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_CGS)
	query := c.Find(q)
	if count, err = query.Count(); err != nil {
		return 0, err
	}
	err = query.All(results)
	return
}

func dbFindSortClientGroups(q bson.M, results *ClientGroups, options map[string]int, sortby string) (count int, err error) {
	if sortby == "" {
		return 0, errors.New("sortby must be an nonempty string")
	}
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_CGS)
	query := c.Find(q)
	if count, err = query.Count(); err != nil {
		return 0, err
	}

	if limit, has := options["limit"]; has {
		if offset, has := options["offset"]; has {
			err = query.Sort(sortby).Limit(limit).Skip(offset).All(results)
			return
		}
	}
	err = query.Sort(sortby).All(results)
	return
}

func LoadJob(id string) (job *Job, err error) {
	job = new(Job)
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_JOBS)
	if err = c.Find(bson.M{"id": id}).One(&job); err == nil {
		return job, nil
	}
	return nil, err
}

func LoadJobPerf(id string) (perf *JobPerf, err error) {
	perf = new(JobPerf)
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_PERF)
	if err = c.Find(bson.M{"id": id}).One(&perf); err == nil {
		return perf, nil
	}
	return nil, err
}

func LoadClientGroup(id string) (clientgroup *ClientGroup, err error) {
	clientgroup = new(ClientGroup)
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_CGS)
	if err = c.Find(bson.M{"id": id}).One(&clientgroup); err == nil {
		return clientgroup, nil
	}
	return nil, err
}

func LoadClientGroupByName(name string) (clientgroup *ClientGroup, err error) {
	clientgroup = new(ClientGroup)
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_CGS)
	if err = c.Find(bson.M{"name": name}).One(&clientgroup); err == nil {
		return clientgroup, nil
	}
	return nil, err
}

func LoadClientGroupByToken(token string) (clientgroup *ClientGroup, err error) {
	clientgroup = new(ClientGroup)
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C(conf.DB_COLL_CGS)
	if err = c.Find(bson.M{"token": token}).One(&clientgroup); err == nil {
		return clientgroup, nil
	}
	return nil, err
}

func DeleteClientGroup(id string) (err error) {
	err = dbDelete(bson.M{"id": id}, conf.DB_COLL_CGS)
	return
}
<|endoftext|>


<commit_before>package blockchain

import "crypto/sha256"

// HashLen is the length in bytes of a hash.
const HashLen = 32

// Hash represents a 256-bit hash of a block or transaction
type Hash [HashLen]byte

// Marshal converts a Hash to a slice.
func (h Hash) Marshal() []byte {
	buf := make([]byte, HashLen)
	for i, b := range h {
		buf[i] = b
	}
	return buf
}

// Marshaller is any type that can convert itself to a byte slice
type Marshaller interface {
	Marshal() []byte
}

// HashSum computes the SHA256 hash  of a Marshaller.
func HashSum(m Marshaller) Hash {
	return sha256.Sum256(m.Marshal())
}
<commit_msg>Hash helpers and converters<commit_after>package blockchain

import (
	"crypto/sha256"
	"encoding/binary"
	"encoding/hex"
	"log"
)

const (
	// HashLen is the length in bytes of a hash.
	HashLen = 32
	// GreaterThan is the value to the CompareTo function returns if h1 is greater than h2
	GreaterThan int = 1
	// LessThan is the value to the CompareTo function returns if h1 is less than h2
	LessThan int = -1
	// EqualTo is the value to the CompareTo function returns if h1 is equal to h2
	EqualTo int = 0
	// MaxDifficulty is the maximum difficulty value represented as a hex string
	MaxDifficulty = "00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
	// MaxHash is the maximum hash value represented as a hex string
	MaxHash = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
)

// Hash represents a 256-bit hash of a block or transaction
type Hash [HashLen]byte

// Marshal converts a Hash to a slice.
func (h Hash) Marshal() []byte {
	buf := make([]byte, HashLen)
	for i, b := range h {
		buf[i] = b
	}
	return buf
}

// Marshaller is any type that can convert itself to a byte slice
type Marshaller interface {
	Marshal() []byte
}

// HashSum computes the SHA256 hash  of a Marshaller.
func HashSum(m Marshaller) Hash {
	return sha256.Sum256(m.Marshal())
}

// CompareTo compares two hashes, it returns 1 if the first hash is larger than the second, -1 if if it is smaller, and 0 if they are equal
func CompareTo(h1 Hash, h2 Hash) int {
	for i := HashLen - 1; i >= 0; i-- {
		if h1[i] > h2[i] {
			return 1
		} else if h1[i] < h2[i] {
			return -1
		}
	}
	return 0
}

// ReverseHash reverses the endianess of a hash
func ReverseHash(h Hash) Hash {
	var reverse Hash
	for i, j := 0, HashLen-1; i < j; i, j = i+1, j-1 {
		reverse[i], reverse[j] = h[j], h[i]
	}
	return reverse
}

// HexStringToHash converts a big endian hex string to a hash
func HexStringToHash(s string) Hash {
	if len(s)%2 != 0 {
		s = "0" + s
	}

	if len(s)/2 < HashLen {
		pre := ""
		for i := 0; i < HashLen-len(s)/2; i++ {
			pre += "00"
		}
		s = pre + s
	}

	var bytes, e = hex.DecodeString(s)

	if e != nil {
		log.Fatal(e)
	}

	var hash Hash
	for i := 0; i < HashLen; i++ {
		hash[i] = bytes[HashLen-1-i]
	}

	return hash
}

// HashToCompact converts a hash to a compact number
func HashToCompact(h Hash) uint32 {
	// Return 0 if hash is equal to 0
	if CompareTo(h, HexStringToHash("0")) == EqualTo {
		return 0
	}

	// TODO: Handle Max Value

	var compact []byte
	compact = make([]byte, 4)

	// Find MSB
	var msb int
	for msb = HashLen - 1; msb >= 0 && h[msb] == 0; msb-- {
	}

	// Set MSB of compact number to the size of the number
	size := msb + 1

	// Prepend 0 if msb is less than 0x7f
	if h[msb] > 0x7f {
		size++
		compact[1] = 0
		compact[2] = h[msb]
		if msb-1 < 0 {
			compact[3] = 0
		} else {
			compact[3] = h[msb-1]
		}
	} else {
		compact[1] = h[msb]

		if msb-1 < 0 {
			compact[2] = 0
		} else {
			compact[2] = h[msb-1]
		}

		if msb-2 < 0 {
			compact[3] = 0
		} else {
			compact[3] = h[msb-2]
		}
	}

	compact[0] = byte(size)

	return binary.BigEndian.Uint32(compact)
}

// CompactToHash converts a compact number to a hash
func CompactToHash(c uint32) Hash {
	if c == 0 {
		return HexStringToHash("0")
	}

	// TODO: Handle Max Value

	buf := make([]byte, 4)
	binary.BigEndian.PutUint32(buf, c)

	size := int(buf[0])
	var h Hash
	for i, j := size-1, 1; j <= 3; i, j = i-1, j+1 {
		if j <= size {
			h[i] = buf[j]
		}
	}

	return h
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/swpecht/GoMM"
	"time"
)

func main() {
	numNodes := 50
	numIterations := 100

	headName := "0.0.0.0:7946"
	clients := GoMM.GetLocalClients(numNodes, headName)

	for i := range clients {
		clients[i].Start()
	}

	// Don't have the root node join itsself
	for i := 1; i < len(clients); i++ {
		clients[i].Join(headName)
	}

	// Activate the pending memebers
	clients[0].UpdateActiveMembers()

	// Wait for all members to activate
	for i := 0; i < len(clients); i++ {
		clients[i].WaitActive()
	}

	stringData := []string{"Hello", "World"}
	floatData := []float64{2.0, 48182.2}

	start := time.Now()
	for i := 0; i < numIterations; i++ {
		clients[0].Broadcast(stringData, floatData)
		ReceiveAllMessages(clients)
	}
	elapsed := time.Since(start)
	fmt.Println("Benchmakr took", elapsed, "for", numIterations, "iterations")
	fmt.Println("Average seconds per iteration:", elapsed.Seconds()/float64(numIterations))
}

// Receive messages all on clients but the root node
func ReceiveAllMessages(clients []GoMM.Client) {
	for i := 0; i < len(clients); i++ {
		<-clients[i].BroadcastChannel
	}
}
<commit_msg>Switched method to determine join address of head node.<commit_after>package main

import (
	"fmt"
	"github.com/swpecht/GoMM"
	"time"
)

func main() {
	numNodes := 8
	numIterations := 100

	clients := GoMM.GetLocalClients(numNodes)
	headName := clients[0].JoinAddr()

	for i := range clients {
		clients[i].Start()
	}

	// Don't have the root node join itsself
	for i := 1; i < len(clients); i++ {
		clients[i].Join(headName)
	}

	// Activate the pending memebers
	clients[0].UpdateActiveMembers()

	// Wait for all members to activate
	for i := 0; i < len(clients); i++ {
		clients[i].WaitActive()
	}

	stringData := []string{"Hello", "World"}
	floatData := []float64{2.0, 48182.2}

	start := time.Now()
	for i := 0; i < numIterations; i++ {
		clients[0].Broadcast(stringData, floatData)
		ReceiveAllMessages(clients)
	}
	elapsed := time.Since(start)
	fmt.Println("Benchmakr took", elapsed, "for", numIterations, "iterations")
	fmt.Println("Average seconds per iteration:", elapsed.Seconds()/float64(numIterations))
}

// Receive messages all on clients but the root node
func ReceiveAllMessages(clients []GoMM.Client) {
	for i := 0; i < len(clients); i++ {
		<-clients[i].BroadcastChannel
	}
}
<|endoftext|>