<commit_before>package raft

import (
	"fmt"
	"math/rand"
	"os"
	"reflect"
	"testing"

	"github.com/hashicorp/raft"
	"github.com/hashicorp/raft-boltdb"
)

// Fuzz tester comparing this to hashicorp/raft-boltdb.
func TestFuzz(t *testing.T) {
	logdb := assertCreate(t, "fuzz")
	defer assertClose(t, logdb)
	boltdb := assertCreateBoltStore(t, "fuzz")
	defer boltdb.Close()

	rand := rand.New(rand.NewSource(0))

	if err := fuzzLogStore(boltdb, logdb, rand, 256); err != nil {
		t.Fatal(err)
	}
}

/// FUZZ TESTER

// Compare a "test" implementation with a "spec" implementation by performing a sequence of random operations
// and comparing the outputs.
func fuzzLogStore(spec raft.LogStore, test raft.LogStore, rand *rand.Rand, maxops int) error {
	// Keep track of the last log entry generated, so indices and terms will be strictly increasing.
	lastLog := raft.Log{Index: 1 + uint64(rand.Intn(10))}

	for i := 0; i < maxops; i++ {
		action := rand.Intn(6)

		switch action {
		case 0:
			specFirst, specErr := spec.FirstIndex()
			testFirst, testErr := test.FirstIndex()

			fmt.Printf("-> calling FirstIndex\n")

			if !compareErrors(specErr, testErr) {
				return notExpected("FirstIndex", "error values inconsistent", specErr, testErr)
			}
			if specErr != nil {
				continue
			}
			if specFirst != testFirst {
				return notExpected("FirstIndex", "first indices not equal", specFirst, testFirst)
			}
		case 1:
			specFirst, specErr := spec.LastIndex()
			testFirst, testErr := test.LastIndex()

			fmt.Printf("-> calling LastIndex\n")

			if !compareErrors(specErr, testErr) {
				return notExpected("LastIndex", "error values inconsistent", specErr, testErr)
			}
			if specErr != nil {
				continue
			}
			if specFirst != testFirst {
				return notExpected("LastIndex", "indices not equal", specFirst, testFirst)
			}
		case 2:
			// Generate an index, weighted towards something in range.
			first, _ := spec.FirstIndex()
			last, _ := spec.LastIndex()
			idrange := int64(last) - int64(first)

			// It's a little annoying that the Int*n functions can't accept 0 as an upper bound.
			index := rand.Int63n(26) - 50 + int64(first)
			if idrange > 0 {
				index = rand.Int63n(idrange) + index
			}
			idx := uint64(index)

			fmt.Printf("-> calling GetLog %v\n", idx)

			specLog := new(raft.Log)
			specErr := spec.GetLog(idx, specLog)
			testLog := new(raft.Log)
			testErr := test.GetLog(idx, testLog)

			if !compareErrors(specErr, testErr) {
				return notExpected("GetLog", fmt.Sprintf("error values inconsistent for ID %v", idx), specErr, testErr)
			}
			if specErr != nil {
				continue
			}
			if !compareLogs(specLog, testLog) {
				return notExpected("GetLog", fmt.Sprintf("log entries not equal for ID %v", idx), specLog, testLog)
			}
		case 3:
			lastLog = randLog(lastLog, rand)

			specErr := spec.StoreLog(&lastLog)
			testErr := test.StoreLog(&lastLog)

			fmt.Printf("-> calling StoreLog %v\n", lastLog)

			if !compareErrors(specErr, testErr) {
				return notExpected("StoreLog", "error values inconsistent", specErr, testErr)
			}
		case 4:
			logs := make([]*raft.Log, rand.Intn(100))
			logsV := make([]raft.Log, len(logs))
			for i := range logs {
				lastLog = randLog(lastLog, rand)
				logsV[i] = lastLog
				logs[i] = &logsV[i]
			}

			fmt.Printf("-> calling StoreLogs %v\n", logsV)

			specErr := spec.StoreLogs(logs)
			testErr := test.StoreLogs(logs)

			if !compareErrors(specErr, testErr) {
				return notExpected("StoreLogs", "error values inconsistent", specErr, testErr)
			}
		case 5:
			// Delete randomly from either the front or back, not the middle. This matches use of
			// this method within hashicorp/raft itself.
			first, _ := spec.FirstIndex()
			last, _ := spec.LastIndex()

			// Same issue here wth rand.Int63n as above.
			if first != last {
				if rand.Intn(2) == 0 {
					first += uint64(rand.Int63n(int64(last - first)))
				} else {
					last -= uint64(rand.Int63n(int64(last - first)))
				}
			}

			fmt.Printf("-> calling DeleteRange %v %v\n", first, last)

			specErr := spec.DeleteRange(first, last)
			testErr := test.DeleteRange(first, last)

			if !compareErrors(specErr, testErr) {
				return notExpected("DeleteRange", "error values inconsistent", specErr, testErr)
			}
			if specErr != nil {
				continue
			}
		}

		// After every operation, check the indices are consistent.
		specFirst, specErr := spec.FirstIndex()
		testFirst, testErr := test.FirstIndex()

		if !compareErrors(specErr, testErr) {
			return badInvariant("error values of FirstIndex inconsistent", specErr, testErr)
		}
		if specErr != nil {
			continue
		}
		if specFirst != testFirst {
			return badInvariant("first indices not equal", specFirst, testFirst)
		}

		specLast, specErr := spec.LastIndex()
		testLast, testErr := test.LastIndex()

		if !compareErrors(specErr, testErr) {
			return badInvariant("error values of LastIndex inconsistent", specErr, testErr)
		}
		if specErr != nil {
			continue
		}
		if specLast != testLast {
			return badInvariant("last indices not equal", specLast, testLast)
		}

		// If there was a rollback, we need to generate earlier indices again.
		if specLast != 0 {
			lastLog.Index = specLast
		}
	}

	return nil
}

// Compare two errors by checking both are nil or non-nil.
func compareErrors(err1 error, err2 error) bool {
	return !((err1 == nil && err2 != nil) || (err1 != nil && err2 == nil))
}

// Compare two raft log values.
func compareLogs(log1 *raft.Log, log2 *raft.Log) bool {
	return log1.Index == log2.Index && log1.Term == log2.Term && log1.Type == log2.Type && reflect.DeepEqual(log1.Data, log2.Data)
}

// Construct an error message.
func notExpected(method, msg string, expected, actual interface{}) error {
	return fmt.Errorf("[%s] %s\nexpected: %v\nactual:   %v", method, msg, expected, actual)
}

// Construct an error message.
func badInvariant(msg string, expected, actual interface{}) error {
	return fmt.Errorf("INVARIANT: %s\nexpected: %v\nactual:   %v", msg, expected, actual)
}

// Generate a random log entry. The pair (index,term) is strictly increasing between invocations.
func randLog(lastLog raft.Log, rand *rand.Rand) raft.Log {
	index := lastLog.Index + 1
	term := lastLog.Term

	// Bias towards entries in the same term.
	if rand.Intn(5) == 0 {
		term++
	}

	return raft.Log{
		Index: index,
		Term:  term,
		Type:  raft.LogType(rand.Uint32()),
		Data:  []byte(fmt.Sprintf("entry %v %v", index, term)),
	}
}

/// ASSERTIONS

func assertCreateBoltStore(t testing.TB, testName string) *raftboltdb.BoltStore {
	_ = os.RemoveAll("../test_db/raft/" + testName + "_bolt")
	db, err := raftboltdb.NewBoltStore("../test_db/raft/" + testName + "_bolt")
	if err != nil {
		t.Fatal(err)
	}
	return db
}
<commit_msg>Check index range in raft fuzz test.<commit_after>package raft

import (
	"fmt"
	"math/rand"
	"os"
	"reflect"
	"testing"

	"github.com/hashicorp/raft"
	"github.com/hashicorp/raft-boltdb"
)

// Fuzz tester comparing this to hashicorp/raft-boltdb.
func TestFuzz(t *testing.T) {
	logdb := assertCreate(t, "fuzz")
	defer assertClose(t, logdb)
	boltdb := assertCreateBoltStore(t, "fuzz")
	defer boltdb.Close()

	rand := rand.New(rand.NewSource(0))

	if err := fuzzLogStore(boltdb, logdb, rand, 256); err != nil {
		t.Fatal(err)
	}
}

/// FUZZ TESTER

// Compare a "test" implementation with a "spec" implementation by performing a sequence of random operations
// and comparing the outputs.
func fuzzLogStore(spec raft.LogStore, test raft.LogStore, rand *rand.Rand, maxops int) error {
	// Keep track of the last log entry generated, so indices and terms will be strictly increasing.
	lastLog := raft.Log{Index: 1 + uint64(rand.Intn(10))}

	for i := 0; i < maxops; i++ {
		action := rand.Intn(4)

		switch action {
		case 0:
			// Generate an index, weighted towards something in range.
			first, _ := spec.FirstIndex()
			last, _ := spec.LastIndex()
			idrange := int64(last) - int64(first)

			// It's a little annoying that the Int*n functions can't accept 0 as an upper bound.
			index := rand.Int63n(26) - 50 + int64(first)
			if idrange > 0 {
				index = rand.Int63n(idrange) + index
			}
			idx := uint64(index)

			fmt.Printf("-> calling GetLog %v\n", idx)

			specLog := new(raft.Log)
			specErr := spec.GetLog(idx, specLog)
			testLog := new(raft.Log)
			testErr := test.GetLog(idx, testLog)

			if !compareErrors(specErr, testErr) {
				return notExpected("GetLog", fmt.Sprintf("error values inconsistent for ID %v", idx), specErr, testErr)
			}
			if specErr != nil {
				continue
			}
			if !compareLogs(specLog, testLog) {
				return notExpected("GetLog", fmt.Sprintf("log entries not equal for ID %v", idx), specLog, testLog)
			}
		case 1:
			lastLog = randLog(lastLog, rand)

			specErr := spec.StoreLog(&lastLog)
			testErr := test.StoreLog(&lastLog)

			fmt.Printf("-> calling StoreLog %v\n", lastLog)

			if !compareErrors(specErr, testErr) {
				return notExpected("StoreLog", "error values inconsistent", specErr, testErr)
			}
		case 2:
			logs := make([]*raft.Log, rand.Intn(100))
			logsV := make([]raft.Log, len(logs))
			for i := range logs {
				lastLog = randLog(lastLog, rand)
				logsV[i] = lastLog
				logs[i] = &logsV[i]
			}

			fmt.Printf("-> calling StoreLogs %v\n", logsV)

			specErr := spec.StoreLogs(logs)
			testErr := test.StoreLogs(logs)

			if !compareErrors(specErr, testErr) {
				return notExpected("StoreLogs", "error values inconsistent", specErr, testErr)
			}
		case 3:
			// Delete randomly from either the front or back, not the middle. This matches use of
			// this method within hashicorp/raft itself.
			first, _ := spec.FirstIndex()
			last, _ := spec.LastIndex()

			// Same issue here wth rand.Int63n as above.
			if first != last {
				if rand.Intn(2) == 0 {
					first += uint64(rand.Int63n(int64(last - first)))
				} else {
					last -= uint64(rand.Int63n(int64(last - first)))
				}
			}

			fmt.Printf("-> calling DeleteRange %v %v\n", first, last)

			specErr := spec.DeleteRange(first, last)
			testErr := test.DeleteRange(first, last)

			if !compareErrors(specErr, testErr) {
				return notExpected("DeleteRange", "error values inconsistent", specErr, testErr)
			}
			if specErr != nil {
				continue
			}
		}

		// After every operation, check the indices are consistent.
		specFirst, specErr := spec.FirstIndex()
		testFirst, testErr := test.FirstIndex()

		if !compareErrors(specErr, testErr) {
			return badInvariant("error values of FirstIndex inconsistent", specErr, testErr)
		}
		if specErr != nil {
			continue
		}
		if specFirst < testFirst {
			return badInvariant("indices not subset", specFirst, testFirst)
		}

		specLast, specErr := spec.LastIndex()
		testLast, testErr := test.LastIndex()

		if !compareErrors(specErr, testErr) {
			return badInvariant("error values of LastIndex inconsistent", specErr, testErr)
		}
		if specErr != nil {
			continue
		}
		if specLast != testLast {
			return badInvariant("last indices not equal", specLast, testLast)
		}

		// If there was a rollback, we need to generate earlier indices again.
		if specLast != 0 {
			lastLog.Index = specLast
		}
	}

	return nil
}

// Compare two errors by checking both are nil or non-nil.
func compareErrors(err1 error, err2 error) bool {
	return !((err1 == nil && err2 != nil) || (err1 != nil && err2 == nil))
}

// Compare two raft log values.
func compareLogs(log1 *raft.Log, log2 *raft.Log) bool {
	return log1.Index == log2.Index && log1.Term == log2.Term && log1.Type == log2.Type && reflect.DeepEqual(log1.Data, log2.Data)
}

// Construct an error message.
func notExpected(method, msg string, expected, actual interface{}) error {
	return fmt.Errorf("[%s] %s\nexpected: %v\nactual:   %v", method, msg, expected, actual)
}

// Construct an error message.
func badInvariant(msg string, expected, actual interface{}) error {
	return fmt.Errorf("INVARIANT: %s\nexpected: %v\nactual:   %v", msg, expected, actual)
}

// Generate a random log entry. The pair (index,term) is strictly increasing between invocations.
func randLog(lastLog raft.Log, rand *rand.Rand) raft.Log {
	index := lastLog.Index + 1
	term := lastLog.Term

	// Bias towards entries in the same term.
	if rand.Intn(5) == 0 {
		term++
	}

	return raft.Log{
		Index: index,
		Term:  term,
		Type:  raft.LogType(rand.Uint32()),
		Data:  []byte(fmt.Sprintf("entry %v %v", index, term)),
	}
}

