<commit_before>package act

import (
	"encoding/gob"
	"fmt"
	"net"
	"time"
)

const (
	ERR = int32(iota)
	NONE
	QUIT
	PAUSE
	CLEAR
	HIDE
	SAVE
	REDRAW

	// Effects
	FADE_OUT
	PULSE
)

var NamedCommands = map[string]int32{
	"clear": CLEAR,
	"quit":  QUIT,
	"pause": PAUSE,
	"hide":  HIDE,
	"save":  SAVE,
}

var NamedEffects = map[string]int32{
	"none":     NONE,
	"fade_out": FADE_OUT,
	"pulse":    PULSE,
}

var EventNames = map[int32]string{}

func init() {
	for name, code := range NamedCommands {
		EventNames[code] = name
	}
	for name, code := range NamedEffects {
		EventNames[code] = name
	}
}

type Event struct {
	Code      int32
	ImageURI  string
	Position  string
	X, Y      int32
	Delay     time.Duration
	FontColor string
	Font      string
	FontSize  int
	BgColor   string
	Text      string
	Multiply  int
	Points    []int // Points are for geometric shapes, x1,y1,...,xN,yN
	DimSpeed  int   // 1..255
}

func NewEvent() *Event {
	return &Event{
		Code:      NONE,
		ImageURI:  "",
		Position:  "",
		X:         0,
		Y:         0,
		Delay:     time.Duration(0),
		FontColor: "white",
		FontSize:  34,
		BgColor:   "000000",
		Text:      "",
		DimSpeed:  3,
	}
}

func (s *Event) String() string {
	return fmt.Sprintf("%s %s", EventNames[s.Code], s.ImageURI)
}

// SendEvent gob encodes the arguments to the bind address
func SendEvent(a *Event, bind string) error {
	conn, err := net.Dial("tcp", bind)
	if err != nil {
		return err
	}
	defer conn.Close()
	err = gob.NewEncoder(conn).Encode(a)
	if err != nil {
		return err
	}
	return nil
}
<commit_msg>Add Tag and REMOVE command<commit_after>package act

import (
	"encoding/gob"
	"fmt"
	"net"
	"time"
)

const (
	ERR = int32(iota)
	NONE
	QUIT
	PAUSE
	CLEAR
	HIDE
	SAVE
	REDRAW
	REMOVE

	// Effects
	FADE_OUT
	PULSE
)

var NamedCommands = map[string]int32{
	"clear": CLEAR,
	"quit":  QUIT,
	"pause": PAUSE,
	"hide":  HIDE,
	"save":  SAVE,
	"rm":    REMOVE,
}

var NamedEffects = map[string]int32{
	"none":     NONE,
	"fade_out": FADE_OUT,
	"pulse":    PULSE,
}

var EventNames = map[int32]string{}

func init() {
	for name, code := range NamedCommands {
		EventNames[code] = name
	}
	for name, code := range NamedEffects {
		EventNames[code] = name
	}
}

type Event struct {
	Code      int32
	ImageURI  string
	Position  string
	X, Y      int32
	Delay     time.Duration
	FontColor string
	Font      string
	FontSize  int
	BgColor   string
	Text      string
	Multiply  int
	Points    []int  // Points are for geometric shapes, x1,y1,...,xN,yN
	DimSpeed  int    // 1..255
	Tag       string // Tagging events enables post manipulation
}

func NewEvent() *Event {
	return &Event{
		Code:      NONE,
		ImageURI:  "",
		Position:  "",
		X:         0,
		Y:         0,
		Delay:     time.Duration(0),
		FontColor: "white",
		FontSize:  34,
		BgColor:   "000000",
		Text:      "",
		DimSpeed:  3,
		Tag:       "",
	}
}

func (s *Event) String() string {
	return fmt.Sprintf("%s %s", EventNames[s.Code], s.ImageURI)
}

// SendEvent gob encodes the arguments to the bind address
func SendEvent(a *Event, bind string) error {
	conn, err := net.Dial("tcp", bind)
	if err != nil {
		return err
	}
	defer conn.Close()
	err = gob.NewEncoder(conn).Encode(a)
	if err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes 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 common

import (
	"github.com/onsi/ginkgo"
	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/kubernetes/test/e2e/framework"
	e2enetwork "k8s.io/kubernetes/test/e2e/framework/network"
)

var _ = ginkgo.Describe("[sig-network] Networking", func() {
	f := framework.NewDefaultFramework("pod-network-test")

	ginkgo.Describe("Granular Checks: Pods", func() {

		// Try to hit all endpoints through a test container, retry 5 times,
		// expect exactly one unique hostname. Each of these endpoints reports
		// its own hostname.
		/*
			Release: v1.9, v1.18
			Testname: Networking, intra pod http
			Description: Create a hostexec pod that is capable of curl to netcat commands. Create a test Pod that will act as a webserver front end exposing ports 8080 for tcp and 8081 for udp. The netserver service proxies are created on specified number of nodes.
			The kubectl exec on the webserver container MUST reach a http port on the each of service proxy endpoints in the cluster and the request MUST be successful. Container will execute curl command to reach the service port within specified max retry limit and MUST result in reporting unique hostnames.
		*/
		framework.ConformanceIt("should function for intra-pod communication: http [NodeConformance]", func() {
			config := e2enetwork.NewCoreNetworkingTestConfig(f, false)

			// Extra debugging info since this is the most common diagnostic for failing clusters, and is a Conformance test.
			errors := []error{}
			for _, endpointPod := range config.EndpointPods {
				if err := config.DialFromTestContainer("http", endpointPod.Status.PodIP, e2enetwork.EndpointHTTPPort, config.MaxTries, 0, sets.NewString(endpointPod.Name)); err != nil {
					errors = append(errors, err)
					framework.Logf("Was able to reach %v on %v ", endpointPod.Status.PodIP, endpointPod.Status.HostIP)
				} else {
					framework.Logf("Warning: Test failure (%v) will occur due to %v", len(errors)+1, err) // convenient error message for diagnosis... how many pods failed, and on what hosts?
				}
			}
			if len(errors) == 0 {
				framework.Logf("Pod polling failure summary:")
				for _, e := range errors {
					framework.Logf("%v", e)
				}
				framework.Failf("Failed due to %v errors polling %v pods", errors, len(config.EndpointPods))
			}
		})

		/*
			Release: v1.9, v1.18
			Testname: Networking, intra pod udp
			Description: Create a hostexec pod that is capable of curl to netcat commands. Create a test Pod that will act as a webserver front end exposing ports 8080 for tcp and 8081 for udp. The netserver service proxies are created on specified number of nodes.
			The kubectl exec on the webserver container MUST reach a udp port on the each of service proxy endpoints in the cluster and the request MUST be successful. Container will execute curl command to reach the service port within specified max retry limit and MUST result in reporting unique hostnames.
		*/
		framework.ConformanceIt("should function for intra-pod communication: udp [NodeConformance]", func() {
			config := e2enetwork.NewCoreNetworkingTestConfig(f, false)
			for _, endpointPod := range config.EndpointPods {
				config.DialFromTestContainer("udp", endpointPod.Status.PodIP, e2enetwork.EndpointUDPPort, config.MaxTries, 0, sets.NewString(endpointPod.Name))
			}
		})

		/*
			Release: v1.9
			Testname: Networking, intra pod http, from node
			Description: Create a hostexec pod that is capable of curl to netcat commands. Create a test Pod that will act as a webserver front end exposing ports 8080 for tcp and 8081 for udp. The netserver service proxies are created on specified number of nodes.
			The kubectl exec on the webserver container MUST reach a http port on the each of service proxy endpoints in the cluster using a http post(protocol=tcp)  and the request MUST be successful. Container will execute curl command to reach the service port within specified max retry limit and MUST result in reporting unique hostnames.
			This test is marked LinuxOnly since HostNetwork is not supported on other platforms like Windows.
		*/
		framework.ConformanceIt("should function for node-pod communication: http [LinuxOnly] [NodeConformance]", func() {
			config := e2enetwork.NewCoreNetworkingTestConfig(f, true)
			for _, endpointPod := range config.EndpointPods {
				config.DialFromNode("http", endpointPod.Status.PodIP, e2enetwork.EndpointHTTPPort, config.MaxTries, 0, sets.NewString(endpointPod.Name))
			}
		})

		/*
			Release: v1.9
			Testname: Networking, intra pod http, from node
			Description: Create a hostexec pod that is capable of curl to netcat commands. Create a test Pod that will act as a webserver front end exposing ports 8080 for tcp and 8081 for udp. The netserver service proxies are created on specified number of nodes.
			The kubectl exec on the webserver container MUST reach a http port on the each of service proxy endpoints in the cluster using a http post(protocol=udp)  and the request MUST be successful. Container will execute curl command to reach the service port within specified max retry limit and MUST result in reporting unique hostnames.
			This test is marked LinuxOnly since HostNetwork is not supported on other platforms like Windows.
		*/
		framework.ConformanceIt("should function for node-pod communication: udp [LinuxOnly] [NodeConformance]", func() {
			config := e2enetwork.NewCoreNetworkingTestConfig(f, true)
			for _, endpointPod := range config.EndpointPods {
				config.DialFromNode("udp", endpointPod.Status.PodIP, e2enetwork.EndpointUDPPort, config.MaxTries, 0, sets.NewString(endpointPod.Name))
			}
		})
	})
})
<commit_msg>minor logic fix<commit_after>/*
Copyright 2016 The Kubernetes 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 common

import (
	"github.com/onsi/ginkgo"
	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/kubernetes/test/e2e/framework"
	e2enetwork "k8s.io/kubernetes/test/e2e/framework/network"
)

var _ = ginkgo.Describe("[sig-network] Networking", func() {
	f := framework.NewDefaultFramework("pod-network-test")

	ginkgo.Describe("Granular Checks: Pods", func() {

		// Try to hit all endpoints through a test container, retry 5 times,
		// expect exactly one unique hostname. Each of these endpoints reports
		// its own hostname.
		/*
			Release: v1.9, v1.18
			Testname: Networking, intra pod http
			Description: Create a hostexec pod that is capable of curl to netcat commands. Create a test Pod that will act as a webserver front end exposing ports 8080 for tcp and 8081 for udp. The netserver service proxies are created on specified number of nodes.
			The kubectl exec on the webserver container MUST reach a http port on the each of service proxy endpoints in the cluster and the request MUST be successful. Container will execute curl command to reach the service port within specified max retry limit and MUST result in reporting unique hostnames.
		*/
		framework.ConformanceIt("should function for intra-pod communication: http [NodeConformance]", func() {
			config := e2enetwork.NewCoreNetworkingTestConfig(f, false)

			// Extra debugging info since this is the most common diagnostic for failing clusters, and is a Conformance test.
			errors := []error{}
			for _, endpointPod := range config.EndpointPods {
				if err := config.DialFromTestContainer("http", endpointPod.Status.PodIP, e2enetwork.EndpointHTTPPort, config.MaxTries, 0, sets.NewString(endpointPod.Name)); err != nil {
					errors = append(errors, err)
					framework.Logf("Was able to reach %v on %v ", endpointPod.Status.PodIP, endpointPod.Status.HostIP)
				} else {
					framework.Logf("Warning: Test failure (%v) will occur due to %v", len(errors)+1, err) // convenient error message for diagnosis... how many pods failed, and on what hosts?
				}
			}
			if len(errors) > 0 {
				framework.Logf("Pod polling failure summary:")
				for _, e := range errors {
					framework.Logf("%v", e)
				}
				framework.Failf("Failed due to %v errors polling %v pods", len(errors), len(config.EndpointPods))
			}
		})

		/*
			Release: v1.9, v1.18
			Testname: Networking, intra pod udp
			Description: Create a hostexec pod that is capable of curl to netcat commands. Create a test Pod that will act as a webserver front end exposing ports 8080 for tcp and 8081 for udp. The netserver service proxies are created on specified number of nodes.
			The kubectl exec on the webserver container MUST reach a udp port on the each of service proxy endpoints in the cluster and the request MUST be successful. Container will execute curl command to reach the service port within specified max retry limit and MUST result in reporting unique hostnames.
		*/
		framework.ConformanceIt("should function for intra-pod communication: udp [NodeConformance]", func() {
			config := e2enetwork.NewCoreNetworkingTestConfig(f, false)
			for _, endpointPod := range config.EndpointPods {
				config.DialFromTestContainer("udp", endpointPod.Status.PodIP, e2enetwork.EndpointUDPPort, config.MaxTries, 0, sets.NewString(endpointPod.Name))
			}
		})

		/*
			Release: v1.9
			Testname: Networking, intra pod http, from node
			Description: Create a hostexec pod that is capable of curl to netcat commands. Create a test Pod that will act as a webserver front end exposing ports 8080 for tcp and 8081 for udp. The netserver service proxies are created on specified number of nodes.
			The kubectl exec on the webserver container MUST reach a http port on the each of service proxy endpoints in the cluster using a http post(protocol=tcp)  and the request MUST be successful. Container will execute curl command to reach the service port within specified max retry limit and MUST result in reporting unique hostnames.
			This test is marked LinuxOnly since HostNetwork is not supported on other platforms like Windows.
		*/
		framework.ConformanceIt("should function for node-pod communication: http [LinuxOnly] [NodeConformance]", func() {
			config := e2enetwork.NewCoreNetworkingTestConfig(f, true)
			for _, endpointPod := range config.EndpointPods {
				config.DialFromNode("http", endpointPod.Status.PodIP, e2enetwork.EndpointHTTPPort, config.MaxTries, 0, sets.NewString(endpointPod.Name))
			}
		})

		/*
			Release: v1.9
			Testname: Networking, intra pod http, from node
			Description: Create a hostexec pod that is capable of curl to netcat commands. Create a test Pod that will act as a webserver front end exposing ports 8080 for tcp and 8081 for udp. The netserver service proxies are created on specified number of nodes.
			The kubectl exec on the webserver container MUST reach a http port on the each of service proxy endpoints in the cluster using a http post(protocol=udp)  and the request MUST be successful. Container will execute curl command to reach the service port within specified max retry limit and MUST result in reporting unique hostnames.
			This test is marked LinuxOnly since HostNetwork is not supported on other platforms like Windows.
		*/
		framework.ConformanceIt("should function for node-pod communication: udp [LinuxOnly] [NodeConformance]", func() {
			config := e2enetwork.NewCoreNetworkingTestConfig(f, true)
			for _, endpointPod := range config.EndpointPods {
				config.DialFromNode("udp", endpointPod.Status.PodIP, e2enetwork.EndpointUDPPort, config.MaxTries, 0, sets.NewString(endpointPod.Name))
			}
		})
	})
})
<|endoftext|>


