<commit_before>// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of Cilium

package labelsfilter

import (
	"encoding/json"
	"fmt"
	"os"
	"regexp"
	"strings"

	k8sConst "github.com/cilium/cilium/pkg/k8s/apis/cilium.io"
	"github.com/cilium/cilium/pkg/labels"
	"github.com/cilium/cilium/pkg/lock"
	"github.com/cilium/cilium/pkg/logging"
	"github.com/cilium/cilium/pkg/logging/logfields"
)

var (
	log                  = logging.DefaultLogger.WithField(logfields.LogSubsys, "labels-filter")
	validLabelPrefixesMU lock.RWMutex
	validLabelPrefixes   *labelPrefixCfg // Label prefixes used to filter from all labels
)

const (
	// LPCfgFileVersion represents the version of a Label Prefix Configuration File
	LPCfgFileVersion = 1

	// reservedLabelsPattern is the prefix pattern for all reserved labels
	reservedLabelsPattern = labels.LabelSourceReserved + ":.*"
)

// LabelPrefix is the cilium's representation of a container label.
// +k8s:deepcopy-gen=false
// +k8s:openapi-gen=false
// +deepequal-gen=false
type LabelPrefix struct {
	// Ignore if true will cause this prefix to be ignored insted of being accepted
	Ignore bool   `json:"invert"`
	Prefix string `json:"prefix"`
	Source string `json:"source"`
	expr   *regexp.Regexp
}

// String returns a human readable representation of the LabelPrefix
func (p LabelPrefix) String() string {
	s := fmt.Sprintf("%s:%s", p.Source, p.Prefix)
	if p.Ignore {
		s = "!" + s
	}

	return s
}

// matches returns true and the length of the matched section if the label is
// matched by the LabelPrefix. The Ignore flag has no effect at this point.
func (p LabelPrefix) matches(l labels.Label) (bool, int) {
	if p.Source != "" && p.Source != l.Source {
		return false, 0
	}

	// If no regular expression is available, fall back to prefix matching
	if p.expr == nil {
		return strings.HasPrefix(l.Key, p.Prefix), len(p.Prefix)
	}

	res := p.expr.FindStringIndex(l.Key)

	// No match if regexp was not found
	if res == nil {
		return false, 0
	}

	// Otherwise match if match was found at start of key
	return res[0] == 0, res[1]
}

// parseLabelPrefix returns a LabelPrefix created from the string label parameter.
func parseLabelPrefix(label string) (*LabelPrefix, error) {
	labelPrefix := LabelPrefix{}
	i := strings.IndexByte(label, ':')
	if i >= 0 {
		labelPrefix.Source = label[:i]
		labelPrefix.Prefix = label[i+1:]
	} else {
		labelPrefix.Prefix = label
	}

	if labelPrefix.Prefix[0] == '!' {
		labelPrefix.Ignore = true
		labelPrefix.Prefix = labelPrefix.Prefix[1:]
	}

	r, err := regexp.Compile(labelPrefix.Prefix)
	if err != nil {
		return nil, fmt.Errorf("unable to compile regexp: %s", err)
	}
	labelPrefix.expr = r

	return &labelPrefix, nil
}

// ParseLabelPrefixCfg parses valid label prefixes from a file and from a slice
// of valid prefixes. Both are optional. If both are provided, both list are
// appended together.
func ParseLabelPrefixCfg(prefixes []string, file string) error {
	var cfg *labelPrefixCfg
	var err error
	var fromCustomFile bool

	// Use default label prefix if configuration file not provided
	if file == "" {
		log.Info("Parsing base label prefixes from default label list")
		cfg = defaultLabelPrefixCfg()
	} else {
		log.Infof("Parsing base label prefixes from file %s", file)
		cfg, err = readLabelPrefixCfgFrom(file)
		if err != nil {
			return fmt.Errorf("unable to read label prefix file: %s", err)
		}

		fromCustomFile = true
	}

	log.Infof("Parsing additional label prefixes from user inputs: %v", prefixes)
	for _, label := range prefixes {
		p, err := parseLabelPrefix(label)
		if err != nil {
			return err
		}

		if !p.Ignore {
			cfg.whitelist = true
		}

		cfg.LabelPrefixes = append(cfg.LabelPrefixes, p)
	}

	if fromCustomFile {
		found := false
		for _, label := range cfg.LabelPrefixes {
			if label.Source+":"+label.Prefix == reservedLabelsPattern {
				found = true
				break
			}
		}

		if !found {
			log.Errorf("'%s' needs to be included in the final label list for "+
				"Cilium to work properly.", reservedLabelsPattern)
		}
	}

	validLabelPrefixes = cfg

	log.Info("Final label prefixes to be used for identity evaluation:")
	for _, l := range validLabelPrefixes.LabelPrefixes {
		log.Infof(" - %s", l)
	}

	return nil
}

// labelPrefixCfg is the label prefix configuration to filter labels of started
// containers.
// +k8s:openapi-gen=false
type labelPrefixCfg struct {
	Version       int            `json:"version"`
	LabelPrefixes []*LabelPrefix `json:"valid-prefixes"`
	// whitelist if true, indicates that an inclusive rule has to match
	// in order for the label to be considered
	whitelist bool
}

// defaultLabelPrefixCfg returns a default LabelPrefixCfg using the latest
// LPCfgFileVersion
func defaultLabelPrefixCfg() *labelPrefixCfg {
	cfg := &labelPrefixCfg{
		Version:       LPCfgFileVersion,
		LabelPrefixes: []*LabelPrefix{},
	}

	expressions := []string{
		reservedLabelsPattern,                             // include all reserved labels
		regexp.QuoteMeta(k8sConst.PodNamespaceLabel),      // include io.kubernetes.pod.namespace
		regexp.QuoteMeta(k8sConst.PodNamespaceMetaLabels), // include all namespace labels
		regexp.QuoteMeta(k8sConst.AppKubernetes),          // include app.kubernetes.io
		`!io\.kubernetes`,                                 // ignore all other io.kubernetes labels
		`!kubernetes\.io`,                                 // ignore all other kubernetes.io labels
		`!.*beta\.kubernetes\.io`,                         // ignore all beta.kubernetes.io labels
		`!k8s\.io`,                                        // ignore all k8s.io labels
		`!pod-template-generation`,                        // ignore pod-template-generation
		`!pod-template-hash`,                              // ignore pod-template-hash
		`!controller-revision-hash`,                       // ignore controller-revision-hash
		`!annotation.*`,                                   // ignore all annotation labels
		`!etcd_node`,                                      // ignore etcd_node label
	}

	for _, e := range expressions {
		p, err := parseLabelPrefix(e)
		if err != nil {
			msg := fmt.Sprintf("BUG: Unable to parse default label prefix '%s': %s", e, err)
			panic(msg)
		}
		cfg.LabelPrefixes = append(cfg.LabelPrefixes, p)
	}

	return cfg
}

// readLabelPrefixCfgFrom reads a label prefix configuration file from fileName.
// return an error if fileName is empty, or if version is not supported.
func readLabelPrefixCfgFrom(fileName string) (*labelPrefixCfg, error) {
	if fileName == "" {
		return nil, fmt.Errorf("label prefix file not provided")
	}

	f, err := os.Open(fileName)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	lpc := labelPrefixCfg{}
	err = json.NewDecoder(f).Decode(&lpc)
	if err != nil {
		return nil, err
	}
	if lpc.Version != LPCfgFileVersion {
		return nil, fmt.Errorf("unsupported version %d", lpc.Version)
	}
	for _, lp := range lpc.LabelPrefixes {
		if lp.Prefix == "" {
			return nil, fmt.Errorf("invalid label prefix file: prefix was empty")
		}
		if lp.Source == "" {
			return nil, fmt.Errorf("invalid label prefix file: source was empty")
		}
		if !lp.Ignore {
			lpc.whitelist = true
		}
	}
	return &lpc, nil
}

func (cfg *labelPrefixCfg) filterLabels(lbls labels.Labels) (identityLabels, informationLabels labels.Labels) {
	if len(lbls) == 0 {
		return nil, nil
	}

	validLabelPrefixesMU.RLock()
	defer validLabelPrefixesMU.RUnlock()

	identityLabels = labels.Labels{}
	informationLabels = labels.Labels{}
	for k, v := range lbls {
		included, ignored := 0, 0

		for _, p := range cfg.LabelPrefixes {
			if m, len := p.matches(v); m {
				if p.Ignore {
					// save length of shortest matching ignore
					if ignored == 0 || len < ignored {
						ignored = len
					}
				} else {
					// save length of longest matching include
					if len > included {
						included = len
					}
				}
			}
		}

		// A label is accepted if :
		// - No inclusive LabelPrefix (Ignore flag not set) is
		//   configured and label is not ignored.
		// - An inclusive LabelPrefix matches the label
		// - If both an inclusive and ignore LabelPrefix match, the
		//   label is accepted if the matching section in the label
		//   is greater than the ignored matching section in label,
		//   e.g. when evaluating the label foo.bar, the prefix rules
		//   {!foo, foo.bar} will cause the label to be accepted
		//   because the inclusive prefix matches over a longer section.
		if (!cfg.whitelist && ignored == 0) || included > ignored {
			// Just want to make sure we don't have labels deleted in
			// on side and disappearing in the other side...
			identityLabels[k] = v
		} else {
			informationLabels[k] = v
		}
	}
	return identityLabels, informationLabels
}

// Filter returns Labels from the given labels that have the same source and the
// same prefix as one of lpc valid prefixes, as well as labels that do not match
// the aforementioned filtering criteria.
func Filter(lbls labels.Labels) (identityLabels, informationLabels labels.Labels) {
	return validLabelPrefixes.filterLabels(lbls)
}
<commit_msg>labelsfilter: Improve sanitization<commit_after>// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of Cilium

package labelsfilter

import (
	"encoding/json"
	"fmt"
	"os"
	"regexp"
	"strings"

	k8sConst "github.com/cilium/cilium/pkg/k8s/apis/cilium.io"
	"github.com/cilium/cilium/pkg/labels"
	"github.com/cilium/cilium/pkg/lock"
	"github.com/cilium/cilium/pkg/logging"
	"github.com/cilium/cilium/pkg/logging/logfields"
)

var (
	log                  = logging.DefaultLogger.WithField(logfields.LogSubsys, "labels-filter")
	validLabelPrefixesMU lock.RWMutex
	validLabelPrefixes   *labelPrefixCfg // Label prefixes used to filter from all labels
)

const (
	// LPCfgFileVersion represents the version of a Label Prefix Configuration File
	LPCfgFileVersion = 1

	// reservedLabelsPattern is the prefix pattern for all reserved labels
	reservedLabelsPattern = labels.LabelSourceReserved + ":.*"
)

// LabelPrefix is the cilium's representation of a container label.
// +k8s:deepcopy-gen=false
// +k8s:openapi-gen=false
// +deepequal-gen=false
type LabelPrefix struct {
	// Ignore if true will cause this prefix to be ignored insted of being accepted
	Ignore bool   `json:"invert"`
	Prefix string `json:"prefix"`
	Source string `json:"source"`
	expr   *regexp.Regexp
}

// String returns a human readable representation of the LabelPrefix
func (p LabelPrefix) String() string {
	s := fmt.Sprintf("%s:%s", p.Source, p.Prefix)
	if p.Ignore {
		s = "!" + s
	}

	return s
}

// matches returns true and the length of the matched section if the label is
// matched by the LabelPrefix. The Ignore flag has no effect at this point.
func (p LabelPrefix) matches(l labels.Label) (bool, int) {
	if p.Source != "" && p.Source != l.Source {
		return false, 0
	}

	// If no regular expression is available, fall back to prefix matching
	if p.expr == nil {
		return strings.HasPrefix(l.Key, p.Prefix), len(p.Prefix)
	}

	res := p.expr.FindStringIndex(l.Key)

	// No match if regexp was not found
	if res == nil {
		return false, 0
	}

	// Otherwise match if match was found at start of key
	return res[0] == 0, res[1]
}

// parseLabelPrefix returns a LabelPrefix created from the string label parameter.
func parseLabelPrefix(label string) (*LabelPrefix, error) {
	labelPrefix := LabelPrefix{}
	i := strings.IndexByte(label, ':')
	if i >= 0 {
		labelPrefix.Source = label[:i]
		labelPrefix.Prefix = label[i+1:]
	} else {
		labelPrefix.Prefix = label
	}

	if len(labelPrefix.Prefix) == 0 {
		return nil, fmt.Errorf("invalid label source %q, prefix %q",
			labelPrefix.Source, labelPrefix.Prefix)
	}
	if labelPrefix.Prefix[0] == '!' {
		labelPrefix.Ignore = true
		labelPrefix.Prefix = labelPrefix.Prefix[1:]
	}

	r, err := regexp.Compile(labelPrefix.Prefix)
	if err != nil {
		return nil, fmt.Errorf("unable to compile regexp: %s", err)
	}
	labelPrefix.expr = r

	return &labelPrefix, nil
}