/// ASSERTIONS

func assertCreateBoltStore(t testing.TB, testName string) *raftboltdb.BoltStore {
	_ = os.RemoveAll("../test_db/raft/" + testName + "_bolt")
	db, err := raftboltdb.NewBoltStore("../test_db/raft/" + testName + "_bolt")
	if err != nil {
		t.Fatal(err)
	}
	return db
}
<|endoftext|>


<commit_before>// Copyright 2016 The etcd Authors
//
// 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 raft

import (
	"bytes"
	pb "github.com/absolute8511/ZanRedisDB/raft/raftpb"
)

// ReadState provides state for read only query.
// It's caller's responsibility to call ReadIndex first before getting
// this state from ready, It's also caller's duty to differentiate if this
// state is what it requests through RequestCtx, eg. given a unique id as
// RequestCtx
var (
	empty = []byte("")
)

type ReadState struct {
	Index      uint64
	RequestCtx []byte
}

type readIndexStatus struct {
	req   pb.Message
	index uint64
	acks  map[uint64]struct{}
}

type readOnly struct {
	option           ReadOnlyOption
	pendingReadIndex map[string]*readIndexStatus
	readIndexQueue   [][]byte
	buf              [][]byte
}

func newReadOnly(option ReadOnlyOption) *readOnly {
	return &readOnly{
		option:           option,
		pendingReadIndex: make(map[string]*readIndexStatus),
		buf:              make([][]byte, 0, 10),
	}
}

// addRequest adds a read only reuqest into readonly struct.
// `index` is the commit index of the raft state machine when it received
// the read only request.
// `m` is the original read only request message from the local or remote node.
func (ro *readOnly) addRequest(index uint64, m pb.Message) {
	if _, ok := ro.pendingReadIndex[string(m.Entries[0].Data)]; ok {
		return
	}
	ro.pendingReadIndex[string(m.Entries[0].Data)] = &readIndexStatus{index: index, req: m, acks: make(map[uint64]struct{})}
	ro.readIndexQueue = append(ro.readIndexQueue, m.Entries[0].Data)
}

// recvAck notifies the readonly struct that the raft state machine received
// an acknowledgment of the heartbeat that attached with the read only request
// context.
func (ro *readOnly) recvAck(m pb.Message) int {
	rs, ok := ro.pendingReadIndex[string(m.Context)]
	if !ok {
		return 0
	}

	rs.acks[m.From] = struct{}{}
	// add one to include an ack from local node
	return len(rs.acks) + 1
}

// advance advances the read only request queue kept by the readonly struct.
// It dequeues the requests until it finds the read only request that has
// the same context as the given `m`.
func (ro *readOnly) advance(m pb.Message) []*readIndexStatus {
	var (
		i     int
		found bool
	)

	rss := []*readIndexStatus{}

	for _, okctx := range ro.readIndexQueue {
		i++
		rs, ok := ro.pendingReadIndex[string(okctx)]
		if !ok {
			panic("cannot find corresponding read state from pending map")
		}
		rss = append(rss, rs)
		if bytes.Equal(okctx, m.Context) {
			found = true
			break
		}
	}

	if found {
		ro.readIndexQueue = ro.readIndexQueue[i:]
		for _, rs := range rss {
			delete(ro.pendingReadIndex, string(rs.req.Context))
		}
		if len(ro.readIndexQueue) == 0 {
			ro.readIndexQueue = ro.buf
		}
		if cap(ro.readIndexQueue) > 1024 && len(ro.readIndexQueue) < cap(ro.buf) {
			tmp := ro.readIndexQueue
			ro.readIndexQueue = ro.buf
			ro.readIndexQueue = append(ro.readIndexQueue, tmp...)
		}
		return rss
	}

	return nil
}

// lastPendingRequestCtx returns the context of the last pending read only
// request in readonly struct.
func (ro *readOnly) lastPendingRequestCtx() []byte {
	if len(ro.readIndexQueue) == 0 {
		return empty
	}
	return ro.readIndexQueue[len(ro.readIndexQueue)-1]
}
<commit_msg>reuse buffer in readindex queue<commit_after>// Copyright 2016 The etcd Authors
//
// 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 raft

import (
	"bytes"
	pb "github.com/absolute8511/ZanRedisDB/raft/raftpb"
)

// ReadState provides state for read only query.
// It's caller's responsibility to call ReadIndex first before getting
// this state from ready, It's also caller's duty to differentiate if this
// state is what it requests through RequestCtx, eg. given a unique id as
// RequestCtx
var (
	empty = []byte("")
)

type ReadState struct {
	Index      uint64
	RequestCtx []byte
}

type readIndexStatus struct {
	req   pb.Message
	index uint64
	acks  map[uint64]struct{}
}

type readOnly struct {
	option           ReadOnlyOption
	pendingReadIndex map[string]*readIndexStatus
	readIndexQueue   [][]byte
	buf              [][]byte
}

func newReadOnly(option ReadOnlyOption) *readOnly {
	r := &readOnly{
		option:           option,
		pendingReadIndex: make(map[string]*readIndexStatus),
		buf:              make([][]byte, 0, 32),
	}
	r.readIndexQueue = r.buf
	return r
}

// addRequest adds a read only reuqest into readonly struct.
// `index` is the commit index of the raft state machine when it received
// the read only request.
// `m` is the original read only request message from the local or remote node.
func (ro *readOnly) addRequest(index uint64, m pb.Message) {
	if _, ok := ro.pendingReadIndex[string(m.Entries[0].Data)]; ok {
		return
	}
	ro.pendingReadIndex[string(m.Entries[0].Data)] = &readIndexStatus{index: index, req: m, acks: make(map[uint64]struct{})}
	ro.readIndexQueue = append(ro.readIndexQueue, m.Entries[0].Data)
}

// recvAck notifies the readonly struct that the raft state machine received
// an acknowledgment of the heartbeat that attached with the read only request
// context.
func (ro *readOnly) recvAck(m pb.Message) int {
	rs, ok := ro.pendingReadIndex[string(m.Context)]
	if !ok {
		return 0
	}

	rs.acks[m.From] = struct{}{}
	// add one to include an ack from local node
	return len(rs.acks) + 1
}

// advance advances the read only request queue kept by the readonly struct.
// It dequeues the requests until it finds the read only request that has
// the same context as the given `m`.
func (ro *readOnly) advance(m pb.Message) []*readIndexStatus {
	var (
		i     int
		found bool
	)

	rss := []*readIndexStatus{}

	for _, okctx := range ro.readIndexQueue {
		i++
		rs, ok := ro.pendingReadIndex[string(okctx)]
		if !ok {
			panic("cannot find corresponding read state from pending map")
		}
		rss = append(rss, rs)
		if bytes.Equal(okctx, m.Context) {
			found = true
			break
		}
	}

	if found {
		ro.readIndexQueue = ro.readIndexQueue[i:]
		for _, rs := range rss {
			delete(ro.pendingReadIndex, string(rs.req.Context))
		}
		if len(ro.readIndexQueue) == 0 {
			ro.readIndexQueue = ro.buf
		} else {
			left := cap(ro.readIndexQueue) - len(ro.readIndexQueue)
			if cap(ro.readIndexQueue) > 2*cap(ro.buf) && cap(ro.readIndexQueue) < 1024 {
				ro.buf = make([][]byte, 0, cap(ro.readIndexQueue))
			}
			if len(ro.readIndexQueue) < cap(ro.buf)/2 &&
				left < 1+cap(ro.readIndexQueue)/8 {
				tmp := ro.readIndexQueue
				ro.readIndexQueue = ro.buf
				ro.readIndexQueue = append(ro.readIndexQueue, tmp...)
			}
		}
		return rss
	}

	return nil
}

// lastPendingRequestCtx returns the context of the last pending read only
// request in readonly struct.
func (ro *readOnly) lastPendingRequestCtx() []byte {
	if len(ro.readIndexQueue) == 0 {
		return empty
	}
	return ro.readIndexQueue[len(ro.readIndexQueue)-1]
}
<|endoftext|>


<commit_before>// Package cel contains some basic operations of Canonical Eventlog.
// Based on Canonical EventLog Spec (Draft) Version: TCG_IWG_CEL_v1_r0p37.
package cel

import (
	"bytes"
	"crypto"
	"encoding/binary"
	"fmt"
	"io"

	"github.com/google/go-tpm/tpm2"
)

const (
	// CEL spec 5.1
	recnumTypeValue  uint8 = 0
	pcrTypeValue     uint8 = 1
	_                uint8 = 2 // nvindex field is not supported yet
	digestsTypeValue uint8 = 3

	tlvTypeFieldLength   int = 1
	tlvLengthFieldLength int = 4

	recnumValueLength uint32 = 8 // support up to 2^64 records
	pcrValueLength    uint32 = 1 // support up to 256 PCRs
)

// TLV definition according to CEL spec TCG_IWG_CEL_v1_r0p37, page 16.
// Length is implicitly defined by len(Value), using uint32 big-endian
// when encoding.
type TLV struct {
	Type  uint8
	Value []byte
}

// MarshalBinary marshals a TLV to a byte slice.
func (tlv TLV) MarshalBinary() (data []byte, err error) {
	buf := make([]byte, len(tlv.Value)+tlvTypeFieldLength+tlvLengthFieldLength)

	buf[0] = tlv.Type
	binary.BigEndian.PutUint32(buf[tlvTypeFieldLength:], uint32(len(tlv.Value)))
	copy(buf[tlvTypeFieldLength+tlvLengthFieldLength:], tlv.Value)

	return buf, nil
}

// UnmarshalBinary unmarshal a byte slice to a TLV.
func (tlv *TLV) UnmarshalBinary(data []byte) error {
	valueLength := binary.BigEndian.Uint32(data[tlvTypeFieldLength : tlvTypeFieldLength+tlvLengthFieldLength])

	if valueLength != uint32(len(data[tlvTypeFieldLength+tlvLengthFieldLength:])) {
		return fmt.Errorf("TLV Length doesn't match the size of its Value")
	}
	tlv.Type = data[0]
	tlv.Value = data[tlvTypeFieldLength+tlvLengthFieldLength:]

	return nil
}

// UnmarshalFirstTLV reads and parse the first TLV from the bytes buffer. The function will
// return io.EOF if the buf ends unexpectedly or cannot fill the TLV.
func UnmarshalFirstTLV(buf *bytes.Buffer) (tlv TLV, err error) {
	typeByte, err := buf.ReadByte()
	if err != nil {
		return tlv, err
	}
	var data []byte
	data = append(data, typeByte)

	// get the length
	lengthBytes := make([]byte, tlvLengthFieldLength)
	bytesRead, err := buf.Read(lengthBytes)
	if err != nil {
		return TLV{}, err
	}
	if bytesRead != tlvLengthFieldLength {
		return TLV{}, io.EOF
	}
	valueLength := binary.BigEndian.Uint32(lengthBytes)
	data = append(data, lengthBytes...)

	valueBytes := make([]byte, valueLength)
	bytesRead, err = buf.Read(valueBytes)
	if err != nil {
		return TLV{}, err
	}
	if uint32(bytesRead) != valueLength {
		return TLV{}, io.EOF
	}
	data = append(data, valueBytes...)

	if err = (&tlv).UnmarshalBinary(data); err != nil {
		return TLV{}, err
	}
	return tlv, nil
}

// Record represents a Canonical Eventlog Record.
type Record struct {
	RecNum  uint64
	PCR     uint8
	Digests map[crypto.Hash][]byte
	Content TLV
}

// Content is a interface for the content in CELR.
type Content interface {
	GenerateDigest(crypto.Hash) ([]byte, error)
	GetTLV() TLV
}

// CEL represents a Canonical Eventlog, which contains a list of Records.
type CEL struct {
	Records []Record
}

// AppendEvent appends a new record to the CEL.
func (c *CEL) AppendEvent(tpm io.ReadWriteCloser, pcr int, hashAlgos []crypto.Hash, event Content) error {
	if len(hashAlgos) == 0 {
		return fmt.Errorf("need to specify at least one hash algorithm")
	}
	digestsMap := make(map[crypto.Hash][]byte)

	for _, hashAlgo := range hashAlgos {
		digest, err := event.GenerateDigest(hashAlgo)
		if err != nil {
			return err
		}
		digestsMap[hashAlgo] = digest

		// TODO: extend the digest to TPM PCR
	}

	celr := Record{
		RecNum:  uint64(len(c.Records)),
		PCR:     uint8(pcr),
		Digests: digestsMap,
		Content: event.GetTLV(),
	}

	c.Records = append(c.Records, celr)
	return nil
}

func createRecNumField(recNum uint64) TLV {
	value := make([]byte, recnumValueLength)
	binary.BigEndian.PutUint64(value, recNum)
	return TLV{recnumTypeValue, value}
}

// UnmarshalRecNum takes in a TLV with its type equals to the recnum type value (0), and
// return its record number.
func UnmarshalRecNum(tlv TLV) (uint64, error) {
	if tlv.Type != recnumTypeValue {
		return 0, fmt.Errorf("type of the TLV [%d] indicates it is not a recnum field [%d]",
			tlv.Type, recnumTypeValue)
	}
	if uint32(len(tlv.Value)) != recnumValueLength {
		return 0, fmt.Errorf(
			"length of the value of the TLV [%d] doesn't match the defined length [%d] of value for recnum",
			len(tlv.Value), recnumValueLength)
	}
	return binary.BigEndian.Uint64(tlv.Value), nil
}

func createPCRField(pcrNum uint8) TLV {
	return TLV{pcrTypeValue, []byte{pcrNum}}
}

