<commit_before>// Copyright (c) 2016 Company 0, LLC.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package ttk

import (
	"strings"

	"github.com/nsf/termbox-go"
)

// WidgetEdit uniquely identifies the edit widget.
const (
	WidgetEdit = "edit"
)

var (
	_ Widgeter = (*Edit)(nil) // ensure interface is satisfied
)

// init registers the Edit Widget.
func init() {
	registeredWidgets[WidgetEdit] = NewEdit
}

// Edit is a text entry widget.  It prints the contents of target onto the
// window.  Note: all spaces are trimmed before and after the target string.
type Edit struct {
	Widget
	trueX      int     // actual x coordinate
	trueY      int     // actual y coordinate
	trueW      int     // actual width
	target     *string // result value of action
	display    []rune  // target as runes
	at         int     // start of displayed text
	width      int     // prefered widget width
	cx         int     // current cursor x position
	cy         int     // current cursor y position
	prevX      int     // previous window max x
	prevY      int     // previous window max y
	visibility Visibility
	attr       Attributes
}

func (e *Edit) Visibility(op Visibility) Visibility {
	switch op {
	case VisibilityGet:
		return e.visibility
	case VisibilityShow:
		e.visibility = op
		e.Render()
	case VisibilityHide:
		e.visibility = op
		e.clear()
	}

	return e.visibility
}

func (e *Edit) clear() {
	e.w.printf(e.trueX, e.trueY, defaultAttributes(), strings.Repeat(" ", e.trueW))
}

// Render implements the Render interface.  This is called from queue context
// so be careful to not use blocking calls.
func (e *Edit) Render() {
	if e.visibility == VisibilityHide {
		e.clear()
		return
	}

	filler := ""
	l := e.display[e.at:]
	if len(l) > e.trueW {
		l = e.display[e.at : e.at+e.trueW]
	} else {
		// just erase right hand side
		filler = strings.Repeat(" ", e.trueW-len(l))
	}
	e.w.printf(e.trueX, e.trueY, e.attr, "%v%v", string(l), filler)
}

func insert(slice []rune, index int, value rune) []rune {
	// Grow the slice by one element.
	slice = append(slice, value)
	// Use copy to move the upper part of the slice out of the way and open a hole.
	copy(slice[index+1:], slice[index:])
	// Store the new value.
	slice[index] = value
	// Return the result.
	return slice
}

// KeyHandler implements the interface.  This is called from queue context
// so be careful to not use blocking calls.
func (e *Edit) KeyHandler(ev termbox.Event) bool {
	var inString int

	switch ev.Key {
	case termbox.KeyCtrlA, termbox.KeyHome:
		e.cx = e.trueX
		e.at = 0
		setCursor(e.cx, e.cy)
		e.Render()
		return true
	case termbox.KeyCtrlE, termbox.KeyEnd:
		if len(e.display) < e.trueW-1 {
			// no need to call display
			e.cx = e.trueX + len(e.display) - e.at
			setCursor(e.cx, e.cy)
			return true
		}
		e.cx = e.trueX + e.trueW - 1
		e.at = len(e.display) - e.trueW + 1
		setCursor(e.cx, e.cy)
		e.Render()
		return true
	case termbox.KeyArrowRight:
		// check to see if we have content on the right hand side
		if e.cx-e.trueX == len(e.display[e.at:]) {
			return true
		}
		e.cx++
		if e.cx > e.trueW+e.trueX-1 {
			e.cx = e.trueW + e.trueX - 1

			// check for end of string before moving at
			if len(e.display[e.at:]) == 0 {
				return true
			}
			e.at++
			e.Render()
			return true
		}
		setCursor(e.cx, e.cy)
		return true
	case termbox.KeyArrowLeft:
		e.cx--
		if e.cx < e.trueX {
			e.cx = e.trueX
			e.at--
			if e.at < 0 {
				e.at = 0
			}
			e.Render()
		}
		setCursor(e.cx, e.cy)
		return true
	case termbox.KeyDelete:
		inString = e.cx - e.trueX + e.at
		if len(e.display) == inString {
			return true
		}
		// remove from slice
		e.display = append(e.display[:inString],
			e.display[inString+1:]...)
		e.Render()
		return true
	case termbox.KeyBackspace, termbox.KeyBackspace2:
		inString = e.cx - e.trueX + e.at
		if inString <= 0 {
			return true
		}
		e.display = append(e.display[:inString-1],
			e.display[inString:]...)

		// cursor left magic
		if e.cx == e.trueX+1 {
			if e.at > e.trueW-1 {
				e.cx = e.trueW - 1
			} else {
				e.cx = e.at
			}
			e.at -= e.cx
		} else {
			e.cx--
		}
		setCursor(e.cx, e.cy)
		e.Render()
		return true
	case termbox.KeySpace:
		// use space
		ev.Ch = ' '
	case termbox.KeyEnter:
		*e.target = string(e.display)
		// return false and let the application decide if it wants
		// to consume the action
		return false
	}

	// normal runes are displayed and stored
	if ev.Ch != 0 && ev.Mod != 0 && ev.Key == 0 {
		// forward special
		return false
	} else if ev.Ch == 0 {
		return false
	}

	inString = e.cx - e.trueX + e.at
	e.display = insert(e.display, inString, ev.Ch)
	if e.cx < e.trueW+e.trueX-1 {
		e.cx++
		setCursor(e.cx, e.cy)
	} else {
		e.at++
	}

	e.Render()
	return true
}

// CanFocus implements the interface.  This is called from queue context
// so be careful to not use blocking calls.
func (e *Edit) CanFocus() bool {
	return true // can focus
}

// Focus implements the interface.  This is called from queue context
// so be careful to not use blocking calls.
func (e *Edit) Focus() {
	if e.cx == -1 || e.cy == -1 {
		// || is deliberate to handle "just in case"
		e.cx = e.trueX
		e.cy = e.trueY
		e.at = 0
	}
	setCursor(e.cx, e.cy)
}

// NewEdit is the Edit initializer.  This call implements the NewWidget
// convention by taking a *Window and and an anchor point to render the widget.
func NewEdit(w *Window, x, y int) (Widgeter, error) {
	return &Edit{
		Widget: MakeWidget(w, x, y),
	}, nil
}

// SetAttributes sets the Attributes.  This will not be displayed immediately.
// SetAttributes shall be called from queue context.
func (e *Edit) SetAttributes(a Attributes) {
	e.attr = a
}

// GetText returns the edit text.
// GetText shall be called from queue context.
func (e *Edit) GetText() string {
	return string(e.display)
}

// SetText sets the edit text.  if end is set to true the cursor and text will
// be set to the end of the string.  This will not be displayed immediately.
// SetText shall be called from queue context.
func (e *Edit) SetText(s *string, end bool) {
	e.target = s
	e.display = []rune(*s)
	e.at = 0

	// send synthesized key to position cursor and text
	ev := termbox.Event{}
	if end {
		ev.Key = termbox.KeyCtrlE
	} else {
		ev.Key = termbox.KeyCtrlA
	}
	e.KeyHandler(ev)
}

func (e *Edit) Resize() {
	inString := e.cx - e.trueX + e.at
	e.trueX = e.x
	e.trueY = e.y
	e.trueW = e.width

	// y<0 is relative to bottom line
	if e.y < 0 {
		e.trueY = e.w.y + e.y + 1
	}

	// e.width <1 means -width from right hand side
	if e.width < 1 {
		e.trueW = e.w.x - e.x + e.width
	}

	// reset cursor and at
	if e.w.y != e.prevY {
		e.cy = e.trueY
		e.prevY = e.w.y
	}
	if e.w.x != e.prevX {
		switch {
		case len(e.display) == inString:
			// end of text
			if len(e.display) < e.trueW-1 {
				e.cx = e.trueX + len(e.display)
				e.at = 0
			} else {
				e.cx = e.trueX + e.trueW - 1
				e.at = len(e.display) - e.trueW + 1
			}
		case inString <= 0:
			// begin of text
			e.at = 0
			e.cx = e.trueX
		default:
			// middle of text
			if e.prevX <= e.w.x {
				// do nothing since x grew
			} else {
				// shift location of at based on shrinkage
				if e.cx >= e.w.x {
					e.cx -= e.prevX - e.w.x
					e.at += e.prevX - e.w.x
				}
			}
		}
		e.prevX = e.w.x
	}
}

