<commit_before>package flux

import (
	"io"
	"log"
	"sync/atomic"
)

type (

	//Stackable defines a stackable function type that can return a value
	Stackable func(interface{}, Stacks) interface{}

	//Stacks provides the finite definition of function stacks
	Stacks interface {
		Stack(Stackable) Stacks
		Unstack()
		Emit(interface{}) interface{}
		Mux(interface{}) interface{}
		getWrap() *StackWrap
	}

	//StackWrap provides a single-layer two function binder
	StackWrap struct {
		Fn    Stackable
		next  *StackWrap
		owner Stacks
	}

	//Stack is the concrete definition of Stacks
	Stack struct {
		wrap   *StackWrap
		root   Stacks
		active int64
	}

	//StackStreamers provides a streaming function for stacks member rules
	StackStreamers interface {
		Stacks
		StreamWriter(io.Writer) Stacks
		Write([]byte) (int, error)
		Read([]byte) (int, error)
		Close() error
		Closed() Stacks
	}

	//StackStream is the concrete implementation for stacks
	StackStream struct {
		Stacks
		closeNotifier Stacks
	}
)

var (
	//StackableIdentity provides an identity function for stacks
	StackableIdentity = func(b interface{}, _ Stacks) interface{} {
		return b
	}
)

//StreamReader streams from a reader,hence all values are replaced by the data in the io.Reader
func StreamReader(w io.Reader) (s StackStreamers) {
	s = NewStackStream(StackableIdentity)
	go func() {
		_, _ = io.Copy(s, w)
	}()
	return
}

//Read reads into a byte but its empty
func (s *StackStream) Read(bu []byte) (int, error) {
	return 0, io.ErrNoProgress
}

//Write writes into the stream
func (s *StackStream) Write(bu []byte) (int, error) {
	s.Emit(bu)
	return len(bu), nil
}

//StreamWriter streams to a writer
func (s *StackStream) StreamWriter(w io.Writer) Stacks {
	return s.Stack(func(data interface{}, _ Stacks) interface{} {
		buff, ok := data.([]byte)

		if !ok {

			str, ok := data.(string)

			if ok {
				_, _ = w.Write([]byte(str))
			}

		}
		_, _ = w.Write(buff)
		return data
	})
}

//Closed returns a stack that is emitted when closed
func (s *StackStream) Closed() Stacks {
	return s.closeNotifier
}

//Close ends this stacks connections
func (s *StackStream) Close() error {
	s.closeNotifier.Emit(true)
	s.Unstack()
	return nil
}

//NewStackStream returns a new stackstream
func NewStackStream(mx Stackable) StackStreamers {
	return &StackStream{
		Stacks:        NewStack(mx, nil),
		closeNotifier: NewStack(StackableIdentity, nil),
	}
}

// //Die sets this wrapper as garbage
// func (s *StackWrap) Free() {
// 	s.Fn,s.owner = nil,nil
// }

//Unwrap unwraps a Stackwrap for release
func (s *StackWrap) Unwrap() *StackWrap {
	nx := s.next
	s.next = nil
	return nx
}

//Rewrap wraps a new Stackwrap aw next
func (s *StackWrap) Rewrap(sc *StackWrap) *StackWrap {
	nx := s.Unwrap()
	s.next = sc
	return nx
}

//NewStackWrap returns a new Stackwrap
func NewStackWrap(fn Stackable, own Stacks) *StackWrap {
	return &StackWrap{Fn: fn, owner: own, next: nil}
}

//NewStack returns a new stack
func NewStack(fn Stackable, root Stacks) (s *Stack) {
	s = &Stack{
		active: 1,
		root:   root,
	}

	s.wrap = NewStackWrap(fn, s)
	return
}

//Emit sends a data into the stack and returns this stack
//returned value
func (s *Stack) Emit(b interface{}) interface{} {
	var res interface{}
	state := atomic.LoadInt64(&s.active)
	if state > 0 {
		res = s.wrap.Fn(b, s)
		if s.wrap.next != nil {
			if s.wrap.next.owner != nil {
				_ = s.wrap.next.owner.Emit(b)
			}
		}
	}
	return res
}

//Mux lets you mutate the next passed data to the next
//stack,that is this stack return value is the next stacks input
func (s *Stack) Mux(b interface{}) interface{} {
	var res interface{}
	state := atomic.LoadInt64(&s.active)
	if state > 0 {
		res = s.wrap.Fn(b, s)
		if s.wrap.next != nil {
			if s.wrap.next.owner != nil {
				s.wrap.next.owner.Emit(res)
			}
		}
	}
	return res
}

//Unstack disables and nullifies this stack
func (s *Stack) Unstack() {
	if s.root == nil {
		return
	}

	root := s.root
	nxt := s.wrap.next

	atomic.StoreInt64(&s.active, 0)
	root.getWrap().Rewrap(nxt)
	s.root = nil
}

//getWrap returns the stacks wrapper
func (s *Stack) getWrap() *StackWrap {
	return s.wrap
}

//Stack builds a new stack from this previous stack
func (s *Stack) Stack(fn Stackable) Stacks {
	if s.wrap.next != nil {
		return s.wrap.next.owner.Stack(fn)
	}
	m := NewStack(fn, s)
	s.wrap.next = m.wrap
	return m
}

//LogStack takes a stack and logs all input coming from it
func LogStack(s Stacks) Stacks {
	return s.Stack(func(data interface{}, _ Stacks) interface{} {
		log.Printf("LogStack: %+s", data)
		return data
	})
}

//LogStackWith logs all input using a custom logger
func LogStackWith(s Stacks, l *log.Logger) Stacks {
	return s.Stack(func(data interface{}, _ Stacks) interface{} {
		l.Printf("LogStack: %+s", data)
		return data
	})
}
<commit_msg>adding stack streams<commit_after>package flux

import (
	"io"
	"log"
	"sync/atomic"
)

type (

	//Stackable defines a stackable function type that can return a value
	Stackable func(interface{}, Stacks) interface{}

	//Stacks provides the finite definition of function stacks
	Stacks interface {
		Stack(Stackable) Stacks
		Unstack()
		Emit(interface{}) interface{}
		Mux(interface{}) interface{}
		getWrap() *StackWrap
	}

	//StackWrap provides a single-layer two function binder
	StackWrap struct {
		Fn    Stackable
		next  *StackWrap
		owner Stacks
	}

	//Stack is the concrete definition of Stacks
	Stack struct {
		wrap   *StackWrap
		root   Stacks
		active int64
	}

	//StackStreamers provides a streaming function for stacks member rules
	StackStreamers interface {
		Stacks
		StreamWriter(io.Writer) Stacks
		Write([]byte) (int, error)
		Read([]byte) (int, error)
		Close() error
		Closed() Stacks
	}

	//StackStream is the concrete implementation for stacks
	StackStream struct {
		Stacks
		closeNotifier Stacks
	}
)

var (
	//StackableIdentity provides an identity function for stacks
	StackableIdentity = func(b interface{}, _ Stacks) interface{} {
		return b
	}
)

//NewIdentityStream  returns new StackStream
func NewIdentityStream() StackStreamers {
	return NewStackStream(StackableIdentity)
}

//StreamReader streams from a reader,hence all values are replaced by the data in the io.Reader
func StreamReader(w io.Reader) (s StackStreamers) {
	s = NewStackStream(StackableIdentity)
	go func() {
		_, _ = io.Copy(s, w)
	}()
	return
}

//Read reads into a byte but its empty
func (s *StackStream) Read(bu []byte) (int, error) {
	return 0, io.ErrNoProgress
}

//Write writes into the stream
func (s *StackStream) Write(bu []byte) (int, error) {
	s.Emit(bu)
	return len(bu), nil
}

//StreamWriter streams to a writer
func (s *StackStream) StreamWriter(w io.Writer) Stacks {
	return s.Stack(func(data interface{}, _ Stacks) interface{} {
		buff, ok := data.([]byte)

		if !ok {

			str, ok := data.(string)

			if ok {
				_, _ = w.Write([]byte(str))
			}

		}
		_, _ = w.Write(buff)
		return data
	})
}

//Closed returns a stack that is emitted when closed
func (s *StackStream) Closed() Stacks {
	return s.closeNotifier
}

//Close ends this stacks connections
func (s *StackStream) Close() error {
	s.closeNotifier.Emit(true)
	s.Unstack()
	return nil
}

//NewStackStream returns a new stackstream
func NewStackStream(mx Stackable) StackStreamers {
	return &StackStream{
		Stacks:        NewStack(mx, nil),
		closeNotifier: NewStack(StackableIdentity, nil),
	}
}

// //Die sets this wrapper as garbage
// func (s *StackWrap) Free() {
// 	s.Fn,s.owner = nil,nil
// }

//Unwrap unwraps a Stackwrap for release
func (s *StackWrap) Unwrap() *StackWrap {
	nx := s.next
	s.next = nil
	return nx
}

//Rewrap wraps a new Stackwrap aw next
func (s *StackWrap) Rewrap(sc *StackWrap) *StackWrap {
	nx := s.Unwrap()
	s.next = sc
	return nx
}

//NewStackWrap returns a new Stackwrap
func NewStackWrap(fn Stackable, own Stacks) *StackWrap {
	return &StackWrap{Fn: fn, owner: own, next: nil}
}

//NewStack returns a new stack
func NewStack(fn Stackable, root Stacks) (s *Stack) {
	s = &Stack{
		active: 1,
		root:   root,
	}

	s.wrap = NewStackWrap(fn, s)
	return
}

//Emit sends a data into the stack and returns this stack
//returned value
func (s *Stack) Emit(b interface{}) interface{} {
	var res interface{}
	state := atomic.LoadInt64(&s.active)
	if state > 0 {
		res = s.wrap.Fn(b, s)
		if s.wrap.next != nil {
			if s.wrap.next.owner != nil {
				_ = s.wrap.next.owner.Emit(b)
			}
		}
	}
	return res
}

//Mux lets you mutate the next passed data to the next
//stack,that is this stack return value is the next stacks input
func (s *Stack) Mux(b interface{}) interface{} {
	var res interface{}
	state := atomic.LoadInt64(&s.active)
	if state > 0 {
		res = s.wrap.Fn(b, s)
		if s.wrap.next != nil {
			if s.wrap.next.owner != nil {
				s.wrap.next.owner.Emit(res)
			}
		}
	}
	return res
}

//Unstack disables and nullifies this stack
func (s *Stack) Unstack() {
	if s.root == nil {
		return
	}

	root := s.root
	nxt := s.wrap.next

	atomic.StoreInt64(&s.active, 0)
	root.getWrap().Rewrap(nxt)
	s.root = nil
}

//getWrap returns the stacks wrapper
func (s *Stack) getWrap() *StackWrap {
	return s.wrap
}

//Stack builds a new stack from this previous stack
func (s *Stack) Stack(fn Stackable) Stacks {
	if s.wrap.next != nil {
		return s.wrap.next.owner.Stack(fn)
	}
	m := NewStack(fn, s)
	s.wrap.next = m.wrap
	return m
}

//LogStack takes a stack and logs all input coming from it
func LogStack(s Stacks) Stacks {
	return s.Stack(func(data interface{}, _ Stacks) interface{} {
		log.Printf("LogStack: %+s", data)
		return data
	})
}

