<commit_before>// Copyright 2015 Hajime Hoshi
//
// 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 audio provides audio players. This can be used with or without ebiten package.
//
// The stream format must be 16-bit little endian and 2 channels.
//
// An audio context has a sample rate you can set and all streams you want to play must have the same
// sample rate.
//
// An audio context can generate 'players' (instances of audio.Player),
// and you can play sound by calling Play function of players.
// When multiple players play, mixing is automatically done.
// Note that too many players may cause distortion.
package audio

import (
	"bytes"
	"errors"
	"io"
	"runtime"
	"sync"
	"time"

	"github.com/hajimehoshi/ebiten"
	"github.com/hajimehoshi/ebiten/audio/internal/driver"
)

type players struct {
	players  map[*Player]struct{}
	seekings map[*Player]struct{}
	sync.RWMutex
}

const (
	channelNum     = 2
	bytesPerSample = 2

	// TODO: This assumes that channelNum is a power of 2.
	mask = ^(channelNum*bytesPerSample - 1)
)

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

func (p *players) Read(b []byte) (int, error) {
	p.Lock()
	defer p.Unlock()

	if len(p.players) == 0 {
		l := len(b)
		l &= mask
		copy(b, make([]byte, l))
		return l, nil
	}
	closed := []*Player{}
	l := len(b)
	for player := range p.players {
		if _, ok := p.seekings[player]; ok {
			continue
		}
		if err := player.readToBuffer(l); err == io.EOF {
			closed = append(closed, player)
		} else if err != nil {
			return 0, err
		}
		l = min(player.bufferLength(), l)
	}
	l &= mask
	b16s := [][]int16{}
	for player := range p.players {
		if _, ok := p.seekings[player]; ok {
			continue
		}
		b16s = append(b16s, player.bufferToInt16(l))
	}
	for i := 0; i < l/2; i++ {
		x := 0
		for _, b16 := range b16s {
			x += int(b16[i])
		}
		if x > (1<<15)-1 {
			x = (1 << 15) - 1
		}
		if x < -(1 << 15) {
			x = -(1 << 15)
		}
		b[2*i] = byte(x)
		b[2*i+1] = byte(x >> 8)
	}
	for player := range p.players {
		if _, ok := p.seekings[player]; ok {
			continue
		}
		player.proceed(l)
	}
	for _, pl := range closed {
		delete(p.players, pl)
	}
	return l, nil
}

func (p *players) addPlayer(player *Player) {
	p.Lock()
	defer p.Unlock()
	p.players[player] = struct{}{}
}

func (p *players) removePlayer(player *Player) {
	p.Lock()
	defer p.Unlock()
	delete(p.players, player)
}

func (p *players) addSeeking(player *Player) {
	p.Lock()
	defer p.Unlock()
	p.seekings[player] = struct{}{}
}

func (p *players) removeSeeking(player *Player) {
	p.Lock()
	defer p.Unlock()
	delete(p.seekings, player)
}

func (p *players) hasPlayer(player *Player) bool {
	p.RLock()
	defer p.RUnlock()
	_, ok := p.players[player]
	return ok
}

func (p *players) hasSource(src ReadSeekCloser) bool {
	p.RLock()
	defer p.RUnlock()
	for player := range p.players {
		if player.src == src {
			return true
		}
	}
	return false
}

// TODO: Enable to specify the format like Mono8?

// A Context is a current state of audio.
//
// There should be at most one Context object.
// This means only one constant sample rate is valid in your one application.
//
// The typical usage with ebiten package is:
//
//    var audioContext *audio.Context
//
//    func update(screen *ebiten.Image) error {
//        // Update updates the audio stream by 1/60 [sec].
//        if err := audioContext.Update(); err != nil {
//            return err
//        }
//        // ...
//    }
//
//    func main() {
//        audioContext, err = audio.NewContext(sampleRate)
//        if err != nil {
//            panic(err)
//        }
//        ebiten.Run(run, update, 320, 240, 2, "Audio test")
//    }
//
// This is 'sync mode' in that game's (logical) time and audio time are synchronized.
// You can also call Update independently from the game loop as 'async mode'.
// In this case, audio goes on even when the game stops e.g. by diactivating the screen.
type Context struct {
	players      *players
	driver       *driver.Player
	sampleRate   int
	frames       int
	writtenBytes int
}

var (
	theContext     *Context
	theContextLock sync.Mutex
)

// NewContext creates a new audio context with the given sample rate (e.g. 44100).
func NewContext(sampleRate int) (*Context, error) {
	theContextLock.Lock()
	defer theContextLock.Unlock()
	if theContext != nil {
		return nil, errors.New("audio: context is already created")
	}
	c := &Context{
		sampleRate: sampleRate,
	}
	theContext = c
	c.players = &players{
		players:  map[*Player]struct{}{},
		seekings: map[*Player]struct{}{},
	}
	return c, nil

}

// Update proceeds the inner (logical) time of the context by 1/60 second.
//
// This is expected to be called in the game's updating function (sync mode)
// or an independent goroutine with timers (async mode).
// In sync mode, the game logical time syncs the audio logical time and
// you will find audio stops when the game stops e.g. when the window is deactivated.
// In async mode, the audio never stops even when the game stops.
func (c *Context) Update() error {
	// Initialize c.driver lazily to enable calling NewContext in an 'init' function.
	// Accessing driver functions requires the environment to be already initialized,
	// but if Ebiten is used for a shared library, the timing when init functions are called
	// is unexpectable.
	// e.g. a variable for JVM on Android might not be set.
	if c.driver == nil {
		// TODO: Rename this other than player
		p, err := driver.NewPlayer(c.sampleRate, channelNum, bytesPerSample)
		c.driver = p
		if err != nil {
			return err
		}
	}
	c.frames++
	bytesPerFrame := c.sampleRate * bytesPerSample * channelNum / ebiten.FPS
	l := (c.frames * bytesPerFrame) - c.writtenBytes
	l &= mask
	c.writtenBytes += l
	buf := make([]byte, l)
	n, err := io.ReadFull(c.players, buf)
	if err != nil {
		return err
	}
	if n != len(buf) {
		return c.driver.Close()
	}
	// TODO: Rename this to Enqueue
	err = c.driver.Proceed(buf)
	if err == io.EOF {
		return c.driver.Close()
	}
	if err != nil {
		return err
	}
	return nil
}

// SampleRate returns the sample rate.
// All audio source must have the same sample rate.
//
// This function is concurrent-safe.
func (c *Context) SampleRate() int {
	return c.sampleRate
}

// ReadSeekCloser is an io.ReadSeeker and io.Closer.
type ReadSeekCloser interface {
	io.ReadSeeker
	io.Closer
}

// Player is an audio player which has one stream.
type Player struct {
	players    *players
	src        ReadSeekCloser
	buf        []byte
	sampleRate int
	pos        int64
	volume     float64
}

// NewPlayer creates a new player with the given stream.
//
// src's format must be linear PCM (16bits little endian, 2 channel stereo)
// without a header (e.g. RIFF header).
// The sample rate must be same as that of the audio context.
//
// Note that the given src can't be shared with other Players.
//
// This function is concurrent-safe.
func NewPlayer(context *Context, src ReadSeekCloser) (*Player, error) {
	if context.players.hasSource(src) {
		return nil, errors.New("audio: src cannot be shared with another Player")
	}
	p := &Player{
		players:    context.players,
		src:        src,
		sampleRate: context.sampleRate,
		buf:        []byte{},
		volume:     1,
	}
	// Get the current position of the source.
	pos, err := p.src.Seek(0, io.SeekCurrent)
	if err != nil {
		return nil, err
	}
	p.pos = pos
	runtime.SetFinalizer(p, (*Player).Close)
	return p, nil
}

type bytesReadSeekCloser struct {
	*bytes.Reader
}

func (b *bytesReadSeekCloser) Close() error {
	return nil
}

// NewPlayerFromBytes creates a new player with the given bytes.
//
// As opposed to NewPlayer, you don't have to care if src is already used by another player or not.
// src can be shared by multiple players.
//
// The format of src should be same as noted at NewPlayer.
//
// This function is concurrent-safe.
func NewPlayerFromBytes(context *Context, src []byte) (*Player, error) {
	b := &bytesReadSeekCloser{bytes.NewReader(src)}
	return NewPlayer(context, b)
}

// Close closes the stream. Ths source stream passed by NewPlayer will also be closed.
//
// When closing, the stream owned by the player will also be closed by calling its Close.
//
// This function is concurrent-safe.
func (p *Player) Close() error {
	p.players.removePlayer(p)
	runtime.SetFinalizer(p, nil)
	return p.src.Close()
}

func (p *Player) readToBuffer(length int) error {
	bb := make([]byte, length)
	n, err := p.src.Read(bb)
	if 0 < n {
		p.buf = append(p.buf, bb[:n]...)
	}
	return err
}

func (p *Player) bufferToInt16(lengthInBytes int) []int16 {
	r := make([]int16, lengthInBytes/2)
	for i := 0; i < lengthInBytes/2; i++ {
		r[i] = int16(p.buf[2*i]) | (int16(p.buf[2*i+1]) << 8)
		r[i] = int16(float64(r[i]) * p.volume)
	}
	return r
}

func (p *Player) proceed(length int) {
	p.buf = p.buf[length:]
	p.pos += int64(length)
}

func (p *Player) bufferLength() int {
	return len(p.buf)
}

// Play plays the stream.
//
// This function is concurrent-safe.
func (p *Player) Play() error {
	p.players.addPlayer(p)
	return nil
}

// IsPlaying returns boolean indicating whether the player is playing.
//
// This function is concurrent-safe.
func (p *Player) IsPlaying() bool {
	return p.players.hasPlayer(p)
}

// Rewind rewinds the current position to the start.
//
// This function is concurrent-safe.
func (p *Player) Rewind() error {
	return p.Seek(0)
}

// Seek seeks the position with the given offset.
//
// This function is concurrent-safe.
func (p *Player) Seek(offset time.Duration) error {
	p.players.addSeeking(p)
	defer p.players.removeSeeking(p)
	o := int64(offset) * bytesPerSample * channelNum * int64(p.sampleRate) / int64(time.Second)
	o &= mask
	p.buf = []byte{}
	pos, err := p.src.Seek(o, io.SeekStart)
	if err != nil {
		return err
	}
	p.pos = pos
	return nil
}

// Pause pauses the playing.
//
// This function is concurrent-safe.
func (p *Player) Pause() error {
	p.players.removePlayer(p)
	return nil
}

// Current returns the current position.
//
// This function is concurrent-safe.
func (p *Player) Current() time.Duration {
	sample := p.pos / bytesPerSample / channelNum
	return time.Duration(sample) * time.Second / time.Duration(p.sampleRate)
}

// Volume returns the current volume of this player [0-1].
func (p *Player) Volume() float64 {
	return p.volume
}

// SetVolume sets the volume of this player.
// volume must be in between 0 and 1. This function panics otherwise.
func (p *Player) SetVolume(volume float64) {
	// The condition must be true when volume is NaN.
	if !(0 <= volume && volume <= 1) {
		panic("audio: volume must be in between 0 and 1")
	}
	p.volume = volume
}
<commit_msg>audio: Fix comment<commit_after>// Copyright 2015 Hajime Hoshi
//
// 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 audio provides audio players. This can be used with or without ebiten package.
//
// The stream format must be 16-bit little endian and 2 channels.
//
// An audio context has a sample rate you can set and all streams you want to play must have the same
// sample rate. However, decoders like audio/vorbis and audio/wav adjust sample rate,
// and you don't have to care about it as long as you use those decoders.
//
// An audio context can generate 'players' (instances of audio.Player),
// and you can play sound by calling Play function of players.
// When multiple players play, mixing is automatically done.
// Note that too many players may cause distortion.
package audio