// AddEdit is a convenience function to add a new edit to a window.  Capacity
// and width determine the maxima of the returned value.  It wraps the
// AddWidget call.  AddEdit must be called from queue.
func (w *Window) AddEdit(x, y, width int, target *string) *Edit {
	// we can ignore error for builtins
	e, _ := w.AddWidget(WidgetEdit, x, y)
	edit := e.(*Edit)
	edit.width = width

	// save current sizes to detect actual window resizes
	edit.prevX = w.x
	edit.prevY = w.y

	edit.Resize()

	// cursor
	edit.cx = -1
	edit.cy = -1

	// set target string
	edit.SetText(target, true)

	// flip attributes
	a := defaultAttributes()
	a2 := Attributes{
		Fg: a.Bg,
		Bg: a.Fg,
	}
	edit.SetAttributes(a2)

	return edit
}
<commit_msg>handle ^u (#16)<commit_after>// Copyright (c) 2016 Company 0, LLC.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package ttk

import (
	"strings"

	"github.com/nsf/termbox-go"
)

// WidgetEdit uniquely identifies the edit widget.
const (
	WidgetEdit = "edit"
)

var (
	_ Widgeter = (*Edit)(nil) // ensure interface is satisfied
)

// init registers the Edit Widget.
func init() {
	registeredWidgets[WidgetEdit] = NewEdit
}

// Edit is a text entry widget.  It prints the contents of target onto the
// window.  Note: all spaces are trimmed before and after the target string.
type Edit struct {
	Widget
	trueX      int     // actual x coordinate
	trueY      int     // actual y coordinate
	trueW      int     // actual width
	target     *string // result value of action
	display    []rune  // target as runes
	at         int     // start of displayed text
	width      int     // prefered widget width
	cx         int     // current cursor x position
	cy         int     // current cursor y position
	prevX      int     // previous window max x
	prevY      int     // previous window max y
	visibility Visibility
	attr       Attributes
}

func (e *Edit) Visibility(op Visibility) Visibility {
	switch op {
	case VisibilityGet:
		return e.visibility
	case VisibilityShow:
		e.visibility = op
		e.Render()
	case VisibilityHide:
		e.visibility = op
		e.clear()
	}

	return e.visibility
}

func (e *Edit) clear() {
	e.w.printf(e.trueX, e.trueY, defaultAttributes(), strings.Repeat(" ", e.trueW))
}

// Render implements the Render interface.  This is called from queue context
// so be careful to not use blocking calls.
func (e *Edit) Render() {
	if e.visibility == VisibilityHide {
		e.clear()
		return
	}

	filler := ""
	l := e.display[e.at:]
	if len(l) > e.trueW {
		l = e.display[e.at : e.at+e.trueW]
	} else {
		// just erase right hand side
		filler = strings.Repeat(" ", e.trueW-len(l))
	}
	e.w.printf(e.trueX, e.trueY, e.attr, "%v%v", string(l), filler)
}

func insert(slice []rune, index int, value rune) []rune {
	// Grow the slice by one element.
	slice = append(slice, value)
	// Use copy to move the upper part of the slice out of the way and open a hole.
	copy(slice[index+1:], slice[index:])
	// Store the new value.
	slice[index] = value
	// Return the result.
	return slice
}

// KeyHandler implements the interface.  This is called from queue context
// so be careful to not use blocking calls.
func (e *Edit) KeyHandler(ev termbox.Event) bool {
	var inString int

	switch ev.Key {
	case termbox.KeyCtrlA, termbox.KeyHome:
		e.cx = e.trueX
		e.at = 0
		setCursor(e.cx, e.cy)
		e.Render()
		return true
	case termbox.KeyCtrlE, termbox.KeyEnd:
		if len(e.display) < e.trueW-1 {
			// no need to call display
			e.cx = e.trueX + len(e.display) - e.at
			setCursor(e.cx, e.cy)
			return true
		}
		e.cx = e.trueX + e.trueW - 1
		e.at = len(e.display) - e.trueW + 1
		setCursor(e.cx, e.cy)
		e.Render()
		return true
	case termbox.KeyCtrlU:
		e.cx = e.trueX
		e.at = 0
		e.display = []rune("")
		setCursor(e.cx, e.cy)
		e.Render()
		return true
	case termbox.KeyArrowRight:
		// check to see if we have content on the right hand side
		if e.cx-e.trueX == len(e.display[e.at:]) {
			return true
		}
		e.cx++
		if e.cx > e.trueW+e.trueX-1 {
			e.cx = e.trueW + e.trueX - 1

			// check for end of string before moving at
			if len(e.display[e.at:]) == 0 {
				return true
			}
			e.at++
			e.Render()
			return true
		}
		setCursor(e.cx, e.cy)
		return true
	case termbox.KeyArrowLeft:
		e.cx--
		if e.cx < e.trueX {
			e.cx = e.trueX
			e.at--
			if e.at < 0 {
				e.at = 0
			}
			e.Render()
		}
		setCursor(e.cx, e.cy)
		return true
	case termbox.KeyDelete:
		inString = e.cx - e.trueX + e.at
		if len(e.display) == inString {
			return true
		}
		// remove from slice
		e.display = append(e.display[:inString],
			e.display[inString+1:]...)
		e.Render()
		return true
	case termbox.KeyBackspace, termbox.KeyBackspace2:
		inString = e.cx - e.trueX + e.at
		if inString <= 0 {
			return true
		}
		e.display = append(e.display[:inString-1],
			e.display[inString:]...)

		// cursor left magic
		if e.cx == e.trueX+1 {
			if e.at > e.trueW-1 {
				e.cx = e.trueW - 1
			} else {
				e.cx = e.at
			}
			e.at -= e.cx
		} else {
			e.cx--
		}
		setCursor(e.cx, e.cy)
		e.Render()
		return true
	case termbox.KeySpace:
		// use space
		ev.Ch = ' '
	case termbox.KeyEnter:
		*e.target = string(e.display)
		// return false and let the application decide if it wants
		// to consume the action
		return false
	}

	// normal runes are displayed and stored
	if ev.Ch != 0 && ev.Mod != 0 && ev.Key == 0 {
		// forward special
		return false
	} else if ev.Ch == 0 {
		return false
	}

	inString = e.cx - e.trueX + e.at
	e.display = insert(e.display, inString, ev.Ch)
	if e.cx < e.trueW+e.trueX-1 {
		e.cx++
		setCursor(e.cx, e.cy)
	} else {
		e.at++
	}

	e.Render()
	return true
}

// CanFocus implements the interface.  This is called from queue context
// so be careful to not use blocking calls.
func (e *Edit) CanFocus() bool {
	return true // can focus
}

// Focus implements the interface.  This is called from queue context
// so be careful to not use blocking calls.
func (e *Edit) Focus() {
	if e.cx == -1 || e.cy == -1 {
		// || is deliberate to handle "just in case"
		e.cx = e.trueX
		e.cy = e.trueY
		e.at = 0
	}
	setCursor(e.cx, e.cy)
}

// NewEdit is the Edit initializer.  This call implements the NewWidget
// convention by taking a *Window and and an anchor point to render the widget.
func NewEdit(w *Window, x, y int) (Widgeter, error) {
	return &Edit{
		Widget: MakeWidget(w, x, y),
	}, nil
}

// SetAttributes sets the Attributes.  This will not be displayed immediately.
// SetAttributes shall be called from queue context.
func (e *Edit) SetAttributes(a Attributes) {
	e.attr = a
}

// GetText returns the edit text.
// GetText shall be called from queue context.
func (e *Edit) GetText() string {
	return string(e.display)
}

// SetText sets the edit text.  if end is set to true the cursor and text will
// be set to the end of the string.  This will not be displayed immediately.
// SetText shall be called from queue context.
func (e *Edit) SetText(s *string, end bool) {
	e.target = s
	e.display = []rune(*s)
	e.at = 0

	// send synthesized key to position cursor and text
	ev := termbox.Event{}
	if end {
		ev.Key = termbox.KeyCtrlE
	} else {
		ev.Key = termbox.KeyCtrlA
	}
	e.KeyHandler(ev)
}

func (e *Edit) Resize() {
	inString := e.cx - e.trueX + e.at
	e.trueX = e.x
	e.trueY = e.y
	e.trueW = e.width

	// y<0 is relative to bottom line
	if e.y < 0 {
		e.trueY = e.w.y + e.y + 1
	}

	// e.width <1 means -width from right hand side
	if e.width < 1 {
		e.trueW = e.w.x - e.x + e.width
	}

	// reset cursor and at
	if e.w.y != e.prevY {
		e.cy = e.trueY
		e.prevY = e.w.y
	}
	if e.w.x != e.prevX {
		switch {
		case len(e.display) == inString:
			// end of text
			if len(e.display) < e.trueW-1 {
				e.cx = e.trueX + len(e.display)
				e.at = 0
			} else {
				e.cx = e.trueX + e.trueW - 1
				e.at = len(e.display) - e.trueW + 1
			}
		case inString <= 0:
			// begin of text
			e.at = 0
			e.cx = e.trueX
		default:
			// middle of text
			if e.prevX <= e.w.x {
				// do nothing since x grew
			} else {
				// shift location of at based on shrinkage
				if e.cx >= e.w.x {
					e.cx -= e.prevX - e.w.x
					e.at += e.prevX - e.w.x
				}
			}
		}
		e.prevX = e.w.x
	}
}

// AddEdit is a convenience function to add a new edit to a window.  Capacity
// and width determine the maxima of the returned value.  It wraps the
// AddWidget call.  AddEdit must be called from queue.
func (w *Window) AddEdit(x, y, width int, target *string) *Edit {
	// we can ignore error for builtins
	e, _ := w.AddWidget(WidgetEdit, x, y)
	edit := e.(*Edit)
	edit.width = width

	// save current sizes to detect actual window resizes
	edit.prevX = w.x
	edit.prevY = w.y

	edit.Resize()

	// cursor
	edit.cx = -1
	edit.cy = -1

	// set target string
	edit.SetText(target, true)

	// flip attributes
	a := defaultAttributes()
	a2 := Attributes{
		Fg: a.Bg,
		Bg: a.Fg,
	}
	edit.SetAttributes(a2)

	return edit
}
<|endoftext|>


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

package ssh

import (
	"bytes"
	"errors"
	"fmt"
	"io"
)

// clientAuthenticate authenticates with the remote server. See RFC 4252.
func (c *connection) clientAuthenticate(config *ClientConfig) error {
	// initiate user auth session
	if err := c.transport.writePacket(Marshal(&serviceRequestMsg{serviceUserAuth})); err != nil {
		return err
	}
	packet, err := c.transport.readPacket()
	if err != nil {
		return err
	}
	var serviceAccept serviceAcceptMsg
	if err := Unmarshal(packet, &serviceAccept); err != nil {
		return err
	}

	// during the authentication phase the client first attempts the "none" method
	// then any untried methods suggested by the server.
	tried := make(map[string]bool)
	for auth := AuthMethod(new(noneAuth)); auth != nil; {
		ok, methods, err := auth.auth(c.transport.getSessionID(), config.User, c.transport, config.Rand)
		if err != nil {
			return err
		}
		if ok {
			// success
			return nil
		}
		tried[auth.method()] = true

		auth = nil

	findNext:
		for _, a := range config.Auth {
			candidateMethod := a.method()
			if tried[candidateMethod] {
				continue
			}
			for _, meth := range methods {
				if meth == candidateMethod {
					auth = a
					break findNext
				}
			}
		}
	}
	return fmt.Errorf("ssh: unable to authenticate, attempted methods %v, no supported methods remain", keys(tried))
}

func keys(m map[string]bool) []string {
	s := make([]string, 0, len(m))

	for key := range m {
		s = append(s, key)
	}
	return s
}

// An AuthMethod represents an instance of an RFC 4252 authentication method.
type AuthMethod interface {
	// auth authenticates user over transport t.
	// Returns true if authentication is successful.
	// If authentication is not successful, a []string of alternative
	// method names is returned.
	auth(session []byte, user string, p packetConn, rand io.Reader) (bool, []string, error)

	// method returns the RFC 4252 method name.
	method() string
}

// "none" authentication, RFC 4252 section 5.2.
type noneAuth int

func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
	if err := c.writePacket(Marshal(&userAuthRequestMsg{
		User:    user,
		Service: serviceSSH,
		Method:  "none",
	})); err != nil {
		return false, nil, err
	}

	return handleAuthResponse(c)
}

func (n *noneAuth) method() string {
	return "none"
}

// passwordCallback is an AuthMethod that fetches the password through
// a function call, e.g. by prompting the user.
type passwordCallback func() (password string, err error)

func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
	type passwordAuthMsg struct {
		User     string `sshtype:"50"`
		Service  string
		Method   string
		Reply    bool
		Password string
	}

	pw, err := cb()
	// REVIEW NOTE: is there a need to support skipping a password attempt?
	// The program may only find out that the user doesn't have a password
	// when prompting.
	if err != nil {
		return false, nil, err
	}

	if err := c.writePacket(Marshal(&passwordAuthMsg{
		User:     user,
		Service:  serviceSSH,
		Method:   cb.method(),
		Reply:    false,
		Password: pw,
	})); err != nil {
		return false, nil, err
	}

	return handleAuthResponse(c)
}

func (cb passwordCallback) method() string {
	return "password"
}

// Password returns an AuthMethod using the given password.
func Password(secret string) AuthMethod {
	return passwordCallback(func() (string, error) { return secret, nil })
}

// PasswordCallback returns an AuthMethod that uses a callback for
// fetching a password.
func PasswordCallback(prompt func() (secret string, err error)) AuthMethod {
	return passwordCallback(prompt)
}

type publickeyAuthMsg struct {
	User    string `sshtype:"50"`
	Service string
	Method  string
	// HasSig indicates to the receiver packet that the auth request is signed and
	// should be used for authentication of the request.
	HasSig   bool
	Algoname string
	PubKey   []byte
	// Sig is tagged with "rest" so Marshal will exclude it during
	// validateKey
	Sig []byte `ssh:"rest"`
}

// publicKeyCallback is an AuthMethod that uses a set of key
// pairs for authentication.
type publicKeyCallback func() ([]Signer, error)

func (cb publicKeyCallback) method() string {
	return "publickey"
}

func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
	// Authentication is performed in two stages. The first stage sends an
	// enquiry to test if each key is acceptable to the remote. The second
	// stage attempts to authenticate with the valid keys obtained in the
	// first stage.

	signers, err := cb()
	if err != nil {
		return false, nil, err
	}
	var validKeys []Signer
	for _, signer := range signers {
		if ok, err := validateKey(signer.PublicKey(), user, c); ok {
			validKeys = append(validKeys, signer)
		} else {
			if err != nil {
				return false, nil, err
			}
		}
	}

	// methods that may continue if this auth is not successful.
	var methods []string
	for _, signer := range validKeys {
		pub := signer.PublicKey()

		pubKey := pub.Marshal()
		sign, err := signer.Sign(rand, buildDataSignedForAuth(session, userAuthRequestMsg{
			User:    user,
			Service: serviceSSH,
			Method:  cb.method(),
		}, []byte(pub.Type()), pubKey))
		if err != nil {
			return false, nil, err
		}

		// manually wrap the serialized signature in a string
		s := Marshal(sign)
		sig := make([]byte, stringLength(len(s)))
		marshalString(sig, s)
		msg := publickeyAuthMsg{
			User:     user,
			Service:  serviceSSH,
			Method:   cb.method(),
			HasSig:   true,
			Algoname: pub.Type(),
			PubKey:   pubKey,
			Sig:      sig,
		}
		p := Marshal(&msg)
		if err := c.writePacket(p); err != nil {
			return false, nil, err
		}
		success, methods, err := handleAuthResponse(c)
		if err != nil {
			return false, nil, err
		}
		if success {
			return success, methods, err
		}
	}
	return false, methods, nil
}

// validateKey validates the key provided is acceptable to the server.
func validateKey(key PublicKey, user string, c packetConn) (bool, error) {
	pubKey := key.Marshal()
	msg := publickeyAuthMsg{
		User:     user,
		Service:  serviceSSH,
		Method:   "publickey",
		HasSig:   false,
		Algoname: key.Type(),
		PubKey:   pubKey,
	}
	if err := c.writePacket(Marshal(&msg)); err != nil {
		return false, err
	}

	return confirmKeyAck(key, c)
}

func confirmKeyAck(key PublicKey, c packetConn) (bool, error) {
	pubKey := key.Marshal()
	algoname := key.Type()

	for {
		packet, err := c.readPacket()
		if err != nil {
			return false, err
		}
		switch packet[0] {
		case msgUserAuthBanner:
			// TODO(gpaul): add callback to present the banner to the user
		case msgUserAuthPubKeyOk:
			var msg userAuthPubKeyOkMsg
			if err := Unmarshal(packet, &msg); err != nil {
				return false, err
			}
			if msg.Algo != algoname || !bytes.Equal(msg.PubKey, pubKey) {
				return false, nil
			}
			return true, nil
		case msgUserAuthFailure:
			return false, nil
		default:
			return false, unexpectedMessageError(msgUserAuthSuccess, packet[0])
		}
	}
}