//LogStackWith logs all input using a custom logger
func LogStackWith(s Stacks, l *log.Logger) Stacks {
	return s.Stack(func(data interface{}, _ Stacks) interface{} {
		l.Printf("LogStack: %+s", data)
		return data
	})
}
<|endoftext|>


<commit_before>package agent

import (
	"bytes"
	"fmt"
	"github.com/hashicorp/consul/consul/structs"
	"io"
	"net/http"
	"strconv"
	"strings"
)

const (
	// maxKVSize is used to limit the maximum payload length
	// of a KV entry. If it exceeds this amount, the client is
	// likely abusing the KV store.
	maxKVSize = 512 * 1024
)

func (s *HTTPServer) KVSEndpoint(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
	// Set default DC
	args := structs.KeyRequest{}
	if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
		return nil, nil
	}

	// Pull out the key name, validation left to each sub-handler
	args.Key = strings.TrimPrefix(req.URL.Path, "/v1/kv/")

	// Check for a key list
	keyList := false
	params := req.URL.Query()
	if _, ok := params["keys"]; ok {
		keyList = true
	}

	// Switch on the method
	switch req.Method {
	case "GET":
		if keyList {
			return s.KVSGetKeys(resp, req, &args)
		} else {
			return s.KVSGet(resp, req, &args)
		}
	case "PUT":
		return s.KVSPut(resp, req, &args)
	case "DELETE":
		return s.KVSDelete(resp, req, &args)
	default:
		resp.WriteHeader(405)
		return nil, nil
	}
	return nil, nil
}

// KVSGet handles a GET request
func (s *HTTPServer) KVSGet(resp http.ResponseWriter, req *http.Request, args *structs.KeyRequest) (interface{}, error) {
	// Check for recurse
	method := "KVS.Get"
	params := req.URL.Query()
	if _, ok := params["recurse"]; ok {
		method = "KVS.List"
	} else if missingKey(resp, args) {
		return nil, nil
	}

	// Make the RPC
	var out structs.IndexedDirEntries
	if err := s.agent.RPC(method, &args, &out); err != nil {
		return nil, err
	}
	setMeta(resp, &out.QueryMeta)

	// Check if we get a not found
	if len(out.Entries) == 0 {
		resp.WriteHeader(404)
		return nil, nil
	}

	// Check if we are in raw mode with a normal get, write out
	// the raw body
	if _, ok := params["raw"]; ok && method == "KVS.Get" {
		body := out.Entries[0].Value
		resp.Header().Set("Content-Length", strconv.FormatInt(int64(len(body)), 10))
		resp.Write(body)
		return nil, nil
	}

	return out.Entries, nil
}

// KVSGetKeys handles a GET request for keys
func (s *HTTPServer) KVSGetKeys(resp http.ResponseWriter, req *http.Request, args *structs.KeyRequest) (interface{}, error) {
	// Check for a seperator, due to historic spelling error,
	// we now are forced to check for both spellings
	var sep string
	params := req.URL.Query()
	if _, ok := params["seperator"]; ok {
		sep = params.Get("seperator")
	}
	if _, ok := params["separator"]; ok {
		sep = params.Get("separator")
	}

	// Construct the args
	listArgs := structs.KeyListRequest{
		Datacenter:   args.Datacenter,
		Prefix:       args.Key,
		Seperator:    sep,
		QueryOptions: args.QueryOptions,
	}

	// Make the RPC
	var out structs.IndexedKeyList
	if err := s.agent.RPC("KVS.ListKeys", &listArgs, &out); err != nil {
		return nil, err
	}
	setMeta(resp, &out.QueryMeta)

	// Check if we get a not found. We do not generate
	// not found for the root, but just provide the empty list
	if len(out.Keys) == 0 && listArgs.Prefix != "" {
		resp.WriteHeader(404)
		return nil, nil
	}

	// Use empty list instead of null
	if out.Keys == nil {
		out.Keys = []string{}
	}
	return out.Keys, nil
}

// KVSPut handles a PUT request
func (s *HTTPServer) KVSPut(resp http.ResponseWriter, req *http.Request, args *structs.KeyRequest) (interface{}, error) {
	if missingKey(resp, args) {
		return nil, nil
	}
	applyReq := structs.KVSRequest{
		Datacenter: args.Datacenter,
		Op:         structs.KVSSet,
		DirEnt: structs.DirEntry{
			Key:   args.Key,
			Flags: 0,
			Value: nil,
		},
	}

	// Check for flags
	params := req.URL.Query()
	if _, ok := params["flags"]; ok {
		flagVal, err := strconv.ParseUint(params.Get("flags"), 10, 64)
		if err != nil {
			return nil, err
		}
		applyReq.DirEnt.Flags = flagVal
	}

	// Check for cas value
	if _, ok := params["cas"]; ok {
		casVal, err := strconv.ParseUint(params.Get("cas"), 10, 64)
		if err != nil {
			return nil, err
		}
		applyReq.DirEnt.ModifyIndex = casVal
		applyReq.Op = structs.KVSCAS
	}

	// Check for lock acquisition
	if _, ok := params["acquire"]; ok {
		applyReq.DirEnt.Session = params.Get("acquire")
		applyReq.Op = structs.KVSLock
	}

	// Check for lock release
	if _, ok := params["release"]; ok {
		applyReq.DirEnt.Session = params.Get("release")
		applyReq.Op = structs.KVSUnlock
	}

	// Check the content-length
	if req.ContentLength > maxKVSize {
		resp.WriteHeader(413)
		resp.Write([]byte(fmt.Sprintf("Value exceeds %d byte limit", maxKVSize)))
		return nil, nil
	}

	// Copy the value
	buf := bytes.NewBuffer(nil)
	if _, err := io.Copy(buf, req.Body); err != nil {
		return nil, err
	}
	applyReq.DirEnt.Value = buf.Bytes()

	// Make the RPC
	var out bool
	if err := s.agent.RPC("KVS.Apply", &applyReq, &out); err != nil {
		return nil, err
	}

	// Only use the out value if this was a CAS
	if applyReq.Op == structs.KVSSet {
		return true, nil
	} else {
		return out, nil
	}
}

// KVSPut handles a DELETE request
func (s *HTTPServer) KVSDelete(resp http.ResponseWriter, req *http.Request, args *structs.KeyRequest) (interface{}, error) {
	applyReq := structs.KVSRequest{
		Datacenter: args.Datacenter,
		Op:         structs.KVSDelete,
		DirEnt: structs.DirEntry{
			Key: args.Key,
		},
	}

	// Check for recurse
	params := req.URL.Query()
	if _, ok := params["recurse"]; ok {
		applyReq.Op = structs.KVSDeleteTree
	} else if missingKey(resp, args) {
		return nil, nil
	}

	// Make the RPC
	var out bool
	if err := s.agent.RPC("KVS.Apply", &applyReq, &out); err != nil {
		return nil, err
	}
	return nil, nil
}

// missingKey checks if the key is missing
func missingKey(resp http.ResponseWriter, args *structs.KeyRequest) bool {
	if args.Key == "" {
		resp.WriteHeader(400)
		resp.Write([]byte("Missing key name"))
		return true
	}
	return false
}
<commit_msg>agent: Copy token in KV PUT/DELETE<commit_after>package agent

import (
	"bytes"
	"fmt"
	"github.com/hashicorp/consul/consul/structs"
	"io"
	"net/http"
	"strconv"
	"strings"
)

const (
	// maxKVSize is used to limit the maximum payload length
	// of a KV entry. If it exceeds this amount, the client is
	// likely abusing the KV store.
	maxKVSize = 512 * 1024
)

func (s *HTTPServer) KVSEndpoint(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
	// Set default DC
	args := structs.KeyRequest{}
	if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
		return nil, nil
	}

	// Pull out the key name, validation left to each sub-handler
	args.Key = strings.TrimPrefix(req.URL.Path, "/v1/kv/")

	// Check for a key list
	keyList := false
	params := req.URL.Query()
	if _, ok := params["keys"]; ok {
		keyList = true
	}

	// Switch on the method
	switch req.Method {
	case "GET":
		if keyList {
			return s.KVSGetKeys(resp, req, &args)
		} else {
			return s.KVSGet(resp, req, &args)
		}
	case "PUT":
		return s.KVSPut(resp, req, &args)
	case "DELETE":
		return s.KVSDelete(resp, req, &args)
	default:
		resp.WriteHeader(405)
		return nil, nil
	}
	return nil, nil
}

// KVSGet handles a GET request
func (s *HTTPServer) KVSGet(resp http.ResponseWriter, req *http.Request, args *structs.KeyRequest) (interface{}, error) {
	// Check for recurse
	method := "KVS.Get"
	params := req.URL.Query()
	if _, ok := params["recurse"]; ok {
		method = "KVS.List"
	} else if missingKey(resp, args) {
		return nil, nil
	}

	// Make the RPC
	var out structs.IndexedDirEntries
	if err := s.agent.RPC(method, &args, &out); err != nil {
		return nil, err
	}
	setMeta(resp, &out.QueryMeta)

	// Check if we get a not found
	if len(out.Entries) == 0 {
		resp.WriteHeader(404)
		return nil, nil
	}

	// Check if we are in raw mode with a normal get, write out
	// the raw body
	if _, ok := params["raw"]; ok && method == "KVS.Get" {
		body := out.Entries[0].Value
		resp.Header().Set("Content-Length", strconv.FormatInt(int64(len(body)), 10))
		resp.Write(body)
		return nil, nil
	}

	return out.Entries, nil
}

// KVSGetKeys handles a GET request for keys
func (s *HTTPServer) KVSGetKeys(resp http.ResponseWriter, req *http.Request, args *structs.KeyRequest) (interface{}, error) {
	// Check for a seperator, due to historic spelling error,
	// we now are forced to check for both spellings
	var sep string
	params := req.URL.Query()
	if _, ok := params["seperator"]; ok {
		sep = params.Get("seperator")
	}
	if _, ok := params["separator"]; ok {
		sep = params.Get("separator")
	}

	// Construct the args
	listArgs := structs.KeyListRequest{
		Datacenter:   args.Datacenter,
		Prefix:       args.Key,
		Seperator:    sep,
		QueryOptions: args.QueryOptions,
	}

	// Make the RPC
	var out structs.IndexedKeyList
	if err := s.agent.RPC("KVS.ListKeys", &listArgs, &out); err != nil {
		return nil, err
	}
	setMeta(resp, &out.QueryMeta)

	// Check if we get a not found. We do not generate
	// not found for the root, but just provide the empty list
	if len(out.Keys) == 0 && listArgs.Prefix != "" {
		resp.WriteHeader(404)
		return nil, nil
	}

	// Use empty list instead of null
	if out.Keys == nil {
		out.Keys = []string{}
	}
	return out.Keys, nil
}