// UnmarshalPCR takes in a TLV with its type equals to the PCR type value (1), and
// return its PCR number.
func UnmarshalPCR(tlv TLV) (pcrNum uint8, err error) {
	if tlv.Type != pcrTypeValue {
		return 0, fmt.Errorf("type of the TLV [%d] indicates it is not a PCR field [%d]",
			tlv.Type, pcrTypeValue)
	}
	if uint32(len(tlv.Value)) != pcrValueLength {
		return 0, fmt.Errorf(
			"length of the value of the TLV [%d] doesn't match the defined length [%d] of value for a PCR field",
			len(tlv.Value), pcrValueLength)
	}

	return tlv.Value[0], nil
}

func createDigestField(digestMap map[crypto.Hash][]byte) (TLV, error) {
	var buf bytes.Buffer
	for hashAlgo, hash := range digestMap {
		if len(hash) != hashAlgo.Size() {
			return TLV{}, fmt.Errorf("digest length [%d] doesn't match the expected length [%d] for the hash algorithm",
				len(hash), hashAlgo.Size())
		}
		tpmHashAlg, err := tpm2.HashToAlgorithm(hashAlgo)
		if err != nil {
			return TLV{}, err
		}
		singleDigestTLV := TLV{uint8(tpmHashAlg), hash}
		d, err := singleDigestTLV.MarshalBinary()
		if err != nil {
			return TLV{}, err
		}
		_, err = buf.Write(d)
		if err != nil {
			return TLV{}, err
		}
	}
	return TLV{digestsTypeValue, buf.Bytes()}, nil
}

// UnmarshalDigests takes in a TLV with its type equals to the digests type value (3), and
// return its digests content in a map, the key is its TPM hash algorithm.
func UnmarshalDigests(tlv TLV) (digestsMap map[crypto.Hash][]byte, err error) {
	if tlv.Type != digestsTypeValue {
		return nil, fmt.Errorf("type of the TLV indicates it doesn't contain digests")
	}

	buf := bytes.NewBuffer(tlv.Value)
	digestsMap = make(map[crypto.Hash][]byte)

	for buf.Len() > 0 {
		digestTLV, err := UnmarshalFirstTLV(buf)
		if err == io.EOF {
			return nil, fmt.Errorf("buffer ends unexpectedly")
		} else if err != nil {
			return nil, err
		}
		hashAlg, err := tpm2.Algorithm(digestTLV.Type).Hash()
		if err != nil {
			return nil, err
		}
		digestsMap[hashAlg] = digestTLV.Value
	}
	return digestsMap, nil
}

// EncodeCELR encodes the CELR to bytes according to the CEL spec and write them
// to the bytes byffer.
func (r *Record) EncodeCELR(buf *bytes.Buffer) error {
	recnumField, err := createRecNumField(r.RecNum).MarshalBinary()
	if err != nil {
		return err
	}
	pcrField, err := createPCRField(r.PCR).MarshalBinary()
	if err != nil {
		return err
	}
	digests, err := createDigestField(r.Digests)
	if err != nil {
		return err
	}
	digestsField, err := digests.MarshalBinary()
	if err != nil {
		return err
	}
	eventField, err := r.Content.MarshalBinary()
	if err != nil {
		return err
	}
	_, err = buf.Write(recnumField)
	if err != nil {
		return err
	}
	_, err = buf.Write(pcrField)
	if err != nil {
		return err
	}
	_, err = buf.Write(digestsField)
	if err != nil {
		return err
	}
	_, err = buf.Write(eventField)
	if err != nil {
		return err
	}
	return nil
}

// EncodeCEL encodes the CEL to bytes according to the CEL spec and write them
// to the bytes buffer.
func (c *CEL) EncodeCEL(buf *bytes.Buffer) error {
	for _, record := range c.Records {
		if err := record.EncodeCELR(buf); err != nil {
			return err
		}
	}
	return nil
}

// DecodeToCEL will read the buf for CEL, will return err if the buffer
// is not complete.
func DecodeToCEL(buf *bytes.Buffer) (CEL, error) {
	var cel CEL
	for buf.Len() > 0 {
		celr, err := DecodeToCELR(buf)
		if err == io.EOF {
			return CEL{}, fmt.Errorf("buffer ends unexpectedly")
		}
		if err != nil {
			return CEL{}, err
		}
		cel.Records = append(cel.Records, celr)
	}
	return cel, nil
}

// DecodeToCELR will read the buf for the next CELR, will return err if
// failed to unmarshal a correct CELR TLV from the buffer.
func DecodeToCELR(buf *bytes.Buffer) (r Record, err error) {
	recnum, err := UnmarshalFirstTLV(buf)
	if err != nil {
		return Record{}, err
	}
	r.RecNum, err = UnmarshalRecNum(recnum)
	if err != nil {
		return Record{}, err
	}

	pcr, err := UnmarshalFirstTLV(buf)
	if err != nil {
		return Record{}, err
	}
	r.PCR, err = UnmarshalPCR(pcr)
	if err != nil {
		return Record{}, err
	}

	digests, err := UnmarshalFirstTLV(buf)
	if err != nil {
		return Record{}, err
	}
	r.Digests, err = UnmarshalDigests(digests)
	if err != nil {
		return Record{}, err
	}

	r.Content, err = UnmarshalFirstTLV(buf)
	if err != nil {
		return Record{}, err
	}
	return r, nil
}
<commit_msg>cel: make unmarshal TLV methods private<commit_after>// Package cel contains some basic operations of Canonical Eventlog.
// Based on Canonical EventLog Spec (Draft) Version: TCG_IWG_CEL_v1_r0p37.
package cel

import (
	"bytes"
	"crypto"
	"encoding/binary"
	"fmt"
	"io"

	"github.com/google/go-tpm/tpm2"
)

const (
	// CEL spec 5.1
	recnumTypeValue  uint8 = 0
	pcrTypeValue     uint8 = 1
	_                uint8 = 2 // nvindex field is not supported yet
	digestsTypeValue uint8 = 3

	tlvTypeFieldLength   int = 1
	tlvLengthFieldLength int = 4

	recnumValueLength uint32 = 8 // support up to 2^64 records
	pcrValueLength    uint32 = 1 // support up to 256 PCRs
)

// TLV definition according to CEL spec TCG_IWG_CEL_v1_r0p37, page 16.
// Length is implicitly defined by len(Value), using uint32 big-endian
// when encoding.
type TLV struct {
	Type  uint8
	Value []byte
}

// MarshalBinary marshals a TLV to a byte slice.
func (tlv TLV) MarshalBinary() (data []byte, err error) {
	buf := make([]byte, len(tlv.Value)+tlvTypeFieldLength+tlvLengthFieldLength)

	buf[0] = tlv.Type
	binary.BigEndian.PutUint32(buf[tlvTypeFieldLength:], uint32(len(tlv.Value)))
	copy(buf[tlvTypeFieldLength+tlvLengthFieldLength:], tlv.Value)

	return buf, nil
}

// UnmarshalBinary unmarshal a byte slice to a TLV.
func (tlv *TLV) UnmarshalBinary(data []byte) error {
	valueLength := binary.BigEndian.Uint32(data[tlvTypeFieldLength : tlvTypeFieldLength+tlvLengthFieldLength])

	if valueLength != uint32(len(data[tlvTypeFieldLength+tlvLengthFieldLength:])) {
		return fmt.Errorf("TLV Length doesn't match the size of its Value")
	}
	tlv.Type = data[0]
	tlv.Value = data[tlvTypeFieldLength+tlvLengthFieldLength:]

	return nil
}

// UnmarshalFirstTLV reads and parse the first TLV from the bytes buffer. The function will
// return io.EOF if the buf ends unexpectedly or cannot fill the TLV.
func UnmarshalFirstTLV(buf *bytes.Buffer) (tlv TLV, err error) {
	typeByte, err := buf.ReadByte()
	if err != nil {
		return tlv, err
	}
	var data []byte
	data = append(data, typeByte)

	// get the length
	lengthBytes := make([]byte, tlvLengthFieldLength)
	bytesRead, err := buf.Read(lengthBytes)
	if err != nil {
		return TLV{}, err
	}
	if bytesRead != tlvLengthFieldLength {
		return TLV{}, io.EOF
	}
	valueLength := binary.BigEndian.Uint32(lengthBytes)
	data = append(data, lengthBytes...)

	valueBytes := make([]byte, valueLength)
	bytesRead, err = buf.Read(valueBytes)
	if err != nil {
		return TLV{}, err
	}
	if uint32(bytesRead) != valueLength {
		return TLV{}, io.EOF
	}
	data = append(data, valueBytes...)

	if err = (&tlv).UnmarshalBinary(data); err != nil {
		return TLV{}, err
	}
	return tlv, nil
}

// Record represents a Canonical Eventlog Record.
type Record struct {
	RecNum  uint64
	PCR     uint8
	Digests map[crypto.Hash][]byte
	Content TLV
}

// Content is a interface for the content in CELR.
type Content interface {
	GenerateDigest(crypto.Hash) ([]byte, error)
	GetTLV() TLV
}

// CEL represents a Canonical Eventlog, which contains a list of Records.
type CEL struct {
	Records []Record
}

// AppendEvent appends a new record to the CEL.
func (c *CEL) AppendEvent(tpm io.ReadWriteCloser, pcr int, hashAlgos []crypto.Hash, event Content) error {
	if len(hashAlgos) == 0 {
		return fmt.Errorf("need to specify at least one hash algorithm")
	}
	digestsMap := make(map[crypto.Hash][]byte)

	for _, hashAlgo := range hashAlgos {
		digest, err := event.GenerateDigest(hashAlgo)
		if err != nil {
			return err
		}
		digestsMap[hashAlgo] = digest

		// TODO: extend the digest to TPM PCR
	}

	celr := Record{
		RecNum:  uint64(len(c.Records)),
		PCR:     uint8(pcr),
		Digests: digestsMap,
		Content: event.GetTLV(),
	}

	c.Records = append(c.Records, celr)
	return nil
}

func createRecNumField(recNum uint64) TLV {
	value := make([]byte, recnumValueLength)
	binary.BigEndian.PutUint64(value, recNum)
	return TLV{recnumTypeValue, value}
}

// UnmarshalRecNum takes in a TLV with its type equals to the recnum type value (0), and
// return its record number.
func unmarshalRecNum(tlv TLV) (uint64, error) {
	if tlv.Type != recnumTypeValue {
		return 0, fmt.Errorf("type of the TLV [%d] indicates it is not a recnum field [%d]",
			tlv.Type, recnumTypeValue)
	}
	if uint32(len(tlv.Value)) != recnumValueLength {
		return 0, fmt.Errorf(
			"length of the value of the TLV [%d] doesn't match the defined length [%d] of value for recnum",
			len(tlv.Value), recnumValueLength)
	}
	return binary.BigEndian.Uint64(tlv.Value), nil
}

func createPCRField(pcrNum uint8) TLV {
	return TLV{pcrTypeValue, []byte{pcrNum}}
}

// UnmarshalPCR takes in a TLV with its type equals to the PCR type value (1), and
// return its PCR number.
func unmarshalPCR(tlv TLV) (pcrNum uint8, err error) {
	if tlv.Type != pcrTypeValue {
		return 0, fmt.Errorf("type of the TLV [%d] indicates it is not a PCR field [%d]",
			tlv.Type, pcrTypeValue)
	}
	if uint32(len(tlv.Value)) != pcrValueLength {
		return 0, fmt.Errorf(
			"length of the value of the TLV [%d] doesn't match the defined length [%d] of value for a PCR field",
			len(tlv.Value), pcrValueLength)
	}

	return tlv.Value[0], nil
}

func createDigestField(digestMap map[crypto.Hash][]byte) (TLV, error) {
	var buf bytes.Buffer
	for hashAlgo, hash := range digestMap {
		if len(hash) != hashAlgo.Size() {
			return TLV{}, fmt.Errorf("digest length [%d] doesn't match the expected length [%d] for the hash algorithm",
				len(hash), hashAlgo.Size())
		}
		tpmHashAlg, err := tpm2.HashToAlgorithm(hashAlgo)
		if err != nil {
			return TLV{}, err
		}
		singleDigestTLV := TLV{uint8(tpmHashAlg), hash}
		d, err := singleDigestTLV.MarshalBinary()
		if err != nil {
			return TLV{}, err
		}
		_, err = buf.Write(d)
		if err != nil {
			return TLV{}, err
		}
	}
	return TLV{digestsTypeValue, buf.Bytes()}, nil
}

// UnmarshalDigests takes in a TLV with its type equals to the digests type value (3), and
// return its digests content in a map, the key is its TPM hash algorithm.
func unmarshalDigests(tlv TLV) (digestsMap map[crypto.Hash][]byte, err error) {
	if tlv.Type != digestsTypeValue {
		return nil, fmt.Errorf("type of the TLV indicates it doesn't contain digests")
	}

	buf := bytes.NewBuffer(tlv.Value)
	digestsMap = make(map[crypto.Hash][]byte)

	for buf.Len() > 0 {
		digestTLV, err := UnmarshalFirstTLV(buf)
		if err == io.EOF {
			return nil, fmt.Errorf("buffer ends unexpectedly")
		} else if err != nil {
			return nil, err
		}
		hashAlg, err := tpm2.Algorithm(digestTLV.Type).Hash()
		if err != nil {
			return nil, err
		}
		digestsMap[hashAlg] = digestTLV.Value
	}
	return digestsMap, nil
}

// EncodeCELR encodes the CELR to bytes according to the CEL spec and write them
// to the bytes byffer.
func (r *Record) EncodeCELR(buf *bytes.Buffer) error {
	recnumField, err := createRecNumField(r.RecNum).MarshalBinary()
	if err != nil {
		return err
	}
	pcrField, err := createPCRField(r.PCR).MarshalBinary()
	if err != nil {
		return err
	}
	digests, err := createDigestField(r.Digests)
	if err != nil {
		return err
	}
	digestsField, err := digests.MarshalBinary()
	if err != nil {
		return err
	}
	eventField, err := r.Content.MarshalBinary()
	if err != nil {
		return err
	}
	_, err = buf.Write(recnumField)
	if err != nil {
		return err
	}
	_, err = buf.Write(pcrField)
	if err != nil {
		return err
	}
	_, err = buf.Write(digestsField)
	if err != nil {
		return err
	}
	_, err = buf.Write(eventField)
	if err != nil {
		return err
	}
	return nil
}