// PublicKeys returns an AuthMethod that uses the given key
// pairs.
func PublicKeys(signers ...Signer) AuthMethod {
	return publicKeyCallback(func() ([]Signer, error) { return signers, nil })
}

// PublicKeysCallback returns an AuthMethod that runs the given
// function to obtain a list of key pairs.
func PublicKeysCallback(getSigners func() (signers []Signer, err error)) AuthMethod {
	return publicKeyCallback(getSigners)
}

// handleAuthResponse returns whether the preceding authentication request succeeded
// along with a list of remaining authentication methods to try next and
// an error if an unexpected response was received.
func handleAuthResponse(c packetConn) (bool, []string, error) {
	for {
		packet, err := c.readPacket()
		if err != nil {
			return false, nil, err
		}

		switch packet[0] {
		case msgUserAuthBanner:
			// TODO: add callback to present the banner to the user
		case msgUserAuthFailure:
			var msg userAuthFailureMsg
			if err := Unmarshal(packet, &msg); err != nil {
				return false, nil, err
			}
			return false, msg.Methods, nil
		case msgUserAuthSuccess:
			return true, nil, nil
		case msgDisconnect:
			return false, nil, io.EOF
		default:
			return false, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0])
		}
	}
}

// KeyboardInteractiveChallenge should print questions, optionally
// disabling echoing (e.g. for passwords), and return all the answers.
// Challenge may be called multiple times in a single session. After
// successful authentication, the server may send a challenge with no
// questions, for which the user and instruction messages should be
// printed.  RFC 4256 section 3.3 details how the UI should behave for
// both CLI and GUI environments.
type KeyboardInteractiveChallenge func(user, instruction string, questions []string, echos []bool) (answers []string, err error)

// KeyboardInteractive returns a AuthMethod using a prompt/response
// sequence controlled by the server.
func KeyboardInteractive(challenge KeyboardInteractiveChallenge) AuthMethod {
	return challenge
}

func (cb KeyboardInteractiveChallenge) method() string {
	return "keyboard-interactive"
}

func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
	type initiateMsg struct {
		User       string `sshtype:"50"`
		Service    string
		Method     string
		Language   string
		Submethods string
	}

	if err := c.writePacket(Marshal(&initiateMsg{
		User:    user,
		Service: serviceSSH,
		Method:  "keyboard-interactive",
	})); err != nil {
		return false, nil, err
	}

	for {
		packet, err := c.readPacket()
		if err != nil {
			return false, nil, err
		}

		// like handleAuthResponse, but with less options.
		switch packet[0] {
		case msgUserAuthBanner:
			// TODO: Print banners during userauth.
			continue
		case msgUserAuthInfoRequest:
			// OK
		case msgUserAuthFailure:
			var msg userAuthFailureMsg
			if err := Unmarshal(packet, &msg); err != nil {
				return false, nil, err
			}
			return false, msg.Methods, nil
		case msgUserAuthSuccess:
			return true, nil, nil
		default:
			return false, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0])
		}

		var msg userAuthInfoRequestMsg
		if err := Unmarshal(packet, &msg); err != nil {
			return false, nil, err
		}

		// Manually unpack the prompt/echo pairs.
		rest := msg.Prompts
		var prompts []string
		var echos []bool
		for i := 0; i < int(msg.NumPrompts); i++ {
			prompt, r, ok := parseString(rest)
			if !ok || len(r) == 0 {
				return false, nil, errors.New("ssh: prompt format error")
			}
			prompts = append(prompts, string(prompt))
			echos = append(echos, r[0] != 0)
			rest = r[1:]
		}

		if len(rest) != 0 {
			return false, nil, errors.New("ssh: extra data following keyboard-interactive pairs")
		}

		answers, err := cb(msg.User, msg.Instruction, prompts, echos)
		if err != nil {
			return false, nil, err
		}

		if len(answers) != len(prompts) {
			return false, nil, errors.New("ssh: not enough answers from keyboard-interactive callback")
		}
		responseLength := 1 + 4
		for _, a := range answers {
			responseLength += stringLength(len(a))
		}
		serialized := make([]byte, responseLength)
		p := serialized
		p[0] = msgUserAuthInfoResponse
		p = p[1:]
		p = marshalUint32(p, uint32(len(answers)))
		for _, a := range answers {
			p = marshalString(p, []byte(a))
		}

		if err := c.writePacket(serialized); err != nil {
			return false, nil, err
		}
	}
}
<commit_msg>go.crypto/ssh: fix authentication after all public keys are rejected by a server.<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package ssh

import (
	"bytes"
	"errors"
	"fmt"
	"io"
)

// clientAuthenticate authenticates with the remote server. See RFC 4252.
func (c *connection) clientAuthenticate(config *ClientConfig) error {
	// initiate user auth session
	if err := c.transport.writePacket(Marshal(&serviceRequestMsg{serviceUserAuth})); err != nil {
		return err
	}
	packet, err := c.transport.readPacket()
	if err != nil {
		return err
	}
	var serviceAccept serviceAcceptMsg
	if err := Unmarshal(packet, &serviceAccept); err != nil {
		return err
	}

	// during the authentication phase the client first attempts the "none" method
	// then any untried methods suggested by the server.
	tried := make(map[string]bool)
	var lastMethods []string
	for auth := AuthMethod(new(noneAuth)); auth != nil; {
		ok, methods, err := auth.auth(c.transport.getSessionID(), config.User, c.transport, config.Rand)
		if err != nil {
			return err
		}
		if ok {
			// success
			return nil
		}
		tried[auth.method()] = true
		if methods == nil {
			methods = lastMethods
		}
		lastMethods = methods

		auth = nil

	findNext:
		for _, a := range config.Auth {
			candidateMethod := a.method()
			if tried[candidateMethod] {
				continue
			}
			for _, meth := range methods {
				if meth == candidateMethod {
					auth = a
					break findNext
				}
			}
		}
	}
	return fmt.Errorf("ssh: unable to authenticate, attempted methods %v, no supported methods remain", keys(tried))
}

func keys(m map[string]bool) []string {
	s := make([]string, 0, len(m))

	for key := range m {
		s = append(s, key)
	}
	return s
}

// An AuthMethod represents an instance of an RFC 4252 authentication method.
type AuthMethod interface {
	// auth authenticates user over transport t.
	// Returns true if authentication is successful.
	// If authentication is not successful, a []string of alternative
	// method names is returned. If the slice is nil, it will be ignored
	// and the previous set of possible methods will be reused.
	auth(session []byte, user string, p packetConn, rand io.Reader) (bool, []string, error)

	// method returns the RFC 4252 method name.
	method() string
}

// "none" authentication, RFC 4252 section 5.2.
type noneAuth int

func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
	if err := c.writePacket(Marshal(&userAuthRequestMsg{
		User:    user,
		Service: serviceSSH,
		Method:  "none",
	})); err != nil {
		return false, nil, err
	}

	return handleAuthResponse(c)
}

func (n *noneAuth) method() string {
	return "none"
}

// passwordCallback is an AuthMethod that fetches the password through
// a function call, e.g. by prompting the user.
type passwordCallback func() (password string, err error)

func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
	type passwordAuthMsg struct {
		User     string `sshtype:"50"`
		Service  string
		Method   string
		Reply    bool
		Password string
	}

	pw, err := cb()
	// REVIEW NOTE: is there a need to support skipping a password attempt?
	// The program may only find out that the user doesn't have a password
	// when prompting.
	if err != nil {
		return false, nil, err
	}

	if err := c.writePacket(Marshal(&passwordAuthMsg{
		User:     user,
		Service:  serviceSSH,
		Method:   cb.method(),
		Reply:    false,
		Password: pw,
	})); err != nil {
		return false, nil, err
	}

	return handleAuthResponse(c)
}

func (cb passwordCallback) method() string {
	return "password"
}

// Password returns an AuthMethod using the given password.
func Password(secret string) AuthMethod {
	return passwordCallback(func() (string, error) { return secret, nil })
}

// PasswordCallback returns an AuthMethod that uses a callback for
// fetching a password.
func PasswordCallback(prompt func() (secret string, err error)) AuthMethod {
	return passwordCallback(prompt)
}

type publickeyAuthMsg struct {
	User    string `sshtype:"50"`
	Service string
	Method  string
	// HasSig indicates to the receiver packet that the auth request is signed and
	// should be used for authentication of the request.
	HasSig   bool
	Algoname string
	PubKey   []byte
	// Sig is tagged with "rest" so Marshal will exclude it during
	// validateKey
	Sig []byte `ssh:"rest"`
}

// publicKeyCallback is an AuthMethod that uses a set of key
// pairs for authentication.
type publicKeyCallback func() ([]Signer, error)

func (cb publicKeyCallback) method() string {
	return "publickey"
}

func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
	// Authentication is performed in two stages. The first stage sends an
	// enquiry to test if each key is acceptable to the remote. The second
	// stage attempts to authenticate with the valid keys obtained in the
	// first stage.

	signers, err := cb()
	if err != nil {
		return false, nil, err
	}
	var validKeys []Signer
	for _, signer := range signers {
		if ok, err := validateKey(signer.PublicKey(), user, c); ok {
			validKeys = append(validKeys, signer)
		} else {
			if err != nil {
				return false, nil, err
			}
		}
	}

	// methods that may continue if this auth is not successful.
	var methods []string
	for _, signer := range validKeys {
		pub := signer.PublicKey()

		pubKey := pub.Marshal()
		sign, err := signer.Sign(rand, buildDataSignedForAuth(session, userAuthRequestMsg{
			User:    user,
			Service: serviceSSH,
			Method:  cb.method(),
		}, []byte(pub.Type()), pubKey))
		if err != nil {
			return false, nil, err
		}

		// manually wrap the serialized signature in a string
		s := Marshal(sign)
		sig := make([]byte, stringLength(len(s)))
		marshalString(sig, s)
		msg := publickeyAuthMsg{
			User:     user,
			Service:  serviceSSH,
			Method:   cb.method(),
			HasSig:   true,
			Algoname: pub.Type(),
			PubKey:   pubKey,
			Sig:      sig,
		}
		p := Marshal(&msg)
		if err := c.writePacket(p); err != nil {
			return false, nil, err
		}
		var success bool
		success, methods, err = handleAuthResponse(c)
		if err != nil {
			return false, nil, err
		}
		if success {
			return success, methods, err
		}
	}
	return false, methods, nil
}

// validateKey validates the key provided is acceptable to the server.
func validateKey(key PublicKey, user string, c packetConn) (bool, error) {
	pubKey := key.Marshal()
	msg := publickeyAuthMsg{
		User:     user,
		Service:  serviceSSH,
		Method:   "publickey",
		HasSig:   false,
		Algoname: key.Type(),
		PubKey:   pubKey,
	}
	if err := c.writePacket(Marshal(&msg)); err != nil {
		return false, err
	}

	return confirmKeyAck(key, c)
}

func confirmKeyAck(key PublicKey, c packetConn) (bool, error) {
	pubKey := key.Marshal()
	algoname := key.Type()

	for {
		packet, err := c.readPacket()
		if err != nil {
			return false, err
		}
		switch packet[0] {
		case msgUserAuthBanner:
			// TODO(gpaul): add callback to present the banner to the user
		case msgUserAuthPubKeyOk:
			var msg userAuthPubKeyOkMsg
			if err := Unmarshal(packet, &msg); err != nil {
				return false, err
			}
			if msg.Algo != algoname || !bytes.Equal(msg.PubKey, pubKey) {
				return false, nil
			}
			return true, nil
		case msgUserAuthFailure:
			return false, nil
		default:
			return false, unexpectedMessageError(msgUserAuthSuccess, packet[0])
		}
	}
}

// PublicKeys returns an AuthMethod that uses the given key
// pairs.
func PublicKeys(signers ...Signer) AuthMethod {
	return publicKeyCallback(func() ([]Signer, error) { return signers, nil })
}

// PublicKeysCallback returns an AuthMethod that runs the given
// function to obtain a list of key pairs.
func PublicKeysCallback(getSigners func() (signers []Signer, err error)) AuthMethod {
	return publicKeyCallback(getSigners)
}