import (
	"bytes"
	"errors"
	"io"
	"runtime"
	"sync"
	"time"

	"github.com/hajimehoshi/ebiten"
	"github.com/hajimehoshi/ebiten/audio/internal/driver"
)

type players struct {
	players  map[*Player]struct{}
	seekings map[*Player]struct{}
	sync.RWMutex
}

const (
	channelNum     = 2
	bytesPerSample = 2

	// TODO: This assumes that channelNum is a power of 2.
	mask = ^(channelNum*bytesPerSample - 1)
)

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

func (p *players) Read(b []byte) (int, error) {
	p.Lock()
	defer p.Unlock()

	if len(p.players) == 0 {
		l := len(b)
		l &= mask
		copy(b, make([]byte, l))
		return l, nil
	}
	closed := []*Player{}
	l := len(b)
	for player := range p.players {
		if _, ok := p.seekings[player]; ok {
			continue
		}
		if err := player.readToBuffer(l); err == io.EOF {
			closed = append(closed, player)
		} else if err != nil {
			return 0, err
		}
		l = min(player.bufferLength(), l)
	}
	l &= mask
	b16s := [][]int16{}
	for player := range p.players {
		if _, ok := p.seekings[player]; ok {
			continue
		}
		b16s = append(b16s, player.bufferToInt16(l))
	}
	for i := 0; i < l/2; i++ {
		x := 0
		for _, b16 := range b16s {
			x += int(b16[i])
		}
		if x > (1<<15)-1 {
			x = (1 << 15) - 1
		}
		if x < -(1 << 15) {
			x = -(1 << 15)
		}
		b[2*i] = byte(x)
		b[2*i+1] = byte(x >> 8)
	}
	for player := range p.players {
		if _, ok := p.seekings[player]; ok {
			continue
		}
		player.proceed(l)
	}
	for _, pl := range closed {
		delete(p.players, pl)
	}
	return l, nil
}

func (p *players) addPlayer(player *Player) {
	p.Lock()
	defer p.Unlock()
	p.players[player] = struct{}{}
}

func (p *players) removePlayer(player *Player) {
	p.Lock()
	defer p.Unlock()
	delete(p.players, player)
}

func (p *players) addSeeking(player *Player) {
	p.Lock()
	defer p.Unlock()
	p.seekings[player] = struct{}{}
}

func (p *players) removeSeeking(player *Player) {
	p.Lock()
	defer p.Unlock()
	delete(p.seekings, player)
}

func (p *players) hasPlayer(player *Player) bool {
	p.RLock()
	defer p.RUnlock()
	_, ok := p.players[player]
	return ok
}

func (p *players) hasSource(src ReadSeekCloser) bool {
	p.RLock()
	defer p.RUnlock()
	for player := range p.players {
		if player.src == src {
			return true
		}
	}
	return false
}

// TODO: Enable to specify the format like Mono8?

// A Context is a current state of audio.
//
// There should be at most one Context object.
// This means only one constant sample rate is valid in your one application.
//
// The typical usage with ebiten package is:
//
//    var audioContext *audio.Context
//
//    func update(screen *ebiten.Image) error {
//        // Update updates the audio stream by 1/60 [sec].
//        if err := audioContext.Update(); err != nil {
//            return err
//        }
//        // ...
//    }
//
//    func main() {
//        audioContext, err = audio.NewContext(sampleRate)
//        if err != nil {
//            panic(err)
//        }
//        ebiten.Run(run, update, 320, 240, 2, "Audio test")
//    }
//
// This is 'sync mode' in that game's (logical) time and audio time are synchronized.
// You can also call Update independently from the game loop as 'async mode'.
// In this case, audio goes on even when the game stops e.g. by diactivating the screen.
type Context struct {
	players      *players
	driver       *driver.Player
	sampleRate   int
	frames       int
	writtenBytes int
}

var (
	theContext     *Context
	theContextLock sync.Mutex
)

// NewContext creates a new audio context with the given sample rate (e.g. 44100).
func NewContext(sampleRate int) (*Context, error) {
	theContextLock.Lock()
	defer theContextLock.Unlock()
	if theContext != nil {
		return nil, errors.New("audio: context is already created")
	}
	c := &Context{
		sampleRate: sampleRate,
	}
	theContext = c
	c.players = &players{
		players:  map[*Player]struct{}{},
		seekings: map[*Player]struct{}{},
	}
	return c, nil

}

// Update proceeds the inner (logical) time of the context by 1/60 second.
//
// This is expected to be called in the game's updating function (sync mode)
// or an independent goroutine with timers (async mode).
// In sync mode, the game logical time syncs the audio logical time and
// you will find audio stops when the game stops e.g. when the window is deactivated.
// In async mode, the audio never stops even when the game stops.
func (c *Context) Update() error {
	// Initialize c.driver lazily to enable calling NewContext in an 'init' function.
	// Accessing driver functions requires the environment to be already initialized,
	// but if Ebiten is used for a shared library, the timing when init functions are called
	// is unexpectable.
	// e.g. a variable for JVM on Android might not be set.
	if c.driver == nil {
		// TODO: Rename this other than player
		p, err := driver.NewPlayer(c.sampleRate, channelNum, bytesPerSample)
		c.driver = p
		if err != nil {
			return err
		}
	}
	c.frames++
	bytesPerFrame := c.sampleRate * bytesPerSample * channelNum / ebiten.FPS
	l := (c.frames * bytesPerFrame) - c.writtenBytes
	l &= mask
	c.writtenBytes += l
	buf := make([]byte, l)
	n, err := io.ReadFull(c.players, buf)
	if err != nil {
		return err
	}
	if n != len(buf) {
		return c.driver.Close()
	}
	// TODO: Rename this to Enqueue
	err = c.driver.Proceed(buf)
	if err == io.EOF {
		return c.driver.Close()
	}
	if err != nil {
		return err
	}
	return nil
}

// SampleRate returns the sample rate.
// All audio source must have the same sample rate.
//
// This function is concurrent-safe.
func (c *Context) SampleRate() int {
	return c.sampleRate
}

// ReadSeekCloser is an io.ReadSeeker and io.Closer.
type ReadSeekCloser interface {
	io.ReadSeeker
	io.Closer
}

// Player is an audio player which has one stream.
type Player struct {
	players    *players
	src        ReadSeekCloser
	buf        []byte
	sampleRate int
	pos        int64
	volume     float64
}

// NewPlayer creates a new player with the given stream.
//
// src's format must be linear PCM (16bits little endian, 2 channel stereo)
// without a header (e.g. RIFF header).
// The sample rate must be same as that of the audio context.
//
// Note that the given src can't be shared with other Players.
//
// This function is concurrent-safe.
func NewPlayer(context *Context, src ReadSeekCloser) (*Player, error) {
	if context.players.hasSource(src) {
		return nil, errors.New("audio: src cannot be shared with another Player")
	}
	p := &Player{
		players:    context.players,
		src:        src,
		sampleRate: context.sampleRate,
		buf:        []byte{},
		volume:     1,
	}
	// Get the current position of the source.
	pos, err := p.src.Seek(0, io.SeekCurrent)
	if err != nil {
		return nil, err
	}
	p.pos = pos
	runtime.SetFinalizer(p, (*Player).Close)
	return p, nil
}

type bytesReadSeekCloser struct {
	*bytes.Reader
}

func (b *bytesReadSeekCloser) Close() error {
	return nil
}

// NewPlayerFromBytes creates a new player with the given bytes.
//
// As opposed to NewPlayer, you don't have to care if src is already used by another player or not.
// src can be shared by multiple players.
//
// The format of src should be same as noted at NewPlayer.
//
// This function is concurrent-safe.
func NewPlayerFromBytes(context *Context, src []byte) (*Player, error) {
	b := &bytesReadSeekCloser{bytes.NewReader(src)}
	return NewPlayer(context, b)
}

// Close closes the stream. Ths source stream passed by NewPlayer will also be closed.
//
// When closing, the stream owned by the player will also be closed by calling its Close.
//
// This function is concurrent-safe.
func (p *Player) Close() error {
	p.players.removePlayer(p)
	runtime.SetFinalizer(p, nil)
	return p.src.Close()
}

func (p *Player) readToBuffer(length int) error {
	bb := make([]byte, length)
	n, err := p.src.Read(bb)
	if 0 < n {
		p.buf = append(p.buf, bb[:n]...)
	}
	return err
}

func (p *Player) bufferToInt16(lengthInBytes int) []int16 {
	r := make([]int16, lengthInBytes/2)
	for i := 0; i < lengthInBytes/2; i++ {
		r[i] = int16(p.buf[2*i]) | (int16(p.buf[2*i+1]) << 8)
		r[i] = int16(float64(r[i]) * p.volume)
	}
	return r
}

func (p *Player) proceed(length int) {
	p.buf = p.buf[length:]
	p.pos += int64(length)
}

func (p *Player) bufferLength() int {
	return len(p.buf)
}

// Play plays the stream.
//
// This function is concurrent-safe.
func (p *Player) Play() error {
	p.players.addPlayer(p)
	return nil
}

// IsPlaying returns boolean indicating whether the player is playing.
//
// This function is concurrent-safe.
func (p *Player) IsPlaying() bool {
	return p.players.hasPlayer(p)
}

// Rewind rewinds the current position to the start.
//
// This function is concurrent-safe.
func (p *Player) Rewind() error {
	return p.Seek(0)
}

// Seek seeks the position with the given offset.
//
// This function is concurrent-safe.
func (p *Player) Seek(offset time.Duration) error {
	p.players.addSeeking(p)
	defer p.players.removeSeeking(p)
	o := int64(offset) * bytesPerSample * channelNum * int64(p.sampleRate) / int64(time.Second)
	o &= mask
	p.buf = []byte{}
	pos, err := p.src.Seek(o, io.SeekStart)
	if err != nil {
		return err
	}
	p.pos = pos
	return nil
}

// Pause pauses the playing.
//
// This function is concurrent-safe.
func (p *Player) Pause() error {
	p.players.removePlayer(p)
	return nil
}

// Current returns the current position.
//
// This function is concurrent-safe.
func (p *Player) Current() time.Duration {
	sample := p.pos / bytesPerSample / channelNum
	return time.Duration(sample) * time.Second / time.Duration(p.sampleRate)
}

// Volume returns the current volume of this player [0-1].
func (p *Player) Volume() float64 {
	return p.volume
}

// SetVolume sets the volume of this player.
// volume must be in between 0 and 1. This function panics otherwise.
func (p *Player) SetVolume(volume float64) {
	// The condition must be true when volume is NaN.
	if !(0 <= volume && volume <= 1) {
		panic("audio: volume must be in between 0 and 1")
	}
	p.volume = volume
}
<|endoftext|>


<commit_before>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package factom

import (
	"encoding/json"
	"fmt"
)

type Authority struct {
	AuthorityChainID  string             `json:"chainid"`
	ManagementChainID string             `json:"manageid"`
	MatryoshkaHash    string             `json:"matroyshka"` // [sic]
	SigningKey        string             `json:"signingkey"`
	Status            string             `json:"status"`
	AnchorKeys        []AnchorSigningKey `json:"anchorkeys"`
}

func (a *Authority) String() string {
	var s string

	s += fmt.Sprintln("AuthorityChainID:", a.AuthorityChainID)
	s += fmt.Sprintln("ManagementChainID:", a.ManagementChainID)
	s += fmt.Sprintln("MatryoshkaHash:", a.MatryoshkaHash)
	s += fmt.Sprintln("SigningKey:", a.SigningKey)
	s += fmt.Sprintln("Status:", a.Status)

	s += fmt.Sprintln("AnchorKeys {")
	for _, k := range a.AnchorKeys {
		s += k.String()
	}
	s += fmt.Sprintln("}")

	// s += fmt.Sprintln("KeyHisory {")
	// for _, k := range a.KeyHistory {
	// 	s += fmt.Sprintln(" ", k)
	// }
	// s += fmt.Sprintln("}")

	return s
}