// KVSPut handles a PUT request
func (s *HTTPServer) KVSPut(resp http.ResponseWriter, req *http.Request, args *structs.KeyRequest) (interface{}, error) {
	if missingKey(resp, args) {
		return nil, nil
	}
	applyReq := structs.KVSRequest{
		Datacenter: args.Datacenter,
		Op:         structs.KVSSet,
		DirEnt: structs.DirEntry{
			Key:   args.Key,
			Flags: 0,
			Value: nil,
		},
	}
	applyReq.Token = args.Token

	// Check for flags
	params := req.URL.Query()
	if _, ok := params["flags"]; ok {
		flagVal, err := strconv.ParseUint(params.Get("flags"), 10, 64)
		if err != nil {
			return nil, err
		}
		applyReq.DirEnt.Flags = flagVal
	}

	// Check for cas value
	if _, ok := params["cas"]; ok {
		casVal, err := strconv.ParseUint(params.Get("cas"), 10, 64)
		if err != nil {
			return nil, err
		}
		applyReq.DirEnt.ModifyIndex = casVal
		applyReq.Op = structs.KVSCAS
	}

	// Check for lock acquisition
	if _, ok := params["acquire"]; ok {
		applyReq.DirEnt.Session = params.Get("acquire")
		applyReq.Op = structs.KVSLock
	}

	// Check for lock release
	if _, ok := params["release"]; ok {
		applyReq.DirEnt.Session = params.Get("release")
		applyReq.Op = structs.KVSUnlock
	}

	// Check the content-length
	if req.ContentLength > maxKVSize {
		resp.WriteHeader(413)
		resp.Write([]byte(fmt.Sprintf("Value exceeds %d byte limit", maxKVSize)))
		return nil, nil
	}

	// Copy the value
	buf := bytes.NewBuffer(nil)
	if _, err := io.Copy(buf, req.Body); err != nil {
		return nil, err
	}
	applyReq.DirEnt.Value = buf.Bytes()

	// Make the RPC
	var out bool
	if err := s.agent.RPC("KVS.Apply", &applyReq, &out); err != nil {
		return nil, err
	}

	// Only use the out value if this was a CAS
	if applyReq.Op == structs.KVSSet {
		return true, nil
	} else {
		return out, nil
	}
}

// KVSPut handles a DELETE request
func (s *HTTPServer) KVSDelete(resp http.ResponseWriter, req *http.Request, args *structs.KeyRequest) (interface{}, error) {
	applyReq := structs.KVSRequest{
		Datacenter: args.Datacenter,
		Op:         structs.KVSDelete,
		DirEnt: structs.DirEntry{
			Key: args.Key,
		},
	}
	applyReq.Token = args.Token

	// Check for recurse
	params := req.URL.Query()
	if _, ok := params["recurse"]; ok {
		applyReq.Op = structs.KVSDeleteTree
	} else if missingKey(resp, args) {
		return nil, nil
	}

	// Make the RPC
	var out bool
	if err := s.agent.RPC("KVS.Apply", &applyReq, &out); err != nil {
		return nil, err
	}
	return nil, nil
}

// missingKey checks if the key is missing
func missingKey(resp http.ResponseWriter, args *structs.KeyRequest) bool {
	if args.Key == "" {
		resp.WriteHeader(400)
		resp.Write([]byte("Missing key name"))
		return true
	}
	return false
}
<|endoftext|>


<commit_before>package features

import (
	"bytes"
	"errors"
	"fmt"
	"os"
	"sync"

	"github.com/cilium/ebpf"
	"github.com/cilium/ebpf/asm"
	"github.com/cilium/ebpf/internal"
	"github.com/cilium/ebpf/internal/sys"
	"github.com/cilium/ebpf/internal/unix"
)

func init() {
	pc.types = make(map[ebpf.ProgramType]error)
	pc.helpers = make(map[ebpf.ProgramType]map[asm.BuiltinFunc]error)
	allocHelperCache()
}

func allocHelperCache() {
	for pt := ebpf.UnspecifiedProgram + 1; pt <= pt.Max(); pt++ {
		pc.helpers[pt] = make(map[asm.BuiltinFunc]error)
	}
}

var (
	pc progCache
)

type progCache struct {
	typeMu sync.Mutex
	types  map[ebpf.ProgramType]error

	helperMu sync.Mutex
	helpers  map[ebpf.ProgramType]map[asm.BuiltinFunc]error
}

func createProgLoadAttr(pt ebpf.ProgramType, helper asm.BuiltinFunc) (*sys.ProgLoadAttr, error) {
	var expectedAttachType ebpf.AttachType
	var progFlags uint32

	insns := asm.Instructions{
		asm.LoadImm(asm.R0, 0, asm.DWord),
		asm.Return(),
	}

	if helper != asm.FnUnspec {
		insns = append(asm.Instructions{helper.Call()}, insns...)
	}

	buf := bytes.NewBuffer(make([]byte, 0, insns.Size()))
	if err := insns.Marshal(buf, internal.NativeEndian); err != nil {
		return nil, err
	}

	bytecode := buf.Bytes()
	instructions := sys.NewSlicePointer(bytecode)

	// Some programs have expected attach types which are checked during the
	// BPD_PROG_LOAD syscall.
	switch pt {
	case ebpf.CGroupSockAddr:
		expectedAttachType = ebpf.AttachCGroupInet4Connect
	case ebpf.CGroupSockopt:
		expectedAttachType = ebpf.AttachCGroupGetsockopt
	case ebpf.SkLookup:
		expectedAttachType = ebpf.AttachSkLookup
	case ebpf.Syscall:
		progFlags = unix.BPF_F_SLEEPABLE
	default:
		expectedAttachType = ebpf.AttachNone
	}

	// Kernels before 5.0 (6c4fc209fcf9 "bpf: remove useless version check for prog load")
	// require the version field to be set to the value of the KERNEL_VERSION
	// macro for kprobe-type programs.
	v, err := internal.KernelVersion()
	if err != nil {
		return nil, fmt.Errorf("detecting kernel version: %w", err)
	}

	return &sys.ProgLoadAttr{
		ProgType:           sys.ProgType(pt),
		Insns:              instructions,
		InsnCnt:            uint32(len(bytecode) / asm.InstructionSize),
		ProgFlags:          progFlags,
		ExpectedAttachType: sys.AttachType(expectedAttachType),
		License:            sys.NewStringPointer("GPL"),
		KernVersion:        v.Kernel(),
	}, nil
}

// HaveProgType probes the running kernel for the availability of the specified program type.
//
// Deprecated: use HaveProgramType() instead.
var HaveProgType = HaveProgramType

// HaveProgramType probes the running kernel for the availability of the specified program type.
//
// See the package documentation for the meaning of the error return value.
func HaveProgramType(pt ebpf.ProgramType) (err error) {
	defer func() {
		// This closure modifies a named return variable.
		err = wrapProbeErrors(err)
	}()

	if err := validateProgramType(pt); err != nil {
		return err
	}

	return haveProgramType(pt)

}

func validateProgramType(pt ebpf.ProgramType) error {
	if pt > pt.Max() {
		return os.ErrInvalid
	}

	if progLoadProbeNotImplemented(pt) {
		// A probe for a these prog types has BTF requirements we currently cannot meet
		// Once we figure out how to add a working probe in this package, we can remove
		// this check
		return fmt.Errorf("a probe for ProgType %s isn't implemented", pt.String())
	}

	return nil
}

func haveProgramType(pt ebpf.ProgramType) error {
	pc.typeMu.Lock()
	defer pc.typeMu.Unlock()
	if err, ok := pc.types[pt]; ok {
		return err
	}

	attr, err := createProgLoadAttr(pt, asm.FnUnspec)
	if err != nil {
		return fmt.Errorf("couldn't create the program load attribute: %w", err)
	}

	fd, err := sys.ProgLoad(attr)
	if fd != nil {
		fd.Close()
	}

	switch {
	// EINVAL occurs when attempting to create a program with an unknown type.
	// E2BIG occurs when ProgLoadAttr contains non-zero bytes past the end
	// of the struct known by the running kernel, meaning the kernel is too old
	// to support the given prog type.
	case errors.Is(err, unix.EINVAL), errors.Is(err, unix.E2BIG):
		err = ebpf.ErrNotSupported

	// ENOTSUPP means the program type is at least known to the kernel.
	case errors.Is(err, sys.ENOTSUPP):
		if pt == ebpf.StructOps {
			err = nil
		}
	}

	pc.types[pt] = err

	return err
}

// HaveProgramHelper probes the running kernel for the availability of the specified helper
// function to a specified program type.
// Return values have the following semantics:
//
//	err == nil: The feature is available.
//	errors.Is(err, ebpf.ErrNotSupported): The feature is not available.
//	err != nil: Any errors encountered during probe execution, wrapped.
//
// Note that the latter case may include false negatives, and that program creation may
// succeed despite an error being returned.
// Only `nil` and `ebpf.ErrNotSupported` are conclusive.
//
// Probe results are cached and persist throughout any process capability changes.
func HaveProgramHelper(pt ebpf.ProgramType, helper asm.BuiltinFunc) (err error) {
	defer func() {
		// This closure modifies a named return variable.
		err = wrapProbeErrors(err)
	}()

	if err := validateProgramType(pt); err != nil {
		return err
	}

	if err := validateProgramHelper(helper); err != nil {
		return err
	}

	return haveProgramHelper(pt, helper)
}

func validateProgramHelper(helper asm.BuiltinFunc) error {
	if helper > helper.Max() {
		return os.ErrInvalid
	}

	return nil
}

func haveProgramHelper(pt ebpf.ProgramType, helper asm.BuiltinFunc) error {
	pc.helperMu.Lock()
	defer pc.helperMu.Unlock()
	if err, ok := pc.helpers[pt][helper]; ok {
		return err
	}

	attr, err := createProgLoadAttr(pt, helper)
	if err != nil {
		return fmt.Errorf("couldn't create the program load attribute: %w", err)
	}

	fd, err := sys.ProgLoad(attr)
	if fd != nil {
		fd.Close()
	}

	switch {
	// EACCES occurs when attempting to create a program probe with a helper
	// while the register args when calling this helper aren't set up properly.
	// We interpret this as the helper being available, because the verifier
	// returns EINVAL if the helper is not supported by the running kernel.
	case errors.Is(err, unix.EACCES):
		// TODO: possibly we need to check verifier output here to be sure
		err = nil

	// EINVAL occurs when attempting to create a program with an unknown helper.
	// E2BIG occurs when BPFProgLoadAttr contains non-zero bytes past the end
	// of the struct known by the running kernel, meaning the kernel is too old
	// to support the given prog type.
	case errors.Is(err, unix.EINVAL), errors.Is(err, unix.E2BIG):
		// TODO: possibly we need to check verifier output here to be sure
		err = ebpf.ErrNotSupported
	}

	pc.helpers[pt][helper] = err

	return err
}

func progLoadProbeNotImplemented(pt ebpf.ProgramType) bool {
	switch pt {
	case ebpf.Tracing, ebpf.Extension, ebpf.LSM:
		return true
	}
	return false
}
<commit_msg>features: fix typo in createProgLoadAttr<commit_after>package features

import (
	"bytes"
	"errors"
	"fmt"
	"os"
	"sync"

	"github.com/cilium/ebpf"
	"github.com/cilium/ebpf/asm"
	"github.com/cilium/ebpf/internal"
	"github.com/cilium/ebpf/internal/sys"
	"github.com/cilium/ebpf/internal/unix"
)

func init() {
	pc.types = make(map[ebpf.ProgramType]error)
	pc.helpers = make(map[ebpf.ProgramType]map[asm.BuiltinFunc]error)
	allocHelperCache()
}

func allocHelperCache() {
	for pt := ebpf.UnspecifiedProgram + 1; pt <= pt.Max(); pt++ {
		pc.helpers[pt] = make(map[asm.BuiltinFunc]error)
	}
}

var (
	pc progCache
)