// handleAuthResponse returns whether the preceding authentication request succeeded
// along with a list of remaining authentication methods to try next and
// an error if an unexpected response was received.
func handleAuthResponse(c packetConn) (bool, []string, error) {
	for {
		packet, err := c.readPacket()
		if err != nil {
			return false, nil, err
		}

		switch packet[0] {
		case msgUserAuthBanner:
			// TODO: add callback to present the banner to the user
		case msgUserAuthFailure:
			var msg userAuthFailureMsg
			if err := Unmarshal(packet, &msg); err != nil {
				return false, nil, err
			}
			return false, msg.Methods, nil
		case msgUserAuthSuccess:
			return true, nil, nil
		case msgDisconnect:
			return false, nil, io.EOF
		default:
			return false, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0])
		}
	}
}

// KeyboardInteractiveChallenge should print questions, optionally
// disabling echoing (e.g. for passwords), and return all the answers.
// Challenge may be called multiple times in a single session. After
// successful authentication, the server may send a challenge with no
// questions, for which the user and instruction messages should be
// printed.  RFC 4256 section 3.3 details how the UI should behave for
// both CLI and GUI environments.
type KeyboardInteractiveChallenge func(user, instruction string, questions []string, echos []bool) (answers []string, err error)

// KeyboardInteractive returns a AuthMethod using a prompt/response
// sequence controlled by the server.
func KeyboardInteractive(challenge KeyboardInteractiveChallenge) AuthMethod {
	return challenge
}

func (cb KeyboardInteractiveChallenge) method() string {
	return "keyboard-interactive"
}

func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
	type initiateMsg struct {
		User       string `sshtype:"50"`
		Service    string
		Method     string
		Language   string
		Submethods string
	}

	if err := c.writePacket(Marshal(&initiateMsg{
		User:    user,
		Service: serviceSSH,
		Method:  "keyboard-interactive",
	})); err != nil {
		return false, nil, err
	}

	for {
		packet, err := c.readPacket()
		if err != nil {
			return false, nil, err
		}

		// like handleAuthResponse, but with less options.
		switch packet[0] {
		case msgUserAuthBanner:
			// TODO: Print banners during userauth.
			continue
		case msgUserAuthInfoRequest:
			// OK
		case msgUserAuthFailure:
			var msg userAuthFailureMsg
			if err := Unmarshal(packet, &msg); err != nil {
				return false, nil, err
			}
			return false, msg.Methods, nil
		case msgUserAuthSuccess:
			return true, nil, nil
		default:
			return false, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0])
		}

		var msg userAuthInfoRequestMsg
		if err := Unmarshal(packet, &msg); err != nil {
			return false, nil, err
		}

		// Manually unpack the prompt/echo pairs.
		rest := msg.Prompts
		var prompts []string
		var echos []bool
		for i := 0; i < int(msg.NumPrompts); i++ {
			prompt, r, ok := parseString(rest)
			if !ok || len(r) == 0 {
				return false, nil, errors.New("ssh: prompt format error")
			}
			prompts = append(prompts, string(prompt))
			echos = append(echos, r[0] != 0)
			rest = r[1:]
		}

		if len(rest) != 0 {
			return false, nil, errors.New("ssh: extra data following keyboard-interactive pairs")
		}

		answers, err := cb(msg.User, msg.Instruction, prompts, echos)
		if err != nil {
			return false, nil, err
		}

		if len(answers) != len(prompts) {
			return false, nil, errors.New("ssh: not enough answers from keyboard-interactive callback")
		}
		responseLength := 1 + 4
		for _, a := range answers {
			responseLength += stringLength(len(a))
		}
		serialized := make([]byte, responseLength)
		p := serialized
		p[0] = msgUserAuthInfoResponse
		p = p[1:]
		p = marshalUint32(p, uint32(len(answers)))
		for _, a := range answers {
			p = marshalString(p, []byte(a))
		}

		if err := c.writePacket(serialized); err != nil {
			return false, nil, err
		}
	}
}
<|endoftext|>


<commit_before>package state

import (
	"fmt"
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/txn"
	"strings"
)

// annotatorDoc represents the internal state of annotations for an Entity in
// MongoDB. Note that the annotations map is not maintained in local storage
// due to the fact that it is not accessed directly, but through
// Annotations/Annotation below.
type annotatorDoc struct {
	GlobalKey   string `bson:"_id"`
	EntityName  string
	Annotations map[string]string
}

// annotator implements annotation-related methods
// for any entity that wishes to use it.
type annotator struct {
	globalKey  string
	entityName string
	st         *State
}

// SetAnnotations adds key/value pairs to annotations in MongoDB.
func (a *annotator) SetAnnotations(pairs map[string]string) error {
	if len(pairs) == 0 {
		return nil
	}
	// Collect in separate maps pairs to be inserted/updated or removed.
	toRemove := make(map[string]bool)
	toInsert := make(map[string]string)
	toUpdate := make(map[string]string)
	for key, value := range pairs {
		if strings.Contains(key, ".") {
			return fmt.Errorf("invalid key %q", key)
		}
		if value == "" {
			toRemove["annotations."+key] = true
		} else {
			toInsert[key] = value
			toUpdate["annotations."+key] = value
		}
	}
	id := a.globalKey
	coll := a.st.annotations.Name
	var ops []txn.Op
	if count, err := a.st.annotations.FindId(id).Count(); err != nil {
		return err
	} else if count == 0 {
		// The document is missing: no need to remove pairs.
		// Insert pairs if required.
		if len(toInsert) == 0 {
			return nil
		}
		insertOp := txn.Op{
			C:      coll,
			Id:     id,
			Assert: txn.DocMissing,
			Insert: &annotatorDoc{id, a.entityName, toInsert},
		}
		ops = append(ops, insertOp)
	} else {
		// The document exists.
		if len(toRemove) != 0 {
			// Remove pairs.
			removeOp := txn.Op{
				C:      coll,
				Id:     id,
				Assert: txn.DocExists,
				Update: D{{"$unset", toRemove}},
			}
			ops = append(ops, removeOp)
		}
		if len(toUpdate) != 0 {
			// Insert/update pairs.
			updateOp := txn.Op{
				C:      coll,
				Id:     id,
				Assert: txn.DocExists,
				Update: D{{"$set", toUpdate}},
			}
			ops = append(ops, updateOp)
		}
	}
	if err := a.st.runner.Run(ops, "", nil); err != nil {
		// TODO(frankban) Bug #1156714: handle possible race conditions.
		return fmt.Errorf("cannot update annotations on %s: %v", id, err)
	}
	return nil
}

// Annotations returns all the annotations corresponding to an entity.
func (a *annotator) Annotations() (map[string]string, error) {
	doc := new(annotatorDoc)
	err := a.st.annotations.FindId(a.globalKey).One(doc)
	if err == mgo.ErrNotFound {
		// Returning an empty map if there are no annotations.
		return make(map[string]string), nil
	}
	if err != nil {
		return nil, err
	}
	return doc.Annotations, nil
}

// Annotation returns the annotation value corresponding to the given key.
// If the requested annotation is not found, an empty string is returned.
func (a *annotator) Annotation(key string) (string, error) {
	ann, err := a.Annotations()
	if err != nil {
		return "", err
	}
	return ann[key], nil
}

// annotationRemoveOp returns an operation to remove a given annotation
// document from MongoDB.
func annotationRemoveOp(st *State, id string) txn.Op {
	return txn.Op{
		C:      st.annotations.Name,
		Id:     id,
		Remove: true,
	}
}
<commit_msg>Prototype contention management.<commit_after>package state

import (
	"fmt"
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/txn"
	"strings"
)

// annotatorDoc represents the internal state of annotations for an Entity in
// MongoDB. Note that the annotations map is not maintained in local storage
// due to the fact that it is not accessed directly, but through
// Annotations/Annotation below.
type annotatorDoc struct {
	GlobalKey   string `bson:"_id"`
	EntityName  string
	Annotations map[string]string
}

// annotator implements annotation-related methods
// for any entity that wishes to use it.
type annotator struct {
	globalKey  string
	entityName string
	st         *State
}

// SetAnnotations adds key/value pairs to annotations in MongoDB.
func (a *annotator) SetAnnotations(pairs map[string]string) error {
	if len(pairs) == 0 {
		return nil
	}
	// Collect in separate maps pairs to be inserted/updated or removed.
	toRemove := make(map[string]bool)
	toInsert := make(map[string]string)
	toUpdate := make(map[string]string)
	for key, value := range pairs {
		if strings.Contains(key, ".") {
			return fmt.Errorf("invalid key %q", key)
		}
		if value == "" {
			toRemove["annotations."+key] = true
		} else {
			toInsert[key] = value
			toUpdate["annotations."+key] = value
		}
	}
	for i := 0; i < 3; i++ {
		ops, err := a.setAnnotationsOps(toInsert, toUpdate, toRemove)
		if err != nil {
			return err
		}
		if len(ops) == 0 {
			return nil
		}
		if err := a.st.runner.Run(ops, "", nil); err == nil {
			return nil
		} else if err != txn.ErrAborted {
			return fmt.Errorf("cannot update annotations on %s: %v", a.globalKey, err)
		}
		if hasAnnotations, err := a.hasAnnotations(pairs); err != nil {
			return err
		} else if hasAnnotations {
			return nil
		}
	}
	return fmt.Errorf("cannot update annotations on %s: %v", a.globalKey, ErrExcessiveContention)
}

// setAnnotationsOps returns the operations required to insert, update or
// remove annotations in MongoDB.
func (a *annotator) setAnnotationsOps(toInsert, toUpdate map[string]string, toRemove map[string]bool) ([]txn.Op, error) {
	id := a.globalKey
	coll := a.st.annotations.Name
	var ops []txn.Op
	if count, err := a.st.annotations.FindId(id).Count(); err != nil {
		return nil, err
	} else if count == 0 {
		// The document is missing: no need to remove pairs.
		// Insert pairs if required.
		if len(toInsert) == 0 {
			return ops, nil
		}
		insertOp := txn.Op{
			C:      coll,
			Id:     id,
			Assert: txn.DocMissing,
			Insert: &annotatorDoc{id, a.entityName, toInsert},
		}
		return append(ops, insertOp), nil
	}
	// The document exists.
	if len(toRemove) != 0 {
		// Remove pairs.
		removeOp := txn.Op{
			C:      coll,
			Id:     id,
			Assert: txn.DocExists,
			Update: D{{"$unset", toRemove}},
		}
		ops = append(ops, removeOp)
	}
	if len(toUpdate) != 0 {
		// Insert/update pairs.
		updateOp := txn.Op{
			C:      coll,
			Id:     id,
			Assert: txn.DocExists,
			Update: D{{"$set", toUpdate}},
		}
		ops = append(ops, updateOp)
	}
	return ops, nil
}

// hasAnnotations checks if the provided annotations already exist.
func (a *annotator) hasAnnotations(pairs map[string]string) (bool, error) {
	ann, err := a.Annotations()
	if err != nil {
		return false, err
	}
	for key, value := range pairs {
		if ann[key] != value {
			return false, nil
		}
	}
	return true, nil
}

// Annotations returns all the annotations corresponding to an entity.
func (a *annotator) Annotations() (map[string]string, error) {
	doc := new(annotatorDoc)
	err := a.st.annotations.FindId(a.globalKey).One(doc)
	if err == mgo.ErrNotFound {
		// Returning an empty map if there are no annotations.
		return make(map[string]string), nil
	}
	if err != nil {
		return nil, err
	}
	return doc.Annotations, nil
}

// Annotation returns the annotation value corresponding to the given key.
// If the requested annotation is not found, an empty string is returned.
func (a *annotator) Annotation(key string) (string, error) {
	ann, err := a.Annotations()
	if err != nil {
		return "", err
	}
	return ann[key], nil
}

// annotationRemoveOp returns an operation to remove a given annotation
// document from MongoDB.
func annotationRemoveOp(st *State, id string) txn.Op {
	return txn.Op{
		C:      st.annotations.Name,
		Id:     id,
		Remove: true,
	}
}
<|endoftext|>


<commit_before>package dns

import (
	"strconv"
        "encoding/hex"
)

// EDNS0 Options and Do bit
const (
	OptionCodeLLQ  = 1      // Not used
	OptionCodeUL   = 2      // Not used
	OptionCodeNSID = 3      // NSID, RFC5001
	_DO            = 1 << 7 // dnssec ok
)

// An ENDS0 option rdata element.
type Option struct {
	Code uint16
	Data string "hex"
}

/*
 * EDNS extended RR.
 * This is the EDNS0 Header
 * 	Name          string "domain-name"
 * 	Opt           uint16 // was type, but is always TypeOPT
 * 	UDPSize       uint16 // was class
 * 	ExtendedRcode uint8  // was TTL
 * 	Version       uint8  // was TTL
 * 	Z             uint16 // was TTL (all flags should be put here)
 * 	Rdlength      uint16 // length of data after the header
 */