<commit_before>package main

import (
	"github.com/streadway/amqp"
	"io"
    "io/ioutil"
    "strings"
	"net/http"
)

func queueRequest(request *http.Request, channel *amqp.Channel) {

}

func sendErrorResponse(err error, w *http.ResponseWriter) {

}

func main() {

    connection, err := amqp.Dial("amqp://localhost:5672")

    if err != nil {
        panic("Could not connect to amqp server")
    }

    channel, err := connection.Channel()

	http.HandleFunc("/", func(w http.ResponseWriter, request *http.Request) {
        uri_split := strings.Split("/", request.RequestURI)

        if len(uri_split) < 1 {
            //TODO error on this condition
        }

        exchange := uri_split[0]
        routing_key := ""
        content_type := request.Header.Get("ContentType")

        if len(uri_split) > 1 {
            routing_key = uri_split[1]
        }

        if content_type == "" {
            content_type = "text/json"
        }

        body, err := ioutil.ReadAll(request.Body)

        if err != nil {
            sendErrorResponse(err, &w)
        }

        err = channel.Publish(
			exchange,
		    routing_key,
			false,
			false,
			amqp.Publishing{
				Headers:         amqp.Table{},
				ContentType:     content_type,
				ContentEncoding: "",
				Body:            body,
				DeliveryMode:    amqp.Persistent,
				Priority:        0,
			},
        )

        if err != nil {
            sendErrorResponse(err, &w)
        }

		io.WriteString(w, "Wrote hello world to queue\n")
	})

    http.ListenAndServe(":12345", nil)
}
<commit_msg>running fmt on amqp_rest.go<commit_after>package main

import (
	"github.com/streadway/amqp"
	"io"
	"io/ioutil"
	"net/http"
	"strings"
)

func queueRequest(request *http.Request, channel *amqp.Channel) {

}

func sendErrorResponse(err error, w *http.ResponseWriter) {

}

func main() {

	connection, err := amqp.Dial("amqp://localhost:5672")

	if err != nil {
		panic("Could not connect to amqp server")
	}

	channel, err := connection.Channel()

	http.HandleFunc("/", func(w http.ResponseWriter, request *http.Request) {
		uri_split := strings.Split("/", request.RequestURI)

		if len(uri_split) < 1 {
			//TODO error on this condition
		}

		exchange := uri_split[0]
		routing_key := ""
		content_type := request.Header.Get("ContentType")

		if len(uri_split) > 1 {
			routing_key = uri_split[1]
		}

		if content_type == "" {
			content_type = "text/json"
		}

		body, err := ioutil.ReadAll(request.Body)

		if err != nil {
			sendErrorResponse(err, &w)
		}

		err = channel.Publish(
			exchange,
			routing_key,
			false,
			false,
			amqp.Publishing{
				Headers:         amqp.Table{},
				ContentType:     content_type,
				ContentEncoding: "",
				Body:            body,
				DeliveryMode:    amqp.Persistent,
				Priority:        0,
			},
		)

		if err != nil {
			sendErrorResponse(err, &w)
		}

		io.WriteString(w, "Wrote hello world to queue\n")
	})

	http.ListenAndServe(":12345", nil)
}
<|endoftext|>


<commit_before>package analytics

import . "github.com/visionmedia/go-debug"
import "github.com/jehiah/go-strftime"
import "github.com/xtgo/uuid"
import . "encoding/json"
import "io/ioutil"
import "net/http"
import "errors"
import "bytes"
import "sync"
import "time"

// Library version.
const Version = "0.0.2"

// Default API end-point.
const api = "https://api.segment.io"

// Message type.
type Message map[string]interface{}

// Debug.
var debug = Debug("analytics")

// Segment.io client
type Client struct {
	FlushAt    int
	FlushAfter time.Duration
	Endpoint   string
	Key        string
	buffer     []Message
	sync.Mutex
}

// Batch message.
type batch struct {
	Messages  []Message `json:"batch"`
	MessageId string    `json:"messageId"`
}

// New creates a new Segment.io client
// with the given write key.
func New(key string) *Client {
	c := &Client{
		FlushAt:    20,
		FlushAfter: 5 * time.Second,
		Key:        key,
		Endpoint:   api,
		buffer:     make([]Message, 0),
	}

	go c.Start()

	return c
}

// Start flusher.
func (c *Client) Start() {
	go func() {
		for {
			time.Sleep(c.FlushAfter)
			debug("interval %v reached", c.FlushAfter)
			c.flush()
		}
	}()
}

// Alias buffers an "alias" message.
func (c *Client) Alias(msg Message) error {
	if msg["userId"] == nil {
		return errors.New("You must pass a 'userId'.")
	}

	if msg["previousId"] == nil {
		return errors.New("You must pass a 'previousId'.")
	}

	c.queue(message(msg, "alias"))

	return nil
}

// Page buffers an "page" message.
func (c *Client) Page(msg Message) error {
	if msg["userId"] == nil && msg["anonymousId"] == nil {
		return errors.New("You must pass either an 'anonymousId' or 'userId'.")
	}

	c.queue(message(msg, "page"))

	return nil
}

// Screen buffers an "screen" message.
func (c *Client) Screen(msg Message) error {
	if msg["userId"] == nil && msg["anonymousId"] == nil {
		return errors.New("You must pass either an 'anonymousId' or 'userId'.")
	}

	c.queue(message(msg, "screen"))

	return nil
}

// Group buffers an "group" message.
func (c *Client) Group(msg Message) error {
	if msg["groupId"] == nil {
		return errors.New("You must pass a 'groupId'.")
	}

	if msg["userId"] == nil && msg["anonymousId"] == nil {
		return errors.New("You must pass either an 'anonymousId' or 'userId'.")
	}

	c.queue(message(msg, "group"))

	return nil
}

// Identify buffers an "identify" message.
func (c *Client) Identify(msg Message) error {
	if msg["userId"] == nil && msg["anonymousId"] == nil {
		return errors.New("You must pass either an 'anonymousId' or 'userId'.")
	}

	c.queue(message(msg, "identify"))

	return nil
}

// Track buffers an "track" message.
func (c *Client) Track(msg Message) error {
	if msg["event"] == nil {
		return errors.New("You must pass 'event'.")
	}

	if msg["userId"] == nil && msg["anonymousId"] == nil {
		return errors.New("You must pass either an 'anonymousId' or 'userId'.")
	}

	c.queue(message(msg, "track"))

	return nil
}

// Return a new initialized message map
// with `msg` values and context merged.
func message(msg Message, call string) Message {
	m := newMessage(call)

	if msg["context"] != nil {
		merge(m["context"].(map[string]interface{}), msg["context"].(map[string]interface{}))
		delete(msg, "context")
	}

	merge(m, msg)

	return m
}

// Return new initialzed message map.
func newMessage(call string) Message {
	return Message{
		"type":      call,
		"timestamp": timestamp(),
		"messageId": uid(),
		"context": map[string]interface{}{
			"version": Version,
			"library": "analytics-go",
		},
	}
}

// Merge two maps.
func merge(dst Message, src Message) {
	for k, v := range src {
		dst[k] = v
	}
}

// Return uuid.
func uid() string {
	return uuid.NewRandom().String()
}

// Return formatted timestamp.
func timestamp() string {
	return strftime.Format("%Y-%m-%dT%H:%M:%S%z", time.Now())
}

// Buffer the given message and flush
// when the buffer exceeds .FlushAt.
func (c *Client) queue(msg Message) {
	c.Lock()
	defer c.Unlock()

	c.buffer = append(c.buffer, msg)

	debug("buffer (%d/%d) %v", len(c.buffer), c.FlushAt, msg)

	if len(c.buffer) >= c.FlushAt {
		go c.flush()
	}
}

// Return a batch message primed
// with context properties.
func batchMessage(msgs []Message) *batch {
	return &batch{
		MessageId: uid(),
		Messages:  msgs,
	}
}

// Flush the buffered messages.
//
// TODO: better error-handling,
// this is really meh, it would
// be better if we used a chan
// to deliver them.
//
func (c *Client) flush() error {
	c.Lock()

	if len(c.buffer) == 0 {
		debug("no messages to flush")
		c.Unlock()
		return nil
	}

	debug("flushing %d messages", len(c.buffer))
	json, err := Marshal(batchMessage(c.buffer))

	if err != nil {
		debug("error: %v", err)
		c.Unlock()
		return err
	}

	c.buffer = nil
	c.Unlock()

	client := &http.Client{}
	url := c.Endpoint + "/v1/import"
	debug("POST %s with %d bytes", url, len(json))
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(json))

	if err != nil {
		debug("error: %v", err)
		return err
	}

	req.Header.Add("User-Agent", "analytics-go (version: "+Version+")")
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Content-Length", string(len(json)))
	req.SetBasicAuth(c.Key, "")

	res, err := client.Do(req)
	defer res.Body.Close()

	if err != nil {
		debug("error: %v", err)
		return err
	}

	debug("%d response", res.StatusCode)

	if res.StatusCode >= 400 {
		body, _ := ioutil.ReadAll(res.Body)
		debug("error: %s", string(body))
		debug("error: %s", string(json))
	}

	return err
}
<commit_msg>fix response close<commit_after>package analytics