type AnchorSigningKey struct {
	BlockChain string `json:"blockchain"`
	KeyLevel   byte   `json:"level"`
	KeyType    byte   `json:"keytype"`
	SigningKey string `json:"key"` //if bytes, it is hex

}

func (k *AnchorSigningKey) String() string {
	var s string

	s += fmt.Sprintln("BlockChain:", k.BlockChain)
	s += fmt.Sprintln("KeyLevel:", k.KeyLevel)
	s += fmt.Sprintln("KeyType:", k.KeyType)
	s += fmt.Sprintln("SigningKey:", k.SigningKey)

	return s
}

// GetAuthorites retrieves a list of the known athorities from factomd
func GetAuthorities() ([]*Authority, error) {
	req := NewJSON2Request("authorities", APICounter(), nil)
	resp, err := factomdRequest(req)
	if err != nil {
		return nil, err
	}
	if resp.Error != nil {
		return nil, resp.Error
	}

	js, err := resp.JSONString()
	fmt.Println("DEBUG: JSON:", js)
	// create a temporary type to unmarshal the json object
	a := new(struct {
		Authorities []*Authority `json:"authorities"`
	})

	if err := json.Unmarshal(resp.JSONResult(), a); err != nil {
		return nil, err
	}

	return a.Authorities, nil
}
<commit_msg>removed debuging statements<commit_after>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package factom

import (
	"encoding/json"
	"fmt"
)

type Authority struct {
	AuthorityChainID  string             `json:"chainid"`
	ManagementChainID string             `json:"manageid"`
	MatryoshkaHash    string             `json:"matroyshka"` // [sic]
	SigningKey        string             `json:"signingkey"`
	Status            string             `json:"status"`
	AnchorKeys        []AnchorSigningKey `json:"anchorkeys"`
}

func (a *Authority) String() string {
	var s string

	s += fmt.Sprintln("AuthorityChainID:", a.AuthorityChainID)
	s += fmt.Sprintln("ManagementChainID:", a.ManagementChainID)
	s += fmt.Sprintln("MatryoshkaHash:", a.MatryoshkaHash)
	s += fmt.Sprintln("SigningKey:", a.SigningKey)
	s += fmt.Sprintln("Status:", a.Status)

	s += fmt.Sprintln("AnchorKeys {")
	for _, k := range a.AnchorKeys {
		s += k.String()
	}
	s += fmt.Sprintln("}")

	// s += fmt.Sprintln("KeyHisory {")
	// for _, k := range a.KeyHistory {
	// 	s += fmt.Sprintln(" ", k)
	// }
	// s += fmt.Sprintln("}")

	return s
}

type AnchorSigningKey struct {
	BlockChain string `json:"blockchain"`
	KeyLevel   byte   `json:"level"`
	KeyType    byte   `json:"keytype"`
	SigningKey string `json:"key"` //if bytes, it is hex

}

func (k *AnchorSigningKey) String() string {
	var s string

	s += fmt.Sprintln("BlockChain:", k.BlockChain)
	s += fmt.Sprintln("KeyLevel:", k.KeyLevel)
	s += fmt.Sprintln("KeyType:", k.KeyType)
	s += fmt.Sprintln("SigningKey:", k.SigningKey)

	return s
}

// GetAuthorites retrieves a list of the known athorities from factomd
func GetAuthorities() ([]*Authority, error) {
	req := NewJSON2Request("authorities", APICounter(), nil)
	resp, err := factomdRequest(req)
	if err != nil {
		return nil, err
	}
	if resp.Error != nil {
		return nil, resp.Error
	}

	// create a temporary type to unmarshal the json object
	a := new(struct {
		Authorities []*Authority `json:"authorities"`
	})

	if err := json.Unmarshal(resp.JSONResult(), a); err != nil {
		return nil, err
	}

	return a.Authorities, nil
}
<|endoftext|>


<commit_before>package db

import "emp/objects"

const (
	PUBKEY   = iota
	PURGE    = iota
	MSG      = iota
	PUBKEYRQ = iota
	NOTFOUND = iota
)

// Hash List
var hashList map[string]int

func Add(hashObj objects.Hash, hashType int) {
	hash := string(hashObj.GetBytes())
	if hashList != nil {
		hashList[hash] = hashType
	}
}

func Delete(hashObj objects.Hash) {
	hash := string(hashObj.GetBytes())
	if hashList != nil {
		delete(hashList, hash)
	}
}

func Contains(hashObj objects.Hash) int {
	hash := string(hashObj.GetBytes())
	if hashList != nil {
		hashType, ok := hashList[hash]
		if ok {
			return hashType
		} else {
			return NOTFOUND
		}
	}
	return NOTFOUND
}

func ObjList() *objects.Obj {
	if hashList == nil {
		return nil
	}

	ret := new(objects.Obj)
	ret.HashList = make([]objects.Hash, 0, 0)

	for key, _ := range hashList {
		ret.HashList = append(ret.HashList, objects.MakeHash([]byte(key)))
	}
	return ret
}
<commit_msg>Double hashed<commit_after>package db

import "emp/objects"

const (
	PUBKEY   = iota
	PURGE    = iota
	MSG      = iota
	PUBKEYRQ = iota
	NOTFOUND = iota
)

// Hash List
var hashList map[string]int

func Add(hashObj objects.Hash, hashType int) {
	hash := string(hashObj.GetBytes())
	if hashList != nil {
		hashList[hash] = hashType
	}
}

func Delete(hashObj objects.Hash) {
	hash := string(hashObj.GetBytes())
	if hashList != nil {
		delete(hashList, hash)
	}
}

func Contains(hashObj objects.Hash) int {
	hash := string(hashObj.GetBytes())
	if hashList != nil {
		hashType, ok := hashList[hash]
		if ok {
			return hashType
		} else {
			return NOTFOUND
		}
	}
	return NOTFOUND
}

func ObjList() *objects.Obj {
	if hashList == nil {
		return nil
	}

	ret := new(objects.Obj)
	ret.HashList = make([]objects.Hash, 0, 0)

	hash := new(objects.Hash)

	for key, _ := range hashList {
		hash.FromBytes([]byte(key))
		ret.HashList = append(ret.HashList, *hash)
	}
	return ret
}
<|endoftext|>


<commit_before>package cloudflare

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
)

// DevicePostureIntegrationConfig contains authentication information
// for a device posture integration.
type DevicePostureIntegrationConfig struct {
	ClientID     string `json:"client_id,omitempty"`
	ClientSecret string `json:"client_secret,omitempty"`
	AuthUrl      string `json:"auth_url,omitempty"`
	ApiUrl       string `json:"api_url,omitempty"`
	ClientKey    string `json:"client_key,omitempty"`
	CustomerID   string `json:"customer_id,omitempty"`
}

// DevicePostureIntegration represents a device posture integration.
type DevicePostureIntegration struct {
	IntegrationID string                         `json:"id,omitempty"`
	Name          string                         `json:"name,omitempty"`
	Type          string                         `json:"type,omitempty"`
	Interval      string                         `json:"interval,omitempty"`
	Config        DevicePostureIntegrationConfig `json:"config,omitempty"`
}

// DevicePostureIntegrationResponse represents the response from the get
// device posture integrations endpoint.
type DevicePostureIntegrationResponse struct {
	Result DevicePostureIntegration `json:"result"`
	Response
	ResultInfo `json:"result_info"`
}

// DevicePostureIntegrationListResponse represents the response from the list
// device posture integrations endpoint.
type DevicePostureIntegrationListResponse struct {
	Result []DevicePostureIntegration `json:"result"`
	Response
	ResultInfo `json:"result_info"`
}