type RR_OPT struct {
	Hdr    RR_Header
	Option []Option "OPT" // Tag is used in Pack and Unpack
}

func (rr *RR_OPT) Header() *RR_Header {
	return &rr.Hdr
}

func (rr *RR_OPT) String() string {
	s := ";; OPT PSEUDOSECTION:\n; EDNS: version " + strconv.Itoa(int(rr.Version())) + "; "
	if rr.Do() {
		s += "flags: do; "
	} else {
		s += "flags: ; "
	}
	s += "udp: " + strconv.Itoa(int(rr.UDPSize()))

	for _, o := range rr.Option {
		switch o.Code {
		case OptionCodeNSID:
			s += "\n; NSID: " + o.Data
                        h, e := hex.DecodeString(o.Data)
                        var r string
                        if e == nil {
                                for _, c := range h {
                                        r += "(" + string(c)  + ")"
                                }
                        s += "  " + r
                        }
		}
	}
	return s
}

// Get the EDNS version (always 0 currently)
func (rr *RR_OPT) Version() uint8 {
        return 0
}

// Set the version of EDNS
func (rr *RR_OPT) SetVersion(v uint8) {
	return
}

// Get the UDP buffer size
func (rr *RR_OPT) UDPSize() uint16 {
	return rr.Hdr.Class
}

// Set the UDP buffer size
func (rr *RR_OPT) SetUDPSize(size uint16) {
	rr.Hdr.Class = size
}

/* from RFC 3225
          +0 (MSB)                +1 (LSB)
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
0: |   EXTENDED-RCODE      |       VERSION         |
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2: |DO|                    Z                       |
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*/

// Get the do bit
func (rr *RR_OPT) Do() bool {
        return byte(rr.Hdr.Ttl >> 8) &_DO == _DO
}

// Set the do bit
func (rr *RR_OPT) SetDo() {
        b1 := byte(rr.Hdr.Ttl >> 24)
        b2 := byte(rr.Hdr.Ttl >> 16)
        b3 := byte(rr.Hdr.Ttl >> 8)
        b4 := byte(rr.Hdr.Ttl)
        b3 |= _DO // Set it
        rr.Hdr.Ttl = uint32(b1)<<24 | uint32(b2)<<16 | uint32(b3)<<8 | uint32(b4)
}

// Return the NSID as hex string
func (rr *RR_OPT) Nsid() string {
	return "NSID: " + rr.Option[0].Data
}

// Set the NSID from a string which is represented as hex characters.
func (rr *RR_OPT) SetNsid(hexnsid string) {
        rr.Option[0].Code = OptionCodeNSID
        rr.Option[0].Data = hexnsid
}
<commit_msg>docs edns0<commit_after>package dns

import (
	"strconv"
        "encoding/hex"
)

// EDNS0 Options
const (
	OptionCodeLLQ  = 1      // not used
	OptionCodeUL   = 2      // not used
	OptionCodeNSID = 3      // NSID, RFC5001
	_DO            = 1 << 7 // dnssec ok
)

// An ENDS0 option rdata element.
type Option struct {
	Code uint16
	Data string "hex"
}

/*
 * EDNS extended RR.
 * This is the EDNS0 Header
 * 	Name          string "domain-name"
 * 	Opt           uint16 // was type, but is always TypeOPT
 * 	UDPSize       uint16 // was class
 * 	ExtendedRcode uint8  // was TTL
 * 	Version       uint8  // was TTL
 * 	Z             uint16 // was TTL (all flags should be put here)
 * 	Rdlength      uint16 // length of data after the header
 */

type RR_OPT struct {
	Hdr    RR_Header
	Option []Option "OPT" // tag is used in Pack and Unpack
}

func (rr *RR_OPT) Header() *RR_Header {
	return &rr.Hdr
}

func (rr *RR_OPT) String() string {
	s := ";; OPT PSEUDOSECTION:\n; EDNS: version " + strconv.Itoa(int(rr.Version())) + "; "
	if rr.Do() {
		s += "flags: do; "
	} else {
		s += "flags: ; "
	}
	s += "udp: " + strconv.Itoa(int(rr.UDPSize()))

	for _, o := range rr.Option {
		switch o.Code {
		case OptionCodeNSID:
			s += "\n; NSID: " + o.Data
                        h, e := hex.DecodeString(o.Data)
                        var r string
                        if e == nil {
                                for _, c := range h {
                                        r += "(" + string(c)  + ")"
                                }
                        s += "  " + r
                        }
		}
	}
	return s
}

// Get the EDNS version (always 0 currently).
func (rr *RR_OPT) Version() uint8 {
        return 0
}

// Set the version of EDNS.
func (rr *RR_OPT) SetVersion(v uint8) {
	return
}

// Get the UDP buffer size.
func (rr *RR_OPT) UDPSize() uint16 {
	return rr.Hdr.Class
}

// Set the UDP buffer size/
func (rr *RR_OPT) SetUDPSize(size uint16) {
	rr.Hdr.Class = size
}

/* from RFC 3225
          +0 (MSB)                +1 (LSB)
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
0: |   EXTENDED-RCODE      |       VERSION         |
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
2: |DO|                    Z                       |
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*/

// Get the DO bit.
func (rr *RR_OPT) Do() bool {
        return byte(rr.Hdr.Ttl >> 8) &_DO == _DO
}

// Set the do bit
func (rr *RR_OPT) SetDo() {
        b1 := byte(rr.Hdr.Ttl >> 24)
        b2 := byte(rr.Hdr.Ttl >> 16)
        b3 := byte(rr.Hdr.Ttl >> 8)
        b4 := byte(rr.Hdr.Ttl)
        b3 |= _DO // Set it
        rr.Hdr.Ttl = uint32(b1)<<24 | uint32(b2)<<16 | uint32(b3)<<8 | uint32(b4)
}

// Return the NSID as hex string.
func (rr *RR_OPT) Nsid() string {
	return "NSID: " + rr.Option[0].Data
}

// Set the NSID from a string which is represented as hex characters.
func (rr *RR_OPT) SetNsid(hexnsid string) {
        rr.Option[0].Code = OptionCodeNSID
        rr.Option[0].Data = hexnsid
}
<|endoftext|>


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

package net

import (
	"context"
	"internal/poll"
	"os"
	"runtime"
	"syscall"
	"unsafe"
)

// canUseConnectEx reports whether we can use the ConnectEx Windows API call
// for the given network type.
func canUseConnectEx(net string) bool {
	switch net {
	case "tcp", "tcp4", "tcp6":
		return true
	}
	// ConnectEx windows API does not support connectionless sockets.
	return false
}

// Network file descriptor.
type netFD struct {
	pfd poll.FD

	// immutable until Close
	family      int
	sotype      int
	isConnected bool
	net         string
	laddr       Addr
	raddr       Addr
}

func newFD(sysfd syscall.Handle, family, sotype int, net string) (*netFD, error) {
	ret := &netFD{
		pfd: poll.FD{
			Sysfd:         sysfd,
			IsStream:      sotype == syscall.SOCK_STREAM,
			ZeroReadIsEOF: sotype != syscall.SOCK_DGRAM && sotype != syscall.SOCK_RAW,
		},
		family: family,
		sotype: sotype,
		net:    net,
	}
	return ret, nil
}

func (fd *netFD) init() error {
	errcall, err := fd.pfd.Init(fd.net)
	if errcall != "" {
		err = wrapSyscallError(errcall, err)
	}
	return err
}

func (fd *netFD) setAddr(laddr, raddr Addr) {
	fd.laddr = laddr
	fd.raddr = raddr
	runtime.SetFinalizer(fd, (*netFD).Close)
}

func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) error {
	// Do not need to call fd.writeLock here,
	// because fd is not yet accessible to user,
	// so no concurrent operations are possible.
	if err := fd.init(); err != nil {
		return err
	}
	if deadline, ok := ctx.Deadline(); ok && !deadline.IsZero() {
		fd.pfd.SetWriteDeadline(deadline)
		defer fd.pfd.SetWriteDeadline(noDeadline)
	}
	if !canUseConnectEx(fd.net) {
		err := connectFunc(fd.pfd.Sysfd, ra)
		return os.NewSyscallError("connect", err)
	}
	// ConnectEx windows API requires an unconnected, previously bound socket.
	if la == nil {
		switch ra.(type) {
		case *syscall.SockaddrInet4:
			la = &syscall.SockaddrInet4{}
		case *syscall.SockaddrInet6:
			la = &syscall.SockaddrInet6{}
		default:
			panic("unexpected type in connect")
		}
		if err := syscall.Bind(fd.pfd.Sysfd, la); err != nil {
			return os.NewSyscallError("bind", err)
		}
	}

	// Wait for the goroutine converting context.Done into a write timeout
	// to exist, otherwise our caller might cancel the context and
	// cause fd.setWriteDeadline(aLongTimeAgo) to cancel a successful dial.
	done := make(chan bool) // must be unbuffered
	defer func() { done <- true }()
	go func() {
		select {
		case <-ctx.Done():
			// Force the runtime's poller to immediately give
			// up waiting for writability.
			fd.pfd.SetWriteDeadline(aLongTimeAgo)
			<-done
		case <-done:
		}
	}()

	// Call ConnectEx API.
	if err := fd.pfd.ConnectEx(ra); err != nil {
		select {
		case <-ctx.Done():
			return mapErr(ctx.Err())
		default:
			if _, ok := err.(syscall.Errno); ok {
				err = os.NewSyscallError("connectex", err)
			}
			return err
		}
	}
	// Refresh socket properties.
	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd.pfd.Sysfd, syscall.SOL_SOCKET, syscall.SO_UPDATE_CONNECT_CONTEXT, (*byte)(unsafe.Pointer(&fd.pfd.Sysfd)), int32(unsafe.Sizeof(fd.pfd.Sysfd))))
}

func (fd *netFD) Close() error {
	runtime.SetFinalizer(fd, nil)
	return fd.pfd.Close()
}

func (fd *netFD) shutdown(how int) error {
	err := fd.pfd.Shutdown(how)
	runtime.KeepAlive(fd)
	return err
}

func (fd *netFD) closeRead() error {
	return fd.shutdown(syscall.SHUT_RD)
}

func (fd *netFD) closeWrite() error {
	return fd.shutdown(syscall.SHUT_WR)
}

func (fd *netFD) Read(buf []byte) (int, error) {
	n, err := fd.pfd.Read(buf)
	runtime.KeepAlive(fd)
	return n, wrapSyscallError("wsarecv", err)
}

func (fd *netFD) readFrom(buf []byte) (int, syscall.Sockaddr, error) {
	n, sa, err := fd.pfd.ReadFrom(buf)
	runtime.KeepAlive(fd)
	return n, sa, wrapSyscallError("wsarecvfrom", err)
}

func (fd *netFD) Write(buf []byte) (int, error) {
	n, err := fd.pfd.Write(buf)
	runtime.KeepAlive(fd)
	return n, wrapSyscallError("wsasend", err)
}

func (c *conn) writeBuffers(v *Buffers) (int64, error) {
	if !c.ok() {
		return 0, syscall.EINVAL
	}
	n, err := c.fd.writeBuffers(v)
	if err != nil {
		return n, &OpError{Op: "WSASend", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
	}
	return n, nil
}

func (fd *netFD) writeBuffers(buf *Buffers) (int64, error) {
	n, err := fd.pfd.Writev((*[][]byte)(buf))
	runtime.KeepAlive(fd)
	return n, wrapSyscallError("wsasend", err)
}

func (fd *netFD) writeTo(buf []byte, sa syscall.Sockaddr) (int, error) {
	n, err := fd.pfd.WriteTo(buf, sa)
	runtime.KeepAlive(fd)
	return n, wrapSyscallError("wsasendto", err)
}

func (fd *netFD) accept() (*netFD, error) {
	s, rawsa, rsan, errcall, err := fd.pfd.Accept(func() (syscall.Handle, error) {
		return sysSocket(fd.family, fd.sotype, 0)
	})

	if err != nil {
		if errcall != "" {
			err = wrapSyscallError(errcall, err)
		}
		return nil, err
	}

	// Associate our new socket with IOCP.
	netfd, err := newFD(s, fd.family, fd.sotype, fd.net)
	if err != nil {
		poll.CloseFunc(s)
		return nil, err
	}
	if err := netfd.init(); err != nil {
		fd.Close()
		return nil, err
	}

	// Get local and peer addr out of AcceptEx buffer.
	var lrsa, rrsa *syscall.RawSockaddrAny
	var llen, rlen int32
	syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&rawsa[0])),
		0, rsan, rsan, &lrsa, &llen, &rrsa, &rlen)
	lsa, _ := lrsa.Sockaddr()
	rsa, _ := rrsa.Sockaddr()

	netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa))
	return netfd, nil
}