import . "github.com/visionmedia/go-debug"
import "github.com/jehiah/go-strftime"
import "github.com/xtgo/uuid"
import . "encoding/json"
import "io/ioutil"
import "net/http"
import "errors"
import "bytes"
import "sync"
import "time"

// Library version.
const Version = "0.0.2"

// Default API end-point.
const api = "https://api.segment.io"

// Message type.
type Message map[string]interface{}

// Debug.
var debug = Debug("analytics")

// Segment.io client
type Client struct {
	FlushAt    int
	FlushAfter time.Duration
	Endpoint   string
	Key        string
	buffer     []Message
	sync.Mutex
}

// Batch message.
type batch struct {
	Messages  []Message `json:"batch"`
	MessageId string    `json:"messageId"`
}

// New creates a new Segment.io client
// with the given write key.
func New(key string) *Client {
	c := &Client{
		FlushAt:    20,
		FlushAfter: 5 * time.Second,
		Key:        key,
		Endpoint:   api,
		buffer:     make([]Message, 0),
	}

	go c.Start()

	return c
}

// Start flusher.
func (c *Client) Start() {
	go func() {
		for {
			time.Sleep(c.FlushAfter)
			debug("interval %v reached", c.FlushAfter)
			c.flush()
		}
	}()
}

// Alias buffers an "alias" message.
func (c *Client) Alias(msg Message) error {
	if msg["userId"] == nil {
		return errors.New("You must pass a 'userId'.")
	}

	if msg["previousId"] == nil {
		return errors.New("You must pass a 'previousId'.")
	}

	c.queue(message(msg, "alias"))

	return nil
}

// Page buffers an "page" message.
func (c *Client) Page(msg Message) error {
	if msg["userId"] == nil && msg["anonymousId"] == nil {
		return errors.New("You must pass either an 'anonymousId' or 'userId'.")
	}

	c.queue(message(msg, "page"))

	return nil
}

// Screen buffers an "screen" message.
func (c *Client) Screen(msg Message) error {
	if msg["userId"] == nil && msg["anonymousId"] == nil {
		return errors.New("You must pass either an 'anonymousId' or 'userId'.")
	}

	c.queue(message(msg, "screen"))

	return nil
}

// Group buffers an "group" message.
func (c *Client) Group(msg Message) error {
	if msg["groupId"] == nil {
		return errors.New("You must pass a 'groupId'.")
	}

	if msg["userId"] == nil && msg["anonymousId"] == nil {
		return errors.New("You must pass either an 'anonymousId' or 'userId'.")
	}

	c.queue(message(msg, "group"))

	return nil
}

// Identify buffers an "identify" message.
func (c *Client) Identify(msg Message) error {
	if msg["userId"] == nil && msg["anonymousId"] == nil {
		return errors.New("You must pass either an 'anonymousId' or 'userId'.")
	}

	c.queue(message(msg, "identify"))

	return nil
}

// Track buffers an "track" message.
func (c *Client) Track(msg Message) error {
	if msg["event"] == nil {
		return errors.New("You must pass 'event'.")
	}

	if msg["userId"] == nil && msg["anonymousId"] == nil {
		return errors.New("You must pass either an 'anonymousId' or 'userId'.")
	}

	c.queue(message(msg, "track"))

	return nil
}

// Return a new initialized message map
// with `msg` values and context merged.
func message(msg Message, call string) Message {
	m := newMessage(call)

	if msg["context"] != nil {
		merge(m["context"].(map[string]interface{}), msg["context"].(map[string]interface{}))
		delete(msg, "context")
	}

	merge(m, msg)

	return m
}

// Return new initialzed message map.
func newMessage(call string) Message {
	return Message{
		"type":      call,
		"timestamp": timestamp(),
		"messageId": uid(),
		"context": map[string]interface{}{
			"version": Version,
			"library": "analytics-go",
		},
	}
}

// Merge two maps.
func merge(dst Message, src Message) {
	for k, v := range src {
		dst[k] = v
	}
}

// Return uuid.
func uid() string {
	return uuid.NewRandom().String()
}

// Return formatted timestamp.
func timestamp() string {
	return strftime.Format("%Y-%m-%dT%H:%M:%S%z", time.Now())
}

// Buffer the given message and flush
// when the buffer exceeds .FlushAt.
func (c *Client) queue(msg Message) {
	c.Lock()
	defer c.Unlock()

	c.buffer = append(c.buffer, msg)

	debug("buffer (%d/%d) %v", len(c.buffer), c.FlushAt, msg)

	if len(c.buffer) >= c.FlushAt {
		go c.flush()
	}
}

// Return a batch message primed
// with context properties.
func batchMessage(msgs []Message) *batch {
	return &batch{
		MessageId: uid(),
		Messages:  msgs,
	}
}

// Flush the buffered messages.
//
// TODO: better error-handling,
// this is really meh, it would
// be better if we used a chan
// to deliver them.
//
func (c *Client) flush() error {
	c.Lock()

	if len(c.buffer) == 0 {
		debug("no messages to flush")
		c.Unlock()
		return nil
	}

	debug("flushing %d messages", len(c.buffer))
	json, err := Marshal(batchMessage(c.buffer))

	if err != nil {
		debug("error: %v", err)
		c.Unlock()
		return err
	}

	c.buffer = nil
	c.Unlock()

	client := &http.Client{}
	url := c.Endpoint + "/v1/import"
	debug("POST %s with %d bytes", url, len(json))
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(json))

	if err != nil {
		debug("error: %v", err)
		return err
	}

	req.Header.Add("User-Agent", "analytics-go (version: "+Version+")")
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Content-Length", string(len(json)))
	req.SetBasicAuth(c.Key, "")

	res, err := client.Do(req)
	if err != nil {
		debug("error: %v", err)
		return err
	}
	defer res.Body.Close()

	debug("%d response", res.StatusCode)

	if res.StatusCode >= 400 {
		body, _ := ioutil.ReadAll(res.Body)
		debug("error: %s", string(body))
		debug("error: %s", string(json))
	}

	return err
}
<|endoftext|>


<commit_before>package api

import (
	"encoding/base64"
	"net/http"
	"strconv"
	"strings"

	"github.com/labstack/echo"
)

type FeedbacksResponse struct {
	Status    string     `json:"status"`
	Feedbacks []Feedback `json:"feedbacks"`
}

type UserCountResponse struct {
	Status string `json:"status"`
	Count  int    `json:"count"`
}

func InitAdminAPI(e *echo.Echo) {
	e.GET("/admin/getAllFeedback", func(c echo.Context) error {
		if GetSessionUserID(&c) == -1 {
			return c.JSON(http.StatusUnauthorized, ErrorResponse{"error", "logged_out"})
		}
		user, _ := Data_GetUserByID(GetSessionUserID(&c))
		if user.Level < 1 {
			return c.JSON(http.StatusUnauthorized, ErrorResponse{"error", "forbidden"})
		}

		rows, err := DB.Query("SELECT feedback.id, feedback.userId, feedback.type, feedback.text, feedback.timestamp, users.name, users.email, feedback.screenshot FROM feedback INNER JOIN users ON feedback.userId = users.id")
		if err != nil {
			ErrorLog_LogError("getting all feedback", err)
			return c.JSON(http.StatusInternalServerError, ErrorResponse{"error", "internal_server_error"})
		}

		feedbacks := []Feedback{}
		for rows.Next() {
			resp := Feedback{-1, -1, "", "", "", "", "", false}
			var screenshot string
			rows.Scan(&resp.ID, &resp.UserID, &resp.Type, &resp.Text, &resp.Timestamp, &resp.UserName, &resp.UserEmail, &screenshot)
			if screenshot != "" {
				resp.HasScreenshot = true
			}
			feedbacks = append(feedbacks, resp)
		}

		return c.JSON(http.StatusOK, FeedbacksResponse{"ok", feedbacks})
	})

	e.GET("/admin/getFeedbackScreenshot/:id", func(c echo.Context) error {
		/* Use id in route so that browser can navigate to screenshot */

		if GetSessionUserID(&c) == -1 {
			return c.JSON(http.StatusUnauthorized, ErrorResponse{"error", "logged_out"})
		}
		user, _ := Data_GetUserByID(GetSessionUserID(&c))
		if user.Level < 1 {
			return c.JSON(http.StatusUnauthorized, ErrorResponse{"error", "forbidden"})
		}

		id, err := strconv.Atoi(strings.Replace(c.Param("id"), ".png", "", -1))
		if err != nil {
			return c.JSON(http.StatusBadRequest, ErrorResponse{"error", "invalid_paramas"})
		}

		rows, err := DB.Query("SELECT screenshot FROM feedback WHERE id = ?", id)
		if err != nil {
			ErrorLog_LogError("getting screenshot", err)
			return c.JSON(http.StatusInternalServerError, ErrorResponse{"error", "internal_server_error"})
		}

		if !rows.Next() {
			return c.JSON(http.StatusNotFound, ErrorResponse{"error", "not_found"})
		}

		var screenshot64 string
		err = rows.Scan(&screenshot64)
		if err != nil {
			ErrorLog_LogError("getting screenshot", err)
			return c.JSON(http.StatusInternalServerError, ErrorResponse{"error", "internal_server_error"})
		}

		rows.Close()

		if screenshot64 == "" {
			return c.JSON(http.StatusNotFound, ErrorResponse{"error", "no_screenshot"})
		}

		screenshot64 = strings.Replace(screenshot64, "data:image/png;base64,", "", 1)

		screenshot, err := base64.StdEncoding.DecodeString(screenshot64)
		if err != nil {
			ErrorLog_LogError("getting screenshot", err)
			return c.JSON(http.StatusInternalServerError, ErrorResponse{"error", "internal_server_error"})
		}

		return c.Blob(http.StatusOK, "image/png;base64", screenshot)
	})

	e.GET("/admin/getUserCount", func(c echo.Context) error {
		if GetSessionUserID(&c) == -1 {
			return c.JSON(http.StatusUnauthorized, ErrorResponse{"error", "logged_out"})
		}
		user, _ := Data_GetUserByID(GetSessionUserID(&c))
		if user.Level < 1 {
			return c.JSON(http.StatusUnauthorized, ErrorResponse{"error", "forbidden"})
		}

		rows, err := DB.Query("SELECT COUNT(*) FROM users")
		if err != nil {
			ErrorLog_LogError("getting user count", err)
			return c.JSON(http.StatusInternalServerError, ErrorResponse{"error", "internal_server_error"})
		}

		rows.Next()
		count := -1
		rows.Scan(&count)

		return c.JSON(http.StatusOK, UserCountResponse{"ok", count})
	})
}
<commit_msg>small tweaks to feedback screenshot code<commit_after>package api

import (
	"encoding/base64"
	"net/http"
	"strconv"
	"strings"

	"github.com/labstack/echo"
)

type FeedbacksResponse struct {
	Status    string     `json:"status"`
	Feedbacks []Feedback `json:"feedbacks"`
}

type UserCountResponse struct {
	Status string `json:"status"`
	Count  int    `json:"count"`
}