// ParseLabelPrefixCfg parses valid label prefixes from a file and from a slice
// of valid prefixes. Both are optional. If both are provided, both list are
// appended together.
func ParseLabelPrefixCfg(prefixes []string, file string) error {
	var cfg *labelPrefixCfg
	var err error
	var fromCustomFile bool

	// Use default label prefix if configuration file not provided
	if file == "" {
		log.Info("Parsing base label prefixes from default label list")
		cfg = defaultLabelPrefixCfg()
	} else {
		log.Infof("Parsing base label prefixes from file %s", file)
		cfg, err = readLabelPrefixCfgFrom(file)
		if err != nil {
			return fmt.Errorf("unable to read label prefix file: %s", err)
		}

		fromCustomFile = true
	}

	log.Infof("Parsing additional label prefixes from user inputs: %v", prefixes)
	for _, label := range prefixes {
		if len(label) == 0 {
			continue
		}
		p, err := parseLabelPrefix(label)
		if err != nil {
			return err
		}

		if !p.Ignore {
			cfg.whitelist = true
		}

		cfg.LabelPrefixes = append(cfg.LabelPrefixes, p)
	}

	if fromCustomFile {
		found := false
		for _, label := range cfg.LabelPrefixes {
			if label.Source+":"+label.Prefix == reservedLabelsPattern {
				found = true
				break
			}
		}

		if !found {
			log.Errorf("'%s' needs to be included in the final label list for "+
				"Cilium to work properly.", reservedLabelsPattern)
		}
	}

	validLabelPrefixes = cfg

	log.Info("Final label prefixes to be used for identity evaluation:")
	for _, l := range validLabelPrefixes.LabelPrefixes {
		log.Infof(" - %s", l)
	}

	return nil
}

// labelPrefixCfg is the label prefix configuration to filter labels of started
// containers.
// +k8s:openapi-gen=false
type labelPrefixCfg struct {
	Version       int            `json:"version"`
	LabelPrefixes []*LabelPrefix `json:"valid-prefixes"`
	// whitelist if true, indicates that an inclusive rule has to match
	// in order for the label to be considered
	whitelist bool
}

// defaultLabelPrefixCfg returns a default LabelPrefixCfg using the latest
// LPCfgFileVersion
func defaultLabelPrefixCfg() *labelPrefixCfg {
	cfg := &labelPrefixCfg{
		Version:       LPCfgFileVersion,
		LabelPrefixes: []*LabelPrefix{},
	}

	expressions := []string{
		reservedLabelsPattern,                             // include all reserved labels
		regexp.QuoteMeta(k8sConst.PodNamespaceLabel),      // include io.kubernetes.pod.namespace
		regexp.QuoteMeta(k8sConst.PodNamespaceMetaLabels), // include all namespace labels
		regexp.QuoteMeta(k8sConst.AppKubernetes),          // include app.kubernetes.io
		`!io\.kubernetes`,                                 // ignore all other io.kubernetes labels
		`!kubernetes\.io`,                                 // ignore all other kubernetes.io labels
		`!.*beta\.kubernetes\.io`,                         // ignore all beta.kubernetes.io labels
		`!k8s\.io`,                                        // ignore all k8s.io labels
		`!pod-template-generation`,                        // ignore pod-template-generation
		`!pod-template-hash`,                              // ignore pod-template-hash
		`!controller-revision-hash`,                       // ignore controller-revision-hash
		`!annotation.*`,                                   // ignore all annotation labels
		`!etcd_node`,                                      // ignore etcd_node label
	}

	for _, e := range expressions {
		p, err := parseLabelPrefix(e)
		if err != nil {
			msg := fmt.Sprintf("BUG: Unable to parse default label prefix '%s': %s", e, err)
			panic(msg)
		}
		cfg.LabelPrefixes = append(cfg.LabelPrefixes, p)
	}

	return cfg
}

// readLabelPrefixCfgFrom reads a label prefix configuration file from fileName.
// return an error if fileName is empty, or if version is not supported.
func readLabelPrefixCfgFrom(fileName string) (*labelPrefixCfg, error) {
	if fileName == "" {
		return nil, fmt.Errorf("label prefix file not provided")
	}

	f, err := os.Open(fileName)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	lpc := labelPrefixCfg{}
	err = json.NewDecoder(f).Decode(&lpc)
	if err != nil {
		return nil, err
	}
	if lpc.Version != LPCfgFileVersion {
		return nil, fmt.Errorf("unsupported version %d", lpc.Version)
	}
	for _, lp := range lpc.LabelPrefixes {
		if lp.Prefix == "" {
			return nil, fmt.Errorf("invalid label prefix file: prefix was empty")
		}
		if lp.Source == "" {
			return nil, fmt.Errorf("invalid label prefix file: source was empty")
		}
		if !lp.Ignore {
			lpc.whitelist = true
		}
	}
	return &lpc, nil
}

func (cfg *labelPrefixCfg) filterLabels(lbls labels.Labels) (identityLabels, informationLabels labels.Labels) {
	if len(lbls) == 0 {
		return nil, nil
	}

	validLabelPrefixesMU.RLock()
	defer validLabelPrefixesMU.RUnlock()

	identityLabels = labels.Labels{}
	informationLabels = labels.Labels{}
	for k, v := range lbls {
		included, ignored := 0, 0

		for _, p := range cfg.LabelPrefixes {
			if m, len := p.matches(v); m {
				if p.Ignore {
					// save length of shortest matching ignore
					if ignored == 0 || len < ignored {
						ignored = len
					}
				} else {
					// save length of longest matching include
					if len > included {
						included = len
					}
				}
			}
		}

		// A label is accepted if :
		// - No inclusive LabelPrefix (Ignore flag not set) is
		//   configured and label is not ignored.
		// - An inclusive LabelPrefix matches the label
		// - If both an inclusive and ignore LabelPrefix match, the
		//   label is accepted if the matching section in the label
		//   is greater than the ignored matching section in label,
		//   e.g. when evaluating the label foo.bar, the prefix rules
		//   {!foo, foo.bar} will cause the label to be accepted
		//   because the inclusive prefix matches over a longer section.
		if (!cfg.whitelist && ignored == 0) || included > ignored {
			// Just want to make sure we don't have labels deleted in
			// on side and disappearing in the other side...
			identityLabels[k] = v
		} else {
			informationLabels[k] = v
		}
	}
	return identityLabels, informationLabels
}

// Filter returns Labels from the given labels that have the same source and the
// same prefix as one of lpc valid prefixes, as well as labels that do not match
// the aforementioned filtering criteria.
func Filter(lbls labels.Labels) (identityLabels, informationLabels labels.Labels) {
	return validLabelPrefixes.filterLabels(lbls)
}
<|endoftext|>


<commit_before>package server

import (
	"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"

	"github.com/openshift/origin/pkg/api/v1beta1"
	"github.com/openshift/origin/pkg/oauth/registry/accesstoken"
	"github.com/openshift/origin/pkg/oauth/registry/authorizetoken"
	"github.com/openshift/origin/pkg/oauth/registry/client"
	"github.com/openshift/origin/pkg/oauth/registry/clientauthorization"
	"github.com/openshift/origin/pkg/oauth/registry/etcd"
)

type Server struct {
	storage map[string]apiserver.RESTStorage
}

func NewServer(helper tools.EtcdHelper) *Server {
	registry := etcd.New(helper)
	s := &Server{
		storage: map[string]apiserver.RESTStorage{
			"accessTokens":         accesstoken.NewREST(registry),
			"authorizeTokens":      authorizetoken.NewREST(registry),
			"clients":              client.NewREST(registry),
			"clientAuthorizations": clientauthorization.NewREST(registry),
		},
	}
	return s
}

// API_v1beta1 returns the resources and codec for API version v1beta1.
func (s *Server) API_v1beta1() (map[string]apiserver.RESTStorage, runtime.Codec) {
	storage := make(map[string]apiserver.RESTStorage)
	for k, v := range s.storage {
		storage[k] = v
	}
	return storage, v1beta1.Codec
}
<commit_msg>Removing underscore from method name<commit_after>package server

import (
	"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"

	"github.com/openshift/origin/pkg/api/v1beta1"
	"github.com/openshift/origin/pkg/oauth/registry/accesstoken"
	"github.com/openshift/origin/pkg/oauth/registry/authorizetoken"
	"github.com/openshift/origin/pkg/oauth/registry/client"
	"github.com/openshift/origin/pkg/oauth/registry/clientauthorization"
	"github.com/openshift/origin/pkg/oauth/registry/etcd"
)

type Server struct {
	storage map[string]apiserver.RESTStorage
}

func NewServer(helper tools.EtcdHelper) *Server {
	registry := etcd.New(helper)
	s := &Server{
		storage: map[string]apiserver.RESTStorage{
			"accessTokens":         accesstoken.NewREST(registry),
			"authorizeTokens":      authorizetoken.NewREST(registry),
			"clients":              client.NewREST(registry),
			"clientAuthorizations": clientauthorization.NewREST(registry),
		},
	}
	return s
}

// APIV1beta1 returns the resources and codec for API version v1beta1.
func (s *Server) APIV1beta1() (map[string]apiserver.RESTStorage, runtime.Codec) {
	storage := make(map[string]apiserver.RESTStorage)
	for k, v := range s.storage {
		storage[k] = v
	}
	return storage, v1beta1.Codec
}
<|endoftext|>


<commit_before>/*
Copyright 2017 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 server

import (
	"fmt"
	"os"

	"github.com/containerd/containerd"
	"github.com/containerd/containerd/errdefs"
	"github.com/cri-o/ocicni"
	"github.com/golang/glog"
	"golang.org/x/net/context"
	"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
)

// StopPodSandbox stops the sandbox. If there are any running containers in the
// sandbox, they should be forcibly terminated.
func (c *criContainerdService) StopPodSandbox(ctx context.Context, r *runtime.StopPodSandboxRequest) (*runtime.StopPodSandboxResponse, error) {
	sandbox, err := c.sandboxStore.Get(r.GetPodSandboxId())
	if err != nil {
		return nil, fmt.Errorf("an error occurred when try to find sandbox %q: %v",
			r.GetPodSandboxId(), err)
	}
	// Use the full sandbox id.
	id := sandbox.ID

	// Stop all containers inside the sandbox. This terminates the container forcibly,
	// and container may still be so production should not rely on this behavior.
	// TODO(random-liu): Delete the sandbox container before this after permanent network namespace
	// is introduced, so that no container will be started after that.
	containers := c.containerStore.List()
	for _, container := range containers {
		if container.SandboxID != id {
			continue
		}
		// Forcibly stop the container. Do not use `StopContainer`, because it introduces a race
		// if a container is removed after list.
		if err = c.stopContainer(ctx, container, 0); err != nil {
			return nil, fmt.Errorf("failed to stop container %q: %v", container.ID, err)
		}
	}

	// Teardown network for sandbox.
	if sandbox.NetNSPath != "" {
		if _, err := os.Stat(sandbox.NetNSPath); err != nil {
			return nil, fmt.Errorf("failed to stat network namespace path %s :%v", sandbox.NetNSPath, err)
		}
		if teardownErr := c.netPlugin.TearDownPod(ocicni.PodNetwork{
			Name:         sandbox.Config.GetMetadata().GetName(),
			Namespace:    sandbox.Config.GetMetadata().GetNamespace(),
			ID:           id,
			NetNS:        sandbox.NetNSPath,
			PortMappings: toCNIPortMappings(sandbox.Config.GetPortMappings()),
		}); teardownErr != nil {
			return nil, fmt.Errorf("failed to destroy network for sandbox %q: %v", id, teardownErr)
		}
		/*TODO:It is still possible that cri-containerd crashes after we teardown the network, but before we remove the network namespace.
		In that case, we'll not be able to remove the sandbox anymore. The chance is slim, but we should be aware of that.
		In the future, once TearDownPod is idempotent, this will be fixed.*/

		//Close the sandbox network namespace if it was created
		if err = sandbox.NetNS.Remove(); err != nil {
			return nil, fmt.Errorf("failed to remove network namespace for sandbox %q:  %v", id, err)
		}
	}

	glog.V(2).Infof("TearDown network for sandbox %q successfully", id)

	sandboxRoot := getSandboxRootDir(c.rootDir, id)
	if err := c.unmountSandboxFiles(sandboxRoot, sandbox.Config); err != nil {
		return nil, fmt.Errorf("failed to unmount sandbox files in %q: %v", sandboxRoot, err)
	}

	if err := c.stopSandboxContainer(ctx, sandbox.Container); err != nil {
		return nil, fmt.Errorf("failed to stop sandbox container %q: %v", id, err)
	}
	return &runtime.StopPodSandboxResponse{}, nil
}