// Unimplemented functions.

func (fd *netFD) dup() (*os.File, error) {
	// TODO: Implement this
	return nil, syscall.EWINDOWS
}

func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
	return 0, 0, 0, nil, syscall.EWINDOWS
}

func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
	return 0, 0, syscall.EWINDOWS
}
<commit_msg>net: make syscall name consistent with others<commit_after>// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package net

import (
	"context"
	"internal/poll"
	"os"
	"runtime"
	"syscall"
	"unsafe"
)

// canUseConnectEx reports whether we can use the ConnectEx Windows API call
// for the given network type.
func canUseConnectEx(net string) bool {
	switch net {
	case "tcp", "tcp4", "tcp6":
		return true
	}
	// ConnectEx windows API does not support connectionless sockets.
	return false
}

// Network file descriptor.
type netFD struct {
	pfd poll.FD

	// immutable until Close
	family      int
	sotype      int
	isConnected bool
	net         string
	laddr       Addr
	raddr       Addr
}

func newFD(sysfd syscall.Handle, family, sotype int, net string) (*netFD, error) {
	ret := &netFD{
		pfd: poll.FD{
			Sysfd:         sysfd,
			IsStream:      sotype == syscall.SOCK_STREAM,
			ZeroReadIsEOF: sotype != syscall.SOCK_DGRAM && sotype != syscall.SOCK_RAW,
		},
		family: family,
		sotype: sotype,
		net:    net,
	}
	return ret, nil
}

func (fd *netFD) init() error {
	errcall, err := fd.pfd.Init(fd.net)
	if errcall != "" {
		err = wrapSyscallError(errcall, err)
	}
	return err
}

func (fd *netFD) setAddr(laddr, raddr Addr) {
	fd.laddr = laddr
	fd.raddr = raddr
	runtime.SetFinalizer(fd, (*netFD).Close)
}

func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) error {
	// Do not need to call fd.writeLock here,
	// because fd is not yet accessible to user,
	// so no concurrent operations are possible.
	if err := fd.init(); err != nil {
		return err
	}
	if deadline, ok := ctx.Deadline(); ok && !deadline.IsZero() {
		fd.pfd.SetWriteDeadline(deadline)
		defer fd.pfd.SetWriteDeadline(noDeadline)
	}
	if !canUseConnectEx(fd.net) {
		err := connectFunc(fd.pfd.Sysfd, ra)
		return os.NewSyscallError("connect", err)
	}
	// ConnectEx windows API requires an unconnected, previously bound socket.
	if la == nil {
		switch ra.(type) {
		case *syscall.SockaddrInet4:
			la = &syscall.SockaddrInet4{}
		case *syscall.SockaddrInet6:
			la = &syscall.SockaddrInet6{}
		default:
			panic("unexpected type in connect")
		}
		if err := syscall.Bind(fd.pfd.Sysfd, la); err != nil {
			return os.NewSyscallError("bind", err)
		}
	}

	// Wait for the goroutine converting context.Done into a write timeout
	// to exist, otherwise our caller might cancel the context and
	// cause fd.setWriteDeadline(aLongTimeAgo) to cancel a successful dial.
	done := make(chan bool) // must be unbuffered
	defer func() { done <- true }()
	go func() {
		select {
		case <-ctx.Done():
			// Force the runtime's poller to immediately give
			// up waiting for writability.
			fd.pfd.SetWriteDeadline(aLongTimeAgo)
			<-done
		case <-done:
		}
	}()

	// Call ConnectEx API.
	if err := fd.pfd.ConnectEx(ra); err != nil {
		select {
		case <-ctx.Done():
			return mapErr(ctx.Err())
		default:
			if _, ok := err.(syscall.Errno); ok {
				err = os.NewSyscallError("connectex", err)
			}
			return err
		}
	}
	// Refresh socket properties.
	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd.pfd.Sysfd, syscall.SOL_SOCKET, syscall.SO_UPDATE_CONNECT_CONTEXT, (*byte)(unsafe.Pointer(&fd.pfd.Sysfd)), int32(unsafe.Sizeof(fd.pfd.Sysfd))))
}

func (fd *netFD) Close() error {
	runtime.SetFinalizer(fd, nil)
	return fd.pfd.Close()
}

func (fd *netFD) shutdown(how int) error {
	err := fd.pfd.Shutdown(how)
	runtime.KeepAlive(fd)
	return err
}

func (fd *netFD) closeRead() error {
	return fd.shutdown(syscall.SHUT_RD)
}

func (fd *netFD) closeWrite() error {
	return fd.shutdown(syscall.SHUT_WR)
}

func (fd *netFD) Read(buf []byte) (int, error) {
	n, err := fd.pfd.Read(buf)
	runtime.KeepAlive(fd)
	return n, wrapSyscallError("wsarecv", err)
}

func (fd *netFD) readFrom(buf []byte) (int, syscall.Sockaddr, error) {
	n, sa, err := fd.pfd.ReadFrom(buf)
	runtime.KeepAlive(fd)
	return n, sa, wrapSyscallError("wsarecvfrom", err)
}

func (fd *netFD) Write(buf []byte) (int, error) {
	n, err := fd.pfd.Write(buf)
	runtime.KeepAlive(fd)
	return n, wrapSyscallError("wsasend", err)
}

func (c *conn) writeBuffers(v *Buffers) (int64, error) {
	if !c.ok() {
		return 0, syscall.EINVAL
	}
	n, err := c.fd.writeBuffers(v)
	if err != nil {
		return n, &OpError{Op: "wsasend", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
	}
	return n, nil
}

func (fd *netFD) writeBuffers(buf *Buffers) (int64, error) {
	n, err := fd.pfd.Writev((*[][]byte)(buf))
	runtime.KeepAlive(fd)
	return n, wrapSyscallError("wsasend", err)
}

func (fd *netFD) writeTo(buf []byte, sa syscall.Sockaddr) (int, error) {
	n, err := fd.pfd.WriteTo(buf, sa)
	runtime.KeepAlive(fd)
	return n, wrapSyscallError("wsasendto", err)
}

func (fd *netFD) accept() (*netFD, error) {
	s, rawsa, rsan, errcall, err := fd.pfd.Accept(func() (syscall.Handle, error) {
		return sysSocket(fd.family, fd.sotype, 0)
	})

	if err != nil {
		if errcall != "" {
			err = wrapSyscallError(errcall, err)
		}
		return nil, err
	}

	// Associate our new socket with IOCP.
	netfd, err := newFD(s, fd.family, fd.sotype, fd.net)
	if err != nil {
		poll.CloseFunc(s)
		return nil, err
	}
	if err := netfd.init(); err != nil {
		fd.Close()
		return nil, err
	}

	// Get local and peer addr out of AcceptEx buffer.
	var lrsa, rrsa *syscall.RawSockaddrAny
	var llen, rlen int32
	syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&rawsa[0])),
		0, rsan, rsan, &lrsa, &llen, &rrsa, &rlen)
	lsa, _ := lrsa.Sockaddr()
	rsa, _ := rrsa.Sockaddr()

	netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa))
	return netfd, nil
}

// Unimplemented functions.

func (fd *netFD) dup() (*os.File, error) {
	// TODO: Implement this
	return nil, syscall.EWINDOWS
}

func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
	return 0, 0, 0, nil, syscall.EWINDOWS
}

func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
	return 0, 0, syscall.EWINDOWS
}
<|endoftext|>


<commit_before>package authenticator

import (
	"log"

	"github.com/dghubble/sling"
	"github.com/piot/hasty-protocol/user"
)

// AuthenticationMessage : todo
type AuthenticationMessage struct {
	AuthenticationToken string `json:"at"`
}

// AuthenticationResponse : todo
type AuthenticationResponse struct {
	SessionID          string `json:"sessionId"`
	UserID             uint64 `json:"userId"`
	LastLoginTimestamp uint64 `json:"lastLoginTimestamp"`
	Username           string `json:"username"`
}

// Authenticate : todo
func Authenticate(url string, path string, headerName string, headerValue string, authenticationToken string) (user.ID, string, error) {
	notificationServerBase := sling.New().Base(url).Set(headerName, headerValue)

	body := &AuthenticationMessage{AuthenticationToken: authenticationToken}
	req, err := notificationServerBase.New().Post(path).BodyJSON(body).Request()
	if err != nil {
		log.Printf("Request error %v", err)
		return user.ID{}, "", err
	}

	successfulResponse := AuthenticationResponse{}
	_, responseErr := notificationServerBase.Do(req, &successfulResponse, &successfulResponse)
	if responseErr != nil {
		log.Printf("responseError:%v", responseErr)
		return user.ID{}, "", responseErr
	}

	userID, _ := user.NewID(successfulResponse.UserID)
	log.Printf("Received userId:%v and username:%v", userID, successfulResponse.Username)
	return userID, successfulResponse.Username, nil
}
<commit_msg>Handling errors from authentication REST<commit_after>package authenticator

import (
	"fmt"
	"log"

	"github.com/dghubble/sling"
	"github.com/piot/hasty-protocol/user"
)

// AuthenticationMessage : todo
type AuthenticationMessage struct {
	AuthenticationToken string `json:"at"`
}

// AuthenticationResponse : todo
type AuthenticationResponse struct {
	SessionID          string `json:"sessionId"`
	UserID             uint64 `json:"userId"`
	LastLoginTimestamp uint64 `json:"lastLoginTimestamp"`
	Username           string `json:"username"`
}

// ErrorResponse : todo
type AuthenticationErrorResponse struct {
	ErrorCode    int    `json:"errorCode"`
	ErrorMessage string `json:"errorMessage"`
}

// Authenticate : todo
func Authenticate(url string, path string, headerName string, headerValue string, authenticationToken string) (user.ID, string, error) {
	notificationServerBase := sling.New().Base(url).Set(headerName, headerValue)

	body := &AuthenticationMessage{AuthenticationToken: authenticationToken}
	req, err := notificationServerBase.New().Post(path).BodyJSON(body).Request()
	if err != nil {
		log.Printf("Request error %v", err)
		return user.ID{}, "", err
	}

	successfulResponse := AuthenticationResponse{}
	unsuccessfulResponse := AuthenticationErrorResponse{}
	response, responseErr := notificationServerBase.Do(req, &successfulResponse, &unsuccessfulResponse)
	if responseErr != nil {
		log.Printf("responseError:%v", responseErr)
		return user.ID{}, "", responseErr
	}

	if response.StatusCode < 200 || response.StatusCode > 299 {
		authenticationError := fmt.Errorf("Could not authenticate: HTTP error %d. %d - '%s'", response.StatusCode, unsuccessfulResponse.ErrorCode, unsuccessfulResponse.ErrorMessage)
		log.Printf("authenticationError:%s", authenticationError)
		return user.ID{}, "", authenticationError
	}

	userID, _ := user.NewID(successfulResponse.UserID)
	log.Printf("Received userId:%v and username:%v", userID, successfulResponse.Username)
	return userID, successfulResponse.Username, nil
}
<|endoftext|>


<commit_before>package verdeps

import "regexp"

const (
	importAnnotation = `import\s+(?:"[^"]*"|` + "`[^`]*`" + `)`
	importComment    = `(?://\s*` +
		importAnnotation +
		`\s*$|/\*\s*` +
		importAnnotation +
		`\s*\*/)`
	packageImportComment = `(?:package\s+\w+)(\s+` + importComment + `(?:.*))`
)

var packageImportCommentRegex = regexp.MustCompile(packageImportComment)

// findPackageImportComment finds the indices of the package import comment if
// one exists. If not, then it returns -1s. This code is inspired by the way
// godeps does this exact thing.
func findPackageImportComment(
	fileData []byte,
	packageStartIndex int,
) (fromIndex int, toIndex int) {
	// Read until the end of the line or the end of the file.
	packageEndIndex := packageStartIndex
	for packageEndIndex >= 0 &&
		packageEndIndex < len(fileData) &&
		fileData[packageEndIndex] != '\n' {
		packageEndIndex++
	}
	// Read backwards until the beginning of the file or the previous line.
	for packageStartIndex >= 0 &&
		packageStartIndex < len(fileData) &&
		fileData[packageStartIndex] != '\n' {
		packageStartIndex--
	}
	// Advance the start index by one to make sure it is securely at the
	// beginning of the line.
	if packageStartIndex+1 >= 0 &&
		packageStartIndex+1 < len(fileData) &&
		fileData[packageStartIndex] == '\n' {
		packageStartIndex++
	}

	// Find matches in [packageStartIndex, packageEndIndex).
	line := fileData[packageStartIndex:packageEndIndex]
	match := packageImportCommentRegex.FindSubmatchIndex(line)
	if match != nil {
		// Adjust the indices for the starting index of "line".
		toIndex = packageStartIndex + match[3]
		fromIndex = packageStartIndex + match[2]
		return fromIndex, toIndex
	}

	return -1, -1
}
<commit_msg>patched boundary checks<commit_after>package verdeps