func InitAdminAPI(e *echo.Echo) {
	e.GET("/admin/getAllFeedback", func(c echo.Context) error {
		if GetSessionUserID(&c) == -1 {
			return c.JSON(http.StatusUnauthorized, ErrorResponse{"error", "logged_out"})
		}
		user, _ := Data_GetUserByID(GetSessionUserID(&c))
		if user.Level < 1 {
			return c.JSON(http.StatusUnauthorized, ErrorResponse{"error", "forbidden"})
		}

		rows, err := DB.Query("SELECT feedback.id, feedback.userId, feedback.type, feedback.text, feedback.screenshot, feedback.timestamp, users.name, users.email FROM feedback INNER JOIN users ON feedback.userId = users.id")
		if err != nil {
			ErrorLog_LogError("getting all feedback", err)
			return c.JSON(http.StatusInternalServerError, ErrorResponse{"error", "internal_server_error"})
		}

		feedbacks := []Feedback{}
		for rows.Next() {
			resp := Feedback{-1, -1, "", "", "", "", "", false}
			var screenshot string
			rows.Scan(&resp.ID, &resp.UserID, &resp.Type, &resp.Text, &screenshot, &resp.Timestamp, &resp.UserName, &resp.UserEmail)
			if screenshot != "" {
				resp.HasScreenshot = true
			}
			feedbacks = append(feedbacks, resp)
		}

		return c.JSON(http.StatusOK, FeedbacksResponse{"ok", feedbacks})
	})

	e.GET("/admin/getFeedbackScreenshot/:id", func(c echo.Context) error {
		if GetSessionUserID(&c) == -1 {
			return c.JSON(http.StatusUnauthorized, ErrorResponse{"error", "logged_out"})
		}
		user, _ := Data_GetUserByID(GetSessionUserID(&c))
		if user.Level < 1 {
			return c.JSON(http.StatusUnauthorized, ErrorResponse{"error", "forbidden"})
		}

		id, err := strconv.Atoi(c.Param("id"))
		if err != nil {
			return c.JSON(http.StatusBadRequest, ErrorResponse{"error", "invalid_paramas"})
		}

		rows, err := DB.Query("SELECT screenshot FROM feedback WHERE id = ?", id)
		if err != nil {
			ErrorLog_LogError("getting screenshot", err)
			return c.JSON(http.StatusInternalServerError, ErrorResponse{"error", "internal_server_error"})
		}

		if !rows.Next() {
			return c.JSON(http.StatusNotFound, ErrorResponse{"error", "not_found"})
		}

		var screenshot64 string
		err = rows.Scan(&screenshot64)
		if err != nil {
			ErrorLog_LogError("getting screenshot", err)
			return c.JSON(http.StatusInternalServerError, ErrorResponse{"error", "internal_server_error"})
		}

		rows.Close()

		if screenshot64 == "" {
			return c.JSON(http.StatusNotFound, ErrorResponse{"error", "no_screenshot"})
		}

		screenshot64 = strings.Replace(screenshot64, "data:image/png;base64,", "", 1)

		screenshot, err := base64.StdEncoding.DecodeString(screenshot64)
		if err != nil {
			ErrorLog_LogError("getting screenshot", err)
			return c.JSON(http.StatusInternalServerError, ErrorResponse{"error", "internal_server_error"})
		}

		return c.Blob(http.StatusOK, "image/png;base64", screenshot)
	})

	e.GET("/admin/getUserCount", func(c echo.Context) error {
		if GetSessionUserID(&c) == -1 {
			return c.JSON(http.StatusUnauthorized, ErrorResponse{"error", "logged_out"})
		}
		user, _ := Data_GetUserByID(GetSessionUserID(&c))
		if user.Level < 1 {
			return c.JSON(http.StatusUnauthorized, ErrorResponse{"error", "forbidden"})
		}

		rows, err := DB.Query("SELECT COUNT(*) FROM users")
		if err != nil {
			ErrorLog_LogError("getting user count", err)
			return c.JSON(http.StatusInternalServerError, ErrorResponse{"error", "internal_server_error"})
		}

		rows.Next()
		count := -1
		rows.Scan(&count)

		return c.JSON(http.StatusOK, UserCountResponse{"ok", count})
	})
}
<|endoftext|>


<commit_before>// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0

package kv

import (
	"bufio"
	"bytes"
	"fmt"
	"os"
	"path"
	"strings"
	"unicode"
	"unicode/utf8"

	"github.com/pkg/errors"
	"sigs.k8s.io/kustomize/api/ifc"
	"sigs.k8s.io/kustomize/api/types"
)

var utf8bom = []byte{0xEF, 0xBB, 0xBF}

// loader reads and validates KV pairs.
type loader struct {
	// Used to read the filesystem.
	ldr ifc.Loader

	// Used to validate various k8s data fields.
	validator ifc.Validator
}

func NewLoader(ldr ifc.Loader, v ifc.Validator) ifc.KvLoader {
	return &loader{ldr: ldr, validator: v}
}

func (kvl *loader) Validator() ifc.Validator {
	return kvl.validator
}

func (kvl *loader) Load(
	args types.KvPairSources) (all []types.Pair, err error) {
	pairs, err := kvl.keyValuesFromEnvFiles(args.EnvSources)
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf(
			"env source files: %v",
			args.EnvSources))
	}
	all = append(all, pairs...)

	pairs, err = keyValuesFromLiteralSources(args.LiteralSources)
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf(
			"literal sources %v", args.LiteralSources))
	}
	all = append(all, pairs...)

	pairs, err = kvl.keyValuesFromFileSources(args.FileSources)
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf(
			"file sources: %v", args.FileSources))
	}
	return append(all, pairs...), nil
}

func keyValuesFromLiteralSources(sources []string) ([]types.Pair, error) {
	var kvs []types.Pair
	for _, s := range sources {
		k, v, err := parseLiteralSource(s)
		if err != nil {
			return nil, err
		}
		kvs = append(kvs, types.Pair{Key: k, Value: v})
	}
	return kvs, nil
}

func (kvl *loader) keyValuesFromFileSources(sources []string) ([]types.Pair, error) {
	var kvs []types.Pair
	for _, s := range sources {
		k, fPath, err := parseFileSource(s)
		if err != nil {
			return nil, err
		}
		content, err := kvl.ldr.Load(fPath)
		if err != nil {
			return nil, err
		}
		kvs = append(kvs, types.Pair{Key: k, Value: string(content)})
	}
	return kvs, nil
}

func (kvl *loader) keyValuesFromEnvFiles(paths []string) ([]types.Pair, error) {
	var kvs []types.Pair
	for _, p := range paths {
		content, err := kvl.ldr.Load(p)
		if err != nil {
			return nil, err
		}
		more, err := kvl.keyValuesFromLines(content)
		if err != nil {
			return nil, err
		}
		kvs = append(kvs, more...)
	}
	return kvs, nil
}

// keyValuesFromLines parses given content in to a list of key-value pairs.
func (kvl *loader) keyValuesFromLines(content []byte) ([]types.Pair, error) {
	var kvs []types.Pair

	scanner := bufio.NewScanner(bytes.NewReader(content))
	currentLine := 0
	for scanner.Scan() {
		// Process the current line, retrieving a key/value pair if
		// possible.
		scannedBytes := scanner.Bytes()
		kv, err := kvl.keyValuesFromLine(scannedBytes, currentLine)
		if err != nil {
			return nil, err
		}
		currentLine++

		if len(kv.Key) == 0 {
			// no key means line was empty or a comment
			continue
		}

		kvs = append(kvs, kv)
	}
	return kvs, nil
}

// KeyValuesFromLine returns a kv with blank key if the line is empty or a comment.
// The value will be retrieved from the environment if necessary.
func (kvl *loader) keyValuesFromLine(line []byte, currentLine int) (types.Pair, error) {
	kv := types.Pair{}

	if !utf8.Valid(line) {
		return kv, fmt.Errorf("line %d has invalid utf8 bytes : %v", line, string(line))
	}

	// We trim UTF8 BOM from the first line of the file but no others
	if currentLine == 0 {
		line = bytes.TrimPrefix(line, utf8bom)
	}

	// trim the line from all leading whitespace first
	line = bytes.TrimLeftFunc(line, unicode.IsSpace)

	// If the line is empty or a comment, we return a blank key/value pair.
	if len(line) == 0 || line[0] == '#' {
		return kv, nil
	}

	data := strings.SplitN(string(line), "=", 2)
	key := data[0]
	if err := kvl.validator.IsEnvVarName(key); err != nil {
		return kv, err
	}

	if len(data) == 2 {
		kv.Value = data[1]
	} else {
		// No value (no `=` in the line) is a signal to obtain the value
		// from the environment.
		kv.Value = os.Getenv(key)
	}
	kv.Key = key
	return kv, nil
}

// ParseFileSource parses the source given.
//
//  Acceptable formats include:
//   1.  source-path: the basename will become the key name
//   2.  source-name=source-path: the source-name will become the key name and
//       source-path is the path to the key file.
//
// Key names cannot include '='.
func parseFileSource(source string) (keyName, filePath string, err error) {
	numSeparators := strings.Count(source, "=")
	switch {
	case numSeparators == 0:
		return path.Base(source), source, nil
	case numSeparators == 1 && strings.HasPrefix(source, "="):
		return "", "", fmt.Errorf("key name for file path %v missing", strings.TrimPrefix(source, "="))
	case numSeparators == 1 && strings.HasSuffix(source, "="):
		return "", "", fmt.Errorf("file path for key name %v missing", strings.TrimSuffix(source, "="))
	case numSeparators > 1:
		return "", "", errors.New("key names or file paths cannot contain '='")
	default:
		components := strings.Split(source, "=")
		return components[0], components[1], nil
	}
}

// ParseLiteralSource parses the source key=val pair into its component pieces.
// This functionality is distinguished from strings.SplitN(source, "=", 2) since
// it returns an error in the case of empty keys, values, or a missing equals sign.
func parseLiteralSource(source string) (keyName, value string, err error) {
	// leading equal is invalid
	if strings.Index(source, "=") == 0 {
		return "", "", fmt.Errorf("invalid literal source %v, expected key=value", source)
	}
	// split after the first equal (so values can have the = character)
	items := strings.SplitN(source, "=", 2)
	if len(items) != 2 {
		return "", "", fmt.Errorf("invalid literal source %v, expected key=value", source)
	}
	return items[0], removeQuotes(items[1]), nil
}

// removeQuotes removes the surrounding quotes from the provided string only if it is surrounded on both sides
// rather than blindly trimming all quotation marks on either side.
func removeQuotes(str string) string {
	if len(str) == 0 || str[0] != str[len(str)-1] {
		return str
	}
	if str[0] == '"' || str[0] == '\'' {
		return str[1 : len(str)-1]
	}
	return str
}
<commit_msg>Emit a warning when env loading bug is being relied on<commit_after>// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0

package kv

import (
	"bufio"
	"bytes"
	"fmt"
	"os"
	"path"
	"strings"
	"unicode"
	"unicode/utf8"

	"github.com/pkg/errors"
	"sigs.k8s.io/kustomize/api/ifc"
	"sigs.k8s.io/kustomize/api/types"
)

var utf8bom = []byte{0xEF, 0xBB, 0xBF}

// loader reads and validates KV pairs.
type loader struct {
	// Used to read the filesystem.
	ldr ifc.Loader

	// Used to validate various k8s data fields.
	validator ifc.Validator
}

func NewLoader(ldr ifc.Loader, v ifc.Validator) ifc.KvLoader {
	return &loader{ldr: ldr, validator: v}
}

func (kvl *loader) Validator() ifc.Validator {
	return kvl.validator
}

func (kvl *loader) Load(
	args types.KvPairSources) (all []types.Pair, err error) {
	pairs, err := kvl.keyValuesFromEnvFiles(args.EnvSources)
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf(
			"env source files: %v",
			args.EnvSources))
	}
	all = append(all, pairs...)

	pairs, err = keyValuesFromLiteralSources(args.LiteralSources)
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf(
			"literal sources %v", args.LiteralSources))
	}
	all = append(all, pairs...)

	pairs, err = kvl.keyValuesFromFileSources(args.FileSources)
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf(
			"file sources: %v", args.FileSources))
	}
	return append(all, pairs...), nil
}

func keyValuesFromLiteralSources(sources []string) ([]types.Pair, error) {
	var kvs []types.Pair
	for _, s := range sources {
		k, v, err := parseLiteralSource(s)
		if err != nil {
			return nil, err
		}
		kvs = append(kvs, types.Pair{Key: k, Value: v})
	}
	return kvs, nil
}