type progCache struct {
	typeMu sync.Mutex
	types  map[ebpf.ProgramType]error

	helperMu sync.Mutex
	helpers  map[ebpf.ProgramType]map[asm.BuiltinFunc]error
}

func createProgLoadAttr(pt ebpf.ProgramType, helper asm.BuiltinFunc) (*sys.ProgLoadAttr, error) {
	var expectedAttachType ebpf.AttachType
	var progFlags uint32

	insns := asm.Instructions{
		asm.LoadImm(asm.R0, 0, asm.DWord),
		asm.Return(),
	}

	if helper != asm.FnUnspec {
		insns = append(asm.Instructions{helper.Call()}, insns...)
	}

	buf := bytes.NewBuffer(make([]byte, 0, insns.Size()))
	if err := insns.Marshal(buf, internal.NativeEndian); err != nil {
		return nil, err
	}

	bytecode := buf.Bytes()
	instructions := sys.NewSlicePointer(bytecode)

	// Some programs have expected attach types which are checked during the
	// BPF_PROG_LOAD syscall.
	switch pt {
	case ebpf.CGroupSockAddr:
		expectedAttachType = ebpf.AttachCGroupInet4Connect
	case ebpf.CGroupSockopt:
		expectedAttachType = ebpf.AttachCGroupGetsockopt
	case ebpf.SkLookup:
		expectedAttachType = ebpf.AttachSkLookup
	case ebpf.Syscall:
		progFlags = unix.BPF_F_SLEEPABLE
	default:
		expectedAttachType = ebpf.AttachNone
	}

	// Kernels before 5.0 (6c4fc209fcf9 "bpf: remove useless version check for prog load")
	// require the version field to be set to the value of the KERNEL_VERSION
	// macro for kprobe-type programs.
	v, err := internal.KernelVersion()
	if err != nil {
		return nil, fmt.Errorf("detecting kernel version: %w", err)
	}

	return &sys.ProgLoadAttr{
		ProgType:           sys.ProgType(pt),
		Insns:              instructions,
		InsnCnt:            uint32(len(bytecode) / asm.InstructionSize),
		ProgFlags:          progFlags,
		ExpectedAttachType: sys.AttachType(expectedAttachType),
		License:            sys.NewStringPointer("GPL"),
		KernVersion:        v.Kernel(),
	}, nil
}

// HaveProgType probes the running kernel for the availability of the specified program type.
//
// Deprecated: use HaveProgramType() instead.
var HaveProgType = HaveProgramType

// HaveProgramType probes the running kernel for the availability of the specified program type.
//
// See the package documentation for the meaning of the error return value.
func HaveProgramType(pt ebpf.ProgramType) (err error) {
	defer func() {
		// This closure modifies a named return variable.
		err = wrapProbeErrors(err)
	}()

	if err := validateProgramType(pt); err != nil {
		return err
	}

	return haveProgramType(pt)

}

func validateProgramType(pt ebpf.ProgramType) error {
	if pt > pt.Max() {
		return os.ErrInvalid
	}

	if progLoadProbeNotImplemented(pt) {
		// A probe for a these prog types has BTF requirements we currently cannot meet
		// Once we figure out how to add a working probe in this package, we can remove
		// this check
		return fmt.Errorf("a probe for ProgType %s isn't implemented", pt.String())
	}

	return nil
}

func haveProgramType(pt ebpf.ProgramType) error {
	pc.typeMu.Lock()
	defer pc.typeMu.Unlock()
	if err, ok := pc.types[pt]; ok {
		return err
	}

	attr, err := createProgLoadAttr(pt, asm.FnUnspec)
	if err != nil {
		return fmt.Errorf("couldn't create the program load attribute: %w", err)
	}

	fd, err := sys.ProgLoad(attr)
	if fd != nil {
		fd.Close()
	}

	switch {
	// EINVAL occurs when attempting to create a program with an unknown type.
	// E2BIG occurs when ProgLoadAttr contains non-zero bytes past the end
	// of the struct known by the running kernel, meaning the kernel is too old
	// to support the given prog type.
	case errors.Is(err, unix.EINVAL), errors.Is(err, unix.E2BIG):
		err = ebpf.ErrNotSupported

	// ENOTSUPP means the program type is at least known to the kernel.
	case errors.Is(err, sys.ENOTSUPP):
		if pt == ebpf.StructOps {
			err = nil
		}
	}

	pc.types[pt] = err

	return err
}

// HaveProgramHelper probes the running kernel for the availability of the specified helper
// function to a specified program type.
// Return values have the following semantics:
//
//	err == nil: The feature is available.
//	errors.Is(err, ebpf.ErrNotSupported): The feature is not available.
//	err != nil: Any errors encountered during probe execution, wrapped.
//
// Note that the latter case may include false negatives, and that program creation may
// succeed despite an error being returned.
// Only `nil` and `ebpf.ErrNotSupported` are conclusive.
//
// Probe results are cached and persist throughout any process capability changes.
func HaveProgramHelper(pt ebpf.ProgramType, helper asm.BuiltinFunc) (err error) {
	defer func() {
		// This closure modifies a named return variable.
		err = wrapProbeErrors(err)
	}()

	if err := validateProgramType(pt); err != nil {
		return err
	}

	if err := validateProgramHelper(helper); err != nil {
		return err
	}

	return haveProgramHelper(pt, helper)
}

func validateProgramHelper(helper asm.BuiltinFunc) error {
	if helper > helper.Max() {
		return os.ErrInvalid
	}

	return nil
}

func haveProgramHelper(pt ebpf.ProgramType, helper asm.BuiltinFunc) error {
	pc.helperMu.Lock()
	defer pc.helperMu.Unlock()
	if err, ok := pc.helpers[pt][helper]; ok {
		return err
	}

	attr, err := createProgLoadAttr(pt, helper)
	if err != nil {
		return fmt.Errorf("couldn't create the program load attribute: %w", err)
	}

	fd, err := sys.ProgLoad(attr)
	if fd != nil {
		fd.Close()
	}

	switch {
	// EACCES occurs when attempting to create a program probe with a helper
	// while the register args when calling this helper aren't set up properly.
	// We interpret this as the helper being available, because the verifier
	// returns EINVAL if the helper is not supported by the running kernel.
	case errors.Is(err, unix.EACCES):
		// TODO: possibly we need to check verifier output here to be sure
		err = nil

	// EINVAL occurs when attempting to create a program with an unknown helper.
	// E2BIG occurs when BPFProgLoadAttr contains non-zero bytes past the end
	// of the struct known by the running kernel, meaning the kernel is too old
	// to support the given prog type.
	case errors.Is(err, unix.EINVAL), errors.Is(err, unix.E2BIG):
		// TODO: possibly we need to check verifier output here to be sure
		err = ebpf.ErrNotSupported
	}

	pc.helpers[pt][helper] = err

	return err
}

func progLoadProbeNotImplemented(pt ebpf.ProgramType) bool {
	switch pt {
	case ebpf.Tracing, ebpf.Extension, ebpf.LSM:
		return true
	}
	return false
}
<|endoftext|>


<commit_before>/*
package aead uses aead crypto to encrypt and authenticate content composed of a plaintext metadata string and a plaintext data string.
An encryption results in a string literal of the form <b64URLmetadata>.<b64URLciphertext>.<b64URLnonce>. The user of this package must supply a
crypto.AEAD created with the same key in order to encrypt, transmit and decrypt a literal produced by Encrypt.
*/
package aead

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"encoding/base64"
	"fmt"
	"strings"
)

/*
NewAEADCipher creates a new AEAD cipher using an aes cipher created with a 32 byte random key for use with this package
*/
func NewAEADCipher() (cipher.AEAD, error) {
	var (
		key         = make([]byte, 32)
		cipherBlock cipher.Block
		aeadCipher  cipher.AEAD
		err         error
	)

	//Create a new key
	_, err = rand.Read(key)
	if err != nil {
		return nil, err
	}
	//The key is used to create an AES Cipher Block
	cipherBlock, err = aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	//The AES Cipher Block is used to create an AEAD GCM which is a 128-bit, block cipher wrapped
	//in a Galois Counter Mode with the standard nonce length.
	//This is used to encrypt/decrypt all subscriber identifiers in the hidden fields of TBD 2nd Factor Selection Forms.
	aeadCipher, err = cipher.NewGCM(cipherBlock)
	if err != nil {
		return nil, err
	}
	return aeadCipher, nil
}

/*
Encrypt generates a literal of the form <b64URLmetadata>.<b64URLciphertext>.<b64URLnonce> given an AEAD, a metadata string and a data
string. Only the data is encrypted - the metadata must be appropriate to expose in the clear. Each call generates a random
nonce of the length required by the aeadCipher.
*/
func Encrypt(aeadCipher cipher.AEAD, metadata, data string) (string, error) {

	var (
		nonce         = make([]byte, aeadCipher.NonceSize())
		ciphertext    []byte
		b64metadata   []byte
		b64ciphertext []byte
		b64nonce      []byte
		buf           bytes.Buffer
		err           error
	)

	//A nonce of the length required by the AEAD is generated
	_, err = rand.Read(nonce)
	if err != nil {
		return "", err
	}

	//Seal encrypts the data using the aeadCipher's key and the nonce and appends an authentication code for the metadata
	ciphertext = aeadCipher.Seal(ciphertext, nonce, []byte(data), []byte(metadata))

	//Base64 Encode metadata, ciphertext and nonce
	b64metadata = make([]byte, base64.URLEncoding.EncodedLen(len([]byte(metadata))))
	base64.StdEncoding.Encode(b64metadata, []byte(metadata))
	b64ciphertext = make([]byte, base64.URLEncoding.EncodedLen(len(ciphertext)))
	base64.URLEncoding.Encode(b64ciphertext, ciphertext)
	b64nonce = make([]byte, base64.URLEncoding.EncodedLen(len(nonce)))
	base64.URLEncoding.Encode(b64nonce, nonce)

	//Compose a <b64URLmetadata>.<b64URLciphertext>.<b64URLnonce> literal
	buf.Write(b64metadata)
	buf.Write([]byte("."))
	buf.Write(b64ciphertext)
	buf.Write([]byte("."))
	buf.Write(b64nonce)

	//Return the AEAD literal
	return string(buf.Bytes()), nil
}

/*
Decrypt decrypts a literal of the form <b64URLmetadata>.<b64URLciphertext>.<b64URLnonce> given an AEAD and
producing metadata, data strings
*/
func Decrypt(aeadCipher cipher.AEAD, literal string) (string, string, error) {
	var (
		literalSubStrings []string
		metadata          []byte
		ciphertext        []byte
		nonce             []byte
		data              []byte
		err               error
	)

	//Split the literal into its base64 encoded metadata, ciphertext and nonce components
	literalSubStrings = strings.Split(literal, ".")
	if len(literalSubStrings) != 3 {
		return "", "", fmt.Errorf("Bad AEAD Literal: %v\n", literal)
	}

	//Decode the metadata, ciphertext and nonce
	metadata, err = base64.URLEncoding.DecodeString(literalSubStrings[0])
	if err != nil {
		return "", "", fmt.Errorf("Decode metadata failed: %v\n", literal)
	}
	ciphertext, err = base64.URLEncoding.DecodeString(literalSubStrings[1])
	if err != nil {
		return "", "", fmt.Errorf("Decode ciphertext failed: %v\n", literal)
	}
	nonce, err = base64.URLEncoding.DecodeString(literalSubStrings[2])
	if err != nil {
		return "", "", fmt.Errorf("Decode nonce failed: %v\n", literal)
	}

	//Open validates the integrity of the metadata using the authentication code in the ciphertext
	//and, if valid, decrypts the ciphertext
	data, err = aeadCipher.Open(data, nonce, ciphertext, metadata)
	if err != nil {
		return "", "", err
	}
	return string(metadata), string(data), nil
}
<commit_msg>Revised NewAEADCipher to accept and existing AES key in addition to generating one<commit_after>/*
package aead uses AEAD crypto with AES keys to encrypt and authenticate content composed of a plaintext metadata string and a plaintext data string.
An encryption results in a string literal of the form <b64URLmetadata>.<b64URLciphertext>.<b64URLnonce>.
*/
package aead

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"encoding/base64"
	"fmt"
	"strings"
)