// stopSandboxContainer kills and deletes sandbox container.
func (c *criContainerdService) stopSandboxContainer(ctx context.Context, container containerd.Container) error {
	task, err := container.Task(ctx, nil)
	if err != nil {
		if errdefs.IsNotFound(err) {
			return nil
		}
		return fmt.Errorf("failed to get sandbox container: %v", err)
	}

	// Delete the sandbox container from containerd.
	_, err = task.Delete(ctx, containerd.WithProcessKill)
	if err != nil && !errdefs.IsNotFound(err) {
		return fmt.Errorf("failed to delete sandbox container: %v", err)
	}

	return nil
}
<commit_msg>Do not teardown when network namespace is removed already.<commit_after>/*
Copyright 2017 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 server

import (
	"fmt"
	"os"

	"github.com/containerd/containerd"
	"github.com/containerd/containerd/errdefs"
	"github.com/cri-o/ocicni"
	"github.com/golang/glog"
	"golang.org/x/net/context"
	"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
)

// StopPodSandbox stops the sandbox. If there are any running containers in the
// sandbox, they should be forcibly terminated.
func (c *criContainerdService) StopPodSandbox(ctx context.Context, r *runtime.StopPodSandboxRequest) (*runtime.StopPodSandboxResponse, error) {
	sandbox, err := c.sandboxStore.Get(r.GetPodSandboxId())
	if err != nil {
		return nil, fmt.Errorf("an error occurred when try to find sandbox %q: %v",
			r.GetPodSandboxId(), err)
	}
	// Use the full sandbox id.
	id := sandbox.ID

	// Stop all containers inside the sandbox. This terminates the container forcibly,
	// and container may still be so production should not rely on this behavior.
	// TODO(random-liu): Delete the sandbox container before this after permanent network namespace
	// is introduced, so that no container will be started after that.
	containers := c.containerStore.List()
	for _, container := range containers {
		if container.SandboxID != id {
			continue
		}
		// Forcibly stop the container. Do not use `StopContainer`, because it introduces a race
		// if a container is removed after list.
		if err = c.stopContainer(ctx, container, 0); err != nil {
			return nil, fmt.Errorf("failed to stop container %q: %v", container.ID, err)
		}
	}

	// Teardown network for sandbox.
	if sandbox.NetNSPath != "" {
		if _, err := os.Stat(sandbox.NetNSPath); err != nil {
			if !os.IsNotExist(err) {
				return nil, fmt.Errorf("failed to stat network namespace path %s :%v", sandbox.NetNSPath, err)
			}
		} else {
			if teardownErr := c.netPlugin.TearDownPod(ocicni.PodNetwork{
				Name:         sandbox.Config.GetMetadata().GetName(),
				Namespace:    sandbox.Config.GetMetadata().GetNamespace(),
				ID:           id,
				NetNS:        sandbox.NetNSPath,
				PortMappings: toCNIPortMappings(sandbox.Config.GetPortMappings()),
			}); teardownErr != nil {
				return nil, fmt.Errorf("failed to destroy network for sandbox %q: %v", id, teardownErr)
			}
		}
		/*TODO:It is still possible that cri-containerd crashes after we teardown the network, but before we remove the network namespace.
		In that case, we'll not be able to remove the sandbox anymore. The chance is slim, but we should be aware of that.
		In the future, once TearDownPod is idempotent, this will be fixed.*/

		//Close the sandbox network namespace if it was created
		if err = sandbox.NetNS.Remove(); err != nil {
			return nil, fmt.Errorf("failed to remove network namespace for sandbox %q:  %v", id, err)
		}
	}

	glog.V(2).Infof("TearDown network for sandbox %q successfully", id)

	sandboxRoot := getSandboxRootDir(c.rootDir, id)
	if err := c.unmountSandboxFiles(sandboxRoot, sandbox.Config); err != nil {
		return nil, fmt.Errorf("failed to unmount sandbox files in %q: %v", sandboxRoot, err)
	}

	if err := c.stopSandboxContainer(ctx, sandbox.Container); err != nil {
		return nil, fmt.Errorf("failed to stop sandbox container %q: %v", id, err)
	}
	return &runtime.StopPodSandboxResponse{}, nil
}