func (kvl *loader) keyValuesFromFileSources(sources []string) ([]types.Pair, error) {
	var kvs []types.Pair
	for _, s := range sources {
		k, fPath, err := parseFileSource(s)
		if err != nil {
			return nil, err
		}
		content, err := kvl.ldr.Load(fPath)
		if err != nil {
			return nil, err
		}
		kvs = append(kvs, types.Pair{Key: k, Value: string(content)})
	}
	return kvs, nil
}

func (kvl *loader) keyValuesFromEnvFiles(paths []string) ([]types.Pair, error) {
	var kvs []types.Pair
	for _, p := range paths {
		content, err := kvl.ldr.Load(p)
		if err != nil {
			return nil, err
		}
		more, err := kvl.keyValuesFromLines(content)
		if err != nil {
			return nil, err
		}
		kvs = append(kvs, more...)
	}
	return kvs, nil
}

// keyValuesFromLines parses given content in to a list of key-value pairs.
func (kvl *loader) keyValuesFromLines(content []byte) ([]types.Pair, error) {
	var kvs []types.Pair

	scanner := bufio.NewScanner(bytes.NewReader(content))
	currentLine := 0
	for scanner.Scan() {
		// Process the current line, retrieving a key/value pair if
		// possible.
		scannedBytes := scanner.Bytes()
		kv, err := kvl.keyValuesFromLine(scannedBytes, currentLine)
		if err != nil {
			return nil, err
		}
		currentLine++

		if len(kv.Key) == 0 {
			// no key means line was empty or a comment
			continue
		}

		kvs = append(kvs, kv)
	}
	return kvs, nil
}

// KeyValuesFromLine returns a kv with blank key if the line is empty or a comment.
func (kvl *loader) keyValuesFromLine(line []byte, currentLine int) (types.Pair, error) {
	kv := types.Pair{}

	if !utf8.Valid(line) {
		return kv, fmt.Errorf("line %d has invalid utf8 bytes : %v", line, string(line))
	}

	// We trim UTF8 BOM from the first line of the file but no others
	if currentLine == 0 {
		line = bytes.TrimPrefix(line, utf8bom)
	}

	// trim the line from all leading whitespace first
	line = bytes.TrimLeftFunc(line, unicode.IsSpace)

	// If the line is empty or a comment, we return a blank key/value pair.
	if len(line) == 0 || line[0] == '#' {
		return kv, nil
	}

	data := strings.SplitN(string(line), "=", 2)
	key := data[0]
	if err := kvl.validator.IsEnvVarName(key); err != nil {
		return kv, err
	}

	if len(data) == 2 {
		kv.Value = data[1]
	} else {
		// No value (no `=` in the line) is a signal to obtain the value
		// from the environment. This behaviour was accidentally imported from kubectl code, and
		// will be removed in the next major release of Kustomize.
		_, _ = fmt.Fprintln(os.Stderr, "WARNING: "+
			"This Kustomization is relying on a bug that loads values from the environment "+
			"when they are omitted from an env file. "+
			"This behaviour will be removed in the next major release of Kustomize.")
		kv.Value = os.Getenv(key)
	}
	kv.Key = key
	return kv, nil
}

// ParseFileSource parses the source given.
//
//  Acceptable formats include:
//   1.  source-path: the basename will become the key name
//   2.  source-name=source-path: the source-name will become the key name and
//       source-path is the path to the key file.
//
// Key names cannot include '='.
func parseFileSource(source string) (keyName, filePath string, err error) {
	numSeparators := strings.Count(source, "=")
	switch {
	case numSeparators == 0:
		return path.Base(source), source, nil
	case numSeparators == 1 && strings.HasPrefix(source, "="):
		return "", "", fmt.Errorf("key name for file path %v missing", strings.TrimPrefix(source, "="))
	case numSeparators == 1 && strings.HasSuffix(source, "="):
		return "", "", fmt.Errorf("file path for key name %v missing", strings.TrimSuffix(source, "="))
	case numSeparators > 1:
		return "", "", errors.New("key names or file paths cannot contain '='")
	default:
		components := strings.Split(source, "=")
		return components[0], components[1], nil
	}
}

// ParseLiteralSource parses the source key=val pair into its component pieces.
// This functionality is distinguished from strings.SplitN(source, "=", 2) since
// it returns an error in the case of empty keys, values, or a missing equals sign.
func parseLiteralSource(source string) (keyName, value string, err error) {
	// leading equal is invalid
	if strings.Index(source, "=") == 0 {
		return "", "", fmt.Errorf("invalid literal source %v, expected key=value", source)
	}
	// split after the first equal (so values can have the = character)
	items := strings.SplitN(source, "=", 2)
	if len(items) != 2 {
		return "", "", fmt.Errorf("invalid literal source %v, expected key=value", source)
	}
	return items[0], removeQuotes(items[1]), nil
}

// removeQuotes removes the surrounding quotes from the provided string only if it is surrounded on both sides
// rather than blindly trimming all quotation marks on either side.
func removeQuotes(str string) string {
	if len(str) == 0 || str[0] != str[len(str)-1] {
		return str
	}
	if str[0] == '"' || str[0] == '\'' {
		return str[1 : len(str)-1]
	}
	return str
}
<|endoftext|>


<commit_before>// Copyright (c) 2014-2017 Bitmark Inc.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package rpc

import (
	"github.com/bitmark-inc/bitmarkd/announce"
	"github.com/bitmark-inc/bitmarkd/block"
	"github.com/bitmark-inc/bitmarkd/difficulty"
	"github.com/bitmark-inc/bitmarkd/fault"
	"github.com/bitmark-inc/bitmarkd/mode"
	"github.com/bitmark-inc/bitmarkd/peer"
	"github.com/bitmark-inc/bitmarkd/reservoir"
	"github.com/bitmark-inc/bitmarkd/version"
	"github.com/bitmark-inc/logger"
	"time"
)

type Node struct {
	log   *logger.L
	start time.Time
}

// list the RPC services available in the network

type NodeArguments struct {
	Start uint64 `json:"start,string"`
	Count int    `json:"count"`
}

type NodeReply struct {
	Nodes     []announce.RPCEntry `json:"nodes"`
	NextStart uint64              `json:"nextStart,string"`
}

func (node *Node) List(arguments *NodeArguments, reply *NodeReply) error {
	if arguments.Count <= 0 || arguments.Count > 100 {
		return fault.ErrInvalidCount
	}
	nodes, nextStart, err := announce.FetchRPCs(arguments.Start, arguments.Count)
	if nil != err {
		return err
	}
	reply.Nodes = nodes
	reply.NextStart = nextStart

	return err
}

// return some information about this node

type InfoArguments struct{}
type ConnectorArguments struct{}
type SubscriberArguments struct{}

type InfoReply struct {
	Chain               string   `json:"chain"`
	Mode                string   `json:"mode"`
	Blocks              uint64   `json:"blocks"`
	RPCs                uint64   `json:"rpcs"`
	TransactionCounters Counters `json:"transactionCounters"`
	Difficulty          float64  `json:"difficulty"`
	Version             string   `json:"version"`
	Uptime              string   `json:"uptime"`
	// Peers    int     `json:"peers"`
	// Miners   uint64  `json:"miners"`
}

type ConnectorReply struct {
	Clients []string
}

type SubscriberReply struct {
	Clients []string
}

type Counters struct {
	Pending  int   `json:"pending"`
	Verified int   `json:"verified"`
	Others   []int `json:"others"`
}

func (node *Node) Info(arguments *InfoArguments, reply *InfoReply) error {

	reply.Chain = mode.ChainName()
	reply.Mode = mode.String()
	reply.Blocks = block.GetHeight()
	reply.RPCs = connectionCount.Uint64()
	// reply.Peers = peer.ConnectionCount()
	// reply.Miners = mine.ConnectionCount()
	reply.TransactionCounters.Pending, reply.TransactionCounters.Verified, reply.TransactionCounters.Others = reservoir.ReadCounters()
	reply.Difficulty = difficulty.Current.Reciprocal()
	reply.Version = version.Version
	reply.Uptime = time.Since(node.start).String()

	return nil
}

func (node *Node) Connectors(arguments *ConnectorArguments, reply *ConnectorReply) error {
	clients := peer.FetchConnectors()
	addrs := make([]string, 0, 10)
	for _, c := range clients {
		if addr := c.String(); addr != "" {
			addrs = append(addrs, addr)
		}
	}
	reply.Clients = addrs
	return nil
}
func (node *Node) Subscribers(arguments *SubscriberArguments, reply *SubscriberReply) error {
	clients := peer.FetchSubscribers()
	addrs := make([]string, 0, 10)
	for _, c := range clients {
		if addr := c.String(); addr != "" {
			addrs = append(addrs, addr)
		}
	}
	reply.Clients = addrs
	return nil
}
<commit_msg>Return nil for readability<commit_after>// Copyright (c) 2014-2017 Bitmark Inc.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package rpc

import (
	"github.com/bitmark-inc/bitmarkd/announce"
	"github.com/bitmark-inc/bitmarkd/block"
	"github.com/bitmark-inc/bitmarkd/difficulty"
	"github.com/bitmark-inc/bitmarkd/fault"
	"github.com/bitmark-inc/bitmarkd/mode"
	"github.com/bitmark-inc/bitmarkd/peer"
	"github.com/bitmark-inc/bitmarkd/reservoir"
	"github.com/bitmark-inc/bitmarkd/version"
	"github.com/bitmark-inc/logger"
	"time"
)

type Node struct {
	log   *logger.L
	start time.Time
}

// list the RPC services available in the network

type NodeArguments struct {
	Start uint64 `json:"start,string"`
	Count int    `json:"count"`
}

type NodeReply struct {
	Nodes     []announce.RPCEntry `json:"nodes"`
	NextStart uint64              `json:"nextStart,string"`
}

func (node *Node) List(arguments *NodeArguments, reply *NodeReply) error {
	if arguments.Count <= 0 || arguments.Count > 100 {
		return fault.ErrInvalidCount
	}
	nodes, nextStart, err := announce.FetchRPCs(arguments.Start, arguments.Count)
	if nil != err {
		return err
	}
	reply.Nodes = nodes
	reply.NextStart = nextStart

	return nil
}

// return some information about this node

type InfoArguments struct{}
type ConnectorArguments struct{}
type SubscriberArguments struct{}

type InfoReply struct {
	Chain               string   `json:"chain"`
	Mode                string   `json:"mode"`
	Blocks              uint64   `json:"blocks"`
	RPCs                uint64   `json:"rpcs"`
	TransactionCounters Counters `json:"transactionCounters"`
	Difficulty          float64  `json:"difficulty"`
	Version             string   `json:"version"`
	Uptime              string   `json:"uptime"`
	// Peers    int     `json:"peers"`
	// Miners   uint64  `json:"miners"`
}

type ConnectorReply struct {
	Clients []string
}

type SubscriberReply struct {
	Clients []string
}

type Counters struct {
	Pending  int   `json:"pending"`
	Verified int   `json:"verified"`
	Others   []int `json:"others"`
}

func (node *Node) Info(arguments *InfoArguments, reply *InfoReply) error {

	reply.Chain = mode.ChainName()
	reply.Mode = mode.String()
	reply.Blocks = block.GetHeight()
	reply.RPCs = connectionCount.Uint64()
	// reply.Peers = peer.ConnectionCount()
	// reply.Miners = mine.ConnectionCount()
	reply.TransactionCounters.Pending, reply.TransactionCounters.Verified, reply.TransactionCounters.Others = reservoir.ReadCounters()
	reply.Difficulty = difficulty.Current.Reciprocal()
	reply.Version = version.Version
	reply.Uptime = time.Since(node.start).String()

	return nil
}