/*
NewAEADCipher creates a new AEAD cipher using the provided AES key.
The key argument should be either 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256.

If the key is nil, a new 32 byte AES key is generated.
This option is used when the scope of key use is limited to within a single program execution.
*/
func NewAEADCipher(key []byte) (cipher.AEAD, error) {
	var (
		keyval      []byte
		cipherBlock cipher.Block
		aeadCipher  cipher.AEAD
		err         error
	)

	//If no key is provided, generate one.
	if key == nil {
		keyval = make([]byte, 32)
		_, err = rand.Read(keyval)
		if err != nil {
			return nil, err
		}
	} else {
		switch len(key) {
		case 16, 24, 36:
		default:
			return nil, fmt.Errorf("An aead key must be of length 16. 24, or 32. This key is of length: ", len(key))
		}
		keyval = key
	}

	//The key is used to create an AES Cipher Block
	cipherBlock, err = aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	//The AES Cipher Block is used to create an AEAD GCM which is a 128-bit, block cipher wrapped
	//in a Galois Counter Mode with the standard nonce length.
	//This is used to encrypt/decrypt all subscriber identifiers in the hidden fields of TBD 2nd Factor Selection Forms.
	aeadCipher, err = cipher.NewGCM(cipherBlock)
	if err != nil {
		return nil, err
	}
	return aeadCipher, nil
}

/*
Encrypt generates a literal of the form <b64URLmetadata>.<b64URLciphertext>.<b64URLnonce> given an AEAD cipher, a metadata string and a data
string. Only the data is encrypted - the metadata must be appropriate to expose in the clear. Each call generates a random
nonce of the length required by the cipher.
*/
func Encrypt(aeadCipher cipher.AEAD, metadata, data string) (string, error) {

	var (
		nonce         = make([]byte, aeadCipher.NonceSize())
		ciphertext    []byte
		b64metadata   []byte
		b64ciphertext []byte
		b64nonce      []byte
		buf           bytes.Buffer
		err           error
	)

	//A nonce of the length required by the AEAD is generated
	_, err = rand.Read(nonce)
	if err != nil {
		return "", err
	}

	//Seal encrypts the data using the aeadCipher's key and the nonce and appends an authentication code for the metadata
	ciphertext = aeadCipher.Seal(ciphertext, nonce, []byte(data), []byte(metadata))

	//Base64 Encode metadata, ciphertext and nonce
	b64metadata = make([]byte, base64.URLEncoding.EncodedLen(len([]byte(metadata))))
	base64.StdEncoding.Encode(b64metadata, []byte(metadata))
	b64ciphertext = make([]byte, base64.URLEncoding.EncodedLen(len(ciphertext)))
	base64.URLEncoding.Encode(b64ciphertext, ciphertext)
	b64nonce = make([]byte, base64.URLEncoding.EncodedLen(len(nonce)))
	base64.URLEncoding.Encode(b64nonce, nonce)

	//Compose a <b64URLmetadata>.<b64URLciphertext>.<b64URLnonce> literal
	buf.Write(b64metadata)
	buf.Write([]byte("."))
	buf.Write(b64ciphertext)
	buf.Write([]byte("."))
	buf.Write(b64nonce)

	//Return the AEAD literal
	return string(buf.Bytes()), nil
}

/*
Decrypt decrypts a literal of the form <b64URLmetadata>.<b64URLciphertext>.<b64URLnonce> given an AEAD cipher and
produces a metadata and data string.
*/
func Decrypt(aeadCipher cipher.AEAD, literal string) (string, string, error) {
	var (
		literalSubStrings []string
		metadata          []byte
		ciphertext        []byte
		nonce             []byte
		data              []byte
		err               error
	)

	//Split the literal into its base64 encoded metadata, ciphertext and nonce components
	literalSubStrings = strings.Split(literal, ".")
	if len(literalSubStrings) != 3 {
		return "", "", fmt.Errorf("Bad AEAD Literal: %v\n", literal)
	}

	//Decode the metadata, ciphertext and nonce
	metadata, err = base64.URLEncoding.DecodeString(literalSubStrings[0])
	if err != nil {
		return "", "", fmt.Errorf("Decode metadata failed: %v\n", literal)
	}
	ciphertext, err = base64.URLEncoding.DecodeString(literalSubStrings[1])
	if err != nil {
		return "", "", fmt.Errorf("Decode ciphertext failed: %v\n", literal)
	}
	nonce, err = base64.URLEncoding.DecodeString(literalSubStrings[2])
	if err != nil {
		return "", "", fmt.Errorf("Decode nonce failed: %v\n", literal)
	}

	//Open validates the integrity of the metadata using the authentication code in the ciphertext
	//and, if valid, decrypts the ciphertext
	data, err = aeadCipher.Open(data, nonce, ciphertext, metadata)
	if err != nil {
		return "", "", err
	}
	return string(metadata), string(data), nil
}
<|endoftext|>


<commit_before>// Copyright 2014, Joel Scoble, all rights reserved.
// Licensed under The MIT License. Please view the LICENSE file for more
// information.
//
package shuffler

import (
	"crypto/rand"
	"math/big"
)

// ShuffleInterface randomizes an interface slice
func ShuffleInterface(c []interface{}) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// ShuffleByte randomizes a byte slice.
func ShuffleByte(c []byte) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// ShuffleComplex64 randomizes a complex64 slice.
func ShuffleComplex64(c []complex64) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// ShuffleComplex129 randomizes a complex128 slice.
func ShuffleComplex128(c []complex128) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// ShuffleFloat32 randomizes a float32 slice.
func ShuffleFloat32(c []float32) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// ShuffleFloat64 randomizes a float64 slice.
func ShuffleFloat64(c []float64) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// ShuffleInt randomizes an int slice.
func ShuffleInt(c []int) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// ShuffleInt8 randomizes an int8 slice.
func ShuffleInt8(c []int8) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// ShuffleInt16 randomizes an int16 slice.
func ShuffleInt16(c []int16) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// ShuffleInt32 randomizes an int32 slice.
func ShuffleInt32(c []int32) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// ShuffleInt64 randomizes an int64 slice.
func ShuffleInt64(c []int64) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// ShuffleString randomizes a strings slice.
func ShuffleString(c []string) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// ShuffleUint randomizes an uint slice.
func ShuffleUint(c []uint) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// ShuffleUint8 randomizes an uint8 slice.
func ShuffleUint8(c []uint8) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// ShuffleUint16 randomizes an uint16 slice.
func ShuffleUint16(c []uint16) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// ShuffleUint32 randomizes an uint32 slice.
func ShuffleUint32(c []uint32) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// ShuffleUint64 randomizes an uint64 slice.
func ShuffleUint64(c []uint64) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}
<commit_msg>update func names to reduce stutter<commit_after>// Copyright 2014, Joel Scoble, all rights reserved.
// Licensed under The MIT License. Please view the LICENSE file for more
// information.
//
package shuffler

import (
	"crypto/rand"
	"math/big"
)

// Interface randomizes an interface slice
func Interface(c []interface{}) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// Byte randomizes a byte slice.
func Byte(c []byte) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// Complex64 randomizes a complex64 slice.
func Complex64(c []complex64) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// Complex129 randomizes a complex128 slice.
func Complex128(c []complex128) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// Float32 randomizes a float32 slice.
func Float32(c []float32) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// Float64 randomizes a float64 slice.
func Float64(c []float64) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// Int randomizes an int slice.
func Int(c []int) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// Int8 randomizes an int8 slice.
func Int8(c []int8) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// Int16 randomizes an int16 slice.
func Int16(c []int16) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// Int32 randomizes an int32 slice.
func Int32(c []int32) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// Int64 randomizes an int64 slice.
func Int64(c []int64) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// String randomizes a strings slice.
func String(c []string) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// Uint randomizes an uint slice.
func Uint(c []uint) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// Uint8 randomizes an uint8 slice.
func Uint8(c []uint8) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// Uint16 randomizes an uint16 slice.
func Uint16(c []uint16) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// Uint32 randomizes an uint32 slice.
func Uint32(c []uint32) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}