// EncodeCEL encodes the CEL to bytes according to the CEL spec and write them
// to the bytes buffer.
func (c *CEL) EncodeCEL(buf *bytes.Buffer) error {
	for _, record := range c.Records {
		if err := record.EncodeCELR(buf); err != nil {
			return err
		}
	}
	return nil
}

// DecodeToCEL will read the buf for CEL, will return err if the buffer
// is not complete.
func DecodeToCEL(buf *bytes.Buffer) (CEL, error) {
	var cel CEL
	for buf.Len() > 0 {
		celr, err := DecodeToCELR(buf)
		if err == io.EOF {
			return CEL{}, fmt.Errorf("buffer ends unexpectedly")
		}
		if err != nil {
			return CEL{}, err
		}
		cel.Records = append(cel.Records, celr)
	}
	return cel, nil
}

// DecodeToCELR will read the buf for the next CELR, will return err if
// failed to unmarshal a correct CELR TLV from the buffer.
func DecodeToCELR(buf *bytes.Buffer) (r Record, err error) {
	recnum, err := UnmarshalFirstTLV(buf)
	if err != nil {
		return Record{}, err
	}
	r.RecNum, err = unmarshalRecNum(recnum)
	if err != nil {
		return Record{}, err
	}

	pcr, err := UnmarshalFirstTLV(buf)
	if err != nil {
		return Record{}, err
	}
	r.PCR, err = unmarshalPCR(pcr)
	if err != nil {
		return Record{}, err
	}

	digests, err := UnmarshalFirstTLV(buf)
	if err != nil {
		return Record{}, err
	}
	r.Digests, err = unmarshalDigests(digests)
	if err != nil {
		return Record{}, err
	}

	r.Content, err = UnmarshalFirstTLV(buf)
	if err != nil {
		return Record{}, err
	}
	return r, nil
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"strings"
)

func help() {
	var cmd string
	if len(os.Args) > 1 {
		cmd = os.Args[1]
		if len(os.Args) > 2 && cmd == "help" {
			cmd = os.Args[2]
		}
	}
	cli.Commands.loadUsages()
	topic, command := cli.ParseCmd(cmd)
	switch {
	case topic == nil:
		Printf("Usage: heroku COMMAND [--app APP] [command-specific-options]\n\n")
		Printf("Help topics, type \"heroku help TOPIC\" for more details:\n\n")
		for _, topic := range nonHiddenTopics(cli.Topics) {
			Printf("  heroku %-30s# %s\n", topic.Name, topic.Description)
		}
	case command == nil:
		Printf("Usage: heroku %s:COMMAND [--app APP] [command-specific-options]\n\n", topic.Name)
		printTopicCommandsHelp(topic)
	case command.Command == "":
		printCommandHelp(command)
		// This is a root command so show the other commands in the topic
		// if there are any
		if len(topic.Commands()) > 1 {
			printTopicCommandsHelp(topic)
		}
	default:
		printCommandHelp(command)
	}
	os.Exit(2)
}

func printTopicCommandsHelp(topic *Topic) {
	commands := topic.Commands()
	if len(commands) > 0 {
		Printf("\nCommands for %s, type \"heroku help %s:COMMAND\" for more details:\n\n", topic.Name, topic.Name)
		for _, command := range nonHiddenCommands(commands) {
			Printf(" heroku %-30s # %s\n", command.Usage, command.Description)
		}
	}
}

func printCommandHelp(command *Command) {
	Printf("Usage: heroku %s\n\n", command.Usage)
	Println(indent(command.buildFullHelp()))
}

func nonHiddenTopics(from []*Topic) []*Topic {
	to := make([]*Topic, 0, len(from))
	for _, topic := range from {
		if !topic.Hidden {
			to = append(to, topic)
		}
	}
	return to
}

func nonHiddenCommands(from []*Command) []*Command {
	to := make([]*Command, 0, len(from))
	for _, command := range from {
		if !command.Hidden {
			to = append(to, command)
		}
	}
	return to
}

func indent(s string) string {
	return " " + strings.Join(strings.Split(s, "\n"), "\n ")
}
<commit_msg>exit help successfully<commit_after>package main

import (
	"os"
	"strings"
)

func help() {
	var cmd string
	if len(os.Args) > 1 {
		cmd = os.Args[1]
		if len(os.Args) > 2 && cmd == "help" {
			cmd = os.Args[2]
		}
	}
	cli.Commands.loadUsages()
	topic, command := cli.ParseCmd(cmd)
	switch {
	case topic == nil:
		Printf("Usage: heroku COMMAND [--app APP] [command-specific-options]\n\n")
		Printf("Help topics, type \"heroku help TOPIC\" for more details:\n\n")
		for _, topic := range nonHiddenTopics(cli.Topics) {
			Printf("  heroku %-30s# %s\n", topic.Name, topic.Description)
		}
	case command == nil:
		Printf("Usage: heroku %s:COMMAND [--app APP] [command-specific-options]\n\n", topic.Name)
		printTopicCommandsHelp(topic)
	case command.Command == "":
		printCommandHelp(command)
		// This is a root command so show the other commands in the topic
		// if there are any
		if len(topic.Commands()) > 1 {
			printTopicCommandsHelp(topic)
		}
	default:
		printCommandHelp(command)
	}
	os.Exit(0)
}

func printTopicCommandsHelp(topic *Topic) {
	commands := topic.Commands()
	if len(commands) > 0 {
		Printf("\nCommands for %s, type \"heroku help %s:COMMAND\" for more details:\n\n", topic.Name, topic.Name)
		for _, command := range nonHiddenCommands(commands) {
			Printf(" heroku %-30s # %s\n", command.Usage, command.Description)
		}
	}
}

func printCommandHelp(command *Command) {
	Printf("Usage: heroku %s\n\n", command.Usage)
	Println(indent(command.buildFullHelp()))
}

func nonHiddenTopics(from []*Topic) []*Topic {
	to := make([]*Topic, 0, len(from))
	for _, topic := range from {
		if !topic.Hidden {
			to = append(to, topic)
		}
	}
	return to
}

func nonHiddenCommands(from []*Command) []*Command {
	to := make([]*Command, 0, len(from))
	for _, command := range from {
		if !command.Hidden {
			to = append(to, command)
		}
	}
	return to
}

func indent(s string) string {
	return " " + strings.Join(strings.Split(s, "\n"), "\n ")
}
<|endoftext|>


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

/*
Hira accepts as argument text romaji
text. It copies the text to standard output, converting
the text that matches the romaji format to hiragana.
Note that the output may not be accurate because of
false matches and the inability to generate things like
the tsu consonant-extending symbol.
*/
package main // import "robpike.io/cmd/hira"

import (
	"fmt"
	"os"
	"strings"
)

func main() {
	do(strings.Join(os.Args[1:], " "))
}

func do(s string) {
	wid := 0
	for i := 0; i < len(s); i += wid {
		if i+3 <= len(s) {
			cha, ok := three[s[i:i+3]]
			if ok {
				wid = 3
				fmt.Printf("%s", cha)
				continue
			}
		}
		if i+2 <= len(s) {
			ka, ok := two[s[i:i+2]]
			if ok {
				wid = 2
				fmt.Printf("%s", ka)
				continue
			}
		}
		wid = 1
		a, ok := one[s[i:i+1]]
		if ok {
			fmt.Printf("%s", a)
			continue
		}
		fmt.Printf("%s", s[i:i+1])
	}
	fmt.Print("\n")
}

var one = map[string]string{
	"a": "あ",
	"i": "い",
	"u": "う",
	"e": "え",
	"o": "お",
	"n": "ん",
	"m": "ん",
}

var two = map[string]string{
	"ka": "か",
	"ca": "か",
	"ga": "が",
	"ki": "き",
	"gi": "ぎ",
	"ku": "く",
	"cu": "く",
	"gu": "ぐ",
	"ke": "け",
	"ge": "げ",
	"ko": "こ",
	"co": "こ",
	"go": "ご",
	"sa": "さ",
	"za": "ざ",
	"si": "し",
	"zi": "じ",
	"su": "す",
	"zu": "ず",
	"se": "せ",
	"ze": "ぜ",
	"so": "そ",
	"zo": "ぞ",
	"ta": "た",
	"da": "だ",
	"ti": "ち",
	"di": "ぢ",
	"tu": "つ",
	"du": "づ",
	"te": "て",
	"de": "で",
	"to": "と",
	"do": "ど",
	"na": "な",
	"ni": "に",
	"nu": "ぬ",
	"ne": "ね",
	"no": "の",
	"ha": "は",
	"va": "ば",
	"pa": "ぱ",
	"hi": "ひ",
	"vi": "び",
	"pi": "ぴ",
	"fu": "ふ",
	"fe": "ふぇ",
	"bu": "ぶ",
	"pu": "ぷ",
	"he": "へ",
	"ve": "べ",
	"pe": "ぺ",
	"ho": "ほ",
	"vo": "ぼ",
	"po": "ぽ",
	"ma": "ま",
	"mi": "み",
	"mu": "む",
	"me": "め",
	"mo": "も",
	"ya": "や",
	"yu": "ゆ",
	"yo": "よ",
	"ra": "ら",
	"ri": "り",
	"ru": "る",
	"re": "れ",
	"ro": "ろ",
	"wa": "わ",
	"wi": "ゐ",
	"we": "ゑ",
	"wo": "を",
	"vu": "ゔ",
}

var three = map[string]string{
	"shi": "し",
	"chi": "ち",
	"tsu": "つ",
	"cha": "ちや", // TODO IS THIS RIGHT
	"chu": "ちゆ", // TODO IS THIS RIGHT
	"cho": "ちよ", // TODO IS THIS RIGHT
	// NEED MORE
}
<commit_msg>kana: add more chars and handule sokuon<commit_after>// Copyright 2014 Rob Pike. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
Hira accepts as argument text romaji
text. It copies the text to standard output, converting
the text that matches the romaji format to hiragana.
Note that the output may not be accurate because of
false matches and the inability to generate things like
the tsu consonant-extending symbol.
*/
package main // import "robpike.io/cmd/hira"

import (
	"fmt"
	"os"
	"strings"
)

func main() {
	do(strings.Join(os.Args[1:], " "))
}

func do(s string) {
	wid := 0
	for i := 0; i < len(s); i += wid {
		if i+3 <= len(s) {
			cha, ok := three[s[i:i+3]]
			if ok {
				wid = 3
				fmt.Printf("%s", cha)
				continue
			}
		}
		if i+2 <= len(s) {
			ka, ok := two[s[i:i+2]]
			if ok {
				if i > 1 && consonants[s[i-1:i]] {
					fmt.Printf("っ")
				}
				wid = 2
				fmt.Printf("%s", ka)
				continue
			}
		}
		wid = 1
		a, ok := one[s[i:i+1]]
		if ok {
			fmt.Printf("%s", a)
			continue
		}
	}
	fmt.Print("\n")
}

var consonants = map[string]bool{
	"b": true,
	"c": true,
	"d": true,
	"f": true,
	"g": true,
	"h": true,
	"j": true,
	"k": true,
	"l": true,
	"p": true,
	"q": true,
	"r": true,
	"s": true,
	"t": true,
	"v": true,
	"w": true,
	"x": true,
	"y": true,
	"z": true,
}

// note the absense of n and m

var one = map[string]string{
	"a": "あ",
	"i": "い",
	"u": "う",
	"e": "え",
	"o": "お",
	"n": "ん",
}

var two = map[string]string{
	"xa": "ぁ",
	"xi": "ぃ",
	"xu": "ぅ",
	"xe": "ぇ",
	"xo": "ぉ",

	"ka": "か",
	"ki": "き",
	"ku": "く",
	"ke": "け",
	"ko": "こ",

	"ga": "が",
	"gi": "ぎ",
	"gu": "ぐ",
	"ge": "げ",
	"go": "ご",

	"sa": "さ",
	"su": "す",
	"se": "せ",
	"so": "そ",

	"za": "ざ",
	"ji": "じ",
	"zu": "ず",
	"ze": "ぜ",
	"zo": "ぞ",

	"ja": "じゃ",
	"ju": "じゅ",
	"jo": "じょ",

	"ta": "た",
	"te": "て",
	"to": "と",

	"ti": "てぃ",
	"tu": "とぅ",

	"di": "でぃ",
	"du": "どぅ",

	"da": "だ",
	"de": "で",
	"do": "ど",

	"na": "な",
	"ni": "に",
	"nu": "ぬ",
	"ne": "ね",
	"no": "の",

	"ha": "は",
	"hi": "ひ",
	"fu": "ふ",
	"he": "へ",
	"ho": "ほ",

	"ba": "ば",
	"bi": "び",
	"bu": "ぶ",
	"be": "べ",
	"bo": "ぼ",

	"pa": "ぱ",
	"pi": "ぴ",
	"pu": "ぷ",
	"pe": "ぺ",
	"po": "ぽ",

	"fa": "ふぁ",
	"fi": "ふぃ",
	"fe": "ふぇ",
	"fo": "ふぉ",

	"ma": "ま",
	"mi": "み",
	"mu": "む",
	"me": "め",
	"mo": "も",

	"ya": "や",
	"yu": "ゆ",
	"ye": "いぇ",
	"yo": "よ",

	"ra": "ら",
	"ri": "り",
	"ru": "る",
	"re": "れ",
	"ro": "ろ",

	"wa": "わ",
	//"wi": "ゐ",
	//"we": "ゑ",
	"wo": "を",

	//"wa": "うぁ",
	"wi": "うぃ",
	"we": "うぇ",
	//"wo": "うぉ",

	"va": "ゔぁ",
	"vi": "ゔぃ",
	"vu": "ゔ",
	"ve": "ゔぇ",
	"vo": "ゔぉ",
}