func (node *Node) Connectors(arguments *ConnectorArguments, reply *ConnectorReply) error {
	clients := peer.FetchConnectors()
	addrs := make([]string, 0, 10)
	for _, c := range clients {
		if addr := c.String(); addr != "" {
			addrs = append(addrs, addr)
		}
	}
	reply.Clients = addrs
	return nil
}
func (node *Node) Subscribers(arguments *SubscriberArguments, reply *SubscriberReply) error {
	clients := peer.FetchSubscribers()
	addrs := make([]string, 0, 10)
	for _, c := range clients {
		if addr := c.String(); addr != "" {
			addrs = append(addrs, addr)
		}
	}
	reply.Clients = addrs
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path"

	"github.com/scode/saltybox/preader"

	"github.com/urfave/cli"

	"github.com/scode/saltybox/secretcrypt"
	"github.com/scode/saltybox/varmor"
)

func passphraseEncrypt(passphrase string, plaintext []byte) (string, error) {
	cipherBytes, err := secretcrypt.Encrypt(passphrase, plaintext)
	if err != nil {
		return "", fmt.Errorf("encryption failed: %s", err)
	}

	varmoredBytes := varmor.Wrap(cipherBytes)

	return string(varmoredBytes), nil
}

func passphraseEncryptFile(inpath string, outpath string, preader preader.PassphraseReader) error {
	plaintext, err := ioutil.ReadFile(inpath)
	if err != nil {
		return fmt.Errorf("failed to read from %s: %s", inpath, err)
	}

	passphrase, err := preader.ReadPassphrase()
	if err != nil {
		return err
	}
	encryptedString, err := passphraseEncrypt(passphrase, plaintext)
	if err != nil {
		return fmt.Errorf("encryption failed: %s", err)
	}

	err = ioutil.WriteFile(outpath, []byte(encryptedString), 0700)
	if err != nil {
		return fmt.Errorf("failed to write to %s: %s", outpath, err)
	}

	return nil
}

func passphraseDecrypt(passphrase string, encryptedString string) ([]byte, error) {
	cipherBytes, err := varmor.Unwrap(encryptedString)
	if err != nil {
		return nil, fmt.Errorf("failed to unarmor: %s", err)
	}

	plaintext, err := secretcrypt.Decrypt(passphrase, cipherBytes)
	if err != nil {
		return nil, fmt.Errorf("failed to decrypt: %s", err)
	}

	return plaintext, nil
}

func passphraseDecryptFile(inpath string, outpath string, preader preader.PassphraseReader) error {
	varmoredBytes, err := ioutil.ReadFile(inpath)
	if err != nil {
		return fmt.Errorf("failed to read from %s: %s", inpath, err)
	}

	passphrase, err := preader.ReadPassphrase()
	if err != nil {
		return err
	}
	plaintext, err := passphraseDecrypt(passphrase, string(varmoredBytes))
	if err != nil {
		return fmt.Errorf("failed to decrypt: %s", err)
	}

	err = ioutil.WriteFile(outpath, plaintext, 0700)
	if err != nil {
		return fmt.Errorf("failed to write to %s: %s", outpath, err)
	}

	return nil
}

func passphraseUpdateFile(plainfile string, cryptfile string, pr preader.PassphraseReader) (err error) {
	// Decrypt existing file in order to validate that the provided passphrase is correct,
	// in order to prevent accidental changing of the passphrase (but we discard the plain
	// text).
	varmoredBytes, err := ioutil.ReadFile(cryptfile)
	if err != nil {
		return fmt.Errorf("failed to read from %s: %s", cryptfile, err)
	}

	cachingPreader := preader.NewCaching(pr)

	passphrase, err := cachingPreader.ReadPassphrase()
	if err != nil {
		return err
	}
	_, err = passphraseDecrypt(passphrase, string(varmoredBytes))
	if err != nil {
		return fmt.Errorf("failed to decrypt: %s", err)
	}

	// Encrypt contents into the target file using atomic semantics (write to tempfile, fsync()
	// and rename). This guarantees that the resulting file will either be the old file or the new
	// file, but never corrupt (assuming a correctly functioning filesystem I/O stack).
	cryptDir, _ := path.Split(cryptfile)

	tmpfile, err := ioutil.TempFile(cryptDir, "saltybox-update-tmp")
	if err != nil {
		return fmt.Errorf("failed to create tempfile: %s", err)
	}
	defer func(fname string) {
		if _, localErr := os.Stat(fname); !os.IsNotExist(localErr) {
			err = os.Remove(fname)
		}
	}(tmpfile.Name())
	defer func(tmpfile *os.File) {
		err = tmpfile.Close()
	}(tmpfile)

	err = passphraseEncryptFile(plainfile, tmpfile.Name(), cachingPreader)
	if err != nil {
		return fmt.Errorf("failed to encrypt: %s", err)
	}

	// Re-open the file to ensure that we are Sync():ing the correct file. Technically this is not
	// required because passphraseEncryptFile() will cause the target file to be truncated rather than recreated.
	// However, let's defensively avoid relying on that subtle behavior and re-open the file.
	reopenedTmpFile, err := os.Open(tmpfile.Name())
	if err != nil {
		return fmt.Errorf("failed to re-open tempfile after encryption: %s", err)
	}
	defer func(f *os.File) {
		err = f.Close()
	}(reopenedTmpFile)

	err = reopenedTmpFile.Sync()
	if err != nil {
		return fmt.Errorf("failed to sync file prior to rename: %s", err)
	}

	err = os.Rename(reopenedTmpFile.Name(), cryptfile)
	if err != nil {
		return fmt.Errorf("failed to rename to target file: %s", err)
	}

	return nil
}

func main() {
	app := cli.NewApp()
	app.Name = "saltybox"
	app.Version = "unknown (master)"
	app.Usage = "an encryption tool"
	app.HideVersion = true

	var passphraseStdinArg bool
	getPassphraseReader := func() preader.PassphraseReader {
		if passphraseStdinArg {
			return preader.NewReader(os.Stdin)
		}

		return preader.NewTerminal()
	}

	var inputArg string
	var outputArg string

	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:        "passphrase-stdin",
			Usage:       "read passphrase from stdin instead of from terminal",
			Destination: &passphraseStdinArg,
		},
	}

	app.Commands = []cli.Command{
		{
			Name:    "encrypt",
			Aliases: []string{"e"},
			Usage:   "encrypt a file",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:        "input, i",
					Usage:       "path to the file whose contents is to be encrypted",
					Required:    true,
					Destination: &inputArg,
				},
				cli.StringFlag{
					Name:        "output, o",
					Usage:       "path to the file to write the encrypted text to",
					Required:    true,
					Destination: &outputArg,
				},
			},
			Action: func(c *cli.Context) error {
				return passphraseEncryptFile(inputArg, outputArg, getPassphraseReader())
			},
		},
		{
			Name:    "decrypt",
			Aliases: []string{"e"},
			Usage:   "decrypt a file",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:        "input, i",
					Usage:       "path to the file whose contents is to be decrypted",
					Required:    true,
					Destination: &inputArg,
				},
				cli.StringFlag{
					Name:        "output, o",
					Usage:       "path to the file to write the unencrypted text to",
					Required:    true,
					Destination: &outputArg,
				},
			},
			Action: func(c *cli.Context) error {
				return passphraseDecryptFile(inputArg, outputArg, getPassphraseReader())
			},
		},
		{
			Name:    "update",
			Aliases: []string{"e"},
			Usage:   "update an encrypted file with new encrypted content",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:        "input, i",
					Usage:       "path to the file whose contents is to be encrypted",
					Required:    true,
					Destination: &inputArg,
				},
				cli.StringFlag{
					Name:        "output, o",
					Usage:       "path to the existing saltybox file to replace with encrypted text",
					Required:    true,
					Destination: &outputArg,
				},
			},
			Action: func(c *cli.Context) error {
				return passphraseUpdateFile(inputArg, outputArg, getPassphraseReader())
			},
		},
	}

	app.Action = func(c *cli.Context) error {
		return errors.New("command is required; use help to see list of commands")
	}

	err := app.Run(os.Args)
	if err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Improve command line documentation. (#43)<commit_after>package main

import (
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path"

	"github.com/scode/saltybox/preader"

	"github.com/urfave/cli"

	"github.com/scode/saltybox/secretcrypt"
	"github.com/scode/saltybox/varmor"
)

func passphraseEncrypt(passphrase string, plaintext []byte) (string, error) {
	cipherBytes, err := secretcrypt.Encrypt(passphrase, plaintext)
	if err != nil {
		return "", fmt.Errorf("encryption failed: %s", err)
	}

	varmoredBytes := varmor.Wrap(cipherBytes)

	return string(varmoredBytes), nil
}

func passphraseEncryptFile(inpath string, outpath string, preader preader.PassphraseReader) error {
	plaintext, err := ioutil.ReadFile(inpath)
	if err != nil {
		return fmt.Errorf("failed to read from %s: %s", inpath, err)
	}

	passphrase, err := preader.ReadPassphrase()
	if err != nil {
		return err
	}
	encryptedString, err := passphraseEncrypt(passphrase, plaintext)
	if err != nil {
		return fmt.Errorf("encryption failed: %s", err)
	}

	err = ioutil.WriteFile(outpath, []byte(encryptedString), 0700)
	if err != nil {
		return fmt.Errorf("failed to write to %s: %s", outpath, err)
	}

	return nil
}

func passphraseDecrypt(passphrase string, encryptedString string) ([]byte, error) {
	cipherBytes, err := varmor.Unwrap(encryptedString)
	if err != nil {
		return nil, fmt.Errorf("failed to unarmor: %s", err)
	}

	plaintext, err := secretcrypt.Decrypt(passphrase, cipherBytes)
	if err != nil {
		return nil, fmt.Errorf("failed to decrypt: %s", err)
	}

	return plaintext, nil
}

func passphraseDecryptFile(inpath string, outpath string, preader preader.PassphraseReader) error {
	varmoredBytes, err := ioutil.ReadFile(inpath)
	if err != nil {
		return fmt.Errorf("failed to read from %s: %s", inpath, err)
	}

	passphrase, err := preader.ReadPassphrase()
	if err != nil {
		return err
	}
	plaintext, err := passphraseDecrypt(passphrase, string(varmoredBytes))
	if err != nil {
		return fmt.Errorf("failed to decrypt: %s", err)
	}

	err = ioutil.WriteFile(outpath, plaintext, 0700)
	if err != nil {
		return fmt.Errorf("failed to write to %s: %s", outpath, err)
	}

	return nil
}

func passphraseUpdateFile(plainfile string, cryptfile string, pr preader.PassphraseReader) (err error) {
	// Decrypt existing file in order to validate that the provided passphrase is correct,
	// in order to prevent accidental changing of the passphrase (but we discard the plain
	// text).
	varmoredBytes, err := ioutil.ReadFile(cryptfile)
	if err != nil {
		return fmt.Errorf("failed to read from %s: %s", cryptfile, err)
	}

	cachingPreader := preader.NewCaching(pr)

	passphrase, err := cachingPreader.ReadPassphrase()
	if err != nil {
		return err
	}
	_, err = passphraseDecrypt(passphrase, string(varmoredBytes))
	if err != nil {
		return fmt.Errorf("failed to decrypt: %s", err)
	}

	// Encrypt contents into the target file using atomic semantics (write to tempfile, fsync()
	// and rename). This guarantees that the resulting file will either be the old file or the new
	// file, but never corrupt (assuming a correctly functioning filesystem I/O stack).
	cryptDir, _ := path.Split(cryptfile)

	tmpfile, err := ioutil.TempFile(cryptDir, "saltybox-update-tmp")
	if err != nil {
		return fmt.Errorf("failed to create tempfile: %s", err)
	}
	defer func(fname string) {
		if _, localErr := os.Stat(fname); !os.IsNotExist(localErr) {
			err = os.Remove(fname)
		}
	}(tmpfile.Name())
	defer func(tmpfile *os.File) {
		err = tmpfile.Close()
	}(tmpfile)

	err = passphraseEncryptFile(plainfile, tmpfile.Name(), cachingPreader)
	if err != nil {
		return fmt.Errorf("failed to encrypt: %s", err)
	}

	// Re-open the file to ensure that we are Sync():ing the correct file. Technically this is not
	// required because passphraseEncryptFile() will cause the target file to be truncated rather than recreated.
	// However, let's defensively avoid relying on that subtle behavior and re-open the file.
	reopenedTmpFile, err := os.Open(tmpfile.Name())
	if err != nil {
		return fmt.Errorf("failed to re-open tempfile after encryption: %s", err)
	}
	defer func(f *os.File) {
		err = f.Close()
	}(reopenedTmpFile)

	err = reopenedTmpFile.Sync()
	if err != nil {
		return fmt.Errorf("failed to sync file prior to rename: %s", err)
	}

	err = os.Rename(reopenedTmpFile.Name(), cryptfile)
	if err != nil {
		return fmt.Errorf("failed to rename to target file: %s", err)
	}

	return nil
}

func main() {
	app := cli.NewApp()
	app.Name = "saltybox"
	app.Version = "unknown (master)"
	app.Usage = "an encryption tool"
	app.HideVersion = true

	var passphraseStdinArg bool
	getPassphraseReader := func() preader.PassphraseReader {
		if passphraseStdinArg {
			return preader.NewReader(os.Stdin)
		}

		return preader.NewTerminal()
	}

	var inputArg string
	var outputArg string

	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:        "passphrase-stdin",
			Usage:       "Read passphrase from stdin instead of from terminal",
			Destination: &passphraseStdinArg,
		},
	}

	app.Commands = []cli.Command{
		{
			Name:    "encrypt",
			Aliases: []string{"e"},
			Usage:   "Encrypt a file",
			Description: `Encrypts the contents of a file (the "input", specified with -i) and writes the encrypted output
   to another file (the "output", specified with -o).

   If the output file does not exist, it will be created. If it does exist, it will be truncated and then written to.`,
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:        "input, i",
					Usage:       "Path to the file whose contents is to be encrypted",
					Required:    true,
					Destination: &inputArg,
				},
				cli.StringFlag{
					Name:        "output, o",
					Usage:       "Path to the file to write the encrypted text to",
					Required:    true,
					Destination: &outputArg,
				},
			},
			Action: func(c *cli.Context) error {
				return passphraseEncryptFile(inputArg, outputArg, getPassphraseReader())
			},
		},
		{
			Name:    "decrypt",
			Aliases: []string{"e"},
			Usage:   "Decrypt a file",
			Description: `Decrypts the contents of a file (the "input", specified with -i) and writes the plain text output
   to another file (the "output", specified with -o).

   If the output file does not exist, it will be created. If it does exist, it will be truncated and then written to.`,
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:        "input, i",
					Usage:       "Path to the file whose contents is to be decrypted",
					Required:    true,
					Destination: &inputArg,
				},
				cli.StringFlag{
					Name:        "output, o",
					Usage:       "Path to the file to write the unencrypted text to",
					Required:    true,
					Destination: &outputArg,
				},
			},
			Action: func(c *cli.Context) error {
				return passphraseDecryptFile(inputArg, outputArg, getPassphraseReader())
			},
		},
		{
			Name:    "update",
			Aliases: []string{"e"},
			Usage:   "Update an encrypted file with new content",
			Description: `Update an existing encrypted file (the "output", specified with -o) to contain the encrypted copy
   of the input (specified with -i).

   If the output file does not already exist, or if it does not appear to be a valid saltybox file, the operation will fail.

   If the passphrase provided by the user does unlock the existing file, the operation will fail. By using the update command,
   the user thereby avoids accidentally changing the passphrase as would be possible if using the encrypt command and separately
   replacing the target file.`,
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:        "input, i",
					Usage:       "Path to the file whose contents is to be encrypted",
					Required:    true,
					Destination: &inputArg,
				},
				cli.StringFlag{
					Name:        "output, o",
					Usage:       "Path to the existing saltybox file to replace with encrypted text",
					Required:    true,
					Destination: &outputArg,
				},
			},
			Action: func(c *cli.Context) error {
				return passphraseUpdateFile(inputArg, outputArg, getPassphraseReader())
			},
		},
	}

	app.Action = func(c *cli.Context) error {
		return errors.New("command is required; use help to see list of commands")
	}

	err := app.Run(os.Args)
	if err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>// Copyright 2019 The gVisor 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.