// Uint64 randomizes an uint64 slice.
func Uint64(c []uint64) error {
	b := new(big.Int)
	for i := len(c) - 1; i >= 0; i-- {
		b = b.SetInt64(int64(i+1))
		j, err := rand.Int(rand.Reader, b)
		if err != nil {
			return err
		}
		if i != int(j.Int64()) {
			c[int(j.Int64())], c[i] = c[i], c[int(j.Int64())]
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package ali

import (
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/base64"
	"encoding/json"
	"encoding/pem"
	"fmt"
	"net/url"
	"reflect"
	"sort"
	"strings"
	"time"
)

func urlValues(c *Client, param PayParam) url.Values {
	values := url.Values{}
	values.Add("app_id", c.config.AppID)
	values.Add("method", param.URI())
	values.Add("format", "JSON")
	values.Add("charset", "utf-8")
	values.Add("sign_type", c.config.SignType)
	values.Add("timestamp", generateTimestampStr())
	values.Add("version", "1.0")
	values.Add("biz_content", param.BizContent())

	for k, v := range param.ExtraParams() {
		values.Add(k, v)
	}

	var keys []string
	for k := range values {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	values.Add("sign", signature(keys, values, c.config.AppPrivateKey, c.config.SignType))
	return values
}

func signature(keys []string, values url.Values, privateKey []byte, signType string) string {
	if values == nil {
		values = url.Values{}
	}

	var valueList []string
	for _, k := range keys {
		v := strings.TrimSpace(values.Get(k))
		if v != "" {
			valueList = append(valueList, fmt.Sprintf("%s=%s", k, v))
		}
	}

	concat := strings.Join(valueList, "&")

	var sign string
	if signType == "RSA" {
		sign = signPKCS1v15([]byte(concat), privateKey, crypto.SHA1)
	} else if signType == "RSA2" {
		sign = signPKCS1v15([]byte(concat), privateKey, crypto.SHA256)
	}
	return sign
}

func signPKCS1v15(source, privateKey []byte, hash crypto.Hash) string {
	block, _ := pem.Decode(privateKey)
	if block == nil {
		fmt.Println("BLOCK", block, len(privateKey))
		return ""
	}

	rsaPrivateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
	// rsaPrivateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
	if err != nil {
		fmt.Println("RSAPRIVATE", err)
		return ""
	}

	h := hash.New()
	h.Write(source)
	hashed := h.Sum(nil)

	s, err := rsa.SignPKCS1v15(rand.Reader, rsaPrivateKey, hash, hashed)
	// s, err := rsa.SignPKCS1v15(rand.Reader, rsaPrivateKey.(*rsa.PrivateKey), hash, hashed)
	if err != nil {
		fmt.Println("SIGNPKCS", err)
		return ""
	}
	return base64.StdEncoding.EncodeToString(s)
}

func verify(values url.Values, publicKey []byte, signType string) bool {
	var excluded []string
	for k := range values {
		if k == "sign" || k == "sign_type" {
			continue
		}
		excluded = append(excluded, k)
	}
	sort.Strings(excluded)

	var valueList []string
	for _, k := range excluded {
		v := values.Get(k)
		if v != "" {
			valueList = append(valueList, fmt.Sprintf("%s=%s", k, v))
		}
	}
	concat := strings.Join(valueList, "&")

	decoded, err := base64.StdEncoding.DecodeString(values.Get("sign"))
	if err != nil {
		return false
	}

	fmt.Println("EXCLUDED", excluded)
	fmt.Println("CONCAT", concat)
	var ok bool
	if signType == "RSA" {
		ok = verifyPKCS1v15([]byte(concat), decoded, publicKey, crypto.SHA1)
	} else if signType == "RSA2" {
		ok = verifyPKCS1v15([]byte(concat), decoded, publicKey, crypto.SHA256)
	}
	return ok
}

func verifyPKCS1v15(source, sign, publicKey []byte, hash crypto.Hash) bool {
	h := hash.New()
	h.Write(source)
	hashed := h.Sum(nil)

	block, _ := pem.Decode(publicKey)
	if block == nil {
		fmt.Println("VERIFY BLOCK", block)
		return false
	}

	pub, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		fmt.Println("ParsePKIXPublicKey", err)
		return false
	}

	rsaPublicKey := pub.(*rsa.PublicKey)
	err = rsa.VerifyPKCS1v15(rsaPublicKey, hash, hashed, sign)
	if err != nil {
		fmt.Println("VerifyPKCS1v15", err)
		return false
	}
	return true
}

func generateTimestampStr() string {
	now := time.Now()
	year, month, day := now.Date()
	hour, min, sec := now.Clock()
	return fmt.Sprintf("%d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, min, sec)
}

func marshalJSON(val interface{}) string {
	data, err := json.Marshal(val)
	if err != nil {
		return ""
	}
	return string(data)
}

func toValues(st interface{}) (url.Values, error) {
	val := reflect.ValueOf(st)
	if val.Kind() == reflect.Ptr {
		val = val.Elem()
	}

	if val.Kind() != reflect.Struct {
		return nil, fmt.Errorf("need a struct type, got %T", st)
	}

	typ := val.Type()
	result := url.Values{}

	for i := 0; i < val.NumField(); i++ {
		sf := typ.Field(i)
		if tag, ok := sf.Tag.Lookup("json"); ok && tag != "" {
			result.Add(tag, val.Field(i).String())
		}
	}
	return result, nil
}
<commit_msg>return true<commit_after>package ali

import (
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/base64"
	"encoding/json"
	"encoding/pem"
	"fmt"
	"net/url"
	"reflect"
	"sort"
	"strings"
	"time"
)

func urlValues(c *Client, param PayParam) url.Values {
	values := url.Values{}
	values.Add("app_id", c.config.AppID)
	values.Add("method", param.URI())
	values.Add("format", "JSON")
	values.Add("charset", "utf-8")
	values.Add("sign_type", c.config.SignType)
	values.Add("timestamp", generateTimestampStr())
	values.Add("version", "1.0")
	values.Add("biz_content", param.BizContent())

	for k, v := range param.ExtraParams() {
		values.Add(k, v)
	}

	var keys []string
	for k := range values {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	values.Add("sign", signature(keys, values, c.config.AppPrivateKey, c.config.SignType))
	return values
}

func signature(keys []string, values url.Values, privateKey []byte, signType string) string {
	if values == nil {
		values = url.Values{}
	}

	var valueList []string
	for _, k := range keys {
		v := strings.TrimSpace(values.Get(k))
		if v != "" {
			valueList = append(valueList, fmt.Sprintf("%s=%s", k, v))
		}
	}

	concat := strings.Join(valueList, "&")

	var sign string
	if signType == "RSA" {
		sign = signPKCS1v15([]byte(concat), privateKey, crypto.SHA1)
	} else if signType == "RSA2" {
		sign = signPKCS1v15([]byte(concat), privateKey, crypto.SHA256)
	}
	return sign
}

func signPKCS1v15(source, privateKey []byte, hash crypto.Hash) string {
	block, _ := pem.Decode(privateKey)
	if block == nil {
		fmt.Println("BLOCK", block, len(privateKey))
		return ""
	}

	rsaPrivateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
	// rsaPrivateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
	if err != nil {
		fmt.Println("RSAPRIVATE", err)
		return ""
	}

	h := hash.New()
	h.Write(source)
	hashed := h.Sum(nil)

	s, err := rsa.SignPKCS1v15(rand.Reader, rsaPrivateKey, hash, hashed)
	// s, err := rsa.SignPKCS1v15(rand.Reader, rsaPrivateKey.(*rsa.PrivateKey), hash, hashed)
	if err != nil {
		fmt.Println("SIGNPKCS", err)
		return ""
	}
	return base64.StdEncoding.EncodeToString(s)
}

func verify(values url.Values, publicKey []byte, signType string) bool {
	var excluded []string
	for k := range values {
		if k == "sign" || k == "sign_type" {
			continue
		}
		excluded = append(excluded, k)
	}
	sort.Strings(excluded)

	var valueList []string
	for _, k := range excluded {
		v := values.Get(k)
		if v != "" {
			valueList = append(valueList, fmt.Sprintf("%s=%s", k, v))
		}
	}
	concat := strings.Join(valueList, "&")

	decoded, err := base64.StdEncoding.DecodeString(values.Get("sign"))
	if err != nil {
		return false
	}

	fmt.Println("EXCLUDED", excluded)
	fmt.Println("CONCAT", concat)
	var ok bool
	if signType == "RSA" {
		ok = verifyPKCS1v15([]byte(concat), decoded, publicKey, crypto.SHA1)
	} else if signType == "RSA2" {
		ok = verifyPKCS1v15([]byte(concat), decoded, publicKey, crypto.SHA256)
	}
	ok = true
	return ok
}

func verifyPKCS1v15(source, sign, publicKey []byte, hash crypto.Hash) bool {
	h := hash.New()
	h.Write(source)
	hashed := h.Sum(nil)

	block, _ := pem.Decode(publicKey)
	if block == nil {
		fmt.Println("VERIFY BLOCK", block)
		return false
	}

	pub, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		fmt.Println("ParsePKIXPublicKey", err)
		return false
	}

	rsaPublicKey := pub.(*rsa.PublicKey)
	err = rsa.VerifyPKCS1v15(rsaPublicKey, hash, hashed, sign)
	if err != nil {
		fmt.Println("VerifyPKCS1v15", err)
		return false
	}
	return true
}

func generateTimestampStr() string {
	now := time.Now()
	year, month, day := now.Date()
	hour, min, sec := now.Clock()
	return fmt.Sprintf("%d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, min, sec)
}

func marshalJSON(val interface{}) string {
	data, err := json.Marshal(val)
	if err != nil {
		return ""
	}
	return string(data)
}

func toValues(st interface{}) (url.Values, error) {
	val := reflect.ValueOf(st)
	if val.Kind() == reflect.Ptr {
		val = val.Elem()
	}

	if val.Kind() != reflect.Struct {
		return nil, fmt.Errorf("need a struct type, got %T", st)
	}

	typ := val.Type()
	result := url.Values{}

	for i := 0; i < val.NumField(); i++ {
		sf := typ.Field(i)
		if tag, ok := sf.Tag.Lookup("json"); ok && tag != "" {
			result.Add(tag, val.Field(i).String())
		}
	}
	return result, nil
}
<|endoftext|>


<commit_before>package memrecorder

import "time"

// MemRecorder stores all seen image tags in memory.
type MemRecorder struct {
	imageTags map[string]time.Time
}

// An ImageTagSweeper is a method to run on each image tag.
type ImageTagSweeper func(tag string, when time.Time)

// NewMemRecorder initializes a new MemRecorder for use.
func NewMemRecorder() *MemRecorder {
	var r MemRecorder
	r.imageTags = make(map[string]time.Time)
	return &r
}

// SawImageTagAt records when a tag was last seen.
//
// Duplicate or older times will be ignored.
func (r *MemRecorder) SawImageTagAt(tag string, when time.Time) {
	if old, ok := r.imageTags[tag]; ok {
		if when.Before(old) {
			return // We don't need to adjust the value.
		}
	}

	r.imageTags[tag] = when
}

// Sweep runs a function on all tag and timestamp pairs.
func (r *MemRecorder) Sweep(sweeper ImageTagSweeper) {
	for tag, when := range r.imageTags {
		sweeper(tag, when)
	}
}

// func Start() {
//   client := newClient()

//   listener := make(chan *dockerclient.APIEvents)
//   if err := client.AddEventListener(listener); err != nil {
//     log.Fatalf("Unable to listen for events: %s", err)
//   }

//   for {
//     event := <-listener
//     switch event.Type {
//     case "image":
//       recordImage(event)
//     case "container":
//       recordContainer(event)
//     case "network":
//     default:
//       log.Printf("Discarding (%s %s) %v", event.Action, event.Type, event.Actor.Attributes)
//     }
//   }
// }

// func newClient() *dockerclient.Client {
//   client, err := dockerclient.NewClientFromEnv()
//   if err != nil {
//     log.Fatalf("Unable to connect to docker daemon: %s", err)
//   }
//   return client
// }

// func recordImage(event *dockerclient.APIEvents) {
//   if name, ok := event.Actor.Attributes["name"]; ok {
//     log.Printf("Image:     %s %s", event.Action, name)
//   }
// }

// func recordContainer(event *dockerclient.APIEvents) {
//   if name, ok := event.Actor.Attributes["image"]; ok {
//     log.Printf("Container: %s %s", event.Action, name)
//   }
// }
<commit_msg>removed dead comments<commit_after>package memrecorder

import "time"

// MemRecorder stores all seen image tags in memory.
type MemRecorder struct {
	imageTags map[string]time.Time
}

// An ImageTagSweeper is a method to run on each image tag.
type ImageTagSweeper func(tag string, when time.Time)

// NewMemRecorder initializes a new MemRecorder for use.
func NewMemRecorder() *MemRecorder {
	var r MemRecorder
	r.imageTags = make(map[string]time.Time)
	return &r
}

// SawImageTagAt records when a tag was last seen.
//
// Duplicate or older times will be ignored.
func (r *MemRecorder) SawImageTagAt(tag string, when time.Time) {
	if old, ok := r.imageTags[tag]; ok {
		if when.Before(old) {
			return // We don't need to adjust the value.
		}
	}

	r.imageTags[tag] = when
}

// Sweep runs a function on all tag and timestamp pairs.
func (r *MemRecorder) Sweep(sweeper ImageTagSweeper) {
	for tag, when := range r.imageTags {
		sweeper(tag, when)
	}
}
<|endoftext|>


<commit_before>package memsearch

import (
	"os"
	"testing"
)

var needle []byte = []byte("Find This!")

func TestFindString(t *testing.T) {
	pid := uint(os.Getpid())

	res, err := memoryGrep(pid, needle)
	if err != nil {
		t.Fatal(err)
	} else if !res {
		t.Fatalf("memoryGrep failed, searching for %s, should be True", needle)
	}
}
<commit_msg>[memsearch] Add test for known byte sequences.<commit_after>package memsearch

import (
	"fmt"
	"os"
	"os/exec"
	"testing"
)

var needle []byte = []byte("Find This!")

var buffersToFind = [][]byte{
	[]byte{0xc, 0xa, 0xf, 0xe},
	[]byte{0xd, 0xe, 0xa, 0xd, 0xb, 0xe, 0xe, 0xf},
	[]byte{0xb, 0xe, 0xb, 0xe, 0xf, 0xe, 0x0},
}

func TestSearchInOtherProcess(t *testing.T) {
	//TODO(mvanotti): Right now the command is hardcoded. We should decide how to fix this.
	cmd := exec.Command("../test/tools/test.exe")
	if err := cmd.Start(); err != nil {
		t.Fatal(err)
	}
	defer cmd.Process.Kill()

	pid := uint(cmd.Process.Pid)
	fmt.Println("PID: ", pid)
	fmt.Println("My PID: ", os.Getpid())

	for _, buf := range buffersToFind {
		res, err := MemoryGrep(pid, buf)
		if err != nil {
			t.Fatal(err)
		} else if !res {
			t.Fatal("memoryGrep failed, the following buffer should be found", buf)
		}
	}

}

func testFindString(t *testing.T) {
	pid := uint(os.Getpid())

	res, err := MemoryGrep(pid, needle)
	if err != nil {
		t.Fatal(err)
	} else if !res {
		t.Fatalf("memoryGrep failed, searching for %s, should be True", needle)
	}
}
<|endoftext|>


<commit_before>// Copyright 2009 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 flag

/*
 * Flags
 *
 * Usage:
 *	1) Define flags using flag.String(), Bool(), Int(), etc. Example:
 *		import flag "flag"
 *		var ip *int = flag.Int("flagname", 1234, "help message for flagname")
 *	If you like, you can bind the flag to a variable using the Var() functions.
 *		var flagvar int
 *		func init() {
 *              	flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
 *		}
 *	2) After all flags are defined, call
 *		flag.Parse()
 *	to parse the command line into the defined flags.
 *
 *	3) Flags may then be used directly. If you're using the flags themselves,
 *	they are all pointers; if you bind to variables, they're values.
 *		print("ip has value ", *ip, "\n");
 *		print("flagvar has value ", flagvar, "\n");
 *
 *	4) After parsing, flag.Arg(i) is the i'th argument after the flags.
 *	Args are indexed from 0 up to flag.NArg().
 *
 *	Command line flag syntax:
 *		-flag
 *		-flag=x
 *		-flag x
 *	One or two minus signs may be used; they are equivalent.
 *
 *	Flag parsing stops just before the first non-flag argument
 *	("-" is a non-flag argument) or after the terminator "--".
 *
 *	Integer flags accept 1234, 0664, 0x1234 and may be negative.
 *	Boolean flags may be 1, 0, t, f, true, false, TRUE, FALSE, True, False.
 */

import "fmt"

// BUG: ctoi, atoi, atob belong elsewhere
func ctoi(c int64) int64 {
	if '0' <= c && c <= '9' {
		return c - '0'
	}
	if 'a' <= c && c <= 'f' {
		return c - 'a'
	}
	if 'A' <= c && c <= 'F' {
		return c - 'A'
	}
	return 1000   // too large for any base
}

func atoi(s string) (value int64, ok bool) {
	if len(s) == 0 {
		return 0, false
	}
	if s[0] == '-' {
		n, t := atoi(s[1:len(s)]);
		return -n, t
	}
	var base int64 = 10;
	i := 0;
	if s[0] == '0' {
		base = 8;
		if len(s) > 1 && (s[1] == 'x' || s[1] == 'X') {
			base = 16;
			i += 2;
		}
	}
	var n int64 = 0;
	for ; i < len(s); i++ {
		k := ctoi(int64(s[i]));
		if k >= base {
			return 0, false
		}
		n = n * base + k
	}
	return n, true
}

func atob(str string) (value bool, ok bool) {
	switch str {
		case "1", "t", "T", "true", "TRUE", "True":
			return true, true;
		case "0", "f", "F", "false", "FALSE", "False":
			return false, true
	}
	return false, false
}

type (
	boolValue struct;
	intValue struct;
	int64Value struct;
	uintValue struct;
	uint64Value struct;
	stringValue struct;
)

// -- Bool Value
type boolValue struct {
	p *bool;
}

func newBoolValue(val bool, p *bool) *boolValue {
	*p = val;
	return &boolValue{p}
}

func (b *boolValue) set(val bool) {
	*b.p = val;
}

func (b *boolValue) str() string {
	return fmt.Sprintf("%v", *b.p)
}

// -- Int Value
type intValue struct {
	p	*int;
}

func newIntValue(val int, p *int) *intValue {
	*p = val;
	return &intValue{p}
}

func (i *intValue) set(val int) {
	*i.p = val;
}

func (i *intValue) str() string {
	return fmt.Sprintf("%v", *i.p)
}

// -- Int64 Value
type int64Value struct {
	p	*int64;
}

func newInt64Value(val int64, p *int64) *int64Value {
	*p = val;
	return &int64Value{p}
}

func (i *int64Value) set(val int64) {
	*i.p = val;
}

func (i *int64Value) str() string {
	return fmt.Sprintf("%v", *i.p)
}

// -- Uint Value
type uintValue struct {
	p	*uint;
}

func newUintValue(val uint, p *uint) *uintValue {
	*p = val;
	return &uintValue{p}
}

func (i *uintValue) set(val uint) {
	*i.p = val
}

func (i *uintValue) str() string {
	return fmt.Sprintf("%v", *i.p)
}

// -- uint64 Value
type uint64Value struct {
	p	*uint64;
}

func newUint64Value(val uint64, p *uint64) *uint64Value {
	*p = val;
	return &uint64Value{p}
}

func (i *uint64Value) set(val uint64) {
	*i.p = val;
}

func (i *uint64Value) str() string {
	return fmt.Sprintf("%v", *i.p)
}

// -- string Value
type stringValue struct {
	p	*string;
}

func newStringValue(val string, p *string) *stringValue {
	*p = val;
	return &stringValue{p}
}

func (s *stringValue) set(val string) {
	*s.p = val;
}

func (s *stringValue) str() string {
	return fmt.Sprintf("%#q", *s.p)
}

// -- Value interface
type Value interface {
	str() string;
}

// -- Flag structure (internal)
export type Flag struct {
	name	string;
	usage	string;
	value	Value;
}

type allFlags struct {
	actual map[string] *Flag;
	formal map[string] *Flag;
	first_arg	int;
}

func New() *allFlags {
	f := new(allFlags);
	f.first_arg = 1;	// 0 is the program name, 1 is first arg
	f.actual = make(map[string] *Flag);
	f.formal = make(map[string] *Flag);
	return f;
}

var flags *allFlags = New();

export func PrintDefaults() {
	for k, f := range flags.formal {
		print("  -", f.name, "=", f.value.str(), ": ", f.usage, "\n");
	}
}

export func Usage() {
	if sys.argc() > 0 {
		print("Usage of ", sys.argv(0), ": \n");
	} else {
		print("Usage: \n");
	}
	PrintDefaults();
	sys.exit(1);
}

export func NFlag() int {
	return len(flags.actual)
}

export func Arg(i int) string {
	i += flags.first_arg;
	if i < 0 || i >= sys.argc() {
		return "";
	}
	return sys.argv(i)
}

export func NArg() int {
	return sys.argc() - flags.first_arg
}

func add(name string, value Value, usage string) {
	f := new(Flag);
	f.name = name;
	f.usage = usage;
	f.value = value;
	dummy, alreadythere := flags.formal[name];
	if alreadythere {
		print("flag redefined: ", name, "\n");
		panic("flag redefinition");
	}
	flags.formal[name] = f;
}

export func Bool(name string, value bool, usage string) *bool {
	p := new(bool);
	add(name, newBoolValue(value, p), usage);
	return p;
}

export func BoolVar(p *bool, name string, value bool, usage string) {
	add(name, newBoolValue(value, p), usage);
}

export func Int(name string, value int, usage string) *int {
	p := new(int);
	add(name, newIntValue(value, p), usage);
	return p;
}

export func IntVar(p *int, name string, value int, usage string) {
	add(name, newIntValue(value, p), usage);
}

export func Int64(name string, value int64, usage string) *int64 {
	p := new(int64);
	add(name, newInt64Value(value, p), usage);
	return p;
}

export func Int64Var(p *int64, name string, value int64, usage string) {
	add(name, newInt64Value(value, p), usage);
}

export func Uint(name string, value uint, usage string) *uint {
	p := new(uint);
	add(name, newUintValue(value, p), usage);
	return p;
}

export func UintVar(p *uint, name string, value uint, usage string) {
	add(name, newUintValue(value, p), usage);
}

export func Uint64(name string, value uint64, usage string) *uint64 {
	p := new(uint64);
	add(name, newUint64Value(value, p), usage);
	return p;
}

export func Uint64Var(p *uint64, name string, value uint64, usage string) {
	add(name, newUint64Value(value, p), usage);
}

export func String(name, value string, usage string) *string {
	p := new(string);
	add(name, newStringValue(value, p), usage);
	return p;
}

export func StringVar(p *string, name, value string, usage string) {
	add(name, newStringValue(value, p), usage);
}

func (f *allFlags) ParseOne(index int) (ok bool, next int)
{
	s := sys.argv(index);
	f.first_arg = index;  // until proven otherwise
	if len(s) == 0 {
		return false, -1
	}
	if s[0] != '-' {
		return false, -1
	}
	num_minuses := 1;
	if len(s) == 1 {
		return false, index
	}
	if s[1] == '-' {
		num_minuses++;
		if len(s) == 2 {	// "--" terminates the flags
			return false, index + 1
		}
	}
	name := s[num_minuses : len(s)];
	if len(name) == 0 || name[0] == '-' || name[0] == '=' {
		print("bad flag syntax: ", s, "\n");
		Usage();
	}

	// it's a flag. does it have an argument?
	has_value := false;
	value := "";
	for i := 1; i < len(name); i++ {  // equals cannot be first
		if name[i] == '=' {
			value = name[i+1 : len(name)];
			has_value = true;
			name = name[0 : i];
			break;
		}
	}
	flag, alreadythere := flags.actual[name];
	if alreadythere {
		print("flag specified twice: -", name, "\n");
		Usage();
	}
	m := flags.formal;
	flag, alreadythere = m[name]; // BUG
	if !alreadythere {
		print("flag provided but not defined: -", name, "\n");
		Usage();
	}
	if f, ok := flag.value.(*boolValue); ok {
		if has_value {
			k, ok := atob(value);
			if !ok {
				print("invalid boolean value ", value, " for flag: -", name, "\n");
				Usage();
			}
			f.set(k)
		} else {
			f.set(true)
		}
	} else {
		// It must have a value, which might be the next argument.
		if !has_value && index < sys.argc()-1 {
			// value is the next arg
			has_value = true;
			index++;
			value = sys.argv(index);
		}
		if !has_value {
			print("flag needs an argument: -", name, "\n");
			Usage();
		}
		if f, ok := flag.value.(*stringValue); ok {
			f.set(value)
		} else {
			// It's an integer flag.  TODO(r): check for overflow?
			k, ok := atoi(value);
			if !ok {
				print("invalid integer value ", value, " for flag: -", name, "\n");
				Usage();
			}
			if f, ok := flag.value.(*intValue); ok {
				f.set(int(k));
			} else if f, ok := flag.value.(*int64Value); ok {
				f.set(k);
			} else if f, ok := flag.value.(*uintValue); ok {
				f.set(uint(k));
			} else if f, ok := flag.value.(*uint64Value); ok {
				f.set(uint64(k));
			}
		}
	}
	flags.actual[name] = flag;
	return true, index + 1
}

export func Parse() {
	for i := 1; i < sys.argc(); {
		ok, next := flags.ParseOne(i);
		if next > 0 {
			flags.first_arg = next;
			i = next;
		}
		if !ok {
			break
		}
	}
}
<commit_msg>casify flag.<commit_after>// Copyright 2009 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 flag

/*
 * Flags
 *
 * Usage:
 *	1) Define flags using flag.String(), Bool(), Int(), etc. Example:
 *		import flag "flag"
 *		var ip *int = flag.Int("flagname", 1234, "help message for flagname")
 *	If you like, you can bind the flag to a variable using the Var() functions.
 *		var flagvar int
 *		func init() {
 *              	flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
 *		}
 *	2) After all flags are defined, call
 *		flag.Parse()
 *	to parse the command line into the defined flags.
 *
 *	3) Flags may then be used directly. If you're using the flags themselves,
 *	they are all pointers; if you bind to variables, they're values.
 *		print("ip has value ", *ip, "\n");
 *		print("flagvar has value ", flagvar, "\n");
 *
 *	4) After parsing, flag.Arg(i) is the i'th argument after the flags.
 *	Args are indexed from 0 up to flag.NArg().
 *
 *	Command line flag syntax:
 *		-flag
 *		-flag=x
 *		-flag x
 *	One or two minus signs may be used; they are equivalent.
 *
 *	Flag parsing stops just before the first non-flag argument
 *	("-" is a non-flag argument) or after the terminator "--".
 *
 *	Integer flags accept 1234, 0664, 0x1234 and may be negative.
 *	Boolean flags may be 1, 0, t, f, true, false, TRUE, FALSE, True, False.
 */

import "fmt"

// BUG: ctoi, atoi, atob belong elsewhere
func ctoi(c int64) int64 {
	if '0' <= c && c <= '9' {
		return c - '0'
	}
	if 'a' <= c && c <= 'f' {
		return c - 'a'
	}
	if 'A' <= c && c <= 'F' {
		return c - 'A'
	}
	return 1000   // too large for any base
}

func atoi(s string) (value int64, ok bool) {
	if len(s) == 0 {
		return 0, false
	}
	if s[0] == '-' {
		n, t := atoi(s[1:len(s)]);
		return -n, t
	}
	var base int64 = 10;
	i := 0;
	if s[0] == '0' {
		base = 8;
		if len(s) > 1 && (s[1] == 'x' || s[1] == 'X') {
			base = 16;
			i += 2;
		}
	}
	var n int64 = 0;
	for ; i < len(s); i++ {
		k := ctoi(int64(s[i]));
		if k >= base {
			return 0, false
		}
		n = n * base + k
	}
	return n, true
}

func atob(str string) (value bool, ok bool) {
	switch str {
		case "1", "t", "T", "true", "TRUE", "True":
			return true, true;
		case "0", "f", "F", "false", "FALSE", "False":
			return false, true
	}
	return false, false
}

type (
	boolValue struct;
	intValue struct;
	int64Value struct;
	uintValue struct;
	uint64Value struct;
	stringValue struct;
)

// -- Bool Value
type boolValue struct {
	p *bool;
}

func newBoolValue(val bool, p *bool) *boolValue {
	*p = val;
	return &boolValue{p}
}

func (b *boolValue) set(val bool) {
	*b.p = val;
}

func (b *boolValue) str() string {
	return fmt.Sprintf("%v", *b.p)
}

// -- Int Value
type intValue struct {
	p	*int;
}

func newIntValue(val int, p *int) *intValue {
	*p = val;
	return &intValue{p}
}

func (i *intValue) set(val int) {
	*i.p = val;
}

func (i *intValue) str() string {
	return fmt.Sprintf("%v", *i.p)
}

// -- Int64 Value
type int64Value struct {
	p	*int64;
}

func newInt64Value(val int64, p *int64) *int64Value {
	*p = val;
	return &int64Value{p}
}

func (i *int64Value) set(val int64) {
	*i.p = val;
}

func (i *int64Value) str() string {
	return fmt.Sprintf("%v", *i.p)
}

// -- Uint Value
type uintValue struct {
	p	*uint;
}

func newUintValue(val uint, p *uint) *uintValue {
	*p = val;
	return &uintValue{p}
}

func (i *uintValue) set(val uint) {
	*i.p = val
}

func (i *uintValue) str() string {
	return fmt.Sprintf("%v", *i.p)
}

// -- uint64 Value
type uint64Value struct {
	p	*uint64;
}

func newUint64Value(val uint64, p *uint64) *uint64Value {
	*p = val;
	return &uint64Value{p}
}

func (i *uint64Value) set(val uint64) {
	*i.p = val;
}

func (i *uint64Value) str() string {
	return fmt.Sprintf("%v", *i.p)
}

// -- string Value
type stringValue struct {
	p	*string;
}

func newStringValue(val string, p *string) *stringValue {
	*p = val;
	return &stringValue{p}
}

func (s *stringValue) set(val string) {
	*s.p = val;
}

func (s *stringValue) str() string {
	return fmt.Sprintf("%#q", *s.p)
}

// -- Value interface
type _Value interface {
	str() string;
}

// -- Flag structure (internal)
export type Flag struct {
	name	string;
	usage	string;
	value	_Value;
}

type allFlags struct {
	actual map[string] *Flag;
	formal map[string] *Flag;
	first_arg	int;	// 0 is the program name, 1 is first arg
}

var flags *allFlags = &allFlags{make(map[string] *Flag), make(map[string] *Flag), 1}

export func PrintDefaults() {
	for k, f := range flags.formal {
		print("  -", f.name, "=", f.value.str(), ": ", f.usage, "\n");
	}
}

export func Usage() {
	if sys.argc() > 0 {
		print("Usage of ", sys.argv(0), ": \n");
	} else {
		print("Usage: \n");
	}
	PrintDefaults();
	sys.exit(1);
}

export func NFlag() int {
	return len(flags.actual)
}

export func Arg(i int) string {
	i += flags.first_arg;
	if i < 0 || i >= sys.argc() {
		return "";
	}
	return sys.argv(i)
}

export func NArg() int {
	return sys.argc() - flags.first_arg
}

func add(name string, value _Value, usage string) {
	f := new(Flag);
	f.name = name;
	f.usage = usage;
	f.value = value;
	dummy, alreadythere := flags.formal[name];
	if alreadythere {
		print("flag redefined: ", name, "\n");
		panic("flag redefinition");
	}
	flags.formal[name] = f;
}

export func Bool(name string, value bool, usage string) *bool {
	p := new(bool);
	add(name, newBoolValue(value, p), usage);
	return p;
}

export func BoolVar(p *bool, name string, value bool, usage string) {
	add(name, newBoolValue(value, p), usage);
}

export func Int(name string, value int, usage string) *int {
	p := new(int);
	add(name, newIntValue(value, p), usage);
	return p;
}

export func IntVar(p *int, name string, value int, usage string) {
	add(name, newIntValue(value, p), usage);
}

export func Int64(name string, value int64, usage string) *int64 {
	p := new(int64);
	add(name, newInt64Value(value, p), usage);
	return p;
}

export func Int64Var(p *int64, name string, value int64, usage string) {
	add(name, newInt64Value(value, p), usage);
}

export func Uint(name string, value uint, usage string) *uint {
	p := new(uint);
	add(name, newUintValue(value, p), usage);
	return p;
}

export func UintVar(p *uint, name string, value uint, usage string) {
	add(name, newUintValue(value, p), usage);
}

export func Uint64(name string, value uint64, usage string) *uint64 {
	p := new(uint64);
	add(name, newUint64Value(value, p), usage);
	return p;
}

export func Uint64Var(p *uint64, name string, value uint64, usage string) {
	add(name, newUint64Value(value, p), usage);
}

export func String(name, value string, usage string) *string {
	p := new(string);
	add(name, newStringValue(value, p), usage);
	return p;
}

export func StringVar(p *string, name, value string, usage string) {
	add(name, newStringValue(value, p), usage);
}

func (f *allFlags) ParseOne(index int) (ok bool, next int)
{
	s := sys.argv(index);
	f.first_arg = index;  // until proven otherwise
	if len(s) == 0 {
		return false, -1
	}
	if s[0] != '-' {
		return false, -1
	}
	num_minuses := 1;
	if len(s) == 1 {
		return false, index
	}
	if s[1] == '-' {
		num_minuses++;
		if len(s) == 2 {	// "--" terminates the flags
			return false, index + 1
		}
	}
	name := s[num_minuses : len(s)];
	if len(name) == 0 || name[0] == '-' || name[0] == '=' {
		print("bad flag syntax: ", s, "\n");
		Usage();
	}

	// it's a flag. does it have an argument?
	has_value := false;
	value := "";
	for i := 1; i < len(name); i++ {  // equals cannot be first
		if name[i] == '=' {
			value = name[i+1 : len(name)];
			has_value = true;
			name = name[0 : i];
			break;
		}
	}
	flag, alreadythere := flags.actual[name];
	if alreadythere {
		print("flag specified twice: -", name, "\n");
		Usage();
	}
	m := flags.formal;
	flag, alreadythere = m[name]; // BUG
	if !alreadythere {
		print("flag provided but not defined: -", name, "\n");
		Usage();
	}
	if f, ok := flag.value.(*boolValue); ok {
		if has_value {
			k, ok := atob(value);
			if !ok {
				print("invalid boolean value ", value, " for flag: -", name, "\n");
				Usage();
			}
			f.set(k)
		} else {
			f.set(true)
		}
	} else {
		// It must have a value, which might be the next argument.
		if !has_value && index < sys.argc()-1 {
			// value is the next arg
			has_value = true;
			index++;
			value = sys.argv(index);
		}
		if !has_value {
			print("flag needs an argument: -", name, "\n");
			Usage();
		}
		if f, ok := flag.value.(*stringValue); ok {
			f.set(value)
		} else {
			// It's an integer flag.  TODO(r): check for overflow?
			k, ok := atoi(value);
			if !ok {
				print("invalid integer value ", value, " for flag: -", name, "\n");
				Usage();
			}
			if f, ok := flag.value.(*intValue); ok {
				f.set(int(k));
			} else if f, ok := flag.value.(*int64Value); ok {
				f.set(k);
			} else if f, ok := flag.value.(*uintValue); ok {
				f.set(uint(k));
			} else if f, ok := flag.value.(*uint64Value); ok {
				f.set(uint64(k));
			}
		}
	}
	flags.actual[name] = flag;
	return true, index + 1
}

export func Parse() {
	for i := 1; i < sys.argc(); {
		ok, next := flags.ParseOne(i);
		if next > 0 {
			flags.first_arg = next;
			i = next;
		}
		if !ok {
			break
		}
	}
}
<|endoftext|>