import "regexp"

const (
	importAnnotation = `import\s+(?:"[^"]*"|` + "`[^`]*`" + `)`
	importComment    = `(?://\s*` +
		importAnnotation +
		`\s*$|/\*\s*` +
		importAnnotation +
		`\s*\*/)`
	packageImportComment = `(?:package\s+\w+)(\s+` + importComment + `(?:.*))`
)

var packageImportCommentRegex = regexp.MustCompile(packageImportComment)

// findPackageImportComment finds the indices of the package import comment if
// one exists. If not, then it returns -1s. This code is inspired by the way
// godeps does this exact thing.
func findPackageImportComment(
	fileData []byte,
	packageStartIndex int,
) (fromIndex int, toIndex int) {
	// Read until the end of the line or the end of the file.
	packageEndIndex := packageStartIndex
	for packageEndIndex < len(fileData)-1 && fileData[packageEndIndex] != '\n' {
		packageEndIndex++
	}
	// Read backwards until the beginning of the file or the previous line.
	for packageStartIndex > 0 && fileData[packageStartIndex] != '\n' {
		packageStartIndex--
	}
	// Advance the start index by one to make sure it is securely at the
	// beginning of the line.
	if packageStartIndex < len(fileData)-1 &&
		fileData[packageStartIndex] == '\n' {
		packageStartIndex++
	}

	// Find matches in [packageStartIndex, packageEndIndex).
	line := fileData[packageStartIndex:packageEndIndex]
	match := packageImportCommentRegex.FindSubmatchIndex(line)
	if match != nil {
		// Adjust the indices for the starting index of "line".
		toIndex = packageStartIndex + match[3]
		fromIndex = packageStartIndex + match[2]
		return fromIndex, toIndex
	}

	return -1, -1
}
<|endoftext|>