// CreateDevicePostureIntegration creates a device posture integration within an account.
//
// API reference: https://api.cloudflare.com/#device-posture-integrations-create-device-posture-integration
func (api *API) CreateDevicePostureIntegration(ctx context.Context, accountID string, integration DevicePostureIntegration) (DevicePostureIntegration, error) {
	uri := fmt.Sprintf("/%s/%s/devices/posture/integration", AccountRouteRoot, accountID)

	res, err := api.makeRequestContext(ctx, http.MethodPost, uri, integration)
	if err != nil {
		fmt.Printf("err:%+v res:%+v\n", err, res)
		return DevicePostureIntegration{}, err
	}

	var devicePostureIntegrationResponse DevicePostureIntegrationResponse
	err = json.Unmarshal(res, &devicePostureIntegrationResponse)
	if err != nil {
		return DevicePostureIntegration{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
	}

	return devicePostureIntegrationResponse.Result, nil
}

// UpdateDevicePostureIntegration updates a device posture integration within an account.
//
// API reference: https://api.cloudflare.com/#device-posture-integrations-update-device-posture-integration
func (api *API) UpdateDevicePostureIntegration(ctx context.Context, accountID string, integration DevicePostureIntegration) (DevicePostureIntegration, error) {
	uri := fmt.Sprintf("/%s/%s/devices/posture/integration/%s", AccountRouteRoot, accountID, integration.IntegrationID)

	res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, integration)
	if err != nil {
		return DevicePostureIntegration{}, err
	}

	var devicePostureIntegrationResponse DevicePostureIntegrationResponse
	err = json.Unmarshal(res, &devicePostureIntegrationResponse)
	if err != nil {
		return DevicePostureIntegration{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
	}

	return devicePostureIntegrationResponse.Result, nil
}

// DevicePostureIntegration returns a specific device posture integrations within an account.
//
// API reference: https://api.cloudflare.com/#device-posture-integrations-device-posture-integration-details
func (api *API) DevicePostureIntegration(ctx context.Context, accountID, integrationID string) (DevicePostureIntegration, error) {
	uri := fmt.Sprintf("/%s/%s/devices/posture/integration/%s", AccountRouteRoot, accountID, integrationID)

	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
	if err != nil {
		return DevicePostureIntegration{}, err
	}

	var devicePostureIntegrationResponse DevicePostureIntegrationResponse
	err = json.Unmarshal(res, &devicePostureIntegrationResponse)
	if err != nil {
		return DevicePostureIntegration{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
	}

	return devicePostureIntegrationResponse.Result, nil
}

// DevicePostureIntegrations returns all device posture integrations within an account.
//
// API reference: https://api.cloudflare.com/#device-posture-integrations-list-device-posture-integrations
func (api *API) DevicePostureIntegrations(ctx context.Context, accountID string) ([]DevicePostureIntegration, ResultInfo, error) {
	uri := fmt.Sprintf("/%s/%s/devices/posture/integration", AccountRouteRoot, accountID)

	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
	if err != nil {
		return []DevicePostureIntegration{}, ResultInfo{}, err
	}

	var devicePostureIntegrationListResponse DevicePostureIntegrationListResponse
	err = json.Unmarshal(res, &devicePostureIntegrationListResponse)
	if err != nil {
		return []DevicePostureIntegration{}, ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
	}

	return devicePostureIntegrationListResponse.Result, devicePostureIntegrationListResponse.ResultInfo, nil
}

// DeleteDevicePostureIntegration deletes a device posture integration.
//
// API reference: https://api.cloudflare.com/#device-posture-integrations-delete-device-posture-integration
func (api *API) DeleteDevicePostureIntegration(ctx context.Context, accountID, ruleID string) error {
	uri := fmt.Sprintf(
		"/%s/%s/devices/posture/integration/%s",
		AccountRouteRoot,
		accountID,
		ruleID,
	)

	_, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil)
	if err != nil {
		return err
	}

	return nil
}

// DevicePostureRule represents a device posture rule.
type DevicePostureRule struct {
	ID          string                   `json:"id,omitempty"`
	Type        string                   `json:"type"`
	Name        string                   `json:"name"`
	Description string                   `json:"description,omitempty"`
	Schedule    string                   `json:"schedule,omitempty"`
	Match       []DevicePostureRuleMatch `json:"match,omitempty"`
	Input       DevicePostureRuleInput   `json:"input,omitempty"`
	Expiration  string                   `json:"expiration,omitempty"`
}

// DevicePostureRuleMatch represents the conditions that the client must match to run the rule.
type DevicePostureRuleMatch struct {
	Platform string `json:"platform,omitempty"`
}

// DevicePostureRuleInput represents the value to be checked against.
type DevicePostureRuleInput struct {
	ID               string `json:"id,omitempty"`
	Path             string `json:"path,omitempty"`
	Exists           bool   `json:"exists,omitempty"`
	Thumbprint       string `json:"thumbprint,omitempty"`
	Sha256           string `json:"sha256,omitempty"`
	Running          bool   `json:"running,omitempty"`
	RequireAll       bool   `json:"requireAll,omitempty"`
	Enabled          bool   `json:"enabled,omitempty"`
	Version          string `json:"version,omitempty"`
	Operator         string `json:"operator,omitempty"`
	Domain           string `json:"domain,omitempty"`
	ComplianceStatus string `json:"compliance_status,omitempty"`
	ConnectionID     string `json:"connection_id,omitempty"`
}

// DevicePostureRuleListResponse represents the response from the list
// device posture rules endpoint.
type DevicePostureRuleListResponse struct {
	Result []DevicePostureRule `json:"result"`
	Response
	ResultInfo `json:"result_info"`
}

// DevicePostureRuleDetailResponse is the API response, containing a single
// device posture rule.
type DevicePostureRuleDetailResponse struct {
	Response
	Result DevicePostureRule `json:"result"`
}

// DevicePostureRules returns all device posture rules within an account.
//
// API reference: https://api.cloudflare.com/#device-posture-rules-list-device-posture-rules
func (api *API) DevicePostureRules(ctx context.Context, accountID string) ([]DevicePostureRule, ResultInfo, error) {
	uri := fmt.Sprintf("/%s/%s/devices/posture", AccountRouteRoot, accountID)

	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
	if err != nil {
		return []DevicePostureRule{}, ResultInfo{}, err
	}

	var devicePostureRuleListResponse DevicePostureRuleListResponse
	err = json.Unmarshal(res, &devicePostureRuleListResponse)
	if err != nil {
		return []DevicePostureRule{}, ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
	}

	return devicePostureRuleListResponse.Result, devicePostureRuleListResponse.ResultInfo, nil
}

// DevicePostureRule returns a single device posture rule based on the rule ID.
//
// API reference: https://api.cloudflare.com/#device-posture-rules-device-posture-rules-details
func (api *API) DevicePostureRule(ctx context.Context, accountID, ruleID string) (DevicePostureRule, error) {
	uri := fmt.Sprintf(
		"/%s/%s/devices/posture/%s",
		AccountRouteRoot,
		accountID,
		ruleID,
	)

	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
	if err != nil {
		return DevicePostureRule{}, err
	}

	var devicePostureRuleDetailResponse DevicePostureRuleDetailResponse
	err = json.Unmarshal(res, &devicePostureRuleDetailResponse)
	if err != nil {
		return DevicePostureRule{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
	}

	return devicePostureRuleDetailResponse.Result, nil
}

// CreateDevicePostureRule creates a new device posture rule.
//
// API reference: https://api.cloudflare.com/#device-posture-rules-create-device-posture-rule
func (api *API) CreateDevicePostureRule(ctx context.Context, accountID string, rule DevicePostureRule) (DevicePostureRule, error) {
	uri := fmt.Sprintf("/%s/%s/devices/posture", AccountRouteRoot, accountID)

	res, err := api.makeRequestContext(ctx, http.MethodPost, uri, rule)
	if err != nil {
		return DevicePostureRule{}, err
	}

	var devicePostureRuleDetailResponse DevicePostureRuleDetailResponse
	err = json.Unmarshal(res, &devicePostureRuleDetailResponse)
	if err != nil {
		return DevicePostureRule{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
	}

	return devicePostureRuleDetailResponse.Result, nil
}

// UpdateDevicePostureRule updates an existing device posture rule.
//
// API reference: https://api.cloudflare.com/#device-posture-rules-update-device-posture-rule
func (api *API) UpdateDevicePostureRule(ctx context.Context, accountID string, rule DevicePostureRule) (DevicePostureRule, error) {
	if rule.ID == "" {
		return DevicePostureRule{}, fmt.Errorf("device posture rule ID cannot be empty")
	}

	uri := fmt.Sprintf(
		"/%s/%s/devices/posture/%s",
		AccountRouteRoot,
		accountID,
		rule.ID,
	)

	res, err := api.makeRequestContext(ctx, http.MethodPut, uri, rule)
	if err != nil {
		return DevicePostureRule{}, err
	}

	var devicePostureRuleDetailResponse DevicePostureRuleDetailResponse
	err = json.Unmarshal(res, &devicePostureRuleDetailResponse)
	if err != nil {
		return DevicePostureRule{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
	}

	return devicePostureRuleDetailResponse.Result, nil
}

// DeleteDevicePostureRule deletes a device posture rule.
//
// API reference: https://api.cloudflare.com/#device-posture-rules-delete-device-posture-rule
func (api *API) DeleteDevicePostureRule(ctx context.Context, accountID, ruleID string) error {
	uri := fmt.Sprintf(
		"/%s/%s/devices/posture/%s",
		AccountRouteRoot,
		accountID,
		ruleID,
	)

	_, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil)
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>device_posture_rule: add input fields for linux OS<commit_after>package cloudflare

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
)

// DevicePostureIntegrationConfig contains authentication information
// for a device posture integration.
type DevicePostureIntegrationConfig struct {
	ClientID     string `json:"client_id,omitempty"`
	ClientSecret string `json:"client_secret,omitempty"`
	AuthUrl      string `json:"auth_url,omitempty"`
	ApiUrl       string `json:"api_url,omitempty"`
	ClientKey    string `json:"client_key,omitempty"`
	CustomerID   string `json:"customer_id,omitempty"`
}

// DevicePostureIntegration represents a device posture integration.
type DevicePostureIntegration struct {
	IntegrationID string                         `json:"id,omitempty"`
	Name          string                         `json:"name,omitempty"`
	Type          string                         `json:"type,omitempty"`
	Interval      string                         `json:"interval,omitempty"`
	Config        DevicePostureIntegrationConfig `json:"config,omitempty"`
}

// DevicePostureIntegrationResponse represents the response from the get
// device posture integrations endpoint.
type DevicePostureIntegrationResponse struct {
	Result DevicePostureIntegration `json:"result"`
	Response
	ResultInfo `json:"result_info"`
}

// DevicePostureIntegrationListResponse represents the response from the list
// device posture integrations endpoint.
type DevicePostureIntegrationListResponse struct {
	Result []DevicePostureIntegration `json:"result"`
	Response
	ResultInfo `json:"result_info"`
}

// CreateDevicePostureIntegration creates a device posture integration within an account.
//
// API reference: https://api.cloudflare.com/#device-posture-integrations-create-device-posture-integration
func (api *API) CreateDevicePostureIntegration(ctx context.Context, accountID string, integration DevicePostureIntegration) (DevicePostureIntegration, error) {
	uri := fmt.Sprintf("/%s/%s/devices/posture/integration", AccountRouteRoot, accountID)

	res, err := api.makeRequestContext(ctx, http.MethodPost, uri, integration)
	if err != nil {
		fmt.Printf("err:%+v res:%+v\n", err, res)
		return DevicePostureIntegration{}, err
	}

	var devicePostureIntegrationResponse DevicePostureIntegrationResponse
	err = json.Unmarshal(res, &devicePostureIntegrationResponse)
	if err != nil {
		return DevicePostureIntegration{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
	}

	return devicePostureIntegrationResponse.Result, nil
}

// UpdateDevicePostureIntegration updates a device posture integration within an account.
//
// API reference: https://api.cloudflare.com/#device-posture-integrations-update-device-posture-integration
func (api *API) UpdateDevicePostureIntegration(ctx context.Context, accountID string, integration DevicePostureIntegration) (DevicePostureIntegration, error) {
	uri := fmt.Sprintf("/%s/%s/devices/posture/integration/%s", AccountRouteRoot, accountID, integration.IntegrationID)

	res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, integration)
	if err != nil {
		return DevicePostureIntegration{}, err
	}

	var devicePostureIntegrationResponse DevicePostureIntegrationResponse
	err = json.Unmarshal(res, &devicePostureIntegrationResponse)
	if err != nil {
		return DevicePostureIntegration{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
	}

	return devicePostureIntegrationResponse.Result, nil
}

// DevicePostureIntegration returns a specific device posture integrations within an account.
//
// API reference: https://api.cloudflare.com/#device-posture-integrations-device-posture-integration-details
func (api *API) DevicePostureIntegration(ctx context.Context, accountID, integrationID string) (DevicePostureIntegration, error) {
	uri := fmt.Sprintf("/%s/%s/devices/posture/integration/%s", AccountRouteRoot, accountID, integrationID)

	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
	if err != nil {
		return DevicePostureIntegration{}, err
	}

	var devicePostureIntegrationResponse DevicePostureIntegrationResponse
	err = json.Unmarshal(res, &devicePostureIntegrationResponse)
	if err != nil {
		return DevicePostureIntegration{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
	}

	return devicePostureIntegrationResponse.Result, nil
}

// DevicePostureIntegrations returns all device posture integrations within an account.
//
// API reference: https://api.cloudflare.com/#device-posture-integrations-list-device-posture-integrations
func (api *API) DevicePostureIntegrations(ctx context.Context, accountID string) ([]DevicePostureIntegration, ResultInfo, error) {
	uri := fmt.Sprintf("/%s/%s/devices/posture/integration", AccountRouteRoot, accountID)

	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
	if err != nil {
		return []DevicePostureIntegration{}, ResultInfo{}, err
	}

	var devicePostureIntegrationListResponse DevicePostureIntegrationListResponse
	err = json.Unmarshal(res, &devicePostureIntegrationListResponse)
	if err != nil {
		return []DevicePostureIntegration{}, ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
	}

	return devicePostureIntegrationListResponse.Result, devicePostureIntegrationListResponse.ResultInfo, nil
}

// DeleteDevicePostureIntegration deletes a device posture integration.
//
// API reference: https://api.cloudflare.com/#device-posture-integrations-delete-device-posture-integration
func (api *API) DeleteDevicePostureIntegration(ctx context.Context, accountID, ruleID string) error {
	uri := fmt.Sprintf(
		"/%s/%s/devices/posture/integration/%s",
		AccountRouteRoot,
		accountID,
		ruleID,
	)

	_, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil)
	if err != nil {
		return err
	}

	return nil
}

// DevicePostureRule represents a device posture rule.
type DevicePostureRule struct {
	ID          string                   `json:"id,omitempty"`
	Type        string                   `json:"type"`
	Name        string                   `json:"name"`
	Description string                   `json:"description,omitempty"`
	Schedule    string                   `json:"schedule,omitempty"`
	Match       []DevicePostureRuleMatch `json:"match,omitempty"`
	Input       DevicePostureRuleInput   `json:"input,omitempty"`
	Expiration  string                   `json:"expiration,omitempty"`
}

// DevicePostureRuleMatch represents the conditions that the client must match to run the rule.
type DevicePostureRuleMatch struct {
	Platform string `json:"platform,omitempty"`
}

// DevicePostureRuleInput represents the value to be checked against.
type DevicePostureRuleInput struct {
	ID               string `json:"id,omitempty"`
	Path             string `json:"path,omitempty"`
	Exists           bool   `json:"exists,omitempty"`
	Thumbprint       string `json:"thumbprint,omitempty"`
	Sha256           string `json:"sha256,omitempty"`
	Running          bool   `json:"running,omitempty"`
	RequireAll       bool   `json:"requireAll,omitempty"`
	Enabled          bool   `json:"enabled,omitempty"`
	Version          string `json:"version,omitempty"`
	OsDistroName     string `json:"os_distro_name,omitempty"`
	OsDistroRevision string `json:"os_distro_revision,omitempty"`
	Operator         string `json:"operator,omitempty"`
	Domain           string `json:"domain,omitempty"`
	ComplianceStatus string `json:"compliance_status,omitempty"`
	ConnectionID     string `json:"connection_id,omitempty"`
}

// DevicePostureRuleListResponse represents the response from the list
// device posture rules endpoint.
type DevicePostureRuleListResponse struct {
	Result []DevicePostureRule `json:"result"`
	Response
	ResultInfo `json:"result_info"`
}

// DevicePostureRuleDetailResponse is the API response, containing a single
// device posture rule.
type DevicePostureRuleDetailResponse struct {
	Response
	Result DevicePostureRule `json:"result"`
}

// DevicePostureRules returns all device posture rules within an account.
//
// API reference: https://api.cloudflare.com/#device-posture-rules-list-device-posture-rules
func (api *API) DevicePostureRules(ctx context.Context, accountID string) ([]DevicePostureRule, ResultInfo, error) {
	uri := fmt.Sprintf("/%s/%s/devices/posture", AccountRouteRoot, accountID)

	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
	if err != nil {
		return []DevicePostureRule{}, ResultInfo{}, err
	}

	var devicePostureRuleListResponse DevicePostureRuleListResponse
	err = json.Unmarshal(res, &devicePostureRuleListResponse)
	if err != nil {
		return []DevicePostureRule{}, ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
	}

	return devicePostureRuleListResponse.Result, devicePostureRuleListResponse.ResultInfo, nil
}

// DevicePostureRule returns a single device posture rule based on the rule ID.
//
// API reference: https://api.cloudflare.com/#device-posture-rules-device-posture-rules-details
func (api *API) DevicePostureRule(ctx context.Context, accountID, ruleID string) (DevicePostureRule, error) {
	uri := fmt.Sprintf(
		"/%s/%s/devices/posture/%s",
		AccountRouteRoot,
		accountID,
		ruleID,
	)

	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
	if err != nil {
		return DevicePostureRule{}, err
	}

	var devicePostureRuleDetailResponse DevicePostureRuleDetailResponse
	err = json.Unmarshal(res, &devicePostureRuleDetailResponse)
	if err != nil {
		return DevicePostureRule{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
	}

	return devicePostureRuleDetailResponse.Result, nil
}

// CreateDevicePostureRule creates a new device posture rule.
//
// API reference: https://api.cloudflare.com/#device-posture-rules-create-device-posture-rule
func (api *API) CreateDevicePostureRule(ctx context.Context, accountID string, rule DevicePostureRule) (DevicePostureRule, error) {
	uri := fmt.Sprintf("/%s/%s/devices/posture", AccountRouteRoot, accountID)

	res, err := api.makeRequestContext(ctx, http.MethodPost, uri, rule)
	if err != nil {
		return DevicePostureRule{}, err
	}

	var devicePostureRuleDetailResponse DevicePostureRuleDetailResponse
	err = json.Unmarshal(res, &devicePostureRuleDetailResponse)
	if err != nil {
		return DevicePostureRule{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
	}

	return devicePostureRuleDetailResponse.Result, nil
}

// UpdateDevicePostureRule updates an existing device posture rule.
//
// API reference: https://api.cloudflare.com/#device-posture-rules-update-device-posture-rule
func (api *API) UpdateDevicePostureRule(ctx context.Context, accountID string, rule DevicePostureRule) (DevicePostureRule, error) {
	if rule.ID == "" {
		return DevicePostureRule{}, fmt.Errorf("device posture rule ID cannot be empty")
	}

	uri := fmt.Sprintf(
		"/%s/%s/devices/posture/%s",
		AccountRouteRoot,
		accountID,
		rule.ID,
	)

	res, err := api.makeRequestContext(ctx, http.MethodPut, uri, rule)
	if err != nil {
		return DevicePostureRule{}, err
	}

	var devicePostureRuleDetailResponse DevicePostureRuleDetailResponse
	err = json.Unmarshal(res, &devicePostureRuleDetailResponse)
	if err != nil {
		return DevicePostureRule{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
	}

	return devicePostureRuleDetailResponse.Result, nil
}

// DeleteDevicePostureRule deletes a device posture rule.
//
// API reference: https://api.cloudflare.com/#device-posture-rules-delete-device-posture-rule
func (api *API) DeleteDevicePostureRule(ctx context.Context, accountID, ruleID string) error {
	uri := fmt.Sprintf(
		"/%s/%s/devices/posture/%s",
		AccountRouteRoot,
		accountID,
		ruleID,
	)

	_, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil)
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>// Package dht implements the bittorrent dht protocol. For more information
// see http://www.bittorrent.org/beps/bep_0005.html.
package dht

import (
	"encoding/hex"
	"errors"
	"net"
	"time"
)

const (
	// StandardMode follows the standard protocol
	StandardMode = iota
	// CrawlMode for crawling the dht network.
	CrawlMode
)

// Config represents the configure of dht.
type Config struct {
	// in mainline dht, k = 8
	K int
	// for crawling mode, we put all nodes in one bucket, so KBucketSize may
	// not be K
	KBucketSize int
	// candidates are udp, udp4, udp6
	Network string
	// format is `ip:port`
	Address string
	// the prime nodes through which we can join in dht network
	PrimeNodes []string
	// the kbucket expired duration
	KBucketExpiredAfter time.Duration
	// the node expired duration
	NodeExpriedAfter time.Duration
	// how long it checks whether the bucket is expired
	CheckKBucketPeriod time.Duration
	// peer token expired duration
	TokenExpiredAfter time.Duration
	// the max transaction id
	MaxTransactionCursor uint64
	// how many nodes routing table can hold
	MaxNodes int
	// callback when got get_peers request
	OnGetPeers func(string, string, int)
	// callback when got announce_peer request
	OnAnnouncePeer func(string, string, int)
	// blcoked ips
	BlockedIPs []string
	// blacklist size
	BlackListMaxSize int
	// StandardMode or CrawlMode
	Mode int
	// the times it tries when send fails
	Try int
	// the size of packet need to be dealt with
	PacketJobLimit int
	// the size of packet handler
	PacketWorkerLimit int
	// the nodes num to be fresh in a kbucket
	RefreshNodeNum int
}

// NewStandardConfig returns a Config pointer with default values.
func NewStandardConfig() *Config {
	return &Config{
		K:           8,
		KBucketSize: 8,
		Network:     "udp4",
		Address:     ":6881",
		PrimeNodes: []string{
			"router.bittorrent.com:6881",
			"router.utorrent.com:6881",
			"dht.transmissionbt.com:6881",
		},
		NodeExpriedAfter:     time.Duration(time.Minute * 15),
		KBucketExpiredAfter:  time.Duration(time.Minute * 15),
		CheckKBucketPeriod:   time.Duration(time.Second * 30),
		TokenExpiredAfter:    time.Duration(time.Minute * 10),
		MaxTransactionCursor: 4294967295, // 2 ^ 32 - 1
		MaxNodes:             5000,
		BlockedIPs:           make([]string, 0),
		BlackListMaxSize:     65536,
		Try:                  2,
		Mode:                 StandardMode,
		PacketJobLimit:       1024,
		PacketWorkerLimit:    256,
		RefreshNodeNum:       8,
	}
}

// NewCrawlConfig returns a config in crawling mode.
func NewCrawlConfig() *Config {
	config := NewStandardConfig()
	config.NodeExpriedAfter = 0
	config.KBucketExpiredAfter = 0
	config.CheckKBucketPeriod = time.Second * 5
	config.KBucketSize = 2147483647 // 2 ^ 31 - 1
	config.Mode = CrawlMode
	config.RefreshNodeNum = 256

	return config
}

// DHT represents a DHT node.
type DHT struct {
	*Config
	node               *node
	conn               *net.UDPConn
	routingTable       *routingTable
	transactionManager *transactionManager
	peersManager       *peersManager
	tokenManager       *tokenManager
	blackList          *blackList
	Ready              bool
	packets            chan packet
	workerTokens       chan struct{}
}

// New returns a DHT pointer. If config is nil, then config will be set to
// the default config.
func New(config *Config) *DHT {
	if config == nil {
		config = NewStandardConfig()
	}

	node, err := newNode(randomString(20), config.Network, config.Address)
	if err != nil {
		panic(err)
	}

	d := &DHT{
		Config:       config,
		node:         node,
		blackList:    newBlackList(config.BlackListMaxSize),
		packets:      make(chan packet, config.PacketJobLimit),
		workerTokens: make(chan struct{}, config.PacketWorkerLimit),
	}

	for _, ip := range config.BlockedIPs {
		d.blackList.insert(ip, -1)
	}

	go func() {
		for _, ip := range getLocalIPs() {
			d.blackList.insert(ip, -1)
		}

		ip, err := getRemoteIP()
		if err != nil {
			d.blackList.insert(ip, -1)
		}
	}()

	return d
}

// IsStandardMode returns whether mode is StandardMode.
func (dht *DHT) IsStandardMode() bool {
	return dht.Mode == StandardMode
}

// IsCrawlMode returns whether mode is CrawlMode.
func (dht *DHT) IsCrawlMode() bool {
	return dht.Mode == CrawlMode
}

// init initializes global varables.
func (dht *DHT) init() {
	listener, err := net.ListenPacket(dht.Network, dht.Address)
	if err != nil {
		panic(err)
	}

	dht.conn = listener.(*net.UDPConn)
	dht.routingTable = newRoutingTable(dht.KBucketSize, dht)
	dht.peersManager = newPeersManager(dht)
	dht.tokenManager = newTokenManager(dht.TokenExpiredAfter, dht)
	dht.transactionManager = newTransactionManager(
		dht.MaxTransactionCursor, dht)

	go dht.transactionManager.run()
	go dht.tokenManager.clear()
	go dht.blackList.clear()
}

// join makes current node join the dht network.
func (dht *DHT) join() {
	for _, addr := range dht.PrimeNodes {
		raddr, err := net.ResolveUDPAddr(dht.Network, addr)
		if err != nil {
			continue
		}

		// NOTE: Temporary node has NOT node id.
		dht.transactionManager.findNode(
			&node{addr: raddr},
			dht.node.id.RawString(),
		)
	}
}

// listen receives message from udp.
func (dht *DHT) listen() {
	go func() {
		buff := make([]byte, 8192)
		for {
			n, raddr, err := dht.conn.ReadFromUDP(buff)
			if err != nil {
				continue
			}

			dht.packets <- packet{buff[:n], raddr}
		}
	}()
}

// id returns a id near to target if target is not null, otherwise it returns
// the dht's node id.
func (dht *DHT) id(target string) string {
	if dht.IsStandardMode() || target == "" {
		return dht.node.id.RawString()
	}
	return target[:15] + dht.node.id.RawString()[15:]
}

// GetPeers returns peers who have announced having infoHash.
func (dht *DHT) GetPeers(infoHash string) ([]*Peer, error) {
	if !dht.Ready {
		return nil, errors.New("dht not ready")
	}

	if len(infoHash) == 40 {
		data, err := hex.DecodeString(infoHash)
		if err != nil {
			return nil, err
		}
		infoHash = string(data)
	}

	peers := dht.peersManager.GetPeers(infoHash, dht.K)
	if len(peers) != 0 {
		return peers, nil
	}

	ch := make(chan struct{})

	go func() {
		neighbors := dht.routingTable.GetNeighbors(
			newBitmapFromString(infoHash), dht.K)

		for _, no := range neighbors {
			dht.transactionManager.getPeers(no, infoHash)
		}

		i := 0
		for _ = range time.Tick(time.Second * 1) {
			i++
			peers = dht.peersManager.GetPeers(infoHash, dht.K)
			if len(peers) != 0 || i == 30 {
				break
			}
		}

		ch <- struct{}{}
	}()

	<-ch
	return peers, nil
}

// Run starts the dht.
func (dht *DHT) Run() {
	dht.init()
	dht.listen()
	dht.join()

	dht.Ready = true

	var pkt packet
	tick := time.Tick(dht.CheckKBucketPeriod)

	for {
		select {
		case pkt = <-dht.packets:
			handle(dht, pkt)
		case <-tick:
			if dht.routingTable.Len() == 0 {
				dht.join()
			} else if dht.transactionManager.len() == 0 {
				go dht.routingTable.Fresh()
			}
		}
	}
}
<commit_msg>replace constant number with math<commit_after>// Package dht implements the bittorrent dht protocol. For more information
// see http://www.bittorrent.org/beps/bep_0005.html.
package dht

import (
	"encoding/hex"
	"errors"
	"math"
	"net"
	"time"
)

const (
	// StandardMode follows the standard protocol
	StandardMode = iota
	// CrawlMode for crawling the dht network.
	CrawlMode
)

// Config represents the configure of dht.
type Config struct {
	// in mainline dht, k = 8
	K int
	// for crawling mode, we put all nodes in one bucket, so KBucketSize may
	// not be K
	KBucketSize int
	// candidates are udp, udp4, udp6
	Network string
	// format is `ip:port`
	Address string
	// the prime nodes through which we can join in dht network
	PrimeNodes []string
	// the kbucket expired duration
	KBucketExpiredAfter time.Duration
	// the node expired duration
	NodeExpriedAfter time.Duration
	// how long it checks whether the bucket is expired
	CheckKBucketPeriod time.Duration
	// peer token expired duration
	TokenExpiredAfter time.Duration
	// the max transaction id
	MaxTransactionCursor uint64
	// how many nodes routing table can hold
	MaxNodes int
	// callback when got get_peers request
	OnGetPeers func(string, string, int)
	// callback when got announce_peer request
	OnAnnouncePeer func(string, string, int)
	// blcoked ips
	BlockedIPs []string
	// blacklist size
	BlackListMaxSize int
	// StandardMode or CrawlMode
	Mode int
	// the times it tries when send fails
	Try int
	// the size of packet need to be dealt with
	PacketJobLimit int
	// the size of packet handler
	PacketWorkerLimit int
	// the nodes num to be fresh in a kbucket
	RefreshNodeNum int
}

// NewStandardConfig returns a Config pointer with default values.
func NewStandardConfig() *Config {
	return &Config{
		K:           8,
		KBucketSize: 8,
		Network:     "udp4",
		Address:     ":6881",
		PrimeNodes: []string{
			"router.bittorrent.com:6881",
			"router.utorrent.com:6881",
			"dht.transmissionbt.com:6881",
		},
		NodeExpriedAfter:     time.Duration(time.Minute * 15),
		KBucketExpiredAfter:  time.Duration(time.Minute * 15),
		CheckKBucketPeriod:   time.Duration(time.Second * 30),
		TokenExpiredAfter:    time.Duration(time.Minute * 10),
		MaxTransactionCursor: math.MaxUint32,
		MaxNodes:             5000,
		BlockedIPs:           make([]string, 0),
		BlackListMaxSize:     65536,
		Try:                  2,
		Mode:                 StandardMode,
		PacketJobLimit:       1024,
		PacketWorkerLimit:    256,
		RefreshNodeNum:       8,
	}
}

// NewCrawlConfig returns a config in crawling mode.
func NewCrawlConfig() *Config {
	config := NewStandardConfig()
	config.NodeExpriedAfter = 0
	config.KBucketExpiredAfter = 0
	config.CheckKBucketPeriod = time.Second * 5
	config.KBucketSize = math.MaxInt32
	config.Mode = CrawlMode
	config.RefreshNodeNum = 256

	return config
}

// DHT represents a DHT node.
type DHT struct {
	*Config
	node               *node
	conn               *net.UDPConn
	routingTable       *routingTable
	transactionManager *transactionManager
	peersManager       *peersManager
	tokenManager       *tokenManager
	blackList          *blackList
	Ready              bool
	packets            chan packet
	workerTokens       chan struct{}
}

// New returns a DHT pointer. If config is nil, then config will be set to
// the default config.
func New(config *Config) *DHT {
	if config == nil {
		config = NewStandardConfig()
	}

	node, err := newNode(randomString(20), config.Network, config.Address)
	if err != nil {
		panic(err)
	}

	d := &DHT{
		Config:       config,
		node:         node,
		blackList:    newBlackList(config.BlackListMaxSize),
		packets:      make(chan packet, config.PacketJobLimit),
		workerTokens: make(chan struct{}, config.PacketWorkerLimit),
	}

	for _, ip := range config.BlockedIPs {
		d.blackList.insert(ip, -1)
	}

	go func() {
		for _, ip := range getLocalIPs() {
			d.blackList.insert(ip, -1)
		}

		ip, err := getRemoteIP()
		if err != nil {
			d.blackList.insert(ip, -1)
		}
	}()

	return d
}

// IsStandardMode returns whether mode is StandardMode.
func (dht *DHT) IsStandardMode() bool {
	return dht.Mode == StandardMode
}

// IsCrawlMode returns whether mode is CrawlMode.
func (dht *DHT) IsCrawlMode() bool {
	return dht.Mode == CrawlMode
}

// init initializes global varables.
func (dht *DHT) init() {
	listener, err := net.ListenPacket(dht.Network, dht.Address)
	if err != nil {
		panic(err)
	}

	dht.conn = listener.(*net.UDPConn)
	dht.routingTable = newRoutingTable(dht.KBucketSize, dht)
	dht.peersManager = newPeersManager(dht)
	dht.tokenManager = newTokenManager(dht.TokenExpiredAfter, dht)
	dht.transactionManager = newTransactionManager(
		dht.MaxTransactionCursor, dht)

	go dht.transactionManager.run()
	go dht.tokenManager.clear()
	go dht.blackList.clear()
}

// join makes current node join the dht network.
func (dht *DHT) join() {
	for _, addr := range dht.PrimeNodes {
		raddr, err := net.ResolveUDPAddr(dht.Network, addr)
		if err != nil {
			continue
		}

		// NOTE: Temporary node has NOT node id.
		dht.transactionManager.findNode(
			&node{addr: raddr},
			dht.node.id.RawString(),
		)
	}
}

// listen receives message from udp.
func (dht *DHT) listen() {
	go func() {
		buff := make([]byte, 8192)
		for {
			n, raddr, err := dht.conn.ReadFromUDP(buff)
			if err != nil {
				continue
			}

			dht.packets <- packet{buff[:n], raddr}
		}
	}()
}

// id returns a id near to target if target is not null, otherwise it returns
// the dht's node id.
func (dht *DHT) id(target string) string {
	if dht.IsStandardMode() || target == "" {
		return dht.node.id.RawString()
	}
	return target[:15] + dht.node.id.RawString()[15:]
}

// GetPeers returns peers who have announced having infoHash.
func (dht *DHT) GetPeers(infoHash string) ([]*Peer, error) {
	if !dht.Ready {
		return nil, errors.New("dht not ready")
	}

	if len(infoHash) == 40 {
		data, err := hex.DecodeString(infoHash)
		if err != nil {
			return nil, err
		}
		infoHash = string(data)
	}

	peers := dht.peersManager.GetPeers(infoHash, dht.K)
	if len(peers) != 0 {
		return peers, nil
	}

	ch := make(chan struct{})

	go func() {
		neighbors := dht.routingTable.GetNeighbors(
			newBitmapFromString(infoHash), dht.K)

		for _, no := range neighbors {
			dht.transactionManager.getPeers(no, infoHash)
		}

		i := 0
		for _ = range time.Tick(time.Second * 1) {
			i++
			peers = dht.peersManager.GetPeers(infoHash, dht.K)
			if len(peers) != 0 || i == 30 {
				break
			}
		}

		ch <- struct{}{}
	}()

	<-ch
	return peers, nil
}

// Run starts the dht.
func (dht *DHT) Run() {
	dht.init()
	dht.listen()
	dht.join()

	dht.Ready = true

	var pkt packet
	tick := time.Tick(dht.CheckKBucketPeriod)

	for {
		select {
		case pkt = <-dht.packets:
			handle(dht, pkt)
		case <-tick:
			if dht.routingTable.Len() == 0 {
				dht.join()
			} else if dht.transactionManager.len() == 0 {
				go dht.routingTable.Fresh()
			}
		}
	}
}
<|endoftext|>


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

package main

import (
	"log"
	"os"

	"golang.org/x/net/context"
	"google.golang.org/cloud/storage"

	"bazil.org/fuse"
	"bazil.org/fuse/fs"
)

const dirSeparator = '/'

// A "directory" in GCS, defined by an object name prefix. All prefixes end
// with dirSeparator except for the special case of the root directory, where
// the prefix is the empty string.
type dir struct {
	authContext  context.Context
	bucketName   string
	objectPrefix string
}

func (d *dir) Attr() fuse.Attr {
	return fuse.Attr{
		// TODO(jacobsa): Expose ACLs from GCS?
		Mode: os.ModeDir | 0700,
	}
}

// A version of readDir that is context-aware. The context must contain auth
// information.
func (d *dir) readDirWithContext(ctx context.Context) (
	ents []fuse.Dirent, fuseErr fuse.Error) {
	log.Printf("ReadDir: [%s]/%s", d.bucketName, d.objectPrefix)

	// List repeatedly until there is no more to list.
	query := &storage.Query{
		Delimiter: string(dirSeparator),
		Prefix:    d.objectPrefix,
	}

	for query != nil {
		// Grab one set of results.
		objects, err := storage.ListObjects(ctx, d.bucketName, query)
		if err != nil {
			log.Println("storage.ListObjects:", err)
			return nil, fuse.EIO
		}

		// Extract objects as files.
		for _, o := range objects.Results {
			ents = append(ents, fuse.Dirent{
				Type: fuse.DT_File,
				Name: o.Name, // TODO(jacobsa): Strip prefix.
			})
		}

		// Extract prefixes as directories.
		for _, p := range objects.Prefixes {
			ents = append(ents, fuse.Dirent{
				Type: fuse.DT_Dir,
				Name: p, // TODO(jacobsa): Strip prefix.
			})
		}

		// Move on to the next set of results.
		query = objects.Next
	}

	return
}

func (d *dir) ReadDir(intr fs.Intr) ([]fuse.Dirent, fuse.Error) {
	ctx, cancel := withIntr(d.authContext, intr)
	defer cancel()

	return d.readDirWithContext(ctx)
}
<commit_msg>Added a skeleton Lookup method.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package main

import (
	"log"
	"os"
	"path"

	"golang.org/x/net/context"
	"google.golang.org/cloud/storage"

	"bazil.org/fuse"
	"bazil.org/fuse/fs"
)

const dirSeparator = '/'

// A "directory" in GCS, defined by an object name prefix. All prefixes end
// with dirSeparator except for the special case of the root directory, where
// the prefix is the empty string.
type dir struct {
	authContext  context.Context
	bucketName   string
	objectPrefix string
}

func (d *dir) Attr() fuse.Attr {
	return fuse.Attr{
		// TODO(jacobsa): Expose ACLs from GCS?
		Mode: os.ModeDir | 0700,
	}
}

func (d *dir) readDir(ctx context.Context) (
	ents []fuse.Dirent, fuseErr fuse.Error) {
	log.Printf("ReadDir: [%s]/%s", d.bucketName, d.objectPrefix)

	// List repeatedly until there is no more to list.
	query := &storage.Query{
		Delimiter: string(dirSeparator),
		Prefix:    d.objectPrefix,
	}

	for query != nil {
		// Grab one set of results.
		objects, err := storage.ListObjects(ctx, d.bucketName, query)
		if err != nil {
			log.Println("storage.ListObjects:", err)
			return nil, fuse.EIO
		}

		// Extract objects as files.
		for _, o := range objects.Results {
			ents = append(ents, fuse.Dirent{
				Type: fuse.DT_File,
				Name: o.Name, // TODO(jacobsa): Strip prefix.
			})
		}

		// Extract prefixes as directories.
		for _, p := range objects.Prefixes {
			ents = append(ents, fuse.Dirent{
				Type: fuse.DT_Dir,
				Name: p, // TODO(jacobsa): Strip prefix.
			})
		}

		// Move on to the next set of results.
		query = objects.Next
	}

	return
}

func (d *dir) lookup(ctx context.Context, name string) (fs.Node, fuse.Error) {
	log.Printf("Lookup: ([%s]/%s) %s", d.bucketName, d.objectPrefix, name)

	// Join the directory's prefix with this node's name to get the full name
	// that we expect to see in GCS (minus the slash that will be on it if it's a
	// prefix representing a directory).
	fullName := path.Join(d.objectPrefix, name)

	// We must determine whether this is a file or a directory. List objects
	// whose names start with fullName.
	//
	// HACK(jacobsa): As of 2015-02-05 the documentation here doesn't guarantee
	// that object listing results are ordered by object name:
	//
	//    https://cloud.google.com/storage/docs/json_api/v1/objects/list
	//
	// Therefore in theory we are not guaranteed to see the object name on the
	// first page of results. It is reasonable to assume however that the results
	// are in order. Still, even if that is the case, we may have trouble with
	// directories since there are characters before '/' that could be in a path
	// name. Perhaps we should be sending a separate request for fullName plus
	// the slash, as much as it pains me to do so.
	query := &storage.Query{
		Delimiter: string(dirSeparator),
		Prefix:    fullName,
	}

	objects, err := storage.ListObjects(ctx, d.bucketName, query)
	if err != nil {
		log.Println("storage.ListObjects:", err)
		return nil, fuse.EIO
	}

	// Is there a matching file name?
	for _, o := range objects.Results {
		if o.Name == fullName {
			log.Println("TODO(jacobsa): Handle files.")
			return nil, fuse.EIO
		}
	}

	// Is there a matching directory name?
	for _, p := range objects.Prefixes {
		if p == fullName+"/" {
			node := &dir{
				authContext:  d.authContext,
				bucketName:   d.bucketName,
				objectPrefix: p,
			}

			return node, nil
		}
	}

	return nil, fuse.ENOENT
}

func (d *dir) ReadDir(intr fs.Intr) ([]fuse.Dirent, fuse.Error) {
	ctx, cancel := withIntr(d.authContext, intr)
	defer cancel()

	return d.readDir(ctx)
}

func (d *dir) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) {
	ctx, cancel := withIntr(d.authContext, intr)
	defer cancel()

	return d.lookup(ctx, name)
}
<|endoftext|>


<commit_before>package application_test

import (
	"time"

	. "github.com/cloudfoundry-incubator/cf-test-helpers/cf"
	"github.com/cloudfoundry-incubator/cf-test-helpers/generator"
	acceptanceTestHelpers "github.com/cloudfoundry-incubator/cf-test-helpers/helpers"
	gatsHelpers "github.com/cloudfoundry/cli-acceptance-tests/helpers"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gexec"
)

var _ = Describe("Env", func() {
	const (
		assertionTimeout = 10 * time.Second
		appTimeout       = 2 * time.Minute
		copyAppTimeout   = 3 * time.Minute
	)

	var (
		context *acceptanceTestHelpers.ConfiguredContext
		env     *acceptanceTestHelpers.Environment
	)

	config := acceptanceTestHelpers.LoadConfig()

	BeforeEach(func() {
		context = acceptanceTestHelpers.NewContext(config)
		env = acceptanceTestHelpers.NewEnvironment(context)

		env.Setup()
		AsUser(context.AdminUserContext(), 30*time.Second, func() {
			envVarGroups := Cf("ssevg", `{}`).Wait(assertionTimeout)
			Expect(envVarGroups).To(Exit(0))

			envVarGroups = Cf("srevg", `{}`).Wait(assertionTimeout)
			Expect(envVarGroups).To(Exit(0))
		})
	})

	AfterEach(func() {
		AsUser(context.AdminUserContext(), 30*time.Second, func() {
			envVarGroups := Cf("ssevg", `{}`).Wait(assertionTimeout)
			Expect(envVarGroups).To(Exit(0))

			envVarGroups = Cf("srevg", `{}`).Wait(assertionTimeout)
			Expect(envVarGroups).To(Exit(0))
			env.Teardown()
		})
	})

	It("returns ann applications running, staging, system provided and user defined environment variables", func() {
		AsUser(context.AdminUserContext(), 60*time.Second, func() {
			ssevgResult := Cf("ssevg", `{"name":"staging-val"}`).Wait(assertionTimeout)
			Expect(ssevgResult).To(Exit(0))
			srevgResult := Cf("srevg", `{"name":"running-val"}`).Wait(assertionTimeout)
			Expect(srevgResult).To(Exit(0))

			space := context.RegularUserContext().Space
			org := context.RegularUserContext().Org

			target := Cf("target", "-o", org, "-s", space).Wait(assertionTimeout)
			Expect(target.ExitCode()).To(Equal(0))

			appName := generator.RandomName()
			app := Cf("push", appName, "-p", gatsHelpers.NewAssets().ServiceBroker).Wait(appTimeout)
			Expect(app).To(Exit(0))

			setEnvResult := Cf("set-env", appName, "set-env-key", "set-env-val").Wait(assertionTimeout)
			Expect(setEnvResult).To(Exit(0))

			envResult := Cf("env", appName).Wait(assertionTimeout)
			Expect(envResult).To(Exit(0))

			output := envResult.Out.Contents()
			Expect(output).To(ContainSubstring("\"VCAP_APPLICATION\": {"))
			Expect(output).To(ContainSubstring("User-Provided:\nset-env-key: set-env-val"))
			Expect(output).To(ContainSubstring("Running Environment Variable Groups:\nname: running-val"))
			Expect(output).To(ContainSubstring("Staging Environment Variable Groups:\nname: staging-val"))
		})
	})
})
<commit_msg>aliases are hard to understand in some cases, this is one of them<commit_after>package application_test

import (
	"time"

	. "github.com/cloudfoundry-incubator/cf-test-helpers/cf"
	"github.com/cloudfoundry-incubator/cf-test-helpers/generator"
	acceptanceTestHelpers "github.com/cloudfoundry-incubator/cf-test-helpers/helpers"
	gatsHelpers "github.com/cloudfoundry/cli-acceptance-tests/helpers"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gexec"
)

var _ = Describe("Env", func() {
	const (
		assertionTimeout = 10 * time.Second
		appTimeout       = 2 * time.Minute
		copyAppTimeout   = 3 * time.Minute
	)

	var (
		context *acceptanceTestHelpers.ConfiguredContext
		env     *acceptanceTestHelpers.Environment
	)

	config := acceptanceTestHelpers.LoadConfig()

	BeforeEach(func() {
		context = acceptanceTestHelpers.NewContext(config)
		env = acceptanceTestHelpers.NewEnvironment(context)

		env.Setup()
		AsUser(context.AdminUserContext(), 30*time.Second, func() {
			envVarGroups := Cf("set-staging-environment-variable-group", `{}`).Wait(assertionTimeout)
			Expect(envVarGroups).To(Exit(0))

			envVarGroups = Cf("set-running-environment-variable-group", `{}`).Wait(assertionTimeout)
			Expect(envVarGroups).To(Exit(0))
		})
	})

	AfterEach(func() {
		AsUser(context.AdminUserContext(), 30*time.Second, func() {
			envVarGroups := Cf("set-staging-environment-variable-group", `{}`).Wait(assertionTimeout)
			Expect(envVarGroups).To(Exit(0))

			envVarGroups = Cf("set-running-environment-variable-group", `{}`).Wait(assertionTimeout)
			Expect(envVarGroups).To(Exit(0))
			env.Teardown()
		})
	})

	It("returns ann applications running, staging, system provided and user defined environment variables", func() {
		AsUser(context.AdminUserContext(), 60*time.Second, func() {
			ssevgResult := Cf("set-staging-environment-variable-group", `{"name":"staging-val"}`).Wait(assertionTimeout)
			Expect(ssevgResult).To(Exit(0))
			srevgResult := Cf("set-running-environment-variable-group", `{"name":"running-val"}`).Wait(assertionTimeout)
			Expect(srevgResult).To(Exit(0))

			space := context.RegularUserContext().Space
			org := context.RegularUserContext().Org

			target := Cf("target", "-o", org, "-s", space).Wait(assertionTimeout)
			Expect(target.ExitCode()).To(Equal(0))

			appName := generator.RandomName()
			app := Cf("push", appName, "-p", gatsHelpers.NewAssets().ServiceBroker).Wait(appTimeout)
			Expect(app).To(Exit(0))

			setEnvResult := Cf("set-env", appName, "set-env-key", "set-env-val").Wait(assertionTimeout)
			Expect(setEnvResult).To(Exit(0))

			envResult := Cf("env", appName).Wait(assertionTimeout)
			Expect(envResult).To(Exit(0))

			output := envResult.Out.Contents()
			Expect(output).To(ContainSubstring("\"VCAP_APPLICATION\": {"))
			Expect(output).To(ContainSubstring("User-Provided:\nset-env-key: set-env-val"))
			Expect(output).To(ContainSubstring("Running Environment Variable Groups:\nname: running-val"))
			Expect(output).To(ContainSubstring("Staging Environment Variable Groups:\nname: staging-val"))
		})
	})
})
<|endoftext|>


<commit_before>/*
Package gdal provides a wrapper for GDAL, the Geospatial Data Abstraction Library.  This C/C++ library provides access to a large number of geospatial raster data formats.  It also contains a wrapper for the related OGR Simple Feature Library which provides similar functionality for vector formats.

Limitations

The majority of the GDAL C API is covered, with the exception of asynchronous readers and a number of less oftenly used functions.  OGR support is currently much less complete.  Spatial reference support is sufficient to support assigning spatial reference values to GDAL datasets from WKT and Proj.4 definitions, but does not cover the majority of spatial reference formats yet.

This wrapper has only been tested on 64-bit Ubuntu Linux, with version 1.9.1 of the GDAL library.

Usage

A simple program to create a georeferenced blank 256x256 GeoTIFF:
	package main

	import (
		"fmt"
		"flag"
		"github.com/lukeroth/gdal"
	)

	func main() {
		flag.Parse()
		filename := flag.Arg(0)
		if filename == "" {
			fmt.Printf("Usage: test_tiff [filename]\n")
			return
		}
		buffer := make([]uint8, 256 * 256)

		driver, err := gdal.GetDriverByName("GTiff")
		if err != nil {
			fmt.Println(err.Error())
			return
		}

		dataset := driver.Create(filename, 256, 256, 1, gdal.Byte, nil)
		defer dataset.Close()

		spatialRef := gdal.CreateSpatialReference("")
		spatialRef.FromEPSG(3857)
		srString, err := spatialRef.ToWKT()
		dataset.SetProjection(srString)
		dataset.SetGeoTransform([]float64{444720, 30, 0, 3751320, 0, -30})
		raster := dataset.RasterBand(1)
		raster.IO(gdal.Write, 0, 0, 256, 256, buffer, 256, 256, 0, 0)
	}
More examples can be found in the ./examples subdirectory.

Recent changes

A more complete changelog can be found on Github.
10/2/2012: Initial OGR and OSR support added; color table and raster attribute table support added.
*/
package gdal
<commit_msg>Updated changelog<commit_after>/*
Package gdal provides a wrapper for GDAL, the Geospatial Data Abstraction Library.  This C/C++ library provides access to a large number of geospatial raster data formats.  It also contains a wrapper for the related OGR Simple Feature Library which provides similar functionality for vector formats.

Limitations

The majority of the GDAL C API is covered, with the exception of asynchronous readers and a number of less oftenly used functions.  OGR support is currently much less complete.  Spatial reference support is sufficient to support assigning spatial reference values to GDAL datasets from WKT and Proj.4 definitions, but does not cover the majority of spatial reference formats yet.

This wrapper has only been tested on 64-bit Ubuntu Linux, with version 1.9.1 of the GDAL library.

Usage

A simple program to create a georeferenced blank 256x256 GeoTIFF:
	package main

	import (
		"fmt"
		"flag"
		"github.com/lukeroth/gdal"
	)

	func main() {
		flag.Parse()
		filename := flag.Arg(0)
		if filename == "" {
			fmt.Printf("Usage: test_tiff [filename]\n")
			return
		}
		buffer := make([]uint8, 256 * 256)

		driver, err := gdal.GetDriverByName("GTiff")
		if err != nil {
			fmt.Println(err.Error())
			return
		}

		dataset := driver.Create(filename, 256, 256, 1, gdal.Byte, nil)
		defer dataset.Close()

		spatialRef := gdal.CreateSpatialReference("")
		spatialRef.FromEPSG(3857)
		srString, err := spatialRef.ToWKT()
		dataset.SetProjection(srString)
		dataset.SetGeoTransform([]float64{444720, 30, 0, 3751320, 0, -30})
		raster := dataset.RasterBand(1)
		raster.IO(gdal.Write, 0, 0, 256, 256, buffer, 256, 256, 0, 0)
	}
More examples can be found in the ./examples subdirectory.

Recent changes

A more complete changelog can be found on Github.
10/3/2012: Restructed OGR code, added initial algorithm functions and placeholders
10/2/2012: Initial OGR and OSR support added; color table and raster attribute table support added.
*/
package gdal
<|endoftext|>


<commit_before>// Copyright 2012-2017, Rolf Veen and contributors.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package ogdl is used to process OGDL, the Ordered Graph Data Language.
//
// OGDL is a textual format to write trees or graphs of text, where
// indentation and spaces define the structure. Here is an example:
//
//    network
//      ip 192.168.1.100
//      gw 192.168.1.9
//
// The languange is simple, either in its textual representation or its
// number of productions (the specification rules), allowing for compact
// implementations.
//
// OGDL character streams are normally formed by Unicode characters, and
// encoded as UTF-8 strings, but any encoding that is ASCII transparent
// is compatible with the specification.
//
// See the full spec at http://ogdl.org.
//
// Installation
//
// To install this package just do:
//
//     go get github.com/rveen/ogdl
//
// An example
//
// If we have a text file 'config.g' containing:
//
//    eth0
//      ip
//        192.168.1.1
//      gateway
//        192.168.1.10
//      mask
//        255.255.255.0
//      timeout
//        20
//
// then,
//
//    g := ogdl.FromFile("config.g")
//    ip := g.Get("eth0.ip").String()
//    to := g.Get("eth0.timeout").Int64(60)
//
//    println("ip:",ip,", timeout:",to)
//
// will print
//
//    ip: 192.168.1.1, timeout: 20
//
// If the timeout parameter was not present, then the default value (60) will be
// assigned to 'to'. The default value is optional, but be aware that Int64() will
// return 0 in case that the parameter doesn't exist.
//
// The configuration file can be written in a conciser way:
//
//    eth0
//      ip      192.168.1.1
//      gateway 192.168.1.10
//      mask    255.255.255.0
//      timeout 20
//
// A template example
//
// The package includes a template processor. It takes an arbitrary input stream
// with some variables in it, and produces an output stream with the variables
// resolved out of a Graph object which acts as context.
//
// For example (given the previous config file):
//
//     g := ogdl.ParseFile("config.g")
//     t := ogdl.NewTemplate("The gateway's IP is $eth0.gateway")
//     b := t.Process(g)
//
// string(b) is then:
//
//     The gateway's IP is 192.168.1.10
//
// Function signature conventions
//
// Some rules are followed:
//
//   .<Type>()      Return the first subnode content converted to the specified type.
//
//   .This<Type>()  Return the node content itself converted to the specified type.
//
//   .Get()         Return the specified path as a (possible nil) *Graph object.
//
//   .Get<Type>()   Return the specified path converted to the specified type.
//                  These series of functions return value and error.
//
package ogdl
<commit_msg>language error<commit_after>// Copyright 2012-2017, Rolf Veen and contributors.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package ogdl is used to process OGDL, the Ordered Graph Data Language.
//
// OGDL is a textual format to write trees or graphs of text, where
// indentation and spaces define the structure. Here is an example:
//
//    network
//      ip 192.168.1.100
//      gw 192.168.1.9
//
// The languange is simple, either in its textual representation or its
// number of productions (the specification rules), allowing for compact
// implementations.
//
// OGDL character streams are normally formed by Unicode characters, and
// encoded as UTF-8 strings, but any encoding that is ASCII transparent
// is compatible with the specification.
//
// See the full spec at http://ogdl.org.
//
// Installation
//
// To install this package just do:
//
//     go get github.com/rveen/ogdl
//
// An example
//
// If we have a text file 'config.g' containing:
//
//    eth0
//      ip
//        192.168.1.1
//      gateway
//        192.168.1.10
//      mask
//        255.255.255.0
//      timeout
//        20
//
// then,
//
//    g := ogdl.FromFile("config.g")
//    ip := g.Get("eth0.ip").String()
//    to := g.Get("eth0.timeout").Int64(60)
//
//    println("ip:",ip,", timeout:",to)
//
// will print
//
//    ip: 192.168.1.1, timeout: 20
//
// If the timeout parameter was not present, then the default value (60) will be
// assigned to 'to'. The default value is optional, but be aware that Int64() will
// return 0 in case that the parameter doesn't exist.
//
// The configuration file can be written in a conciser way:
//
//    eth0
//      ip      192.168.1.1
//      gateway 192.168.1.10
//      mask    255.255.255.0
//      timeout 20
//
// A template example
//
// The package includes a template processor. It takes an arbitrary input stream
// with some variables in it, and produces an output stream with the variables
// resolved out of a Graph object which acts as context.
//
// For example (given the previous config file):
//
//     g := ogdl.FromFile("config.g")
//     t := ogdl.NewTemplate("The gateway's IP is $eth0.gateway")
//     b := t.Process(g)
//
// string(b) is then:
//
//     The gateway's IP is 192.168.1.10
//
// Function signature conventions
//
// Some rules are followed:
//
//   .<Type>()      Return the first subnode content converted to the specified type.
//
//   .This<Type>()  Return the node content itself converted to the specified type.
//
//   .Get()         Return the specified path as a (possible nil) *Graph object.
//
//   .Get<Type>()   Return the specified path converted to the specified type.
//                  These series of functions return value and error.
//
package ogdl
<|endoftext|>


<commit_before>package goinsta // gopkg.in/ahmdrz/goinsta.v2

/*
	Goinsta is unofficial API of Instagram for Golang.
	This library provides private API methods.

	We changed the API for the comfort of the user.
	The new API is object-oriented making the programming bot task less repetitive.

	Currently the API is very complete (we did it in a week xd).
	If you see that Goinsta needs any method or any new feature you are free to open
	an issue in github.com/ahmdrz/goinsta we will work to solve your issue as soon as possible. Also you can make your own contributions. See github.com/ahmdrz/goinsta/blob/master/CONTRIBUTION.md
*/
<commit_msg>Changed doc.go file<commit_after>package goinsta // github.com/ahmdrz/goinsta

/*
	Goinsta is unofficial API of Instagram for Golang.
	This library provides private API methods.

	We changed the API for the comfort of the user.
	The new API is object-oriented making the programming bot task less repetitive.

	Currently the API is very complete (we did it in a week xd).
	If you see that Goinsta needs any method or any new feature you are free to open
	an issue in github.com/ahmdrz/goinsta we will work to solve your issue as soon as possible. Also you can make your own contributions. See github.com/ahmdrz/goinsta/blob/master/CONTRIBUTION.md
*/
<|endoftext|>


<commit_before>/*
Foo bar.

Supported versions

This library supports reading v2.3 and v2.4 tags, but only writing
v2.4 tags.

The primary reason for not allowing writing older versions is that
they cannot represent all data that is available with v2.4, and
designing the API in a way that's both user friendly and able to
reject data is not worth the trouble.

Automatic upgrading

The library's internal representation of tags matches that of v2.4.
When tags with an older version are being read, they will be
automatically converted to v2.4.

One consequence of this is that when you read a file with v2.3 tags
and immediately save it, it will now be a file with valid v2.4 tags.

The upgrade process makes the following changes to the tags:

  - TYER, TDAT and TIME get replaced by TDRC
  - TORY gets replaced by TDOR
  - XDOR gets replaced by TDOR
  - The slash as a separator for multiple values gets replaced by null bytes

One special case is the TRDA frame because there is no way to
automatically convert it to v2.4. The upgrade process will not
directly delete the frame, so that you can manually upgrade it if
desired, but it won't be written back to the file. The frame is rarely
used and insignificant, so it's not a big loss.

Accessing and manipulating frames

There are two ways to access frames: Using provided getter and setter
methods (there is one for every standard frame), and working directly
with the underlying frames.

For frames that usually support multiple values, e.g. languages, there
will be two different setters and getters: One that operates on slices
and one that operates on single values. When getting a single value,
it will return the first value from the underlying list. When setting
a single value, it will overwrite the list with a single value.

Text frames and user text frames can be manipulated with the
GetTextFrame* and SetTextFrame* class of functions. There are special
methods for working with integers, slices and times. This class of
functions expects the raw frame names (e.g. "TLEN"), with the special
case of user text frames ("TXXX") where it expects a format of the
kind "TXXX:The frame description" to address a specific user text
frame.

*/
package id3
<commit_msg>mention encodings in docs<commit_after>/*
Foo bar.

Supported versions

This library supports reading v2.3 and v2.4 tags, but only writing
v2.4 tags.

The primary reason for not allowing writing older versions is that
they cannot represent all data that is available with v2.4, and
designing the API in a way that's both user friendly and able to
reject data is not worth the trouble.

Automatic upgrading

The library's internal representation of tags matches that of v2.4.
When tags with an older version are being read, they will be
automatically converted to v2.4.

One consequence of this is that when you read a file with v2.3 tags
and immediately save it, it will now be a file with valid v2.4 tags.

The upgrade process makes the following changes to the tags:

  - TYER, TDAT and TIME get replaced by TDRC
  - TORY gets replaced by TDOR
  - XDOR gets replaced by TDOR
  - The slash as a separator for multiple values gets replaced by null bytes

One special case is the TRDA frame because there is no way to
automatically convert it to v2.4. The upgrade process will not
directly delete the frame, so that you can manually upgrade it if
desired, but it won't be written back to the file. The frame is rarely
used and insignificant, so it's not a big loss.

Accessing and manipulating frames

There are two ways to access frames: Using provided getter and setter
methods (there is one for every standard frame), and working directly
with the underlying frames.

For frames that usually support multiple values, e.g. languages, there
will be two different setters and getters: One that operates on slices
and one that operates on single values. When getting a single value,
it will return the first value from the underlying list. When setting
a single value, it will overwrite the list with a single value.

Text frames and user text frames can be manipulated with the
GetTextFrame* and SetTextFrame* class of functions. There are special
methods for working with integers, slices and times. This class of
functions expects the raw frame names (e.g. "TLEN"), with the special
case of user text frames ("TXXX") where it expects a format of the
kind "TXXX:The frame description" to address a specific user text
frame.

Encodings

While ID3v2 allows a variety of encodings (ISO-8859-1, UTF-16 and in
v2.4 also UTF-8), this library only supports writing UTF-8. When
reading frames with different encodings, they will be converted to
UTF-8.

The rationale behind this is that UTF-8 is the encoding assumed by
most of the Go standard library, and that the other encodings have no
realistic benefits over UTF-8.

*/
package id3
<|endoftext|>