var three = map[string]string{
	"kya": "きゃ",
	"kyu": "きゅ",
	"kyo": "きょ",

	"gya": "ぎゃ",
	"gyu": "ぎゅ",
	"gyo": "ぎょ",

	"shi": "し",

	"sha": "しゃ",
	"shu": "しゅ",
	"sho": "しょ",

	"chi": "ち",
	"tsu": "つ",

	"dhi": "ぢ",
	"dhu": "づ",

	"cha": "ちゃ",
	"chu": "ちゅ",
	"che": "ちぇ",
	"cho": "ちょ",

	"dha": "ぢゃ",
	//"dhu": "ぢゅ",
	"dhe": "ぢぇ",
	"dho": "ぢょ",

	"nya": "にゃ",
	"nyu": "にゅ",
	"nyo": "にょ",

	"hya": "ひゃ",
	"hyu": "ひゅ",
	"hyo": "ひょ",

	"bya": "びゃ",
	"byu": "びゅ",
	"byo": "びょ",

	"pya": "ぴゃ",
	"pyu": "ぴゅ",
	"pyo": "ぴょ",

	"mya": "みゃ",
	"myu": "みゅ",
	"myo": "みょ",

	"xya": "ゃ",
	"xyu": "ゅ",
	"xyo": "ょ",

	"rya": "りゃ",
	"ryu": "りゅ",
	"ryo": "りょ",
}

var hiragana2romanji = map[string]string{
	"a": "あ",
	"i": "い",
	"u": "う",
	"e": "え",
	"o": "お",

	"xa": "ぁ",
	"xi": "ぃ",
	"xu": "ぅ",
	"xe": "ぇ",
	"xo": "ぉ",

	"ka": "か",
	"ki": "き",
	"ku": "く",
	"ke": "け",
	"ko": "こ",

	"ga": "が",
	"gi": "ぎ",
	"gu": "ぐ",
	"ge": "げ",
	"go": "ご",

	"kya": "きゃ",
	"kyu": "きゅ",
	"kyo": "きょ",

	"gya": "ぎゃ",
	"gyu": "ぎゅ",
	"gyo": "ぎょ",

	"sa":  "さ",
	"shi": "し",
	"su":  "す",
	"se":  "せ",
	"so":  "そ",

	"za": "ざ",
	"ji": "じ",
	"zu": "ず",
	"ze": "ぜ",
	"zo": "ぞ",

	"sha": "しゃ",
	"shu": "しゅ",
	"sho": "しょ",

	"ja": "じゃ",
	"ju": "じゅ",
	"jo": "じょ",

	"ta":  "た",
	"chi": "ち",
	"tsu": "つ",
	"te":  "て",
	"to":  "と",

	"ti": "てぃ",
	"tu": "とぅ",

	"di": "でぃ",
	"du": "どぅ",

	"da":  "だ",
	"dhi": "ぢ",
	"dhu": "づ",
	"de":  "で",
	"do":  "ど",

	"cha": "ちゃ",
	"chu": "ちゅ",
	"che": "ちぇ",
	"cho": "ちょ",

	"dha": "ぢゃ",
	//"dhu": "ぢゅ",
	"dhe": "ぢぇ",
	"dho": "ぢょ",

	"na": "な",
	"ni": "に",
	"nu": "ぬ",
	"ne": "ね",
	"no": "の",

	"nya": "にゃ",
	"nyu": "にゅ",
	"nyo": "にょ",

	"ha": "は",
	"hi": "ひ",
	"fu": "ふ",
	"he": "へ",
	"ho": "ほ",

	"hya": "ひゃ",
	"hyu": "ひゅ",
	"hyo": "ひょ",

	"ba": "ば",
	"bi": "び",
	"bu": "ぶ",
	"be": "べ",
	"bo": "ぼ",

	"bya": "びゃ",
	"byu": "びゅ",
	"byo": "びょ",

	"pa": "ぱ",
	"pi": "ぴ",
	"pu": "ぷ",
	"pe": "ぺ",
	"po": "ぽ",

	"pya": "ぴゃ",
	"pyu": "ぴゅ",
	"pyo": "ぴょ",

	"fa": "ふぁ",
	"fi": "ふぃ",
	"fe": "ふぇ",
	"fo": "ふぉ",

	"ma": "ま",
	"mi": "み",
	"mu": "む",
	"me": "め",
	"mo": "も",

	"mya": "みゃ",
	"myu": "みゅ",
	"myo": "みょ",

	"ya": "や",
	"yu": "ゆ",
	"ye": "いぇ",
	"yo": "よ",

	"xya": "ゃ",
	"xyu": "ゅ",
	"xyo": "ょ",

	"ra": "ら",
	"ri": "り",
	"ru": "る",
	"re": "れ",
	"ro": "ろ",

	"rya": "りゃ",
	"ryu": "りゅ",
	"ryo": "りょ",

	"wa": "わ",
	//"wi": "ゐ",
	//"we": "ゑ",
	"wo": "を",

	//"wa": "うぁ",
	"wi": "うぃ",
	"we": "うぇ",
	//"wo": "うぉ",

	"va": "ゔぁ",
	"vi": "ゔぃ",
	"vu": "ゔ",
	"ve": "ゔぇ",
	"vo": "ゔぉ",

	"n": "ん",
}
<|endoftext|>


<commit_before>package util

import (
    "github.com/jinzhu/gorm"
    "github.com/golang/glog"
    "github.com/spacexnice/ctlplane/pro/api"
    "os"
    _ "github.com/mattn/go-sqlite3"
)

var DEFAULT_DB = "./gorm.db"

func open() *gorm.DB {
    db, err := gorm.Open("sqlite3", DEFAULT_DB)
    if err != nil {
        panic(err)
        return nil
    }
    return &db
}
func OpenInit() *gorm.DB {
    var db *gorm.DB
    if Exist(DEFAULT_DB) {
        glog.Info("DEFAULT_DB[./gorm.db] Loaded! ")
        db = open()
        return db
    }
    if db = open(); db == nil {
        return nil
    }
    db.LogMode(true)
    db.CreateTable(&api.Repository{})
    db.CreateTable(&api.Tag{})
    return db
}

// 检查文件或目录是否存在
// 如果由 filename 指定的文件或目录存在则返回 true，否则返回 false
func Exist(filename string) bool {
    _, err := os.Stat(filename)
    return err == nil || os.IsExist(err)
}<commit_msg>gormdb point change<commit_after>package util

import (
    "github.com/jinzhu/gorm"
    "github.com/golang/glog"
    "github.com/spacexnice/ctlplane/pro/api"
    "os"
    _ "github.com/mattn/go-sqlite3"
)

var DEFAULT_DB = "./gorm.db"

func open() *gorm.DB {
    db, err := gorm.Open("sqlite3", DEFAULT_DB)
    if err != nil {
        panic(err)
        return nil
    }
    return db
}
func OpenInit() *gorm.DB {
    var db *gorm.DB
    if Exist(DEFAULT_DB) {
        glog.Info("DEFAULT_DB[./gorm.db] Loaded! ")
        db = open()
        return db
    }
    if db = open(); db == nil {
        return nil
    }
    db.LogMode(true)
    db.CreateTable(&api.Repository{})
    db.CreateTable(&api.Tag{})
    return db
}

// 检查文件或目录是否存在
// 如果由 filename 指定的文件或目录存在则返回 true，否则返回 false
func Exist(filename string) bool {
    _, err := os.Stat(filename)
    return err == nil || os.IsExist(err)
}<|endoftext|>


<commit_before>package main

import (
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/fatih/structs"
	"github.com/gorilla/mux"
	"github.com/maliceio/go-plugin-utils/clitable"
	"github.com/maliceio/go-plugin-utils/database/elasticsearch"
	"github.com/maliceio/go-plugin-utils/utils"
	"github.com/parnurzeal/gorequest"
	"github.com/urfave/cli"
)

// Version stores the plugin's version
var Version string

// BuildTime stores the plugin's build time
var BuildTime string

var path string

const (
	name     = "clamav"
	category = "av"
)

type pluginResults struct {
	ID   string      `json:"id" structs:"id,omitempty"`
	Data ResultsData `json:"clamav" structs:"clamav"`
}

// ClamAV json object
type ClamAV struct {
	Results ResultsData `json:"clamav"`
}

// ResultsData json object
type ResultsData struct {
	Infected bool   `json:"infected" structs:"infected"`
	Result   string `json:"result" structs:"result"`
	Engine   string `json:"engine" structs:"engine"`
	Known    string `json:"known" structs:"known"`
	Updated  string `json:"updated" structs:"updated"`
	Error    string `json:"error" structs:"error"`
	Markdown string `json:"markdown" structs:"markdown"`
}

func assert(err error) {
	if err != nil {
		log.WithFields(log.Fields{
			"plugin":   name,
			"category": category,
			"path":     path,
		}).Fatal(err)
	}
}

// AvScan performs antivirus scan
func AvScan(timeout int) ClamAV {

	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second)
	defer cancel()

	return ClamAV{
		Results: ParseClamAvOutput(utils.RunCommand(ctx, "/usr/bin/clamscan", "--stdout", path)),
	}
}

// ParseClamAvOutput convert clamav output into ClamAV struct
func ParseClamAvOutput(clamout string, err error) ResultsData {

	if err != nil {
		return ResultsData{Error: err.Error()}
	}

	log.WithFields(log.Fields{
		"plugin":   name,
		"category": category,
		"path":     path,
	}).Debug("ClamAV Output: ", clamout)

	clamAV := ResultsData{}

	lines := strings.Split(clamout, "\n")
	// Extract AV Scan Result
	result := lines[0]
	if len(result) != 0 {
		pathAndResult := strings.Split(result, ":")
		if strings.Contains(pathAndResult[1], "OK") {
			clamAV.Infected = false
		} else {
			clamAV.Infected = true
			clamAV.Result = strings.TrimSpace(strings.TrimRight(pathAndResult[1], "FOUND"))
		}
	} else {
		fmt.Println("[ERROR] empty scan result: ", result)
		os.Exit(2)
	}
	// Extract Clam Details from SCAN SUMMARY
	for _, line := range lines[1:] {
		if len(line) != 0 {
			keyvalue := strings.Split(line, ":")
			if len(keyvalue) != 0 {
				switch {
				case strings.Contains(keyvalue[0], "Known viruses"):
					clamAV.Known = strings.TrimSpace(keyvalue[1])
				case strings.Contains(line, "Engine version"):
					clamAV.Engine = strings.TrimSpace(keyvalue[1])
				}
			}
		}
	}

	clamAV.Updated = getUpdatedDate()

	return clamAV
}

func updateAV(ctx context.Context) error {
	fmt.Println("Updating ClamAV...")
	fmt.Println(utils.RunCommand(ctx, "freshclam"))
	// Update UPDATED file
	t := time.Now().Format("20060102")
	err := ioutil.WriteFile("/opt/malice/UPDATED", []byte(t), 0644)
	return err
}

func getUpdatedDate() string {
	if _, err := os.Stat("/opt/malice/UPDATED"); os.IsNotExist(err) {
		return BuildTime
	}
	updated, err := ioutil.ReadFile("/opt/malice/UPDATED")
	assert(err)
	return string(updated)
}

func printMarkDownTable(clamav ClamAV, toString bool) string {
	table := clitable.New([]string{"Infected", "Result", "Engine", "Updated"})
	table.AddRow(map[string]interface{}{
		"Infected": clamav.Results.Infected,
		"Result":   clamav.Results.Result,
		"Engine":   clamav.Results.Engine,
		// "Known":    clamav.Results.Known,
		"Updated": clamav.Results.Updated,
	})
	table.Markdown = true

	if toString {
		return table.String("ClamAV")
	}
	fmt.Println("#### ClamAV")
	table.Print()
	return ""
}

func printStatus(resp gorequest.Response, body string, errs []error) {
	fmt.Println(body)
}

func webService() {
	router := mux.NewRouter().StrictSlash(true)
	router.HandleFunc("/scan", webAvScan).Methods("POST")
	log.Info("web service listening on port :3993")
	log.Fatal(http.ListenAndServe(":3993", router))
}

func webAvScan(w http.ResponseWriter, r *http.Request) {

	r.ParseMultipartForm(32 << 20)
	file, header, err := r.FormFile("malware")
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprintln(w, "Please supply a valid file to scan.")
		log.Error(err)
	}
	defer file.Close()

	log.Debug("Uploaded fileName: ", header.Filename)

	tmpfile, err := ioutil.TempFile("/malware", "web_")
	if err != nil {
		log.Fatal(err)
	}
	defer os.Remove(tmpfile.Name()) // clean up

	data, err := ioutil.ReadAll(file)

	if _, err = tmpfile.Write(data); err != nil {
		log.Fatal(err)
	}
	if err = tmpfile.Close(); err != nil {
		log.Fatal(err)
	}

	// Do AV scan
	path = tmpfile.Name()
	clamav := AvScan(60)

	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)

	if err := json.NewEncoder(w).Encode(clamav); err != nil {
		log.Fatal(err)
	}
}