<commit_before>/* Copyright 2016 nix <https://github.com/nixn>

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 main

import (
	"fmt"
	"github.com/coreos/etcd/clientv3"
	"golang.org/x/net/context"
	"log"
	"strconv"
	"strings"
	"time"
)

var (
	cli     *clientv3.Client
	timeout = 2 * time.Second
)

func setConfigFileParameter(value string) error {
	client, err := clientv3.NewFromConfigFile(value)
	if err != nil {
		return fmt.Errorf("failed to create client instance: %s", err)
	}
	cli = client
	return nil
}

func setupClient(params map[string]interface{}) ([]string, error) {
	haveConfigFile, err := readParameter("config-file", params, setConfigFileParameter)
	if err != nil {
		return nil, err
	}
	if haveConfigFile {
		return []string{}, nil
	}
	cfg := clientv3.Config{DialTimeout: timeout}
	// timeout
	if tmo, ok := params["timeout"]; ok {
		if tmo, ok := tmo.(string); ok {
			if tmo, err := strconv.ParseUint(tmo, 10, 32); err == nil {
				if tmo > 0 {
					timeout = time.Duration(tmo) * time.Millisecond
					cfg.DialTimeout = timeout
				} else {
					return nil, fmt.Errorf("Timeout may not be zero")
				}
			} else {
				return nil, fmt.Errorf("Failed to parse timeout value: %s", err)
			}
		} else {
			return nil, fmt.Errorf("parameters.timeout is not a string")
		}
	}
	logMessages := []string{fmt.Sprintf("timeout: %s", timeout)}
	// endpoints
	if endpoints, ok := params["endpoints"]; ok {
		if endpoints, ok := endpoints.(string); ok {
			endpoints := strings.Split(endpoints, "|")
			cfg.Endpoints = endpoints
			if client, err := clientv3.New(cfg); err == nil {
				cli = client
			} else {
				return nil, fmt.Errorf("Failed to parse endpoints: %s", err)
			}
		} else {
			return nil, fmt.Errorf("parameters.endpoints is not a string")
		}
	} else {
		cfg.Endpoints = []string{"[::1]:2379", "127.0.0.1:2379"}
		if client, err := clientv3.New(cfg); err == nil {
			cli = client
		} else {
			return nil, fmt.Errorf("Failed to create client: %s", err)
		}
	}
	return logMessages, nil
}

func closeClient() {
	cli.Close()
}

func get(key string, multi bool, revision *int64) (*clientv3.GetResponse, error) {
	log.Println("loading", key)
	opts := []clientv3.OpOption{}
	if multi {
		opts = append(opts, clientv3.WithPrefix())
	}
	if revision != nil {
		opts = append(opts, clientv3.WithRev(*revision))
	}
	ctx, cancel := context.WithTimeout(context.Background(), timeout)
	since := time.Now()
	response, err := cli.Get(ctx, key, opts...)
	dur := time.Since(since)
	cancel()
	log.Println("loading", key, "dur:", dur)
	return response, err
}
<commit_msg>log also etcd parsed etcd connection settings on initialize<commit_after>/* Copyright 2016 nix <https://github.com/nixn>

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 main

import (
	"fmt"
	"github.com/coreos/etcd/clientv3"
	"golang.org/x/net/context"
	"log"
	"strconv"
	"strings"
	"time"
)

var (
	cli     *clientv3.Client
	timeout = 2 * time.Second
)

func setConfigFileParameter(value string) error {
	client, err := clientv3.NewFromConfigFile(value)
	if err != nil {
		return fmt.Errorf("failed to create client instance: %s", err)
	}
	cli = client
	return nil
}

func setupClient(params map[string]interface{}) ([]string, error) {
	haveConfigFile, err := readParameter("config-file", params, setConfigFileParameter)
	if err != nil {
		return nil, err
	}
	if haveConfigFile {
		return []string{fmt.Sprintf("config-file: %s", params["config-file"])}, nil
	}
	cfg := clientv3.Config{DialTimeout: timeout}
	// timeout
	if tmo, ok := params["timeout"]; ok {
		if tmo, ok := tmo.(string); ok {
			if tmo, err := strconv.ParseUint(tmo, 10, 32); err == nil {
				if tmo > 0 {
					timeout = time.Duration(tmo) * time.Millisecond
					cfg.DialTimeout = timeout
				} else {
					return nil, fmt.Errorf("Timeout may not be zero")
				}
			} else {
				return nil, fmt.Errorf("Failed to parse timeout value: %s", err)
			}
		} else {
			return nil, fmt.Errorf("parameters.timeout is not a string")
		}
	}
	logMessages := []string{fmt.Sprintf("timeout: %s", timeout)}
	// endpoints
	if endpoints, ok := params["endpoints"]; ok {
		if endpoints, ok := endpoints.(string); ok {
			endpoints := strings.Split(endpoints, "|")
			cfg.Endpoints = endpoints
			client, err := clientv3.New(cfg)
			if err != nil {
				return nil, fmt.Errorf("Failed to parse endpoints: %s", err)
			}
			cli = client
		} else {
			return nil, fmt.Errorf("parameters.endpoints is not a string")
		}
	} else {
		cfg.Endpoints = []string{"[::1]:2379", "127.0.0.1:2379"}
		client, err := clientv3.New(cfg)
		if err != nil {
			return nil, fmt.Errorf("Failed to create client: %s", err)
		}
		cli = client
	}
	logMessages = append(logMessages, fmt.Sprintf("endpoints: %v", cfg.Endpoints))
	return logMessages, nil
}

func closeClient() {
	cli.Close()
}

func get(key string, multi bool, revision *int64) (*clientv3.GetResponse, error) {
	log.Println("loading", key)
	opts := []clientv3.OpOption{}
	if multi {
		opts = append(opts, clientv3.WithPrefix())
	}
	if revision != nil {
		opts = append(opts, clientv3.WithRev(*revision))
	}
	ctx, cancel := context.WithTimeout(context.Background(), timeout)
	since := time.Now()
	response, err := cli.Get(ctx, key, opts...)
	dur := time.Since(since)
	cancel()
	log.Println("loading", key, "dur:", dur)
	return response, err
}
<|endoftext|>


<commit_before>package space

import (
	"fmt"
	"strings"

	"github.com/cloudfoundry/cli/cf/commandregistry"
	. "github.com/cloudfoundry/cli/cf/i18n"
	"github.com/cloudfoundry/cli/cf/models"
	"github.com/cloudfoundry/cli/flags"
	"github.com/cloudfoundry/cli/plugin/models"

	"github.com/cloudfoundry/cli/cf/api/spacequotas"
	"github.com/cloudfoundry/cli/cf/configuration/coreconfig"
	"github.com/cloudfoundry/cli/cf/formatters"
	"github.com/cloudfoundry/cli/cf/requirements"
	"github.com/cloudfoundry/cli/cf/terminal"
)

type ShowSpace struct {
	ui          terminal.UI
	config      coreconfig.Reader
	spaceReq    requirements.SpaceRequirement
	quotaRepo   spacequotas.SpaceQuotaRepository
	pluginModel *plugin_models.GetSpace_Model
	pluginCall  bool
}

func init() {
	commandregistry.Register(&ShowSpace{})
}

func (cmd *ShowSpace) MetaData() commandregistry.CommandMetadata {
	fs := make(map[string]flags.FlagSet)
	fs["guid"] = &flags.BoolFlag{Name: "guid", Usage: T("Retrieve and display the given space's guid.  All other output for the space is suppressed.")}
	fs["security-group-rules"] = &flags.BoolFlag{Name: "security-group-rules", Usage: T("Retrieve the rules for all the security groups associated with the space")}
	return commandregistry.CommandMetadata{
		Name:        "space",
		Description: T("Show space info"),
		Usage: []string{
			T("CF_NAME space SPACE"),
		},
		Flags: fs,
	}
}

func (cmd *ShowSpace) Requirements(requirementsFactory requirements.Factory, fc flags.FlagContext) []requirements.Requirement {
	if len(fc.Args()) != 1 {
		cmd.ui.Failed(T("Incorrect Usage. Requires an argument\n\n") + commandregistry.Commands.CommandUsage("space"))
	}

	cmd.spaceReq = requirementsFactory.NewSpaceRequirement(fc.Args()[0])

	reqs := []requirements.Requirement{
		requirementsFactory.NewLoginRequirement(),
		requirementsFactory.NewTargetedOrgRequirement(),
		cmd.spaceReq,
	}

	return reqs
}

func (cmd *ShowSpace) SetDependency(deps commandregistry.Dependency, pluginCall bool) commandregistry.Command {
	cmd.ui = deps.UI
	cmd.config = deps.Config
	cmd.quotaRepo = deps.RepoLocator.GetSpaceQuotaRepository()
	cmd.pluginCall = pluginCall
	cmd.pluginModel = deps.PluginModels.Space
	return cmd
}

func (cmd *ShowSpace) Execute(c flags.FlagContext) error {
	space := cmd.spaceReq.GetSpace()
	if cmd.pluginCall {
		cmd.populatePluginModel(space)
		return nil
	}
	if c.Bool("guid") {
		cmd.ui.Say(space.GUID)
	} else {
		cmd.ui.Say(T("Getting info for space {{.TargetSpace}} in org {{.OrgName}} as {{.CurrentUser}}...",
			map[string]interface{}{
				"TargetSpace": terminal.EntityNameColor(space.Name),
				"OrgName":     terminal.EntityNameColor(space.Organization.Name),
				"CurrentUser": terminal.EntityNameColor(cmd.config.Username()),
			}))

		quotaString, err := cmd.quotaString(space)
		if err != nil {
			return err
		}

		cmd.ui.Ok()
		cmd.ui.Say("")
		table := cmd.ui.Table([]string{terminal.EntityNameColor(space.Name), "", ""})
		table.Add("", T("Org:"), terminal.EntityNameColor(space.Organization.Name))

		apps := []string{}
		for _, app := range space.Applications {
			apps = append(apps, terminal.EntityNameColor(app.Name))
		}
		table.Add("", T("Apps:"), strings.Join(apps, ", "))

		domains := []string{}
		for _, domain := range space.Domains {
			domains = append(domains, terminal.EntityNameColor(domain.Name))
		}
		table.Add("", T("Domains:"), strings.Join(domains, ", "))

		services := []string{}
		for _, service := range space.ServiceInstances {
			services = append(services, terminal.EntityNameColor(service.Name))
		}
		table.Add("", T("Services:"), strings.Join(services, ", "))

		securityGroups := []string{}
		for _, group := range space.SecurityGroups {
			securityGroups = append(securityGroups, terminal.EntityNameColor(group.Name))
		}
		table.Add("", T("Security Groups:"), strings.Join(securityGroups, ", "))

		table.Add("", T("Space Quota:"), quotaString)

		table.Print()
	}
	if c.Bool("security-group-rules") {
		cmd.ui.Say("")
		for _, group := range space.SecurityGroups {
			cmd.ui.Say(T("Getting rules for the security group  : {{.SecurityGroupName}}...",
				map[string]interface{}{"SecurityGroupName": terminal.EntityNameColor(group.Name)}))
			table := cmd.ui.Table([]string{"", "", "", ""})
			for _, rules := range group.Rules {
				for ruleName, ruleValue := range rules {
					table.Add("", ruleName, ":", fmt.Sprintf("%v", ruleValue))
				}
				table.Add("", "", "", "")
			}
			table.Print()
		}
	}

	return nil
}

func (cmd *ShowSpace) quotaString(space models.Space) (string, error) {
	if space.SpaceQuotaGUID == "" {
		return "", nil
	}

	quota, err := cmd.quotaRepo.FindByGUID(space.SpaceQuotaGUID)
	if err != nil {
		return "", err
	}

	spaceQuota := fmt.Sprintf(
		"%s (%s memory limit, %s instance memory limit, %d routes, %d services, paid services %s, %s app instance limit)",
		quota.Name,
		quota.FormattedMemoryLimit(),
		quota.FormattedInstanceMemoryLimit(),
		quota.RoutesLimit,
		quota.ServicesLimit,
		formatters.Allowed(quota.NonBasicServicesAllowed),
		T(quota.FormattedAppInstanceLimit()),
	)

	return spaceQuota, nil
}

func (cmd *ShowSpace) populatePluginModel(space models.Space) {
	cmd.pluginModel.Name = space.Name
	cmd.pluginModel.Guid = space.GUID

	cmd.pluginModel.Organization.Name = space.Organization.Name
	cmd.pluginModel.Organization.Guid = space.Organization.GUID

	for _, app := range space.Applications {
		a := plugin_models.GetSpace_Apps{
			Name: app.Name,
			Guid: app.GUID,
		}
		cmd.pluginModel.Applications = append(cmd.pluginModel.Applications, a)
	}

	for _, domain := range space.Domains {
		d := plugin_models.GetSpace_Domains{
			Name: domain.Name,
			Guid: domain.GUID,
			OwningOrganizationGuid: domain.OwningOrganizationGUID,
			Shared:                 domain.Shared,
		}
		cmd.pluginModel.Domains = append(cmd.pluginModel.Domains, d)
	}

	for _, service := range space.ServiceInstances {
		si := plugin_models.GetSpace_ServiceInstance{
			Name: service.Name,
			Guid: service.GUID,
		}
		cmd.pluginModel.ServiceInstances = append(cmd.pluginModel.ServiceInstances, si)
	}
	for _, group := range space.SecurityGroups {
		sg := plugin_models.GetSpace_SecurityGroup{
			Name:  group.Name,
			Guid:  group.GUID,
			Rules: group.Rules,
		}
		cmd.pluginModel.SecurityGroups = append(cmd.pluginModel.SecurityGroups, sg)
	}

	quota, err := cmd.quotaRepo.FindByGUID(space.SpaceQuotaGUID)
	if err == nil {
		cmd.pluginModel.SpaceQuota.Name = quota.Name
		cmd.pluginModel.SpaceQuota.Guid = quota.GUID
		cmd.pluginModel.SpaceQuota.MemoryLimit = quota.MemoryLimit
		cmd.pluginModel.SpaceQuota.InstanceMemoryLimit = quota.InstanceMemoryLimit
		cmd.pluginModel.SpaceQuota.RoutesLimit = quota.RoutesLimit
		cmd.pluginModel.SpaceQuota.ServicesLimit = quota.ServicesLimit
		cmd.pluginModel.SpaceQuota.NonBasicServicesAllowed = quota.NonBasicServicesAllowed
	}
}
<commit_msg>Add color for space quota<commit_after>package space

import (
	"fmt"
	"strings"

	"github.com/cloudfoundry/cli/cf/commandregistry"
	. "github.com/cloudfoundry/cli/cf/i18n"
	"github.com/cloudfoundry/cli/cf/models"
	"github.com/cloudfoundry/cli/flags"
	"github.com/cloudfoundry/cli/plugin/models"

	"github.com/cloudfoundry/cli/cf/api/spacequotas"
	"github.com/cloudfoundry/cli/cf/configuration/coreconfig"
	"github.com/cloudfoundry/cli/cf/formatters"
	"github.com/cloudfoundry/cli/cf/requirements"
	"github.com/cloudfoundry/cli/cf/terminal"
)

type ShowSpace struct {
	ui          terminal.UI
	config      coreconfig.Reader
	spaceReq    requirements.SpaceRequirement
	quotaRepo   spacequotas.SpaceQuotaRepository
	pluginModel *plugin_models.GetSpace_Model
	pluginCall  bool
}

func init() {
	commandregistry.Register(&ShowSpace{})
}

func (cmd *ShowSpace) MetaData() commandregistry.CommandMetadata {
	fs := make(map[string]flags.FlagSet)
	fs["guid"] = &flags.BoolFlag{Name: "guid", Usage: T("Retrieve and display the given space's guid.  All other output for the space is suppressed.")}
	fs["security-group-rules"] = &flags.BoolFlag{Name: "security-group-rules", Usage: T("Retrieve the rules for all the security groups associated with the space")}
	return commandregistry.CommandMetadata{
		Name:        "space",
		Description: T("Show space info"),
		Usage: []string{
			T("CF_NAME space SPACE"),
		},
		Flags: fs,
	}
}

func (cmd *ShowSpace) Requirements(requirementsFactory requirements.Factory, fc flags.FlagContext) []requirements.Requirement {
	if len(fc.Args()) != 1 {
		cmd.ui.Failed(T("Incorrect Usage. Requires an argument\n\n") + commandregistry.Commands.CommandUsage("space"))
	}

	cmd.spaceReq = requirementsFactory.NewSpaceRequirement(fc.Args()[0])

	reqs := []requirements.Requirement{
		requirementsFactory.NewLoginRequirement(),
		requirementsFactory.NewTargetedOrgRequirement(),
		cmd.spaceReq,
	}

	return reqs
}

func (cmd *ShowSpace) SetDependency(deps commandregistry.Dependency, pluginCall bool) commandregistry.Command {
	cmd.ui = deps.UI
	cmd.config = deps.Config
	cmd.quotaRepo = deps.RepoLocator.GetSpaceQuotaRepository()
	cmd.pluginCall = pluginCall
	cmd.pluginModel = deps.PluginModels.Space
	return cmd
}

func (cmd *ShowSpace) Execute(c flags.FlagContext) error {
	space := cmd.spaceReq.GetSpace()
	if cmd.pluginCall {
		cmd.populatePluginModel(space)
		return nil
	}
	if c.Bool("guid") {
		cmd.ui.Say(space.GUID)
	} else {
		cmd.ui.Say(T("Getting info for space {{.TargetSpace}} in org {{.OrgName}} as {{.CurrentUser}}...",
			map[string]interface{}{
				"TargetSpace": terminal.EntityNameColor(space.Name),
				"OrgName":     terminal.EntityNameColor(space.Organization.Name),
				"CurrentUser": terminal.EntityNameColor(cmd.config.Username()),
			}))

		quotaString, err := cmd.quotaString(space)
		if err != nil {
			return err
		}

		cmd.ui.Ok()
		cmd.ui.Say("")
		table := cmd.ui.Table([]string{terminal.EntityNameColor(space.Name), "", ""})
		table.Add("", T("Org:"), terminal.EntityNameColor(space.Organization.Name))

		apps := []string{}
		for _, app := range space.Applications {
			apps = append(apps, terminal.EntityNameColor(app.Name))
		}
		table.Add("", T("Apps:"), strings.Join(apps, ", "))

		domains := []string{}
		for _, domain := range space.Domains {
			domains = append(domains, terminal.EntityNameColor(domain.Name))
		}
		table.Add("", T("Domains:"), strings.Join(domains, ", "))

		services := []string{}
		for _, service := range space.ServiceInstances {
			services = append(services, terminal.EntityNameColor(service.Name))
		}
		table.Add("", T("Services:"), strings.Join(services, ", "))

		securityGroups := []string{}
		for _, group := range space.SecurityGroups {
			securityGroups = append(securityGroups, terminal.EntityNameColor(group.Name))
		}
		table.Add("", T("Security Groups:"), strings.Join(securityGroups, ", "))

		table.Add("", T("Space Quota:"), terminal.EntityNameColor(quotaString))

		table.Print()
	}
	if c.Bool("security-group-rules") {
		cmd.ui.Say("")
		for _, group := range space.SecurityGroups {
			cmd.ui.Say(T("Getting rules for the security group  : {{.SecurityGroupName}}...",
				map[string]interface{}{"SecurityGroupName": terminal.EntityNameColor(group.Name)}))
			table := cmd.ui.Table([]string{"", "", "", ""})
			for _, rules := range group.Rules {
				for ruleName, ruleValue := range rules {
					table.Add("", ruleName, ":", fmt.Sprintf("%v", ruleValue))
				}
				table.Add("", "", "", "")
			}
			table.Print()
		}
	}

	return nil
}

func (cmd *ShowSpace) quotaString(space models.Space) (string, error) {
	if space.SpaceQuotaGUID == "" {
		return "", nil
	}

	quota, err := cmd.quotaRepo.FindByGUID(space.SpaceQuotaGUID)
	if err != nil {
		return "", err
	}

	spaceQuota := fmt.Sprintf(
		"%s (%s memory limit, %s instance memory limit, %d routes, %d services, paid services %s, %s app instance limit)",
		quota.Name,
		quota.FormattedMemoryLimit(),
		quota.FormattedInstanceMemoryLimit(),
		quota.RoutesLimit,
		quota.ServicesLimit,
		formatters.Allowed(quota.NonBasicServicesAllowed),
		T(quota.FormattedAppInstanceLimit()),
	)

	return spaceQuota, nil
}

func (cmd *ShowSpace) populatePluginModel(space models.Space) {
	cmd.pluginModel.Name = space.Name
	cmd.pluginModel.Guid = space.GUID

	cmd.pluginModel.Organization.Name = space.Organization.Name
	cmd.pluginModel.Organization.Guid = space.Organization.GUID

	for _, app := range space.Applications {
		a := plugin_models.GetSpace_Apps{
			Name: app.Name,
			Guid: app.GUID,
		}
		cmd.pluginModel.Applications = append(cmd.pluginModel.Applications, a)
	}

	for _, domain := range space.Domains {
		d := plugin_models.GetSpace_Domains{
			Name: domain.Name,
			Guid: domain.GUID,
			OwningOrganizationGuid: domain.OwningOrganizationGUID,
			Shared:                 domain.Shared,
		}
		cmd.pluginModel.Domains = append(cmd.pluginModel.Domains, d)
	}

	for _, service := range space.ServiceInstances {
		si := plugin_models.GetSpace_ServiceInstance{
			Name: service.Name,
			Guid: service.GUID,
		}
		cmd.pluginModel.ServiceInstances = append(cmd.pluginModel.ServiceInstances, si)
	}
	for _, group := range space.SecurityGroups {
		sg := plugin_models.GetSpace_SecurityGroup{
			Name:  group.Name,
			Guid:  group.GUID,
			Rules: group.Rules,
		}
		cmd.pluginModel.SecurityGroups = append(cmd.pluginModel.SecurityGroups, sg)
	}

	quota, err := cmd.quotaRepo.FindByGUID(space.SpaceQuotaGUID)
	if err == nil {
		cmd.pluginModel.SpaceQuota.Name = quota.Name
		cmd.pluginModel.SpaceQuota.Guid = quota.GUID
		cmd.pluginModel.SpaceQuota.MemoryLimit = quota.MemoryLimit
		cmd.pluginModel.SpaceQuota.InstanceMemoryLimit = quota.InstanceMemoryLimit
		cmd.pluginModel.SpaceQuota.RoutesLimit = quota.RoutesLimit
		cmd.pluginModel.SpaceQuota.ServicesLimit = quota.ServicesLimit
		cmd.pluginModel.SpaceQuota.NonBasicServicesAllowed = quota.NonBasicServicesAllowed
	}
}
<|endoftext|>