// These benchmarks emulate memfs benchmarks. Ext4 images must be created
// before this benchmark is run using the `make_deep_ext4.sh` script at
// /tmp/image-{depth}.ext4 for all the depths tested below.
package benchmark_test

import (
	"fmt"
	"os"
	"runtime"
	"strings"
	"testing"

	"gvisor.dev/gvisor/pkg/context"
	"gvisor.dev/gvisor/pkg/fspath"
	"gvisor.dev/gvisor/pkg/sentry/contexttest"
	"gvisor.dev/gvisor/pkg/sentry/fsimpl/ext"
	"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
	"gvisor.dev/gvisor/pkg/sentry/vfs"
)

var depths = []int{1, 2, 3, 8, 64, 100}

const filename = "file.txt"

// setUp opens imagePath as an ext Filesystem and returns all necessary
// elements required to run tests. If error is nil, it also returns a tear
// down function which must be called after the test is run for clean up.
func setUp(b *testing.B, imagePath string) (context.Context, *vfs.VirtualFilesystem, *vfs.VirtualDentry, func(), error) {
	f, err := os.Open(imagePath)
	if err != nil {
		return nil, nil, nil, nil, err
	}

	ctx := contexttest.Context(b)
	creds := auth.CredentialsFromContext(ctx)

	// Create VFS.
	vfsObj := vfs.New()
	vfsObj.MustRegisterFilesystemType("extfs", ext.FilesystemType{}, &vfs.RegisterFilesystemTypeOptions{
		AllowUserMount: true,
	})
	mntns, err := vfsObj.NewMountNamespace(ctx, creds, imagePath, "extfs", &vfs.GetFilesystemOptions{InternalData: int(f.Fd())})
	if err != nil {
		f.Close()
		return nil, nil, nil, nil, err
	}

	root := mntns.Root()

	tearDown := func() {
		root.DecRef()

		if err := f.Close(); err != nil {
			b.Fatalf("tearDown failed: %v", err)
		}
	}
	return ctx, vfsObj, &root, tearDown, nil
}

// mount mounts extfs at the path operation passed. Returns a tear down
// function which must be called after the test is run for clean up.
func mount(b *testing.B, imagePath string, vfsfs *vfs.VirtualFilesystem, pop *vfs.PathOperation) func() {
	b.Helper()

	f, err := os.Open(imagePath)
	if err != nil {
		b.Fatalf("could not open image at %s: %v", imagePath, err)
	}

	ctx := contexttest.Context(b)
	creds := auth.CredentialsFromContext(ctx)

	if err := vfsfs.MountAt(ctx, creds, imagePath, pop, "extfs", &vfs.MountOptions{
		GetFilesystemOptions: vfs.GetFilesystemOptions{
			InternalData: int(f.Fd()),
		},
	}); err != nil {
		b.Fatalf("failed to mount tmpfs submount: %v", err)
	}
	return func() {
		if err := f.Close(); err != nil {
			b.Fatalf("tearDown failed: %v", err)
		}
	}
}

// BenchmarkVFS2Ext4fsStat emulates BenchmarkVFS2MemfsStat.
func BenchmarkVFS2Ext4fsStat(b *testing.B) {
	for _, depth := range depths {
		b.Run(fmt.Sprintf("%d", depth), func(b *testing.B) {
			ctx, vfsfs, root, tearDown, err := setUp(b, fmt.Sprintf("/tmp/image-%d.ext4", depth))
			if err != nil {
				b.Fatalf("setUp failed: %v", err)
			}
			defer tearDown()

			creds := auth.CredentialsFromContext(ctx)
			var filePathBuilder strings.Builder
			filePathBuilder.WriteByte('/')
			for i := 1; i <= depth; i++ {
				filePathBuilder.WriteString(fmt.Sprintf("%d", i))
				filePathBuilder.WriteByte('/')
			}
			filePathBuilder.WriteString(filename)
			filePath := filePathBuilder.String()

			runtime.GC()
			b.ResetTimer()
			for i := 0; i < b.N; i++ {
				stat, err := vfsfs.StatAt(ctx, creds, &vfs.PathOperation{
					Root:               *root,
					Start:              *root,
					Path:               fspath.Parse(filePath),
					FollowFinalSymlink: true,
				}, &vfs.StatOptions{})
				if err != nil {
					b.Fatalf("stat(%q) failed: %v", filePath, err)
				}
				// Sanity check.
				if stat.Size > 0 {
					b.Fatalf("got wrong file size (%d)", stat.Size)
				}
			}
		})
	}
}

// BenchmarkVFS2ExtfsMountStat emulates BenchmarkVFS2MemfsMountStat.
func BenchmarkVFS2ExtfsMountStat(b *testing.B) {
	for _, depth := range depths {
		b.Run(fmt.Sprintf("%d", depth), func(b *testing.B) {
			// Create root extfs with depth 1 so we can mount extfs again at /1/.
			ctx, vfsfs, root, tearDown, err := setUp(b, fmt.Sprintf("/tmp/image-%d.ext4", 1))
			if err != nil {
				b.Fatalf("setUp failed: %v", err)
			}
			defer tearDown()

			creds := auth.CredentialsFromContext(ctx)
			mountPointName := "/1/"
			pop := vfs.PathOperation{
				Root:  *root,
				Start: *root,
				Path:  fspath.Parse(mountPointName),
			}

			// Save the mount point for later use.
			mountPoint, err := vfsfs.GetDentryAt(ctx, creds, &pop, &vfs.GetDentryOptions{})
			if err != nil {
				b.Fatalf("failed to walk to mount point: %v", err)
			}
			defer mountPoint.DecRef()

			// Create extfs submount.
			mountTearDown := mount(b, fmt.Sprintf("/tmp/image-%d.ext4", depth), vfsfs, &pop)
			defer mountTearDown()

			var filePathBuilder strings.Builder
			filePathBuilder.WriteString(mountPointName)
			for i := 1; i <= depth; i++ {
				filePathBuilder.WriteString(fmt.Sprintf("%d", i))
				filePathBuilder.WriteByte('/')
			}
			filePathBuilder.WriteString(filename)
			filePath := filePathBuilder.String()

			runtime.GC()
			b.ResetTimer()
			for i := 0; i < b.N; i++ {
				stat, err := vfsfs.StatAt(ctx, creds, &vfs.PathOperation{
					Root:               *root,
					Start:              *root,
					Path:               fspath.Parse(filePath),
					FollowFinalSymlink: true,
				}, &vfs.StatOptions{})
				if err != nil {
					b.Fatalf("stat(%q) failed: %v", filePath, err)
				}
				// Sanity check. touch(1) always creates files of size 0 (empty).
				if stat.Size > 0 {
					b.Fatalf("got wrong file size (%d)", stat.Size)
				}
			}
		})
	}
}
<commit_msg>Add contextual comment.<commit_after>// Copyright 2019 The gVisor 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.

// These benchmarks emulate memfs benchmarks. Ext4 images must be created
// before this benchmark is run using the `make_deep_ext4.sh` script at
// /tmp/image-{depth}.ext4 for all the depths tested below.
//
// The benchmark itself cannot run the script because the script requires
// sudo privileges to create the file system images.
package benchmark_test

import (
	"fmt"
	"os"
	"runtime"
	"strings"
	"testing"

	"gvisor.dev/gvisor/pkg/context"
	"gvisor.dev/gvisor/pkg/fspath"
	"gvisor.dev/gvisor/pkg/sentry/contexttest"
	"gvisor.dev/gvisor/pkg/sentry/fsimpl/ext"
	"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
	"gvisor.dev/gvisor/pkg/sentry/vfs"
)