func main() {

	var elastic string

	cli.AppHelpTemplate = utils.AppHelpTemplate
	app := cli.NewApp()

	app.Name = "clamav"
	app.Author = "blacktop"
	app.Email = "https://github.com/blacktop"
	app.Version = Version + ", BuildTime: " + BuildTime
	app.Compiled, _ = time.Parse("20060102", BuildTime)
	app.Usage = "Malice ClamAV Plugin"
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "verbose, V",
			Usage: "verbose output",
		},
		cli.BoolFlag{
			Name:  "table, t",
			Usage: "output as Markdown table",
		},
		cli.BoolFlag{
			Name:   "callback, c",
			Usage:  "POST results to Malice webhook",
			EnvVar: "MALICE_ENDPOINT",
		},
		cli.BoolFlag{
			Name:   "proxy, x",
			Usage:  "proxy settings for Malice webhook endpoint",
			EnvVar: "MALICE_PROXY",
		},
		cli.StringFlag{
			Name:        "elasitcsearch",
			Value:       "",
			Usage:       "elasitcsearch address for Malice to store results",
			EnvVar:      "MALICE_ELASTICSEARCH",
			Destination: &elastic,
		},
		cli.IntFlag{
			Name:   "timeout",
			Value:  60,
			Usage:  "malice plugin timeout (in seconds)",
			EnvVar: "MALICE_TIMEOUT",
		},
	}
	app.Commands = []cli.Command{
		{
			Name:    "update",
			Aliases: []string{"u"},
			Usage:   "Update virus definitions",
			Action: func(c *cli.Context) error {
				ctx, cancel := context.WithTimeout(
					context.Background(),
					time.Duration(c.Int("timeout"))*time.Second,
				)
				defer cancel()

				return updateAV(ctx)
			},
		},
		{
			Name:  "web",
			Usage: "Create a ClamAV scan web service",
			Action: func(c *cli.Context) error {
				webService()
				return nil
			},
		},
	}
	app.Action = func(c *cli.Context) error {

		var err error

		if c.Bool("verbose") {
			log.SetLevel(log.DebugLevel)
		}

		if c.Args().Present() {
			path, err = filepath.Abs(c.Args().First())
			assert(err)

			if _, err = os.Stat(path); os.IsNotExist(err) {
				assert(err)
			}

			clamav := AvScan(c.Int("timeout"))

			// upsert into Database
			elasticsearch.InitElasticSearch(elastic)
			elasticsearch.WritePluginResultsToDatabase(elasticsearch.PluginResults{
				ID:       utils.Getopt("MALICE_SCANID", utils.GetSHA256(path)),
				Name:     name,
				Category: category,
				Data:     structs.Map(clamav.Results),
			})

			if c.Bool("table") {
				printMarkDownTable(clamav, false)
			} else {
				// add markdown output as a string
				clamav.Results.Markdown = printMarkDownTable(clamav, true)
				// convert to JSON
				clamavJSON, err := json.Marshal(clamav)
				assert(err)
				if c.Bool("post") {
					request := gorequest.New()
					if c.Bool("proxy") {
						request = gorequest.New().Proxy(os.Getenv("MALICE_PROXY"))
					}
					request.Post(os.Getenv("MALICE_ENDPOINT")).
						Set("X-Malice-ID", utils.Getopt("MALICE_SCANID", utils.GetSHA256(path))).
						Send(string(clamavJSON)).
						End(printStatus)

					return nil
				}
				fmt.Println(string(clamavJSON))
			}
		} else {
			log.Fatal(fmt.Errorf("Please supply a file to scan with malice/clamav"))
		}
		return nil
	}

	err := app.Run(os.Args)
	assert(err)
}
<commit_msg>clear out scan.go<commit_after>package main

import (
	"fmt"
	"os"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/maliceio/go-plugin-utils/utils"
	"github.com/urfave/cli"
)

// Version stores the plugin's version
var Version string

// BuildTime stores the plugin's build time
var BuildTime string

var path string

const (
	name     = "bro"
	category = "net"
)

func main() {

	var elastic string

	cli.AppHelpTemplate = utils.AppHelpTemplate
	app := cli.NewApp()

	app.Name = "bro"
	app.Author = "blacktop"
	app.Email = "https://github.com/blacktop"
	app.Version = Version + ", BuildTime: " + BuildTime
	app.Compiled, _ = time.Parse("20060102", BuildTime)
	app.Usage = "Malice Bro Plugin"
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "verbose, V",
			Usage: "verbose output",
		},
		cli.BoolFlag{
			Name:  "table, t",
			Usage: "output as Markdown table",
		},
		cli.BoolFlag{
			Name:   "callback, c",
			Usage:  "POST results to Malice webhook",
			EnvVar: "MALICE_ENDPOINT",
		},
		cli.BoolFlag{
			Name:   "proxy, x",
			Usage:  "proxy settings for Malice webhook endpoint",
			EnvVar: "MALICE_PROXY",
		},
		cli.StringFlag{
			Name:        "elasitcsearch",
			Value:       "",
			Usage:       "elasitcsearch address for Malice to store results",
			EnvVar:      "MALICE_ELASTICSEARCH",
			Destination: &elastic,
		},
		cli.IntFlag{
			Name:   "timeout",
			Value:  60,
			Usage:  "malice plugin timeout (in seconds)",
			EnvVar: "MALICE_TIMEOUT",
		},
	}
	app.Action = func(c *cli.Context) error {

		if c.Bool("verbose") {
			log.SetLevel(log.DebugLevel)
		}

		if c.Args().Present() {
			log.Info("NOT DONE YET (WIP)")
		} else {
			log.Fatal(fmt.Errorf("Please supply a file to scan with malice/clamav"))
		}
		return nil
	}

	err := app.Run(os.Args)
	utils.Assert(err)
}
<|endoftext|>


<commit_before>package stripe

import "encoding/json"

// PaymentMethodFPXAccountHolderType is a list of string values that FPX AccountHolderType accepts.
type PaymentMethodFPXAccountHolderType string

// List of values that PaymentMethodFPXAccountHolderType can take
const (
	PaymentMethodFPXAccountHolderTypeIndividual PaymentMethodFPXAccountHolderType = "individual"
	PaymentMethodFPXAccountHolderTypeCompany    PaymentMethodFPXAccountHolderType = "company"
)

// PaymentMethodType is the list of allowed values for the payment method type.
type PaymentMethodType string

// List of values that PaymentMethodType can take.
const (
	PaymentMethodTypeAUBECSDebit    PaymentMethodType = "au_becs_debit"
	PaymentMethodTypeBACSDebit      PaymentMethodType = "bacs_debit"
	PaymentMethodTypeCard           PaymentMethodType = "card"
	PaymentMethodTypeCardPresent    PaymentMethodType = "card_present"
	PaymentMethodTypeFPX            PaymentMethodType = "fpx"
	PaymentMethodTypeIdeal          PaymentMethodType = "ideal"
	PaymentMethodTypeInteracPresent PaymentMethodType = "interac_present"
	PaymentMethodTypeP24            PaymentMethodType = "p24"
	PaymentMethodTypeSepaDebit      PaymentMethodType = "sepa_debit"
)

// PaymentMethodCardBrand is the list of allowed values for the brand property on a
// Card PaymentMethod.
type PaymentMethodCardBrand string

// List of values that PaymentMethodCardBrand can take.
const (
	PaymentMethodCardBrandAmex       PaymentMethodCardBrand = "amex"
	PaymentMethodCardBrandDiners     PaymentMethodCardBrand = "diners"
	PaymentMethodCardBrandDiscover   PaymentMethodCardBrand = "discover"
	PaymentMethodCardBrandJCB        PaymentMethodCardBrand = "jcb"
	PaymentMethodCardBrandMastercard PaymentMethodCardBrand = "mastercard"
	PaymentMethodCardBrandUnionpay   PaymentMethodCardBrand = "unionpay"
	PaymentMethodCardBrandUnknown    PaymentMethodCardBrand = "unknown"
	PaymentMethodCardBrandVisa       PaymentMethodCardBrand = "visa"
)

// PaymentMethodCardNetwork is the list of allowed values to represent the network
// used for a card-like transaction.
type PaymentMethodCardNetwork string

// List of values that PaymentMethodCardNetwork can take.
const (
	PaymentMethodCardNetworkAmex       PaymentMethodCardNetwork = "amex"
	PaymentMethodCardNetworkDiners     PaymentMethodCardNetwork = "diners"
	PaymentMethodCardNetworkDiscover   PaymentMethodCardNetwork = "discover"
	PaymentMethodCardNetworkInterac    PaymentMethodCardNetwork = "interac"
	PaymentMethodCardNetworkJCB        PaymentMethodCardNetwork = "jcb"
	PaymentMethodCardNetworkMastercard PaymentMethodCardNetwork = "mastercard"
	PaymentMethodCardNetworkUnionpay   PaymentMethodCardNetwork = "unionpay"
	PaymentMethodCardNetworkUnknown    PaymentMethodCardNetwork = "unknown"
	PaymentMethodCardNetworkVisa       PaymentMethodCardNetwork = "visa"
)

// PaymentMethodCardWalletType is the list of allowed values for the type a wallet can take on
// a Card PaymentMethod.
type PaymentMethodCardWalletType string

// List of values that PaymentMethodCardWalletType can take.
const (
	PaymentMethodCardWalletTypeAmexExpressCheckout PaymentMethodCardWalletType = "amex_express_checkout"
	PaymentMethodCardWalletTypeApplePay            PaymentMethodCardWalletType = "apple_pay"
	PaymentMethodCardWalletTypeGooglePay           PaymentMethodCardWalletType = "google_pay"
	PaymentMethodCardWalletTypeMasterpass          PaymentMethodCardWalletType = "masterpass"
	PaymentMethodCardWalletTypeSamsungPay          PaymentMethodCardWalletType = "samsung_pay"
	PaymentMethodCardWalletTypeVisaCheckout        PaymentMethodCardWalletType = "visa_checkout"
)

// BillingDetailsParams is the set of parameters that can be used as billing details
// when creating or updating a PaymentMethod
type BillingDetailsParams struct {
	Address *AddressParams `form:"address"`
	Email   *string        `form:"email"`
	Name    *string        `form:"name"`
	Phone   *string        `form:"phone"`
}

// PaymentMethodAUBECSDebitParams is the set of parameters allowed for the `AUBECSDebit` hash when creating a
// PaymentMethod of type AUBECSDebit.
type PaymentMethodAUBECSDebitParams struct {
	AccountNumber *string `form:"account_number"`
	BSBNumber     *string `form:"bsb_number"`
}

// PaymentMethodBACSDebitParams is the set of parameters allowed for BACS Debit payment method.
type PaymentMethodBACSDebitParams struct {
	AccountNumber *string `form:"account_number"`
	SortCode      *string `form:"sort_code"`
}

// PaymentMethodBancontactParams is the set of parameters allowed for the `bancontact` hash when creating a
// PaymentMethod of type Bancontact.
type PaymentMethodBancontactParams struct {
}

// PaymentMethodCardParams is the set of parameters allowed for the `card` hash when creating a
// PaymentMethod of type card.
type PaymentMethodCardParams struct {
	CVC      *string `form:"cvc"`
	ExpMonth *string `form:"exp_month"`
	ExpYear  *string `form:"exp_year"`
	Number   *string `form:"number"`
	Token    *string `form:"token"`
}

// PaymentMethodEPSParams is the set of parameters allowed for the `eps` hash when creating a
// PaymentMethod of type EPS.
type PaymentMethodEPSParams struct {
}

// PaymentMethodFPXParams is the set of parameters allowed for the `fpx` hash when creating a
// PaymentMethod of type fpx.
type PaymentMethodFPXParams struct {
	AccountHolderType *string `form:"account_holder_type"`
	Bank              *string `form:"bank"`
}

// PaymentMethodGiropayParams is the set of parameters allowed for the `giropay` hash when creating a
// PaymentMethod of type Giropay.
type PaymentMethodGiropayParams struct {
}

// PaymentMethodIdealParams is the set of parameters allowed for the `ideal` hash when creating a
// PaymentMethod of type ideal.
type PaymentMethodIdealParams struct {
	Bank *string `form:"bank"`
}

// PaymentMethodInteracPresentParams is the set of parameters allowed for the `interac_present` hash when creating a
// PaymentMethod of type interac_present.
type PaymentMethodInteracPresentParams struct {
}

// PaymentMethodP24Params is the set of parameters allowed for the `p24` hash when creating a
// PaymentMethod of type P24.
type PaymentMethodP24Params struct {
}

// PaymentMethodSepaDebitParams is the set of parameters allowed for the `sepa_debit` hash when
// creating a PaymentMethod of type sepa_debit.
type PaymentMethodSepaDebitParams struct {
	Iban *string `form:"iban"`
}

// PaymentMethodParams is the set of parameters that can be used when creating or updating a
// PaymentMethod.
type PaymentMethodParams struct {
	Params         `form:"*"`
	AUBECSDebit    *PaymentMethodAUBECSDebitParams    `form:"au_becs_debit"`
	BACSDebit      *PaymentMethodBACSDebitParams      `form:"bacs_debit"`
	Bancontact     *PaymentMethodBancontactParams     `form:"bancontact"`
	BillingDetails *BillingDetailsParams              `form:"billing_details"`
	Card           *PaymentMethodCardParams           `form:"card"`
	EPS            *PaymentMethodEPSParams            `form:"eps"`
	FPX            *PaymentMethodFPXParams            `form:"fpx"`
	Giropay        *PaymentMethodGiropayParams        `form:"giropay"`
	Ideal          *PaymentMethodIdealParams          `form:"ideal"`
	InteracPresent *PaymentMethodInteracPresentParams `form:"interac_present"`
	P24            *PaymentMethodP24Params            `form:"p24"`
	SepaDebit      *PaymentMethodSepaDebitParams      `form:"sepa_debit"`
	Type           *string                            `form:"type"`

	// The following parameters are used when cloning a PaymentMethod to the connected account
	Customer      *string `form:"customer"`
	PaymentMethod *string `form:"payment_method"`
}