// stopSandboxContainer kills and deletes sandbox container.
func (c *criContainerdService) stopSandboxContainer(ctx context.Context, container containerd.Container) error {
	task, err := container.Task(ctx, nil)
	if err != nil {
		if errdefs.IsNotFound(err) {
			return nil
		}
		return fmt.Errorf("failed to get sandbox container: %v", err)
	}

	// Delete the sandbox container from containerd.
	_, err = task.Delete(ctx, containerd.WithProcessKill)
	if err != nil && !errdefs.IsNotFound(err) {
		return fmt.Errorf("failed to delete sandbox container: %v", err)
	}

	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2014 The Kubernetes Authors All rights reserved.

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 exec

import (
	"fmt"
)

// A simple scripted Interface type.
type FakeExec struct {
	CommandScript []FakeCommandAction
	CommandCalls  int
	LookPathFunc  func(string) (string, error)
}

type FakeCommandAction func(cmd string, args ...string) Cmd

func (fake *FakeExec) Command(cmd string, args ...string) Cmd {
	if fake.CommandCalls > len(fake.CommandScript)-1 {
		panic("ran out of Command() actions")
	}
	i := fake.CommandCalls
	fake.CommandCalls++
	return fake.CommandScript[i](cmd, args...)
}

func (fake *FakeExec) LookPath(file string) (string, error) {
	return fake.LookPathFunc(file)
}

// A simple scripted Cmd type.
type FakeCmd struct {
	Argv                 []string
	CombinedOutputScript []FakeCombinedOutputAction
	CombinedOutputCalls  int
	CombinedOutputLog    [][]string
	Dirs                 []string
}

func InitFakeCmd(fake *FakeCmd, cmd string, args ...string) Cmd {
	fake.Argv = append([]string{cmd}, args...)
	return fake
}

type FakeCombinedOutputAction func() ([]byte, error)

func (fake *FakeCmd) SetDir(dir string) {
	fake.Dirs = append(fake.Dirs, dir)
}

func (fake *FakeCmd) CombinedOutput() ([]byte, error) {
	if fake.CombinedOutputCalls > len(fake.CombinedOutputScript)-1 {
		panic("ran out of CombinedOutput() actions")
	}
	if fake.CombinedOutputLog == nil {
		fake.CombinedOutputLog = [][]string{}
	}
	i := fake.CombinedOutputCalls
	fake.CombinedOutputLog = append(fake.CombinedOutputLog, append([]string{}, fake.Argv...))
	fake.CombinedOutputCalls++
	return fake.CombinedOutputScript[i]()
}

// A simple fake ExitError type.
type FakeExitError struct {
	Status int
}

func (fake *FakeExitError) String() string {
	return fmt.Sprintf("exit %d", fake.Status)
}

func (fake *FakeExitError) Error() string {
	return fake.String()
}

func (fake *FakeExitError) Exited() bool {
	return true
}

func (fake *FakeExitError) ExitStatus() int {
	return fake.Status
}
<commit_msg>Print unhandeled command in FakeExec<commit_after>/*
Copyright 2014 The Kubernetes Authors All rights reserved.

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 exec

import (
	"fmt"
)

// A simple scripted Interface type.
type FakeExec struct {
	CommandScript []FakeCommandAction
	CommandCalls  int
	LookPathFunc  func(string) (string, error)
}

type FakeCommandAction func(cmd string, args ...string) Cmd

func (fake *FakeExec) Command(cmd string, args ...string) Cmd {
	if fake.CommandCalls > len(fake.CommandScript)-1 {
		panic(fmt.Sprintf("ran out of Command() actions. Could not handle command [%d]: %s args: %v", fake.CommandCalls, cmd, args))
	}
	i := fake.CommandCalls
	fake.CommandCalls++
	return fake.CommandScript[i](cmd, args...)
}

func (fake *FakeExec) LookPath(file string) (string, error) {
	return fake.LookPathFunc(file)
}

// A simple scripted Cmd type.
type FakeCmd struct {
	Argv                 []string
	CombinedOutputScript []FakeCombinedOutputAction
	CombinedOutputCalls  int
	CombinedOutputLog    [][]string
	Dirs                 []string
}

func InitFakeCmd(fake *FakeCmd, cmd string, args ...string) Cmd {
	fake.Argv = append([]string{cmd}, args...)
	return fake
}

type FakeCombinedOutputAction func() ([]byte, error)

func (fake *FakeCmd) SetDir(dir string) {
	fake.Dirs = append(fake.Dirs, dir)
}

func (fake *FakeCmd) CombinedOutput() ([]byte, error) {
	if fake.CombinedOutputCalls > len(fake.CombinedOutputScript)-1 {
		panic("ran out of CombinedOutput() actions")
	}
	if fake.CombinedOutputLog == nil {
		fake.CombinedOutputLog = [][]string{}
	}
	i := fake.CombinedOutputCalls
	fake.CombinedOutputLog = append(fake.CombinedOutputLog, append([]string{}, fake.Argv...))
	fake.CombinedOutputCalls++
	return fake.CombinedOutputScript[i]()
}

// A simple fake ExitError type.
type FakeExitError struct {
	Status int
}

func (fake *FakeExitError) String() string {
	return fmt.Sprintf("exit %d", fake.Status)
}

func (fake *FakeExitError) Error() string {
	return fake.String()
}

func (fake *FakeExitError) Exited() bool {
	return true
}

func (fake *FakeExitError) ExitStatus() int {
	return fake.Status
}
<|endoftext|>


<commit_before>package main

import (
    "flag"
    "fmt"
    "bufio"
    "os"
    "strings"
    "io"
    "net/http"
    "net/url"
    "bytes"
    "log"
    "runtime/pprof"
)

var post = flag.String("post", "", "Address to make a POST request to. Data will be in the body")
var get = flag.String("get", "", `Address to make a GET request to.
     Address should be a format string where data can be subbed in`)
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
var numPublishers = flag.Int("n", 5, "Number of concurrent publishers")

type Publisher interface {
    Publish(string) error
}

type PublisherInfo struct {
    addr string
}

// ---------- Post -------------------------

type PostPublisher struct {
    PublisherInfo
}

func (p *PostPublisher) Publish(msg string) error {
    var buffer bytes.Buffer
    buffer.Write([]byte(msg))
    resp, err := http.Post(p.addr, "application/octet-stream", &buffer)
    defer resp.Body.Close()
    defer buffer.Reset()
    return err
}

// ----------- Get ---------------------------

type GetPublisher struct {
    PublisherInfo
}

func (p *GetPublisher) Publish(msg string) error {
    endpoint := fmt.Sprintf(p.addr, url.QueryEscape(msg))
    resp, err := http.Get(endpoint)
    defer resp.Body.Close()
    return err
}

// ---------- Main Logic ----------------------

func PublishLoop(pub Publisher, publishMsgs chan string, exitChan chan bool) {
    exit := false
    for {
        var msg string
        select {
        case msg = <-publishMsgs:
        // log.Println("Publishing message: ", msg)

        err := pub.Publish(msg)
        if err != nil {
            log.Println("ERROR publishing: ", err)
            exit = true
        }
        case <- exitChan:
            exit = true
        }
        if exit {
            break
        }
    }
}

func main() {
    flag.Parse()
    if *cpuprofile != "" {
        f, err := os.Create(*cpuprofile)
        if err != nil {
            log.Fatal(err)
        }
        pprof.StartCPUProfile(f)
        defer pprof.StopCPUProfile()
    }
    var publisher Publisher
    if len(*post) > 0 {
        publisher = &PostPublisher{PublisherInfo{*post}}
    }else if len(*get) > 0 {
        if strings.Count(*get, "%s") != 1{
            log.Fatal("Invalid get address - must be a format string")
        }
        publisher = &GetPublisher{PublisherInfo{*get}}
    } else {
        log.Fatal("Need get or post address!")
    }

    msgsChan := make(chan string, *numPublishers)
    publishExitChan := make(chan bool)
    for i := 0; i < *numPublishers; i++ {
        go PublishLoop(publisher, msgsChan, publishExitChan)
    }
    reader := bufio.NewReader(os.Stdin)
    for {
        line, err := reader.ReadString('\n')
        if err != nil {
            if err != io.EOF {
                log.Println(fmt.Sprintf("ERROR: %s", err))
            }
            break
        }
        line = strings.TrimSpace(line)
        msgsChan <- line
    }
    for i := 0; i < *numPublishers; i++ {
        publishExitChan <- true
    }
}
<commit_msg>fix concurrency / termination logic<commit_after>package main

import (
    "flag"
    "fmt"
    "bufio"
    "os"
    "strings"
    "io"
    "net/http"
    "net/url"
    "bytes"
    "log"
    "runtime/pprof"
)

var post = flag.String("post", "", "Address to make a POST request to. Data will be in the body")
var get = flag.String("get", "", `Address to make a GET request to.
     Address should be a format string where data can be subbed in`)
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
var numPublishers = flag.Int("n", 5, "Number of concurrent publishers")

type Publisher interface {
    Publish(string) error
}

type PublisherInfo struct {
    addr string
}

// ---------- Post -------------------------

type PostPublisher struct {
    PublisherInfo
}

func (p *PostPublisher) Publish(msg string) error {
    var buffer bytes.Buffer
    buffer.Write([]byte(msg))
    resp, err := http.Post(p.addr, "application/octet-stream", &buffer)
    defer resp.Body.Close()
    defer buffer.Reset()
    return err
}

// ----------- Get ---------------------------

type GetPublisher struct {
    PublisherInfo
}

func (p *GetPublisher) Publish(msg string) error {
    endpoint := fmt.Sprintf(p.addr, url.QueryEscape(msg))
    resp, err := http.Get(endpoint)
    defer resp.Body.Close()
    return err
}

// ---------- Main Logic ----------------------

func PublishLoop(done chan struct{}, pub Publisher, publishMsgs chan string) {
    for msg := range publishMsgs {
        err := pub.Publish(msg)
        if err != nil {
            log.Println("ERROR publishing: ", err)
            break
        }
    }
    done <- struct{}{}
}

func main() {
    flag.Parse()
    if *cpuprofile != "" {
        f, err := os.Create(*cpuprofile)
        if err != nil {
            log.Fatal(err)
        }
        pprof.StartCPUProfile(f)
        defer pprof.StopCPUProfile()
    }
    var publisher Publisher
    if len(*post) > 0 {
        publisher = &PostPublisher{PublisherInfo{*post}}
    }else if len(*get) > 0 {
        if strings.Count(*get, "%s") != 1{
            log.Fatal("Invalid get address - must be a format string")
        }
        publisher = &GetPublisher{PublisherInfo{*get}}
    } else {
        log.Fatal("Need get or post address!")
    }

    msgsChan := make(chan string)
    publishExitChan := make(chan struct{})
    for i := 0; i < *numPublishers; i++ {
        go PublishLoop(publishExitChan, publisher, msgsChan)
    }
    reader := bufio.NewReader(os.Stdin)
    for {
        line, err := reader.ReadString('\n')
        if err != nil {
            if err != io.EOF {
                log.Println(fmt.Sprintf("ERROR: %s", err))
            }
            break
        }
        line = strings.TrimSpace(line)
        msgsChan <- line
    }
    close(msgsChan)
    for i := 0; i < *numPublishers; i++ {
        <-publishExitChan
    }
    close(publishExitChan)
}
<|endoftext|>


<commit_before>// SPDX-License-Identifier: MIT

package utils

import (
	"io/ioutil"
	"path/filepath"
	"testing"

	"github.com/issue9/assert"
)

func TestFileExists(t *testing.T) {
	a := assert.New(t)

	// 测试文件
	a.True(FileExists("utils.go"))
	a.False(FileExists("unknown.go"))

	// 测试文件夹
	a.True(FileExists("./"))
	a.False(FileExists("./unknown_dir/"))
}

func TestDumpGoFile(t *testing.T) {
	a := assert.New(t)

	a.NotError(DumpGoFile("./testdata/go.go", "var x=1"))
	content, err := ioutil.ReadFile("./testdata/go.go")
	a.NotError(err)
	a.Equal(string(content), "var x = 1")
}

func TestCurrentPath(t *testing.T) {
	a := assert.New(t)

	dir, err := filepath.Abs("./file.go")
	a.NotError(err).NotEmpty(dir)

	d, err := filepath.Abs(CurrentPath("./file.go"))
	a.NotError(err).NotEmpty(d)

	a.Equal(d, dir)
}

func TestCurrentDir(t *testing.T) {
	a := assert.New(t)

	dir, err := filepath.Abs("./")
	a.NotError(err).NotEmpty(dir)

	a.Equal(CurrentDir(), dir)
}

func TestCurrentFile(t *testing.T) {
	a := assert.New(t)

	filename, err := filepath.Abs("./file_test.go")
	a.NotError(err).NotEmpty(filename)

	a.Equal(CurrentFile(), filepath.FromSlash(filename))
}

func TestCurrentFunction(t *testing.T) {
	a := assert.New(t)

	a.Equal(CurrentFunction(), "TestCurrentFunction")
}

func TestCurrentLine(t *testing.T) {
	a := assert.New(t)

	a.Equal(CurrentLine(), 73)
}
<commit_msg>test: 修正 windows 下测试错误<commit_after>// SPDX-License-Identifier: MIT

package utils

import (
	"io/ioutil"
	"path/filepath"
	"testing"

	"github.com/issue9/assert"
)

func TestFileExists(t *testing.T) {
	a := assert.New(t)

	// 测试文件
	a.True(FileExists("utils.go"))
	a.False(FileExists("unknown.go"))

	// 测试文件夹
	a.True(FileExists("./"))
	a.False(FileExists("./unknown_dir/"))
}

func TestDumpGoFile(t *testing.T) {
	a := assert.New(t)

	a.NotError(DumpGoFile("./testdata/go.go", "var x=1"))
	content, err := ioutil.ReadFile("./testdata/go.go")
	a.NotError(err)
	a.Equal(string(content), "var x = 1")
}

func TestCurrentPath(t *testing.T) {
	a := assert.New(t)

	dir, err := filepath.Abs("./file.go")
	a.NotError(err).NotEmpty(dir)

	d, err := filepath.Abs(CurrentPath("./file.go"))
	a.NotError(err).NotEmpty(d)

	a.Equal(d, dir)
}

func TestCurrentDir(t *testing.T) {
	a := assert.New(t)

	dir, err := filepath.Abs("./")
	a.NotError(err).NotEmpty(dir)

	a.Equal(CurrentDir(), dir)
}

func TestCurrentFile(t *testing.T) {
	a := assert.New(t)

	filename, err := filepath.Abs("./file_test.go")
	a.NotError(err).NotEmpty(filename)

	a.Equal(CurrentFile(), filepath.ToSlash(filename))
}

func TestCurrentFunction(t *testing.T) {
	a := assert.New(t)

	a.Equal(CurrentFunction(), "TestCurrentFunction")
}

func TestCurrentLine(t *testing.T) {
	a := assert.New(t)

	a.Equal(CurrentLine(), 73)
}
<|endoftext|>


<commit_before>package ccserialize

import (
	"reflect"
	"strconv"
	"strings"
)

func Serialize(input interface{}) string {
	switch reflect.ValueOf(input).Kind() {
	case reflect.Int:
		return strconv.Itoa(input.(int))
	case reflect.Int64:
		return strconv.FormatInt(input.(int64), 10)
	case reflect.Float64:
		return strconv.FormatFloat(input.(float64), 'f', 6, 64)
	case reflect.String:
		return "\"" + strings.Replace(input.(string), "\"", "\\\"", -1) + "\""
	case reflect.Map:
		t := reflect.TypeOf(input)
		v := reflect.ValueOf(input)
		it := reflect.TypeOf((*interface{})(nil)).Elem()
		m := reflect.MakeMap(reflect.MapOf(t.Key(), it))

		for _, mk := range v.MapKeys() {
			m.SetMapIndex(mk, v.MapIndex(mk))
		}

		return mapSerialize(m.Interface().(map[string]interface{}))
	case reflect.Slice:
		s := reflect.ValueOf(input)
		ret := make([]interface{}, s.Len())

		for i := 0; i < s.Len(); i++ {
			ret[i] = s.Index(i).Interface()
		}

		return arraySerialize(ret)
	case reflect.Struct:
		return structSerialize(input)
	default:
		panic("Attempt to serialize unsupported type.")
	}
}

func structSerialize(input interface{}) string {
	serializedString := "{"

	intStr := reflect.ValueOf(input)
	str := reflect.TypeOf(input)
	for i := 0; i < str.NumField(); i++ {
		f := intStr.Field(i)
		keyName := str.Field(i).Name
		if str.Field(i).Tag.Get("ccserialize") != "" {
			keyName = str.Field(i).Tag.Get("ccserialize")
		}

		serializedString = serializedString + "[\"" + strings.ToLower(keyName) + "\"]="
		serializedString = serializedString + Serialize(f.Interface()) + ","
	}

	return serializedString + "}"
}

func arraySerialize(input []interface{}) string {
	serializedString := "{"
	for k, v := range input {
		serializedString = serializedString + "[" + strconv.Itoa(k+1) + "]=" + Serialize(v) + ","
	}
	return serializedString + "}"
}

func mapSerialize(input map[string]interface{}) string {
	serializedString := "{"
	for k, v := range input {
		serializedString = serializedString + "[\"" + k + "\"]=" + Serialize(v) + ","
	}
	return serializedString + "}"
}
<commit_msg>Add support for more types of integers<commit_after>package ccserialize

import (
	"reflect"
	"strconv"
	"strings"
)

func Serialize(input interface{}) string {
	switch reflect.ValueOf(input).Kind() {
	case reflect.Int:
		return strconv.Itoa(input.(int))
	case reflect.Uint8:
		return Serialize(int(input.(uint8)))
	case reflect.Int8:
		return Serialize(int(input.(int8)))
	case reflect.Uint16:
		return Serialize(int(input.(uint16)))
	case reflect.Int16:
		return Serialize(int(input.(int16)))
	case reflect.Uint32:
		return Serialize(int64(input.(uint32)))
	case reflect.Int32:
		return Serialize(int(input.(int32)))
	case reflect.Int64:
		return strconv.FormatInt(input.(int64), 10)
	case reflect.Float64:
		return strconv.FormatFloat(input.(float64), 'f', 6, 64)
	case reflect.String:
		return "\"" + strings.Replace(input.(string), "\"", "\\\"", -1) + "\""
	case reflect.Map:
		t := reflect.TypeOf(input)
		v := reflect.ValueOf(input)
		it := reflect.TypeOf((*interface{})(nil)).Elem()
		m := reflect.MakeMap(reflect.MapOf(t.Key(), it))

		for _, mk := range v.MapKeys() {
			m.SetMapIndex(mk, v.MapIndex(mk))
		}

		return mapSerialize(m.Interface().(map[string]interface{}))
	case reflect.Slice:
		s := reflect.ValueOf(input)
		ret := make([]interface{}, s.Len())

		for i := 0; i < s.Len(); i++ {
			ret[i] = s.Index(i).Interface()
		}

		return arraySerialize(ret)
	case reflect.Struct:
		return structSerialize(input)
	default:
		panic("Attempt to serialize unsupported type.")
	}
}

func structSerialize(input interface{}) string {
	serializedString := "{"

	intStr := reflect.ValueOf(input)
	str := reflect.TypeOf(input)
	for i := 0; i < str.NumField(); i++ {
		f := intStr.Field(i)
		keyName := str.Field(i).Name
		if str.Field(i).Tag.Get("ccserialize") != "" {
			keyName = str.Field(i).Tag.Get("ccserialize")
		}

		serializedString = serializedString + "[\"" + strings.ToLower(keyName) + "\"]="
		serializedString = serializedString + Serialize(f.Interface()) + ","
	}

	return serializedString + "}"
}

func arraySerialize(input []interface{}) string {
	serializedString := "{"
	for k, v := range input {
		serializedString = serializedString + "[" + strconv.Itoa(k+1) + "]=" + Serialize(v) + ","
	}
	return serializedString + "}"
}

func mapSerialize(input map[string]interface{}) string {
	serializedString := "{"
	for k, v := range input {
		serializedString = serializedString + "[\"" + k + "\"]=" + Serialize(v) + ","
	}
	return serializedString + "}"
}
<|endoftext|>


<commit_before>package vault

import (
	"io/ioutil"
	"math/rand"
	"os"
	"testing"
	"time"
)

var (
	TEST_DIR = os.Getenv("GOPATH") + "/src/github.com/ieee0824/thor/test"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

func randStringRunes(n int) string {
	b := make([]rune, n)
	for i := range b {
		b[i] = letterRunes[rand.Intn(len(letterRunes))]
	}
	return string(b)
}

func TestIsSecret(t *testing.T) {
	plainTextPath := TEST_DIR + "/vaultTestFiles/plain.json"
	chipherTextPath := TEST_DIR + "/vaultTestFiles/chipher.json"

	plain, err := ioutil.ReadFile(plainTextPath)
	if err != nil {
		t.Error(err)
	} else if IsSecret(plain) {
		t.Errorf("The result is illegal. I want %v, but it is actually %v.", false, IsSecret(plain))
	}

	chipher, err := ioutil.ReadFile(chipherTextPath)
	if err != nil {
		t.Error(err)
	} else if !IsSecret(chipher) {
		t.Errorf("The result is illegal. I want %v, but it is actually %v.", true, IsSecret(chipher))
	}
}

func TestEncryption(t *testing.T) {
	var randomStr = randStringRunes(65536)
	var key = "test"
	var invalidKey = "johnDoe"

	encrypter := NewString(randomStr)

	if err := encrypter.Encrypt(key); err != nil {
		t.Error(err)
	} else if string(encrypter.Chipher) == randomStr {
		t.Errorf("cipher text and plain text is match")
	}

	if result, err := encrypter.Decrypt(key); err != nil {
		t.Error(err)
	} else if string(result) != randomStr {
		t.Errorf("cipher text and plain text is not match")
	}

	if _, err := encrypter.Decrypt(invalidKey); err == nil {
		t.Errorf("There is no error with an invalid key.")
	}

}
<commit_msg>改ざん検出できるか<commit_after>package vault

import (
	"io/ioutil"
	"math/rand"
	"os"
	"testing"
	"time"
)

var (
	TEST_DIR = os.Getenv("GOPATH") + "/src/github.com/ieee0824/thor/test"
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

func randStringRunes(n int) string {
	b := make([]rune, n)
	for i := range b {
		b[i] = letterRunes[rand.Intn(len(letterRunes))]
	}
	return string(b)
}

func TestIsSecret(t *testing.T) {
	plainTextPath := TEST_DIR + "/vaultTestFiles/plain.json"
	chipherTextPath := TEST_DIR + "/vaultTestFiles/chipher.json"

	plain, err := ioutil.ReadFile(plainTextPath)
	if err != nil {
		t.Error(err)
	} else if IsSecret(plain) {
		t.Errorf("The result is illegal. I want %v, but it is actually %v.", false, IsSecret(plain))
	}

	chipher, err := ioutil.ReadFile(chipherTextPath)
	if err != nil {
		t.Error(err)
	} else if !IsSecret(chipher) {
		t.Errorf("The result is illegal. I want %v, but it is actually %v.", true, IsSecret(chipher))
	}
}

func falsification(d []byte) []byte {

	for i, v := range d {
		if i%2 == 0 {
			d[i] <<= rand.Intn(8)
		} else {
			d[i] >>= rand.Intn(8)
		}
	}
	return d
}

func TestEncryption(t *testing.T) {
	var randomStr = randStringRunes(65536)
	var key = "test"
	var invalidKey = "johnDoe"

	encrypter := NewString(randomStr)

	if err := encrypter.Encrypt(key); err != nil {
		t.Error(err)
	} else if string(encrypter.Chipher) == randomStr {
		t.Errorf("cipher text and plain text is match")
	}

	if result, err := encrypter.Decrypt(key); err != nil {
		t.Error(err)
	} else if string(result) != randomStr {
		t.Errorf("cipher text and plain text is not match")
	}

	if _, err := encrypter.Decrypt(invalidKey); err == nil {
		t.Errorf("There is no error with an invalid key.")
	}
	encrypter.Chipher = falsification(encrypter.Chipher)
	if _, err := encrypter.Decrypt(invalidKey); err == nil {
		t.Errorf("There is no error with an invalid key.")
	}

}
<|endoftext|>


<commit_before>package queue

import (
	"code.google.com/p/go-uuid/uuid"

	"encoding/json"
	"fmt"
	"io"
	"os"
	"path"
)

// Metadata for the message body.
type bodyMetadata struct {
	RefCount int
}

// Message body. It is preserved on disk as long as one or more messages
// reference it. Once no more messages reference the body, it is removed.
type Body struct {
	directory string
	id        string
	m         bodyMetadata
}

// Determine the name of the file where the message body is stored.
func (b *Body) messageBodyFilename() string {
	return path.Join(b.directory, b.id)
}

// Determine the name of the file where metadata is stored.
func (b *Body) metadataFilename() string {
	return fmt.Sprint("%s.json", b.messageBodyFilename())
}

// Update the metadata on disk.
func (b *Body) updateMetadata() error {
	f, err := os.OpenFile(b.metadataFilename(), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		return err
	}
	return json.NewEncoder(f).Encode(&b.m)
}

// Create a new message body from the specified reader.
func NewBody(directory string) *Body {
	return &Body{
		directory: directory,
		id:        uuid.New(),
	}
}

// Attempt to load the specified message body.
func LoadBody(directory, id string) (*Body, error) {
	b := &Body{
		directory: directory,
		id:        id,
	}
	if f, err := os.Open(b.metadataFilename()); err == nil {
		if err = json.NewDecoder(f).Decode(&b.m); err != nil {
			return nil, err
		}
	} else {
		return nil, err
	}
	return b, nil
}

// Increase the reference count for the body.
func (b *Body) Add() error {
	b.m.RefCount++
	return b.updateMetadata()
}

// Decrease the reference count for the body.
func (b *Body) Release() error {
	b.m.RefCount--
	if b.m.RefCount == 0 {
		if err := os.Remove(b.metadataFilename()); err != nil {
			return err
		}
		return os.Remove(b.messageBodyFilename())
	} else {
		return b.updateMetadata()
	}
}

// Obtain an io.Reader for the message body.
func (b *Body) Reader() (io.Reader, error) {
	return os.Open(b.messageBodyFilename())
}

// Obtain an io.Writer for the message body.
func (b *Body) Writer() (io.Writer, error) {
	return os.OpenFile(b.messageBodyFilename(), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
}
<commit_msg>NewBody() now returns an io.WriteCloser.<commit_after>package queue

import (
	"encoding/json"
	"fmt"
	"io"
	"os"
	"path"
)

// Metadata for the message body.
type bodyMetadata struct {
	RefCount int
}

// Message body. It is preserved on disk as long as one or more messages
// reference it. Once no more messages reference the body, it is removed.
type Body struct {
	directory string
	id        string
	m         bodyMetadata
}

// Determine the name of the file where the message body is stored.
func (b *Body) messageBodyFilename() string {
	return path.Join(b.directory, b.id)
}

// Determine the name of the file where metadata is stored.
func (b *Body) metadataFilename() string {
	return fmt.Sprintf("%s.json", b.messageBodyFilename())
}

// Update the metadata on disk.
func (b *Body) updateMetadata() error {
	f, err := os.OpenFile(b.metadataFilename(), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		return err
	}
	return json.NewEncoder(f).Encode(&b.m)
}

// Create a new message body from the specified reader.
func NewBody(directory, id string) (*Body, io.WriteCloser, error) {
	b := &Body{
		id:        id,
		directory: directory,
	}
	if f, err := os.OpenFile(b.messageBodyFilename(), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600); err != nil {
		return nil, nil, err
	} else {
		return b, f, nil
	}
}

// Attempt to load the specified message body.
func LoadBody(directory, id string) (*Body, error) {
	b := &Body{
		directory: directory,
		id:        id,
	}
	if f, err := os.Open(b.metadataFilename()); err == nil {
		if err = json.NewDecoder(f).Decode(&b.m); err != nil {
			return nil, err
		}
	} else {
		return nil, err
	}
	return b, nil
}

// Increase the reference count for the body.
func (b *Body) Add() error {
	b.m.RefCount++
	return b.updateMetadata()
}

// Decrease the reference count for the body.
func (b *Body) Release() error {
	b.m.RefCount--
	if b.m.RefCount == 0 {
		if err := os.Remove(b.metadataFilename()); err != nil {
			return err
		}
		return os.Remove(b.messageBodyFilename())
	} else {
		return b.updateMetadata()
	}
}

// Obtain an io.Reader for the message body.
func (b *Body) Reader() (io.Reader, error) {
	return os.Open(b.messageBodyFilename())
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"math"
	"sync"

	piazza "github.com/venicegeo/pz-gocommon/gocommon"
	"github.com/venicegeo/pz-workflow/workflow"
)

var client *workflow.Client

const pageSize = 1000

type GetNumObjectsF func() (int, error)
type DeletePageOfObjectsF func(int, int) error

func main() {
	var err error

	client, err = makeClient()
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("*** ALERTS ***")
	err = deleteAllObjects(client.GetNumAlerts, deletePageOfAlerts)
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("*** TRIGGERS ***")
	err = deleteAllObjects(client.GetNumTriggers, deletePageOfTriggers)
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("*** EVENTS ***")
	err = deleteAllEvents(client.GetNumEvents, deletePageOfEvents)
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("*** EVENT TYPES ***")
	err = deleteAllEventTypes(client.GetNumEventTypes, deletePageOfEventTypes)
	if err != nil {
		log.Fatal(err)
	}
}

func deleteAllObjects(getNumObjectsF GetNumObjectsF, deletePageOfObjectsF DeletePageOfObjectsF) error {
	for {
		count, err := getNumObjectsF()
		if err != nil {
			return err
		}
		log.Printf("Num objects: %d", count)
		if count < pageSize {
			break
		}

		// let's keep a few around, just for kicks
		count -= pageSize

		numThreads := int(math.Ceil(float64(count / pageSize)))

		var wg sync.WaitGroup
		wg.Add(numThreads)

		for id := 0; id < numThreads; id++ {
			go func(id int) {
				defer wg.Done()
				_ = deletePageOfObjectsF(pageSize, id)
			}(id)
		}

		wg.Wait()
	}

	return nil
}

func makeClient() (*workflow.Client, error) {
	apiServer, err := piazza.GetApiServer()
	if err != nil {
		return nil, err
	}

	apiKey, err := piazza.GetApiKey(apiServer)
	if err != nil {
		return nil, err
	}

	url := "https://" + apiServer
	url = "https://pz-workflow.int.geointservices.io"

	log.Printf("Url: %s", url)
	log.Printf("Key: %s", apiKey)

	client, err := workflow.NewClient2(url, apiKey)
	if err != nil {
		return nil, err
	}

	return client, nil
}

func deletePageOfAlerts(perPage int, page int) error {
	id := page

	alerts, err := client.GetAllAlerts(perPage, page)
	if err != nil {
		return err
	}

	tot := len(*alerts)
	//log.Printf("Got %d alerts", tot)
	if tot != perPage {
		return nil
	}

	for i, alert := range *alerts {
		if i > 0 && i%100 == 0 {
			log.Printf("[%d] Deleted %d alerts", id, i)
		}

		err = client.DeleteAlert(alert.AlertID)
		if err != nil {
			// ignore err cases for now
			//log.Printf("error %#v", err)
		}
	}
	log.Printf("[%d] Deleted all %d alerts", id, tot)

	return nil
}

func deletePageOfEvents(perPage int, page int) error {
	id := page

	events, err := client.GetAllEvents(perPage, page)
	if err != nil {
		return err
	}

	tot := len(*events)
	//log.Printf("Got %d events", tot)
	if tot != perPage {
		return nil
	}

	for i, event := range *events {
		if i > 0 && i%100 == 0 {
			log.Printf("[%d] Deleted %d events", id, i)
		}

		err = client.DeleteEvent(event.EventID)
		if err != nil {
			// ignore err cases for now
			//log.Printf("error %#v", err)
		}
	}
	log.Printf("[%d] Deleted all %d events", id, tot)

	return nil
}

func deletePageOfEventTypes(perPage int, page int) error {
	id := page

	eventtypes, err := client.GetAllEventTypes(perPage, page)
	if err != nil {
		return err
	}

	tot := len(*eventtypes)
	//log.Printf("Got %d eventtypes", tot)
	if tot != perPage {
		return nil
	}

	for i, eventtype := range *eventtypes {
		if i > 0 && i%100 == 0 {
			log.Printf("[%d] Deleted %d eventtypes", id, i)
		}

		err = client.DeleteEventType(eventtype.EventTypeID)
		if err != nil {
			// ignore err cases for now
			//log.Printf("error %#v", err)
		}
	}
	log.Printf("[%d] Deleted all %d eventtypes", id, tot)

	return nil
}

func deletePageOfTriggers(perPage int, page int) error {
	id := page

	triggers, err := client.GetAllTriggers(perPage, page)
	if err != nil {
		return err
	}

	tot := len(*triggers)
	//log.Printf("Got %d triggers", tot)
	if tot != perPage {
		return nil
	}

	for i, trigger := range *triggers {
		if i > 0 && i%100 == 0 {
			log.Printf("[%d] Deleted %d triggers", id, i)
		}

		err = client.DeleteTrigger(trigger.TriggerID)
		if err != nil {
			// ignore err cases for now
			//log.Printf("error %#v", err)
		}
	}
	log.Printf("[%d] Deleted all %d triggers", id, tot)

	return nil
}
<commit_msg>in progress<commit_after>package main

import (
	"log"
	"math"
	"sync"

	piazza "github.com/venicegeo/pz-gocommon/gocommon"
	"github.com/venicegeo/pz-workflow/workflow"
)

var client *workflow.Client

const pageSize = 1000
const maxThreads = 10

type GetNumObjectsF func() (int, error)
type DeletePageOfObjectsF func(int, int) error

func main() {
	var err error

	client, err = makeClient()
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("*** ALERTS ***")
	err = deleteAllObjects(client.GetNumAlerts, deletePageOfAlerts)
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("*** TRIGGERS ***")
	err = deleteAllObjects(client.GetNumTriggers, deletePageOfTriggers)
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("*** EVENTS ***")
	err = deleteAllObjects(client.GetNumEvents, deletePageOfEvents)
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("*** EVENT TYPES ***")
	err = deleteAllObjects(client.GetNumEventTypes, deletePageOfEventTypes)
	if err != nil {
		log.Fatal(err)
	}
}

func deleteAllObjects(getNumObjectsF GetNumObjectsF, deletePageOfObjectsF DeletePageOfObjectsF) error {
	count, err := getNumObjectsF()
	if err != nil {
		return err
	}
	log.Printf("Num objects: %d", count)

	if count == 0 {
		return nil
	}

	numPages := int(math.Ceil(float64(count) / float64(pageSize)))
	log.Printf("Num pages: %d", numPages)

	delPage := func(wg *sync.WaitGroup, id int) {
		defer wg.Done()
		log.Printf("[%d] started", id)
		err = deletePageOfObjectsF(pageSize, id)
		log.Printf("[%d] ended: %#v", id, err)
	}

	for i := 0; i < numPages; i += maxThreads {
		var wg sync.WaitGroup
		wg.Add(maxThreads)
		for j := 0; j < maxThreads; j++ {
			id := i + j
			go delPage(&wg, id)
		}
		wg.Wait()
	}

	return nil
}

func makeClient() (*workflow.Client, error) {
	apiServer, err := piazza.GetApiServer()
	if err != nil {
		return nil, err
	}

	apiKey, err := piazza.GetApiKey(apiServer)
	if err != nil {
		return nil, err
	}

	url := "https://" + apiServer
	url = "https://pz-workflow.int.geointservices.io"

	log.Printf("Url: %s", url)
	log.Printf("Key: %s", apiKey)

	client, err := workflow.NewClient2(url, apiKey)
	if err != nil {
		return nil, err
	}

	return client, nil
}

func deletePageOfAlerts(perPage int, page int) error {
	id := page

	alerts, err := client.GetAllAlerts(perPage, page)
	if err != nil {
		return err
	}

	tot := len(*alerts)
	log.Printf("[%d] got %d alerts", id, tot)

	for i, alert := range *alerts {
		if i > 0 && i%100 == 0 {
			log.Printf("[%d] deleted %d alerts", id, i)
		}

		err = client.DeleteAlert(alert.AlertID)
		if err != nil {
			log.Printf("[%d] error %#v", id, err)
			return err
		}
	}
	log.Printf("[%d] deleted all %d alerts", id, tot)

	return nil
}

func deletePageOfEvents(perPage int, page int) error {
	id := page

	events, err := client.GetAllEvents(perPage, page)
	if err != nil {
		return err
	}

	tot := len(*events)
	log.Printf("Got %d events", tot)

	for i, event := range *events {
		if i > 0 && i%100 == 0 {
			log.Printf("[%d] Deleted %d events", id, i)
		}

		err = client.DeleteEvent(event.EventID)
		if err != nil {
			// ignore err cases for now
			//log.Printf("error %#v", err)
		}
	}
	log.Printf("[%d] Deleted all %d events", id, tot)

	return nil
}

func deletePageOfEventTypes(perPage int, page int) error {
	id := page

	eventtypes, err := client.GetAllEventTypes(perPage, page)
	if err != nil {
		return err
	}

	tot := len(*eventtypes)
	log.Printf("Got %d eventtypes", tot)

	for i, eventtype := range *eventtypes {
		if i > 0 && i%100 == 0 {
			log.Printf("[%d] Deleted %d eventtypes", id, i)
		}

		err = client.DeleteEventType(eventtype.EventTypeID)
		if err != nil {
			// ignore err cases for now
			log.Printf("error %#v", err)
		}
	}
	log.Printf("[%d] Deleted all %d eventtypes", id, tot)

	return nil
}

func deletePageOfTriggers(perPage int, page int) error {
	id := page

	triggers, err := client.GetAllTriggers(perPage, page)
	if err != nil {
		return err
	}

	tot := len(*triggers)
	log.Printf("[%d] got %d of %d triggers", id, tot, perPage)

	for i, trigger := range *triggers {
		if i > 0 && i%100 == 0 {
			log.Printf("[%d] Deleted %d triggers", id, i)
		}

		err = client.DeleteTrigger(trigger.TriggerID)
		if err != nil {
			// ignore err cases for now
			log.Printf("[%d] error %#v", id, err)
		} else {
			log.Printf("[%d] deleted trigger %d", id, i)
		}
	}
	log.Printf("[%d] Deleted all %d triggers", id, tot)

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"strings"

	"github.com/spf13/cobra"

	"github.com/NebulousLabs/Sia/api"
	"github.com/NebulousLabs/Sia/modules"
)

// coinUnits converts a siacoin amount to base units.
func coinUnits(amount string) (string, error) {
	units := []string{"pS", "nS", "uS", "mS", "SC", "KS", "MS", "GS", "TS"}
	for i, unit := range units {
		if strings.HasSuffix(amount, unit) {
			base := strings.TrimSuffix(amount, unit)
			zeros := 27 + 3*(i-3)
			// may need to adjust for non-integer values
			if d := strings.IndexByte(base, '.'); d != -1 {
				zeros -= len(base) - d - 1
				if zeros < 0 {
					return "", errors.New("non-integer number of hastings")
				}
				base = base[:d] + base[d+1:]
			}
			return base + strings.Repeat("0", zeros), nil
		}
	}
	return amount, nil // hastings
}

var (
	walletCmd = &cobra.Command{
		Use:   "wallet",
		Short: "Perform wallet actions",
		Long:  "Generate a new address, send coins to another wallet, or view info about the wallet.",
		Run:   wrap(walletstatuscmd),
	}

	walletAddressCmd = &cobra.Command{
		Use:   "address",
		Short: "Get a new wallet address",
		Long:  "Generate a new wallet address.",
		Run:   wrap(walletaddresscmd),
	}

	walletSendCmd = &cobra.Command{
		Use:   "send [amount] [dest]",
		Short: "Send coins to another wallet",
		Long: `Send coins to another wallet. 'dest' must be a 64-byte hexadecimal address.
'amount' can be specified in units, e.g. 1.23KS. Supported units are:
	pS (pico,  10^-12 SC)
	nS (nano,  10^-9 SC)
	uS (micro, 10^-6 SC)
	mS (milli, 10^-3 SC)
	SC
	KS (kilo, 10^3 SC)
	MS (mega, 10^6 SC)
	GS (giga, 10^9 SC)
	TS (tera, 10^12 SC)
If no unit is supplied, hastings (smallest possible unit, 10^-27 SC) will be assumed.
`,
		Run: wrap(walletsendcmd),
	}

	walletSiafundsCmd = &cobra.Command{
		Use:   "siafunds",
		Short: "Display siafunds balance",
		Long:  "Display siafunds balance and siacoin claim balance.",
		Run:   wrap(walletsiafundscmd),
	}

	walletSiafundsSendCmd = &cobra.Command{
		Use:   "send [amount] [dest] [keyfiles]",
		Short: "Send siafunds",
		Long: `Send siafunds to an address, and transfer their siacoins to the wallet.
Run 'wallet send --help' to see a list of available units.`,
		Run: walletsiafundssendcmd, // see function docstring
	}

	walletSiafundsTrackCmd = &cobra.Command{
		Use:   "track [keyfile]",
		Short: "Track a siafund address generated by siag",
		Long:  "Track a siafund address generated by siag.",
		Run:   wrap(walletsiafundstrackcmd),
	}

	walletStatusCmd = &cobra.Command{
		Use:   "status",
		Short: "View wallet status",
		Long:  "View wallet status, including the current balance and number of addresses.",
		Run:   wrap(walletstatuscmd),
	}
)

// TODO: this should be defined outside of siac
type walletAddr struct {
	Address string
}

func walletaddresscmd() {
	addr := new(walletAddr)
	err := getAPI("/wallet/address", addr)
	if err != nil {
		fmt.Println("Could not generate new address:", err)
		return
	}
	fmt.Printf("Created new address: %s\n", addr.Address)
}

func walletsendcmd(amount, dest string) {
	adjAmount, err := coinUnits(amount)
	if err != nil {
		fmt.Println("Could not parse amount:", err)
		return
	}
	err = post("/wallet/send", fmt.Sprintf("amount=%s&destination=%s", adjAmount, dest))
	if err != nil {
		fmt.Println("Could not send:", err)
		return
	}
	fmt.Printf("Sent %s to %s\n", adjAmount, dest)
}

func walletsiafundscmd() {
	bal := new(api.WalletSiafundsBalance)
	err := getAPI("/wallet/siafunds/balance", bal)
	if err != nil {
		fmt.Println("Could not get siafunds balance:", err)
		return
	}
	fmt.Printf("Siafunds Balance: %s\nClaim Balance: %s\n", bal.SiafundBalance, bal.SiacoinClaimBalance)
}

// special because list of keyfiles is variadic
func walletsiafundssendcmd(cmd *cobra.Command, args []string) {
	if len(args) < 3 {
		cmd.Usage()
		return
	}
	amount, dest, keyfiles := args[0], args[1], args[2:]
	for i := range keyfiles {
		keyfiles[i] = abs(keyfiles[i])
	}

	qs := fmt.Sprintf("amount=%s&destination=%s&keyfiles=%s", amount, dest, strings.Join(keyfiles, ","))

	err := post("/wallet/siafunds/send", qs)
	if err != nil {
		fmt.Println("Could not track siafunds:", err)
		return
	}
	fmt.Printf("Sent %s siafunds to %s\n", amount, dest)
}

func walletsiafundstrackcmd(keyfile string) {
	err := post("/wallet/siafunds/watchsiagaddress", "keyfile="+abs(keyfile))
	if err != nil {
		fmt.Println("Could not track siafunds:", err)
		return
	}
	fmt.Printf(`Added %s to tracked siafunds.

You must restart siad to update your siafund balance.
Do not delete the original keyfile.
`, keyfile)
}

func walletstatuscmd() {
	status := new(modules.WalletInfo)
	err := getAPI("/wallet/status", status)
	if err != nil {
		fmt.Println("Could not get wallet status:", err)
		return
	}
	fmt.Printf(`Wallet status:
Balance:   %v (confirmed)
           %v (unconfirmed)
Addresses: %d
`, status.Balance, status.FullBalance, status.NumAddresses)
}
<commit_msg>use big.Rat instead of string manipulation<commit_after>package main

import (
	"errors"
	"fmt"
	"math/big"
	"strings"

	"github.com/spf13/cobra"

	"github.com/NebulousLabs/Sia/api"
	"github.com/NebulousLabs/Sia/modules"
)

// coinUnits converts a siacoin amount to base units.
func coinUnits(amount string) (string, error) {
	units := []string{"pS", "nS", "uS", "mS", "SC", "KS", "MS", "GS", "TS"}
	for i, unit := range units {
		if strings.HasSuffix(amount, unit) {
			// scan into big.Rat
			r, ok := new(big.Rat).SetString(strings.TrimSuffix(amount, unit))
			if !ok {
				return "", errors.New("malformed amount")
			}
			// convert units
			exp := 27 + 3*(int64(i)-4)
			mag := new(big.Int).Exp(big.NewInt(10), big.NewInt(exp), nil)
			r.Mul(r, new(big.Rat).SetInt(mag))
			// r must be an integer at this point
			if !r.IsInt() {
				return "", errors.New("non-integer number of hastings")
			}
			return r.RatString(), nil
		}
	}
	return amount, nil // hastings
}

var (
	walletCmd = &cobra.Command{
		Use:   "wallet",
		Short: "Perform wallet actions",
		Long:  "Generate a new address, send coins to another wallet, or view info about the wallet.",
		Run:   wrap(walletstatuscmd),
	}

	walletAddressCmd = &cobra.Command{
		Use:   "address",
		Short: "Get a new wallet address",
		Long:  "Generate a new wallet address.",
		Run:   wrap(walletaddresscmd),
	}

	walletSendCmd = &cobra.Command{
		Use:   "send [amount] [dest]",
		Short: "Send coins to another wallet",
		Long: `Send coins to another wallet. 'dest' must be a 64-byte hexadecimal address.
'amount' can be specified in units, e.g. 1.23KS. Supported units are:
	pS (pico,  10^-12 SC)
	nS (nano,  10^-9 SC)
	uS (micro, 10^-6 SC)
	mS (milli, 10^-3 SC)
	SC
	KS (kilo, 10^3 SC)
	MS (mega, 10^6 SC)
	GS (giga, 10^9 SC)
	TS (tera, 10^12 SC)
If no unit is supplied, hastings (smallest possible unit, 10^-27 SC) will be assumed.`,
		Run: wrap(walletsendcmd),
	}

	walletSiafundsCmd = &cobra.Command{
		Use:   "siafunds",
		Short: "Display siafunds balance",
		Long:  "Display siafunds balance and siacoin claim balance.",
		Run:   wrap(walletsiafundscmd),
	}

	walletSiafundsSendCmd = &cobra.Command{
		Use:   "send [amount] [dest] [keyfiles]",
		Short: "Send siafunds",
		Long: `Send siafunds to an address, and transfer their siacoins to the wallet.
Run 'wallet send --help' to see a list of available units.`,
		Run: walletsiafundssendcmd, // see function docstring
	}

	walletSiafundsTrackCmd = &cobra.Command{
		Use:   "track [keyfile]",
		Short: "Track a siafund address generated by siag",
		Long:  "Track a siafund address generated by siag.",
		Run:   wrap(walletsiafundstrackcmd),
	}

	walletStatusCmd = &cobra.Command{
		Use:   "status",
		Short: "View wallet status",
		Long:  "View wallet status, including the current balance and number of addresses.",
		Run:   wrap(walletstatuscmd),
	}
)

// TODO: this should be defined outside of siac
type walletAddr struct {
	Address string
}

func walletaddresscmd() {
	addr := new(walletAddr)
	err := getAPI("/wallet/address", addr)
	if err != nil {
		fmt.Println("Could not generate new address:", err)
		return
	}
	fmt.Printf("Created new address: %s\n", addr.Address)
}

func walletsendcmd(amount, dest string) {
	adjAmount, err := coinUnits(amount)
	if err != nil {
		fmt.Println("Could not parse amount:", err)
		return
	}
	err = post("/wallet/send", fmt.Sprintf("amount=%s&destination=%s", adjAmount, dest))
	if err != nil {
		fmt.Println("Could not send:", err)
		return
	}
	fmt.Printf("Sent %s to %s\n", adjAmount, dest)
}

func walletsiafundscmd() {
	bal := new(api.WalletSiafundsBalance)
	err := getAPI("/wallet/siafunds/balance", bal)
	if err != nil {
		fmt.Println("Could not get siafunds balance:", err)
		return
	}
	fmt.Printf("Siafunds Balance: %s\nClaim Balance: %s\n", bal.SiafundBalance, bal.SiacoinClaimBalance)
}

// special because list of keyfiles is variadic
func walletsiafundssendcmd(cmd *cobra.Command, args []string) {
	if len(args) < 3 {
		cmd.Usage()
		return
	}
	amount, dest, keyfiles := args[0], args[1], args[2:]
	for i := range keyfiles {
		keyfiles[i] = abs(keyfiles[i])
	}
	qs := fmt.Sprintf("amount=%s&destination=%s&keyfiles=%s", amount, dest, strings.Join(keyfiles, ","))

	err := post("/wallet/siafunds/send", qs)
	if err != nil {
		fmt.Println("Could not track siafunds:", err)
		return
	}
	fmt.Printf("Sent %s siafunds to %s\n", amount, dest)
}

func walletsiafundstrackcmd(keyfile string) {
	err := post("/wallet/siafunds/watchsiagaddress", "keyfile="+abs(keyfile))
	if err != nil {
		fmt.Println("Could not track siafunds:", err)
		return
	}
	fmt.Printf(`Added %s to tracked siafunds.

You must restart siad to update your siafund balance.
Do not delete the original keyfile.
`, keyfile)
}

func walletstatuscmd() {
	status := new(modules.WalletInfo)
	err := getAPI("/wallet/status", status)
	if err != nil {
		fmt.Println("Could not get wallet status:", err)
		return
	}
	fmt.Printf(`Wallet status:
Balance:   %v (confirmed)
           %v (unconfirmed)
Addresses: %d
`, status.Balance, status.FullBalance, status.NumAddresses)
}
<|endoftext|>


<commit_before>package tools

import "math"

// Sum returns the sum of its argument.
func Sum(a ...int) int {
	var s int
	for _, v := range a {
		s += v
	}
	return s
}

// SqrtInt computes the square root of n and casts to an int.
func SqrtInt(n int) int {
	return int(math.Sqrt(float64(n)))
}

// Divisors returns all the proper divisors of n.
func Divisors(n int) []int {
	d := []int{1}
	for i := 2; i <= SqrtInt(n); i++ {
		if n%i == 0 {
			d = append(d, i)
			if other := n / i; other != i {
				d = append(d, other)
			}
		}
	}
	return d
}

// SumDivisors sums all the proper divisors of n.
func SumDivisors(n int) int {
	return Sum(Divisors(n)...)
}

// Perms return a channel of each permutation of a slice.
func Perms(slice []int) chan []int {
	c := make(chan []int)
	go func() {
		if len(slice) == 1 {
			c <- slice
		} else {
			for i, v := range slice {
				b := append([]int(nil), slice[:i]...)
				b = append(b, slice[i+1:]...)
				for p := range Perms(b) {
					c <- append([]int{v}, p...)
				}
			}
		}
		close(c)
	}()
	return c
}

// Divmod gives the quotient and remainder of integer division.
func Divmod(a, b int) (int, int) {
	return a / b, a % b
}
<commit_msg>+ common math funcs<commit_after>package tools

import (
	"math"
	"math/big"
	"strconv"
)

// Sum returns the sum of its argument.
func Sum(a ...int) int {
	var s int
	for _, v := range a {
		s += v
	}
	return s
}

// SqrtInt computes the square root of n and casts to an int.
func SqrtInt(n int) int {
	return int(math.Sqrt(float64(n)))
}

// Divisors returns all the proper divisors of n.
func Divisors(n int) []int {
	d := []int{1}
	for i := 2; i <= SqrtInt(n); i++ {
		if n%i == 0 {
			d = append(d, i)
			if other := n / i; other != i {
				d = append(d, other)
			}
		}
	}
	return d
}

// SumDivisors sums all the proper divisors of n.
func SumDivisors(n int) int {
	return Sum(Divisors(n)...)
}

// Perms return a channel of each permutation of a slice.
func Perms(slice []int) chan []int {
	c := make(chan []int)
	go func() {
		if len(slice) == 1 {
			c <- slice
		} else {
			for i, v := range slice {
				b := append([]int(nil), slice[:i]...)
				b = append(b, slice[i+1:]...)
				for p := range Perms(b) {
					c <- append([]int{v}, p...)
				}
			}
		}
		close(c)
	}()
	return c
}

// Divmod gives the quotient and remainder of integer division.
func Divmod(a, b int) (int, int) {
	return a / b, a % b
}

// PrimeFactors gives the prime factors of an int.
func PrimeFactors(n int) map[int]int {
	factors := make(map[int]int)
	d := 2
	for n > 1 {
		for n%d == 0 {
			n /= d
			factors[d]++
		}
		d++
	}
	return factors
}

// IsPrime determines if a given number is prime.
// https://en.wikipedia.org/wiki/Primality_test
func IsPrime(n int) bool {
	if n <= 1 {
		return false
	}
	if n <= 3 {
		return true
	}
	if n%2 == 0 || n%3 == 0 {
		return false
	}
	b := SqrtInt(n)
	for i := 5; i <= b; i += 6 {
		if n%i == 0 || n%(i+2) == 0 {
			return false
		}
	}
	return true
}

// Exp computes x to the power of y.
func Exp(x, y int) *big.Int {
	a := big.NewInt(1)
	b := big.NewInt(int64(x))
	for i := 0; i < y; i++ {
		a.Mul(a, b)
	}
	return a
}

// DigitSum sums the digit^p of a given number.
func DigitSum(n, p int) *big.Int {
	s := big.NewInt(0)
	for _, c := range strconv.Itoa(n) {
		i, _ := strconv.Atoi(string(c))
		s.Add(s, Exp(i, p))
	}
	return s
}

// JoinInts joins slice of ints and return it as an int.
func JoinInts(slice []int) int {
	var sum int
	len := len(slice) - 1
	for i, v := range slice {
		p := 1
		for j := 0; j < len-i; j++ {
			p *= 10
		}
		sum += p * v
	}
	return sum
}

// ProdInts computes the product of the slice of ints.
func ProdInts(slice []int) int {
	p := 1
	for _, v := range slice {
		p *= v
	}
	return p
}

// MinInt returns the smaller number of a and b.
func MinInt(a, b int) int {
	if a < b {
		return a
	}
	return b
}

// MaxInt returns the larger number of a and b.
func MaxInt(a, b int) int {
	if a > b {
		return a
	}
	return b
}

// SimplifyFraction simplifies a/b and return the (numerator, denominator).
func SimplifyFraction(a, b int) (int, int) {
	pa := PrimeFactors(a)
	pb := PrimeFactors(b)
	for k, v := range pa {
		v2, ok := pb[k]
		if !ok {
			continue
		}
		m := MinInt(v, v2)
		pa[k] = v - m
		pb[k] = v2 - m
	}
	sa := 1
	for k, v := range pa {
		for i := 0; i < v; i++ {
			sa *= k
		}
	}
	sb := 1
	for k, v := range pb {
		for i := 0; i < v; i++ {
			sb *= k
		}
	}
	return sa, sb
}
<|endoftext|>


<commit_before>package UserManager

import "testing"
import "github.com/stretchr/testify/assert"

//TestGenerateHash Tests if two exact same inputs in the hash function get the same output.
func TestGenerateHash(t *testing.T) {
	hash, salt := GeneratePasswordHash("MeinPasswort")
	hash2, salt2 := GeneratePasswordHash("MeinPasswort")
	assert.NotEqual(t, hash, hash2, "Error, Two Hashes of the same Passwort are identical")
	assert.NotEqual(t, salt, salt2, "Error, Two Runs of generate hash returned the same Salt")
}

//TestVerifyHash Test if a specific Plaintext+Salt = a specific hash
func TestVerifyHash(t *testing.T) {
	var v bool
	v = verifyPasswordHash("Psw", "ABC", "25928498b28c3268d911dd78d7ff820e0f14ed32b7ac2d397746f1778038b968d9e6364fd4b3da2e7026bdf574c104779fac9ce9064b6b9ae09ac043f8d131d4")
	if !v {
		t.Error("Expected true , got ", v)
	}
}

func TestVerifyUser(t *testing.T) {

}
<commit_msg>refactor<commit_after>package UserManager

import "testing"
import "github.com/stretchr/testify/assert"

//TestGenerateHash Tests if two exact same inputs in the hash function get the same output.
func TestGenerateHash(t *testing.T) {
	hash, salt := generatePasswordHash("MeinPasswort")
	hash2, salt2 := generatePasswordHash("MeinPasswort")
	assert.NotEqual(t, hash, hash2, "Error, Two Hashes of the same Passwort are identical")
	assert.NotEqual(t, salt, salt2, "Error, Two Runs of generate hash returned the same Salt")
}

//TestVerifyHash Test if a specific Plaintext+Salt = a specific hash
func TestVerifyHash(t *testing.T) {
	var v bool
	v = verifyPasswordHash("Psw", "ABC", "25928498b28c3268d911dd78d7ff820e0f14ed32b7ac2d397746f1778038b968d9e6364fd4b3da2e7026bdf574c104779fac9ce9064b6b9ae09ac043f8d131d4")
	if !v {
		t.Error("Expected true , got ", v)
	}
}

func TestVerifyUser(t *testing.T) {

}
<|endoftext|>


<commit_before>package analyze

import (
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"net/http"
	"regexp"

	"strings"

	"github.com/deckarep/golang-set"
	"github.com/jzelinskie/geddit"
)

func AnalyzeComments(s *geddit.OAuthSession, comments []*geddit.Comment) error {
	r, err := regexp.Compile(`github\.com\/[\w\-]+\/[\w\-]+`)
	if err != nil {
		return err
	}
	for _, comment := range comments {
		if (comment.Author == "github-stats-bot") || (strings.Contains(strings.ToLower(comment.Author), "bot")) {
			continue
		}
		if r.MatchString(comment.Body) {
			linkSet := mapset.NewSet()
			for _, link := range r.FindAllString(comment.Body, -1) {
				linkSet.Add(link)
			}
			var links []string
			for _, link := range linkSet.ToSlice() {
				links = append(links, link.(string))
			}
			if err = postReply(s, comment, links); err != nil {
				return err
			}
		}
	}
	return nil
}

func postReply(s *geddit.OAuthSession, comment *geddit.Comment, links []string) error {
	footer := "***\n^(This is Earth radio, and now here's human music ♫)\n\n^[Source](https://github.com/anaskhan96/github-stats-bot) ^| ^[PMme](https://np.reddit.com/message/compose?to=github-stats-bot)"
	var reply string
	for _, link := range links {
		var data map[string]interface{}
		if err := getStats(link, &data); err != nil {
			return err
		}
		if data["message"] == "Not Found" {
			return errors.New("Wrong GitHub API endpoint")
		}
		description := data["description"].(string)
		stargazers := int(data["stargazers_count"].(float64))
		forks := int(data["forks_count"].(float64))
		issuesURL := "https://" + link + "/issues"
		pullsURL := "https://" + link + "/pulls"
		reply += fmt.Sprintf("\n[%s](https://%s)\n\n> *Description*: %s\n\n> *Stars*: %d\n\n> *Forks*: %d\n\n> [Issues](%s) | [Pull Requests](%s)\n\n",
			link[11:], link, description, stargazers, forks, issuesURL, pullsURL)
	}
	reply += footer
	if _, err := s.Reply(comment, reply); err != nil {
		return err
	}
	log.Println("Replied to", comment.Author)
	return nil
}

func getStats(link string, data *map[string]interface{}) error {
	res, err := http.Get("https://api.github.com/repos/" + link[11:])
	if err != nil {
		return err
	}
	defer res.Body.Close()
	if err = json.NewDecoder(res.Body).Decode(&data); err != nil {
		return err
	}
	return nil
}
<commit_msg>one step closer to recognizing a bot<commit_after>package analyze

import (
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"net/http"
	"regexp"

	"strings"

	"github.com/deckarep/golang-set"
	"github.com/jzelinskie/geddit"
)

func AnalyzeComments(s *geddit.OAuthSession, comments []*geddit.Comment) error {
	r, err := regexp.Compile(`github\.com\/[\w\-]+\/[\w\-]+`)
	if err != nil {
		return err
	}
	for _, comment := range comments {
		if (comment.Author == "github-stats-bot") || (strings.Contains(strings.ToLower(comment.Author), "bot")) {
			continue
		}
		if r.MatchString(comment.Body) {
			linkSet := mapset.NewSet()
			for _, link := range r.FindAllString(comment.Body, -1) {
				linkSet.Add(link)
			}
			var links []string
			for _, link := range linkSet.ToSlice() {
				links = append(links, link.(string))
			}
			if err = postReply(s, comment, links); err != nil {
				return err
			}
		}
	}
	return nil
}

func postReply(s *geddit.OAuthSession, comment *geddit.Comment, links []string) error {
	footer := "***\n^(This is Earth radio, and now here's human music ♫)\n\n^[Source](https://github.com/anaskhan96/github-stats-bot) ^| ^[PMme](https://np.reddit.com/message/compose?to=github-stats-bot)"
	var reply string
	for _, link := range links {
		var data map[string]interface{}
		if err := getStats(link, &data); err != nil {
			return err
		}
		if data["message"] == "Not Found" {
			return errors.New("Wrong GitHub API endpoint")
		}
		description := data["description"].(string)
		// The things I have to do to check if it's a bot
		if strings.Contains(strings.ToLower(description), "bot") {
			continue
		}
		stargazers := int(data["stargazers_count"].(float64))
		forks := int(data["forks_count"].(float64))
		issuesURL := "https://" + link + "/issues"
		pullsURL := "https://" + link + "/pulls"
		reply += fmt.Sprintf("\n[%s](https://%s)\n\n> *Description*: %s\n\n> *Stars*: %d\n\n> *Forks*: %d\n\n> [Issues](%s) | [Pull Requests](%s)\n\n",
			link[11:], link, description, stargazers, forks, issuesURL, pullsURL)
	}
	reply += footer
	if _, err := s.Reply(comment, reply); err != nil {
		return err
	}
	log.Println("Replied to", comment.Author)
	return nil
}

func getStats(link string, data *map[string]interface{}) error {
	res, err := http.Get("https://api.github.com/repos/" + link[11:])
	if err != nil {
		return err
	}
	defer res.Body.Close()
	if err = json.NewDecoder(res.Body).Decode(&data); err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package main

/* Heavily based off of https://github.com/dghubble/go-twitter/blob/master/examples/streaming.go */

import "go-peddown2/database"
import (
	"database/sql"
	"flag"
	"fmt"
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/coreos/pkg/flagutil"
	"github.com/dghubble/go-twitter/twitter"
	"github.com/dghubble/oauth1"
)

func main() {

	flags := flag.NewFlagSet("user-auth", flag.ExitOnError)
	consumerKey := flags.String("consumer-key", "", "Twitter Consumer Key")
	consumerSecret := flags.String("consumer-secret", "", "Twitter Consumer Secret")
	accessToken := flags.String("access-token", "", "Twitter Access Token")
	accessSecret := flags.String("access-secret", "", "Twitter Access Secret")
	databasePath := flags.String("database", "./peddown.db", "Database Path")
	flags.Parse(os.Args[1:])
	flagutil.SetFlagsFromEnv(flags, "TWITTER")

	if *consumerKey == "" || *consumerSecret == "" || *accessToken == "" || *accessSecret == "" {
		log.Fatal("Consumer key/secret and Access token/secret required")
	}

	var err error
	database.Conn, err = sql.Open("sqlite3", *databasePath)
	if err != nil {
		log.Fatal(err)
	}

	// Confirm database is populated
	database.CheckDatabase(database.Conn)
	defer database.Conn.Close()

	config := oauth1.NewConfig(*consumerKey, *consumerSecret)
	token := oauth1.NewToken(*accessToken, *accessSecret)
	// OAuth1 http.Client will automatically authorize Requests
	httpClient := config.Client(oauth1.NoContext, token)

	// Twitter Client
	client := twitter.NewClient(httpClient)

	// Convenience Demux demultiplexed stream messages
	// What to do with each type of tweet
	demux := twitter.NewSwitchDemux()

	demux.Tweet = func(tweet *twitter.Tweet) {
		// Log that something was found.
		fmt.Println("Pedestrian Down!")
		fmt.Println(tweet.Text)
		fmt.Printf("https://twitter.com/%s/status/%s\n", tweet.User.ScreenName, tweet.IDStr)

		//If not @yyctransport skip
		if tweet.User.ID != 1729579022 {
			return
		}

		// Save information to the database here.
		/*
		*	id (integer)
		* incidentid (int) = -1
		* tweetDate <tweet.created_at)
		* tweetID tweet.IDStr
		* tweetURL fmt.Printf("https://twitter.com/%s/status/%s\n", tweet.User.ScreenName, tweet.IDStr)
		* tweetText tweet.Text
		 */

		tweetURL := fmt.Sprintf("https://twitter.com/yyctransport/status/%s", tweet.IDStr)
		number := 0

		err = database.Conn.QueryRow("select count(*)+1 from tweets where strftime('%Y', tweetDate) = strftime('%Y', 'now');").Scan(&number)
		if err != nil {
			log.Fatal("Database error", err)
		}

		suffix := "th"
		switch number % 10 {
		case 1:
			if (number % 100) != 11 {
				suffix = "st"
			}
		case 2:
			if (number % 100) != 12 {
				suffix = "nd"
			}
		case 3:
			if (number % 100) != 13 {
				suffix = "rd"
			}
		}

		t := time.Now()
		year := t.Format("2006")

		tweetContent := fmt.Sprintf("%d%s tweeted pedestrian incident in %s.\n#yycwalk #yyccc #ableg #visionzero\n@bmasonndp @shoffmanAB\n\n%s\n", number, suffix, year, tweetURL)
		tweet, resp, err := client.Statuses.Update(tweetContent, nil)

		// Log Twitter's response
		fmt.Println(tweetContent)
		fmt.Println(resp)
		fmt.Println(err)

		sqlStmt := `
			insert into tweets(tweetDate, tweetID, tweetURL, tweetText) values (?, ?, ?, ?)
		`
		// Need to convert tweet.CreatedAt to YYYY-MM-DD HH:MM:SS for storage in SQLite
		tweetTime, err := time.Parse(time.RubyDate, tweet.CreatedAt)
		if err != nil {
			log.Panic(err)
		}
		database.Conn.Exec(sqlStmt, tweetTime.Format("2006-01-02 03:04:05"), tweet.IDStr, tweetURL, tweet.Text)
		if err != nil {
			log.Panic(err)
		}
	}

	fmt.Println("Starting Stream...")

	// FILTER
	filterParams := &twitter.StreamFilterParams{
		Track:         []string{"ALERT ped,ALERT pedestrian"},
		StallWarnings: twitter.Bool(true),
	}
	stream, err := client.Streams.Filter(filterParams)
	if err != nil {
		log.Fatal(err)
	}

	// Receive messages until stopped or stream quits
	go demux.HandleChan(stream.Messages)

	// Wait for SIGINT and SIGTERM (HIT CTRL-C)
	ch := make(chan os.Signal)
	signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
	log.Println(<-ch)

	fmt.Println("Stopping Stream...")
	stream.Stop()
}
<commit_msg>Rollup of tweaks from name changes and a modest API change over the past few years<commit_after>package main

/* Heavily based off of https://github.com/dghubble/go-twitter/blob/master/examples/streaming.go */

import "go-peddown2/database"
import (
	"database/sql"
	"flag"
	"fmt"
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/coreos/pkg/flagutil"
	"github.com/dghubble/go-twitter/twitter"
	"github.com/dghubble/oauth1"
)

func main() {

	flags := flag.NewFlagSet("user-auth", flag.ExitOnError)
	consumerKey := flags.String("consumer-key", "", "Twitter Consumer Key")
	consumerSecret := flags.String("consumer-secret", "", "Twitter Consumer Secret")
	accessToken := flags.String("access-token", "", "Twitter Access Token")
	accessSecret := flags.String("access-secret", "", "Twitter Access Secret")
	databasePath := flags.String("database", "./peddown.db", "Database Path")
	flags.Parse(os.Args[1:])
	flagutil.SetFlagsFromEnv(flags, "TWITTER")

	if *consumerKey == "" || *consumerSecret == "" || *accessToken == "" || *accessSecret == "" {
		log.Fatal("Consumer key/secret and Access token/secret required")
	}

	var err error
	database.Conn, err = sql.Open("sqlite3", *databasePath)
	if err != nil {
		log.Fatal(err)
	}

	// Confirm database is populated
	database.CheckDatabase(database.Conn)
	defer database.Conn.Close()

	config := oauth1.NewConfig(*consumerKey, *consumerSecret)
	token := oauth1.NewToken(*accessToken, *accessSecret)
	// OAuth1 http.Client will automatically authorize Requests
	httpClient := config.Client(oauth1.NoContext, token)

	// Twitter Client
	client := twitter.NewClient(httpClient)

	// Convenience Demux demultiplexed stream messages
	// What to do with each type of tweet
	demux := twitter.NewSwitchDemux()

	demux.Tweet = func(tweet *twitter.Tweet) {
		// Log that something was found.
		fmt.Println("Pedestrian Down!")
		fmt.Println(tweet.FullText)
		fmt.Printf("https://twitter.com/%s/status/%s\n", tweet.User.ScreenName, tweet.IDStr)

		//If not @yyctransport skip
		if tweet.User.ID != 1729579022 {
			return
		}

		// Save information to the database here.
		/*
		*	id (integer)
		* incidentid (int) = -1
		* tweetDate <tweet.created_at)
		* tweetID tweet.IDStr
		* tweetURL fmt.Printf("https://twitter.com/%s/status/%s\n", tweet.User.ScreenName, tweet.IDStr)
		* tweetText tweet.FullText
		 */

		tweetURL := fmt.Sprintf("https://twitter.com/yyctransport/status/%s", tweet.IDStr)
		number := 0

		err = database.Conn.QueryRow("select count(*)+1 from tweets where strftime('%Y', tweetDate) = strftime('%Y', 'now');").Scan(&number)
		if err != nil {
			log.Fatal("Database error", err)
		}

		suffix := "th"
		switch number % 10 {
		case 1:
			if (number % 100) != 11 {
				suffix = "st"
			}
		case 2:
			if (number % 100) != 12 {
				suffix = "nd"
			}
		case 3:
			if (number % 100) != 13 {
				suffix = "rd"
			}
		}

		t := time.Now()
		year := t.Format("2006")

		tweetContent := fmt.Sprintf("%d%s tweeted pedestrian incident in %s.\n#yycwalk #yyccc #ableg #visionzero\n@RajanJSaw @shandro\n@lornedach @DShepYEG\n\n%s\n", number, suffix, year, tweetURL)
		tweet, resp, err := client.Statuses.Update(tweetContent, nil)

		// Log Twitter's response
		fmt.Println(tweetContent)
		fmt.Println(resp)
		fmt.Println(err)

		sqlStmt := `
			insert into tweets(tweetDate, tweetID, tweetURL, tweetText) values (?, ?, ?, ?)
		`
		// Need to convert tweet.CreatedAt to YYYY-MM-DD HH:MM:SS for storage in SQLite
		tweetTime, err := time.Parse(time.RubyDate, tweet.CreatedAt)
		if err != nil {
			log.Panic(err)
		}
		database.Conn.Exec(sqlStmt, tweetTime.Format("2006-01-02 03:04:05"), tweet.IDStr, tweetURL, tweetContent)
		if err != nil {
			log.Panic(err)
		}
	}

	fmt.Println("Starting Stream...")

	// FILTER
	filterParams := &twitter.StreamFilterParams{
		Track:         []string{"ALERT ped,ALERT pedestrian"},
		StallWarnings: twitter.Bool(true),
	}
	stream, err := client.Streams.Filter(filterParams)
	if err != nil {
		log.Fatal(err)
	}

	// Receive messages until stopped or stream quits
	go demux.HandleChan(stream.Messages)

	// Wait for SIGINT and SIGTERM (HIT CTRL-C)
	ch := make(chan os.Signal)
	signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
	log.Println(<-ch)

	fmt.Println("Stopping Stream...")
	stream.Stop()
}
<|endoftext|>