var depths = []int{1, 2, 3, 8, 64, 100}

const filename = "file.txt"

// setUp opens imagePath as an ext Filesystem and returns all necessary
// elements required to run tests. If error is nil, it also returns a tear
// down function which must be called after the test is run for clean up.
func setUp(b *testing.B, imagePath string) (context.Context, *vfs.VirtualFilesystem, *vfs.VirtualDentry, func(), error) {
	f, err := os.Open(imagePath)
	if err != nil {
		return nil, nil, nil, nil, err
	}

	ctx := contexttest.Context(b)
	creds := auth.CredentialsFromContext(ctx)

	// Create VFS.
	vfsObj := vfs.New()
	vfsObj.MustRegisterFilesystemType("extfs", ext.FilesystemType{}, &vfs.RegisterFilesystemTypeOptions{
		AllowUserMount: true,
	})
	mntns, err := vfsObj.NewMountNamespace(ctx, creds, imagePath, "extfs", &vfs.GetFilesystemOptions{InternalData: int(f.Fd())})
	if err != nil {
		f.Close()
		return nil, nil, nil, nil, err
	}

	root := mntns.Root()

	tearDown := func() {
		root.DecRef()

		if err := f.Close(); err != nil {
			b.Fatalf("tearDown failed: %v", err)
		}
	}
	return ctx, vfsObj, &root, tearDown, nil
}

// mount mounts extfs at the path operation passed. Returns a tear down
// function which must be called after the test is run for clean up.
func mount(b *testing.B, imagePath string, vfsfs *vfs.VirtualFilesystem, pop *vfs.PathOperation) func() {
	b.Helper()

	f, err := os.Open(imagePath)
	if err != nil {
		b.Fatalf("could not open image at %s: %v", imagePath, err)
	}

	ctx := contexttest.Context(b)
	creds := auth.CredentialsFromContext(ctx)

	if err := vfsfs.MountAt(ctx, creds, imagePath, pop, "extfs", &vfs.MountOptions{
		GetFilesystemOptions: vfs.GetFilesystemOptions{
			InternalData: int(f.Fd()),
		},
	}); err != nil {
		b.Fatalf("failed to mount tmpfs submount: %v", err)
	}
	return func() {
		if err := f.Close(); err != nil {
			b.Fatalf("tearDown failed: %v", err)
		}
	}
}

// BenchmarkVFS2Ext4fsStat emulates BenchmarkVFS2MemfsStat.
func BenchmarkVFS2Ext4fsStat(b *testing.B) {
	for _, depth := range depths {
		b.Run(fmt.Sprintf("%d", depth), func(b *testing.B) {
			ctx, vfsfs, root, tearDown, err := setUp(b, fmt.Sprintf("/tmp/image-%d.ext4", depth))
			if err != nil {
				b.Fatalf("setUp failed: %v", err)
			}
			defer tearDown()

			creds := auth.CredentialsFromContext(ctx)
			var filePathBuilder strings.Builder
			filePathBuilder.WriteByte('/')
			for i := 1; i <= depth; i++ {
				filePathBuilder.WriteString(fmt.Sprintf("%d", i))
				filePathBuilder.WriteByte('/')
			}
			filePathBuilder.WriteString(filename)
			filePath := filePathBuilder.String()

			runtime.GC()
			b.ResetTimer()
			for i := 0; i < b.N; i++ {
				stat, err := vfsfs.StatAt(ctx, creds, &vfs.PathOperation{
					Root:               *root,
					Start:              *root,
					Path:               fspath.Parse(filePath),
					FollowFinalSymlink: true,
				}, &vfs.StatOptions{})
				if err != nil {
					b.Fatalf("stat(%q) failed: %v", filePath, err)
				}
				// Sanity check.
				if stat.Size > 0 {
					b.Fatalf("got wrong file size (%d)", stat.Size)
				}
			}
		})
	}
}

// BenchmarkVFS2ExtfsMountStat emulates BenchmarkVFS2MemfsMountStat.
func BenchmarkVFS2ExtfsMountStat(b *testing.B) {
	for _, depth := range depths {
		b.Run(fmt.Sprintf("%d", depth), func(b *testing.B) {
			// Create root extfs with depth 1 so we can mount extfs again at /1/.
			ctx, vfsfs, root, tearDown, err := setUp(b, fmt.Sprintf("/tmp/image-%d.ext4", 1))
			if err != nil {
				b.Fatalf("setUp failed: %v", err)
			}
			defer tearDown()

			creds := auth.CredentialsFromContext(ctx)
			mountPointName := "/1/"
			pop := vfs.PathOperation{
				Root:  *root,
				Start: *root,
				Path:  fspath.Parse(mountPointName),
			}

			// Save the mount point for later use.
			mountPoint, err := vfsfs.GetDentryAt(ctx, creds, &pop, &vfs.GetDentryOptions{})
			if err != nil {
				b.Fatalf("failed to walk to mount point: %v", err)
			}
			defer mountPoint.DecRef()

			// Create extfs submount.
			mountTearDown := mount(b, fmt.Sprintf("/tmp/image-%d.ext4", depth), vfsfs, &pop)
			defer mountTearDown()

			var filePathBuilder strings.Builder
			filePathBuilder.WriteString(mountPointName)
			for i := 1; i <= depth; i++ {
				filePathBuilder.WriteString(fmt.Sprintf("%d", i))
				filePathBuilder.WriteByte('/')
			}
			filePathBuilder.WriteString(filename)
			filePath := filePathBuilder.String()

			runtime.GC()
			b.ResetTimer()
			for i := 0; i < b.N; i++ {
				stat, err := vfsfs.StatAt(ctx, creds, &vfs.PathOperation{
					Root:               *root,
					Start:              *root,
					Path:               fspath.Parse(filePath),
					FollowFinalSymlink: true,
				}, &vfs.StatOptions{})
				if err != nil {
					b.Fatalf("stat(%q) failed: %v", filePath, err)
				}
				// Sanity check. touch(1) always creates files of size 0 (empty).
				if stat.Size > 0 {
					b.Fatalf("got wrong file size (%d)", stat.Size)
				}
			}
		})
	}
}
<|endoftext|>


<commit_before>// mountcli is a little package for interacting with the local "mount" command
package mountcli

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

// An OS specific mount tag that we're filtering by.
const defaultFuseTag = "osxfusefs"

type Mount struct {
	// The name of the binary we'll be running and parsing. Should almost always
	// be "mount"
	binName string

	// the following vars exist primarily for mocking ability, and ensuring
	// an enclosed environment within the struct.

	// A func to run the given binary and return the output as a string
	binRunner func(string) (string, error)
}

// NewMount creates a new Mount instance.
func NewMount() *Mount {
	return &Mount{
		binName:   "mount",
		binRunner: binRunner,
	}
}

// FindMountedPathByName returns the systems mounted path for the given name.
func (m *Mount) FindMountedPathByName(name string) (string, error) {
	out, err := m.binRunner(m.binName)
	if err != nil {
		return "", err
	}

	prefix := fmt.Sprintf("%s on ", name)
	lines := strings.Split(out, "\n")
	for _, line := range lines {
		if !strings.HasPrefix(line, prefix) {
			continue
		}

		line = line[len(prefix):]
		index := strings.LastIndex(line, fmt.Sprintf(" ("))
		if index == -1 {
			continue
		}

		return line[:index], nil
	}

	return "", nil
}

func binRunner(bin string) (string, error) {
	cmd := exec.Command(bin, "-t", defaultFuseTag)

	out, err := cmd.CombinedOutput()
	if err != nil {
		return "", err
	}

	return string(out), nil
}
<commit_msg>klientctl: Added Darwin build tag<commit_after>// +build darwin
// mountcli is a little package for interacting with the local "mount" command
package mountcli

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

// An OS specific mount tag that we're filtering by.
const defaultFuseTag = "osxfusefs"

type Mount struct {
	// The name of the binary we'll be running and parsing. Should almost always
	// be "mount"
	binName string

	// the following vars exist primarily for mocking ability, and ensuring
	// an enclosed environment within the struct.

	// A func to run the given binary and return the output as a string
	binRunner func(string) (string, error)
}

// NewMount creates a new Mount instance.
func NewMount() *Mount {
	return &Mount{
		binName:   "mount",
		binRunner: binRunner,
	}
}

// FindMountedPathByName returns the systems mounted path for the given name.
func (m *Mount) FindMountedPathByName(name string) (string, error) {
	out, err := m.binRunner(m.binName)
	if err != nil {
		return "", err
	}

	prefix := fmt.Sprintf("%s on ", name)
	lines := strings.Split(out, "\n")
	for _, line := range lines {
		if !strings.HasPrefix(line, prefix) {
			continue
		}

		line = line[len(prefix):]
		index := strings.LastIndex(line, fmt.Sprintf(" ("))
		if index == -1 {
			continue
		}

		return line[:index], nil
	}

	return "", nil
}

func binRunner(bin string) (string, error) {
	cmd := exec.Command(bin, "-t", defaultFuseTag)

	out, err := cmd.CombinedOutput()
	if err != nil {
		return "", err
	}

	return string(out), nil
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"net/http"
	"os"
	"sort"

	"github.com/codegangsta/martini"
	"github.com/codegangsta/martini-contrib/render"
	"github.com/jingweno/travisarchive/filestore"
	"github.com/joho/godotenv"
)

type ByTime []filestore.File

func (t ByTime) Len() int           { return len(t) }
func (t ByTime) Swap(i, j int)      { t[i], t[j] = t[j], t[i] }
func (t ByTime) Less(i, j int) bool { return t[i].Time.Before(t[j].Time) }

func init() {
	godotenv.Load("../.env")
}

func main() {
	fs, err := filestore.New("s3")
	if err != nil {
		log.Fatal(err)
	}

	port := os.Getenv("PORT")
	m := martini.Classic()
	m.Map(fs)
	m.Use(martini.Static("../web/public"))
	m.Use(render.Renderer(render.Options{
		Directory: "../web/templates",
		Layout:    "layout",
	}))
	m.Get("/", func(fs *filestore.S3, r render.Render) {
		files, err := fs.List("builds")
		sort.Sort(ByTime(files))
		if err != nil {
			log.Fatal(err)
		}

		r.HTML(200, "home", files)
	})

	log.Printf("starting server at %s", port)
	err = http.ListenAndServe(":"+port, m)
	if err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Reverse the sorting<commit_after>package main

import (
	"log"
	"net/http"
	"os"
	"sort"

	"github.com/codegangsta/martini"
	"github.com/codegangsta/martini-contrib/render"
	"github.com/jingweno/travisarchive/filestore"
	"github.com/joho/godotenv"
)

type ByTime []filestore.File

func (t ByTime) Len() int           { return len(t) }
func (t ByTime) Swap(i, j int)      { t[i], t[j] = t[j], t[i] }
func (t ByTime) Less(i, j int) bool { return t[i].Time.After(t[j].Time) }

func init() {
	godotenv.Load("../.env")
}

func main() {
	fs, err := filestore.New("s3")
	if err != nil {
		log.Fatal(err)
	}

	port := os.Getenv("PORT")
	m := martini.Classic()
	m.Map(fs)
	m.Use(martini.Static("../web/public"))
	m.Use(render.Renderer(render.Options{
		Directory: "../web/templates",
		Layout:    "layout",
	}))
	m.Get("/", func(fs *filestore.S3, r render.Render) {
		files, err := fs.List("builds")
		sort.Sort(ByTime(files))
		if err != nil {
			log.Fatal(err)
		}

		r.HTML(200, "home", files)
	})

	log.Printf("starting server at %s", port)
	err = http.ListenAndServe(":"+port, m)
	if err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>