// PaymentMethodAttachParams is the set of parameters that can be used when attaching a
// PaymentMethod to a Customer.
type PaymentMethodAttachParams struct {
	Params   `form:"*"`
	Customer *string `form:"customer"`
}

// PaymentMethodDetachParams is the set of parameters that can be used when detaching a
// PaymentMethod.
type PaymentMethodDetachParams struct {
	Params `form:"*"`
}

// PaymentMethodListParams is the set of parameters that can be used when listing PaymentMethods.
type PaymentMethodListParams struct {
	ListParams `form:"*"`
	Customer   *string `form:"customer"`
	Type       *string `form:"type"`
}

// BillingDetails represents the billing details associated with a PaymentMethod.
type BillingDetails struct {
	Address *Address `json:"address"`
	Email   string   `json:"email"`
	Name    string   `json:"name"`
	Phone   string   `json:"phone"`
}

// PaymentMethodAUBECSDebit represents AUBECSDebit-specific properties (Australia Only).
type PaymentMethodAUBECSDebit struct {
	BSBNumber   string `json:"bsb_number"`
	Fingerprint string `json:"fingerprint"`
	Last4       string `json:"last4"`
}

// PaymentMethodBACSDebit represents the BACS Debit properties.
type PaymentMethodBACSDebit struct {
}

// PaymentMethodBancontact represents the Bancontact properties.
type PaymentMethodBancontact struct {
}

// PaymentMethodCardChecks represents the checks associated with a Card PaymentMethod.
type PaymentMethodCardChecks struct {
	AddressLine1Check      CardVerification `json:"address_line1_check"`
	AddressPostalCodeCheck CardVerification `json:"address_postal_code_check"`
	CVCCheck               CardVerification `json:"cvc_check"`
}

// PaymentMethodCardThreeDSecureUsage represents the 3DS usage for that Card PaymentMethod.
type PaymentMethodCardThreeDSecureUsage struct {
	Supported bool `json:"supported"`
}

// PaymentMethodCardWallet represents the details of the card wallet if this Card PaymentMethod
// is part of a card wallet.
type PaymentMethodCardWallet struct {
	DynamicLast4 string                      `json:"dynamic_last4"`
	Type         PaymentMethodCardWalletType `json:"type"`
}

// PaymentMethodCard represents the card-specific properties.
type PaymentMethodCard struct {
	Brand             PaymentMethodCardBrand              `json:"brand"`
	Checks            *PaymentMethodCardChecks            `json:"checks"`
	Country           string                              `json:"country"`
	ExpMonth          uint64                              `json:"exp_month"`
	ExpYear           uint64                              `json:"exp_year"`
	Fingerprint       string                              `json:"fingerprint"`
	Funding           CardFunding                         `json:"funding"`
	Last4             string                              `json:"last4"`
	ThreeDSecureUsage *PaymentMethodCardThreeDSecureUsage `json:"three_d_secure_usage"`
	Wallet            *PaymentMethodCardWallet            `json:"wallet"`

	// Please note that the fields below are for internal use only and are not returned
	// as part of standard API requests.
	Description string `json:"description"`
	IIN         string `json:"iin"`
	Issuer      string `json:"issuer"`
}

// PaymentMethodCardPresent represents the card-present-specific properties.
type PaymentMethodCardPresent struct {
}

// PaymentMethodEPS represents the EPS properties.
type PaymentMethodEPS struct {
}

// PaymentMethodFPX represents FPX-specific properties (Malaysia Only).
type PaymentMethodFPX struct {
	AccountHolderType PaymentMethodFPXAccountHolderType `json:"account_holder_type"`
	Bank              string                            `json:"bank"`
	TransactionID     string                            `json:"transaction_id"`
}

// PaymentMethodGiropay represents the Giropay properties.
type PaymentMethodGiropay struct {
}

// PaymentMethodIdeal represents the iDEAL-specific properties.
type PaymentMethodIdeal struct {
	Bank string `json:"bank"`
	Bic  string `json:"bic"`
}

// PaymentMethodInteracPresent represents the interac present properties.
type PaymentMethodInteracPresent struct {
}

// PaymentMethodP24 represents the P24 properties.
type PaymentMethodP24 struct {
}

// PaymentMethodSepaDebit represents the SEPA-debit-specific properties.
type PaymentMethodSepaDebit struct {
	BankCode    string `json:"bank_code"`
	BranchCode  string `json:"branch_code"`
	Country     string `json:"country"`
	Fingerprint string `json:"fingerprint"`
	Last4       string `json:"last4"`
}

// PaymentMethod is the resource representing a PaymentMethod.
type PaymentMethod struct {
	APIResource
	AUBECSDebit    *PaymentMethodAUBECSDebit    `json:"au_becs_debit"`
	BACSDebit      *PaymentMethodBACSDebit      `json:"bacs_debit"`
	Bancontact     *PaymentMethodBancontact     `json:"bancontact"`
	BillingDetails *BillingDetails              `json:"billing_details"`
	Card           *PaymentMethodCard           `json:"card"`
	CardPresent    *PaymentMethodCardPresent    `json:"card_present"`
	Created        int64                        `json:"created"`
	Customer       *Customer                    `json:"customer"`
	EPS            *PaymentMethodEPS            `json:"eps"`
	FPX            *PaymentMethodFPX            `json:"fpx"`
	Giropay        *PaymentMethodGiropay        `json:"giropay"`
	ID             string                       `json:"id"`
	Ideal          *PaymentMethodIdeal          `json:"ideal"`
	InteracPresent *PaymentMethodInteracPresent `json:"interac_present"`
	Livemode       bool                         `json:"livemode"`
	Metadata       map[string]string            `json:"metadata"`
	Object         string                       `json:"object"`
	P24            *PaymentMethodP24            `json:"p24"`
	SepaDebit      *PaymentMethodSepaDebit      `json:"sepa_debit"`
	Type           PaymentMethodType            `json:"type"`
}

// PaymentMethodList is a list of PaymentMethods as retrieved from a list endpoint.
type PaymentMethodList struct {
	APIResource
	ListMeta
	Data []*PaymentMethod `json:"data"`
}

// UnmarshalJSON handles deserialization of a PaymentMethod.
// This custom unmarshaling is needed because the resulting
// property may be an id or the full struct if it was expanded.
func (i *PaymentMethod) UnmarshalJSON(data []byte) error {
	if id, ok := ParseID(data); ok {
		i.ID = id
		return nil
	}

	type pm PaymentMethod
	var v pm
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}

	*i = PaymentMethod(v)
	return nil
}
<commit_msg>Add missing information for BACS Debit in `PaymentMethod`<commit_after>package stripe

import "encoding/json"

// PaymentMethodFPXAccountHolderType is a list of string values that FPX AccountHolderType accepts.
type PaymentMethodFPXAccountHolderType string

// List of values that PaymentMethodFPXAccountHolderType can take
const (
	PaymentMethodFPXAccountHolderTypeIndividual PaymentMethodFPXAccountHolderType = "individual"
	PaymentMethodFPXAccountHolderTypeCompany    PaymentMethodFPXAccountHolderType = "company"
)

// PaymentMethodType is the list of allowed values for the payment method type.
type PaymentMethodType string

// List of values that PaymentMethodType can take.
const (
	PaymentMethodTypeAUBECSDebit    PaymentMethodType = "au_becs_debit"
	PaymentMethodTypeBACSDebit      PaymentMethodType = "bacs_debit"
	PaymentMethodTypeCard           PaymentMethodType = "card"
	PaymentMethodTypeCardPresent    PaymentMethodType = "card_present"
	PaymentMethodTypeFPX            PaymentMethodType = "fpx"
	PaymentMethodTypeIdeal          PaymentMethodType = "ideal"
	PaymentMethodTypeInteracPresent PaymentMethodType = "interac_present"
	PaymentMethodTypeP24            PaymentMethodType = "p24"
	PaymentMethodTypeSepaDebit      PaymentMethodType = "sepa_debit"
)

// PaymentMethodCardBrand is the list of allowed values for the brand property on a
// Card PaymentMethod.
type PaymentMethodCardBrand string

// List of values that PaymentMethodCardBrand can take.
const (
	PaymentMethodCardBrandAmex       PaymentMethodCardBrand = "amex"
	PaymentMethodCardBrandDiners     PaymentMethodCardBrand = "diners"
	PaymentMethodCardBrandDiscover   PaymentMethodCardBrand = "discover"
	PaymentMethodCardBrandJCB        PaymentMethodCardBrand = "jcb"
	PaymentMethodCardBrandMastercard PaymentMethodCardBrand = "mastercard"
	PaymentMethodCardBrandUnionpay   PaymentMethodCardBrand = "unionpay"
	PaymentMethodCardBrandUnknown    PaymentMethodCardBrand = "unknown"
	PaymentMethodCardBrandVisa       PaymentMethodCardBrand = "visa"
)

// PaymentMethodCardNetwork is the list of allowed values to represent the network
// used for a card-like transaction.
type PaymentMethodCardNetwork string

// List of values that PaymentMethodCardNetwork can take.
const (
	PaymentMethodCardNetworkAmex       PaymentMethodCardNetwork = "amex"
	PaymentMethodCardNetworkDiners     PaymentMethodCardNetwork = "diners"
	PaymentMethodCardNetworkDiscover   PaymentMethodCardNetwork = "discover"
	PaymentMethodCardNetworkInterac    PaymentMethodCardNetwork = "interac"
	PaymentMethodCardNetworkJCB        PaymentMethodCardNetwork = "jcb"
	PaymentMethodCardNetworkMastercard PaymentMethodCardNetwork = "mastercard"
	PaymentMethodCardNetworkUnionpay   PaymentMethodCardNetwork = "unionpay"
	PaymentMethodCardNetworkUnknown    PaymentMethodCardNetwork = "unknown"
	PaymentMethodCardNetworkVisa       PaymentMethodCardNetwork = "visa"
)

// PaymentMethodCardWalletType is the list of allowed values for the type a wallet can take on
// a Card PaymentMethod.
type PaymentMethodCardWalletType string

// List of values that PaymentMethodCardWalletType can take.
const (
	PaymentMethodCardWalletTypeAmexExpressCheckout PaymentMethodCardWalletType = "amex_express_checkout"
	PaymentMethodCardWalletTypeApplePay            PaymentMethodCardWalletType = "apple_pay"
	PaymentMethodCardWalletTypeGooglePay           PaymentMethodCardWalletType = "google_pay"
	PaymentMethodCardWalletTypeMasterpass          PaymentMethodCardWalletType = "masterpass"
	PaymentMethodCardWalletTypeSamsungPay          PaymentMethodCardWalletType = "samsung_pay"
	PaymentMethodCardWalletTypeVisaCheckout        PaymentMethodCardWalletType = "visa_checkout"
)

// BillingDetailsParams is the set of parameters that can be used as billing details
// when creating or updating a PaymentMethod
type BillingDetailsParams struct {
	Address *AddressParams `form:"address"`
	Email   *string        `form:"email"`
	Name    *string        `form:"name"`
	Phone   *string        `form:"phone"`
}

// PaymentMethodAUBECSDebitParams is the set of parameters allowed for the `AUBECSDebit` hash when creating a
// PaymentMethod of type AUBECSDebit.
type PaymentMethodAUBECSDebitParams struct {
	AccountNumber *string `form:"account_number"`
	BSBNumber     *string `form:"bsb_number"`
}

// PaymentMethodBACSDebitParams is the set of parameters allowed for BACS Debit payment method.
type PaymentMethodBACSDebitParams struct {
	AccountNumber *string `form:"account_number"`
	SortCode      *string `form:"sort_code"`
}

// PaymentMethodBancontactParams is the set of parameters allowed for the `bancontact` hash when creating a
// PaymentMethod of type Bancontact.
type PaymentMethodBancontactParams struct {
}

// PaymentMethodCardParams is the set of parameters allowed for the `card` hash when creating a
// PaymentMethod of type card.
type PaymentMethodCardParams struct {
	CVC      *string `form:"cvc"`
	ExpMonth *string `form:"exp_month"`
	ExpYear  *string `form:"exp_year"`
	Number   *string `form:"number"`
	Token    *string `form:"token"`
}

// PaymentMethodEPSParams is the set of parameters allowed for the `eps` hash when creating a
// PaymentMethod of type EPS.
type PaymentMethodEPSParams struct {
}

// PaymentMethodFPXParams is the set of parameters allowed for the `fpx` hash when creating a
// PaymentMethod of type fpx.
type PaymentMethodFPXParams struct {
	AccountHolderType *string `form:"account_holder_type"`
	Bank              *string `form:"bank"`
}

// PaymentMethodGiropayParams is the set of parameters allowed for the `giropay` hash when creating a
// PaymentMethod of type Giropay.
type PaymentMethodGiropayParams struct {
}

// PaymentMethodIdealParams is the set of parameters allowed for the `ideal` hash when creating a
// PaymentMethod of type ideal.
type PaymentMethodIdealParams struct {
	Bank *string `form:"bank"`
}

// PaymentMethodInteracPresentParams is the set of parameters allowed for the `interac_present` hash when creating a
// PaymentMethod of type interac_present.
type PaymentMethodInteracPresentParams struct {
}

// PaymentMethodP24Params is the set of parameters allowed for the `p24` hash when creating a
// PaymentMethod of type P24.
type PaymentMethodP24Params struct {
}

// PaymentMethodSepaDebitParams is the set of parameters allowed for the `sepa_debit` hash when
// creating a PaymentMethod of type sepa_debit.
type PaymentMethodSepaDebitParams struct {
	Iban *string `form:"iban"`
}

// PaymentMethodParams is the set of parameters that can be used when creating or updating a
// PaymentMethod.
type PaymentMethodParams struct {
	Params         `form:"*"`
	AUBECSDebit    *PaymentMethodAUBECSDebitParams    `form:"au_becs_debit"`
	BACSDebit      *PaymentMethodBACSDebitParams      `form:"bacs_debit"`
	Bancontact     *PaymentMethodBancontactParams     `form:"bancontact"`
	BillingDetails *BillingDetailsParams              `form:"billing_details"`
	Card           *PaymentMethodCardParams           `form:"card"`
	EPS            *PaymentMethodEPSParams            `form:"eps"`
	FPX            *PaymentMethodFPXParams            `form:"fpx"`
	Giropay        *PaymentMethodGiropayParams        `form:"giropay"`
	Ideal          *PaymentMethodIdealParams          `form:"ideal"`
	InteracPresent *PaymentMethodInteracPresentParams `form:"interac_present"`
	P24            *PaymentMethodP24Params            `form:"p24"`
	SepaDebit      *PaymentMethodSepaDebitParams      `form:"sepa_debit"`
	Type           *string                            `form:"type"`

	// The following parameters are used when cloning a PaymentMethod to the connected account
	Customer      *string `form:"customer"`
	PaymentMethod *string `form:"payment_method"`
}

// PaymentMethodAttachParams is the set of parameters that can be used when attaching a
// PaymentMethod to a Customer.
type PaymentMethodAttachParams struct {
	Params   `form:"*"`
	Customer *string `form:"customer"`
}

// PaymentMethodDetachParams is the set of parameters that can be used when detaching a
// PaymentMethod.
type PaymentMethodDetachParams struct {
	Params `form:"*"`
}

// PaymentMethodListParams is the set of parameters that can be used when listing PaymentMethods.
type PaymentMethodListParams struct {
	ListParams `form:"*"`
	Customer   *string `form:"customer"`
	Type       *string `form:"type"`
}

// BillingDetails represents the billing details associated with a PaymentMethod.
type BillingDetails struct {
	Address *Address `json:"address"`
	Email   string   `json:"email"`
	Name    string   `json:"name"`
	Phone   string   `json:"phone"`
}

// PaymentMethodAUBECSDebit represents AUBECSDebit-specific properties (Australia Only).
type PaymentMethodAUBECSDebit struct {
	BSBNumber   string `json:"bsb_number"`
	Fingerprint string `json:"fingerprint"`
	Last4       string `json:"last4"`
}

// PaymentMethodBACSDebit represents the BACS Debit properties.
type PaymentMethodBACSDebit struct {
	Fingerprint string `json:"fingerprint"`
	Last4       string `json:"last4"`
	SortCode    string `json:"sort_code"`
}

// PaymentMethodBancontact represents the Bancontact properties.
type PaymentMethodBancontact struct {
}

// PaymentMethodCardChecks represents the checks associated with a Card PaymentMethod.
type PaymentMethodCardChecks struct {
	AddressLine1Check      CardVerification `json:"address_line1_check"`
	AddressPostalCodeCheck CardVerification `json:"address_postal_code_check"`
	CVCCheck               CardVerification `json:"cvc_check"`
}

// PaymentMethodCardThreeDSecureUsage represents the 3DS usage for that Card PaymentMethod.
type PaymentMethodCardThreeDSecureUsage struct {
	Supported bool `json:"supported"`
}

// PaymentMethodCardWallet represents the details of the card wallet if this Card PaymentMethod
// is part of a card wallet.
type PaymentMethodCardWallet struct {
	DynamicLast4 string                      `json:"dynamic_last4"`
	Type         PaymentMethodCardWalletType `json:"type"`
}

// PaymentMethodCard represents the card-specific properties.
type PaymentMethodCard struct {
	Brand             PaymentMethodCardBrand              `json:"brand"`
	Checks            *PaymentMethodCardChecks            `json:"checks"`
	Country           string                              `json:"country"`
	ExpMonth          uint64                              `json:"exp_month"`
	ExpYear           uint64                              `json:"exp_year"`
	Fingerprint       string                              `json:"fingerprint"`
	Funding           CardFunding                         `json:"funding"`
	Last4             string                              `json:"last4"`
	ThreeDSecureUsage *PaymentMethodCardThreeDSecureUsage `json:"three_d_secure_usage"`
	Wallet            *PaymentMethodCardWallet            `json:"wallet"`

	// Please note that the fields below are for internal use only and are not returned
	// as part of standard API requests.
	Description string `json:"description"`
	IIN         string `json:"iin"`
	Issuer      string `json:"issuer"`
}

// PaymentMethodCardPresent represents the card-present-specific properties.
type PaymentMethodCardPresent struct {
}

// PaymentMethodEPS represents the EPS properties.
type PaymentMethodEPS struct {
}

// PaymentMethodFPX represents FPX-specific properties (Malaysia Only).
type PaymentMethodFPX struct {
	AccountHolderType PaymentMethodFPXAccountHolderType `json:"account_holder_type"`
	Bank              string                            `json:"bank"`
	TransactionID     string                            `json:"transaction_id"`
}

// PaymentMethodGiropay represents the Giropay properties.
type PaymentMethodGiropay struct {
}

// PaymentMethodIdeal represents the iDEAL-specific properties.
type PaymentMethodIdeal struct {
	Bank string `json:"bank"`
	Bic  string `json:"bic"`
}

// PaymentMethodInteracPresent represents the interac present properties.
type PaymentMethodInteracPresent struct {
}

// PaymentMethodP24 represents the P24 properties.
type PaymentMethodP24 struct {
}

// PaymentMethodSepaDebit represents the SEPA-debit-specific properties.
type PaymentMethodSepaDebit struct {
	BankCode    string `json:"bank_code"`
	BranchCode  string `json:"branch_code"`
	Country     string `json:"country"`
	Fingerprint string `json:"fingerprint"`
	Last4       string `json:"last4"`
}

// PaymentMethod is the resource representing a PaymentMethod.
type PaymentMethod struct {
	APIResource
	AUBECSDebit    *PaymentMethodAUBECSDebit    `json:"au_becs_debit"`
	BACSDebit      *PaymentMethodBACSDebit      `json:"bacs_debit"`
	Bancontact     *PaymentMethodBancontact     `json:"bancontact"`
	BillingDetails *BillingDetails              `json:"billing_details"`
	Card           *PaymentMethodCard           `json:"card"`
	CardPresent    *PaymentMethodCardPresent    `json:"card_present"`
	Created        int64                        `json:"created"`
	Customer       *Customer                    `json:"customer"`
	EPS            *PaymentMethodEPS            `json:"eps"`
	FPX            *PaymentMethodFPX            `json:"fpx"`
	Giropay        *PaymentMethodGiropay        `json:"giropay"`
	ID             string                       `json:"id"`
	Ideal          *PaymentMethodIdeal          `json:"ideal"`
	InteracPresent *PaymentMethodInteracPresent `json:"interac_present"`
	Livemode       bool                         `json:"livemode"`
	Metadata       map[string]string            `json:"metadata"`
	Object         string                       `json:"object"`
	P24            *PaymentMethodP24            `json:"p24"`
	SepaDebit      *PaymentMethodSepaDebit      `json:"sepa_debit"`
	Type           PaymentMethodType            `json:"type"`
}

// PaymentMethodList is a list of PaymentMethods as retrieved from a list endpoint.
type PaymentMethodList struct {
	APIResource
	ListMeta
	Data []*PaymentMethod `json:"data"`
}

// UnmarshalJSON handles deserialization of a PaymentMethod.
// This custom unmarshaling is needed because the resulting
// property may be an id or the full struct if it was expanded.
func (i *PaymentMethod) UnmarshalJSON(data []byte) error {
	if id, ok := ParseID(data); ok {
		i.ID = id
		return nil
	}

	type pm PaymentMethod
	var v pm
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}

	*i = PaymentMethod(v)
	return nil
}
<|endoftext|>


<commit_before>package com

import (
	"crypto/sha1"
	"fmt"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestMakePassword(t *testing.T) {
	panic(RestoreTime(`2001-01-01T00:00:03Z`).Format(`2006-01-02 15:04:05`))
	hashed := MakePassword(`github.com/webx-top/com`, ``)
	fmt.Println(`hashed`, hashed, len(hashed))
	if CheckPassword(`github.com/webx-top/com`, hashed, ``) == false {
		t.Errorf(`The passwords do not match`)
	}
	salt := Salt()
	fmt.Println(`salt:`, salt)
	hashed = MakePassword(`github.com/webx-top/com`, salt, 2, 4, 6, 8, 13, 19, 32)
	fmt.Println(`hashed`, hashed, len(hashed))
	if CheckPassword(`github.com/webx-top/com`, hashed, salt, 2, 4, 6, 8, 13, 19, 32) == false {
		t.Errorf(`The passwords do not match`)
	}
	salt = Salt()
	hashed = MakePassword(`github.com/webx-top/com`, salt, 13)
	fmt.Println(`hashed`, hashed, len(hashed))
	if CheckPassword(`github.com/webx-top/com`, hashed, salt, 13) == false {
		t.Errorf(`The passwords do not match`)
	}
	salt = `github.com/webx-top/com`
	dk := PBKDF2Key([]byte("some password"), []byte(salt), 4096, 32, sha1.New)
	fmt.Println(`PBKDF2:`, string(dk))
}

func TestAbsURL(t *testing.T) {
	pageURL := AbsURL(`https://www.coscms.com/system/download/index`, `../download2/index`)
	assert.Equal(t, `https://www.coscms.com/system/download2/index`, pageURL)

	pageURL = AbsURL(`https://www.coscms.com/system/download/index`, `../../system2/download2/index`)
	assert.Equal(t, `https://www.coscms.com/system2/download2/index`, pageURL)

	pageURL = AbsURL(`https://www.coscms.com/system/download/index`, `/payment/index/index`)
	assert.Equal(t, `https://www.coscms.com/payment/index/index`, pageURL)

	pageURL = AbsURL(`https://www.coscms.com/system/download/index`, `./payment/index/index`)
	assert.Equal(t, `https://www.coscms.com/system/download/payment/index/index`, pageURL)

	fmt.Println(`SelfDir:`, SelfDir())
	fmt.Println(`SelfPath:`, SelfPath())
}
<commit_msg>update<commit_after>package com

import (
	"crypto/sha1"
	"fmt"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestMakePassword(t *testing.T) {
	hashed := MakePassword(`github.com/webx-top/com`, ``)
	fmt.Println(`hashed`, hashed, len(hashed))
	if CheckPassword(`github.com/webx-top/com`, hashed, ``) == false {
		t.Errorf(`The passwords do not match`)
	}
	salt := Salt()
	fmt.Println(`salt:`, salt)
	hashed = MakePassword(`github.com/webx-top/com`, salt, 2, 4, 6, 8, 13, 19, 32)
	fmt.Println(`hashed`, hashed, len(hashed))
	if CheckPassword(`github.com/webx-top/com`, hashed, salt, 2, 4, 6, 8, 13, 19, 32) == false {
		t.Errorf(`The passwords do not match`)
	}
	salt = Salt()
	hashed = MakePassword(`github.com/webx-top/com`, salt, 13)
	fmt.Println(`hashed`, hashed, len(hashed))
	if CheckPassword(`github.com/webx-top/com`, hashed, salt, 13) == false {
		t.Errorf(`The passwords do not match`)
	}
	salt = `github.com/webx-top/com`
	dk := PBKDF2Key([]byte("some password"), []byte(salt), 4096, 32, sha1.New)
	fmt.Println(`PBKDF2:`, string(dk))
}

func TestAbsURL(t *testing.T) {
	pageURL := AbsURL(`https://www.coscms.com/system/download/index`, `../download2/index`)
	assert.Equal(t, `https://www.coscms.com/system/download2/index`, pageURL)

	pageURL = AbsURL(`https://www.coscms.com/system/download/index`, `../../system2/download2/index`)
	assert.Equal(t, `https://www.coscms.com/system2/download2/index`, pageURL)

	pageURL = AbsURL(`https://www.coscms.com/system/download/index`, `/payment/index/index`)
	assert.Equal(t, `https://www.coscms.com/payment/index/index`, pageURL)

	pageURL = AbsURL(`https://www.coscms.com/system/download/index`, `./payment/index/index`)
	assert.Equal(t, `https://www.coscms.com/system/download/payment/index/index`, pageURL)

	fmt.Println(`SelfDir:`, SelfDir())
	fmt.Println(`SelfPath:`, SelfPath())
}
<|endoftext|>


<commit_before>package prompt

import (
	"os"
	"bufio"
	"strings"

	"golang.org/x/crypto/ssh/terminal"
	"github.com/jhunt/ansi"
)

func Normal(label string, args ...interface{}) string {
	ansi.Printf(label, args...)
	s, _ := bufio.NewReader(os.Stdin).ReadString('\n')
	return strings.TrimSuffix(s, "\n")
}

func Secure(label string, args ...interface{}) string {
	ansi.Printf(label, args...)
	b, _ := terminal.ReadPassword(int(os.Stdin.Fd()))
	ansi.Printf("\n")
	return string(b)
}
<commit_msg>prompt.Secure should accept input from stdin<commit_after>package prompt

import (
	"bufio"
	"os"
	"strings"

	"github.com/jhunt/ansi"
	"github.com/mattn/go-isatty"
	"golang.org/x/crypto/ssh/terminal"
)

func Normal(label string, args ...interface{}) string {
	ansi.Printf(label, args...)
	s, _ := bufio.NewReader(os.Stdin).ReadString('\n')
	return strings.TrimSuffix(s, "\n")
}

func Secure(label string, args ...interface{}) string {
	if !isatty.IsTerminal(os.Stdin.Fd()) {
		s, _ := bufio.NewReader(os.Stdin).ReadString('\n')
		return strings.TrimSuffix(s, "\n")
	}

	ansi.Printf(label, args...)
	b, _ := terminal.ReadPassword(int(os.Stdin.Fd()))
	ansi.Printf("\n")
	return string(b)
}
<|endoftext|>