<commit_before>package cmd

import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"sort"
	"strings"

	"github.com/Masterminds/cookoo"
)

var ErrPkgNotFound = errors.New("package not found")

// Tree prints a tree representing dependencies.
func Tree(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
	buildContext, err := GetBuildContext()
	if err != nil {
		return nil, err
	}
	showcore := p.Get("showcore", false).(bool)
	basedir := p.Get("dir", ".").(string)
	myName := guessPackageName(buildContext, basedir)

	if basedir == "." {
		var err error
		basedir, err = os.Getwd()
		if err != nil {
			Error("Could not get working directory")
			return nil, err
		}
	}

	fmt.Println(myName)
	displayTree(buildContext, basedir, myName, 1, showcore)
	return nil, nil
}

// ListDeps lists all of the dependencies of the current project.
//
// Params:
//
// Returns:
//
func ListDeps(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
	buildContext, err := GetBuildContext()
	if err != nil {
		return nil, err
	}
	basedir := p.Get("dir", ".").(string)
	myName := guessPackageName(buildContext, basedir)

	basedir, err = filepath.Abs(basedir)
	if err != nil {
		return nil, err
	}

	direct := map[string]bool{}
	d := walkDeps(buildContext, basedir, myName)
	for _, i := range d {
		listDeps(buildContext, direct, i, basedir)
	}

	sortable := make([]string, len(direct))
	i := 0
	for k, _ := range direct {
		sortable[i] = k
		i++
	}

	sort.Strings(sortable)

	for _, k := range sortable {
		dec := "no"
		if direct[k] {
			dec = "yes"
		}
		fmt.Printf("%s (Present: %s)\n", k, dec)
	}

	return nil, nil
}

func listDeps(b *BuildCtxt, info map[string]bool, name, path string) {
	found := findPkg(b, name, path)
	switch found.PType {
	case ptypeUnknown:
		info[name] = false
		break
	case ptypeGoroot:
		break
	default:
		info[name] = true
		for _, i := range walkDeps(b, found.Path, found.Name) {
			listDeps(b, info, i, found.Path)
		}
	}
}

func displayTree(b *BuildCtxt, basedir, myName string, level int, core bool) {
	deps := walkDeps(b, basedir, myName)
	for _, name := range deps {
		found := findPkg(b, name, basedir)
		if found.PType == ptypeUnknown {
			msg := "glide get " + found.Name
			fmt.Printf("\t%s\t(%s)\n", found.Name, msg)
			continue
		}
		if !core && found.PType == ptypeGoroot {
			continue
		}
		fmt.Print(strings.Repeat("\t", level))
		fmt.Printf("%s   (%s)\n", found.Name, found.Path)
		displayTree(b, found.Path, found.Name, level+1, core)
	}
}

type ptype int8

const (
	ptypeUnknown ptype = iota
	ptypeLocal
	ptypeVendor
	ptypeGopath
	ptypeGoroot
)

type pinfo struct {
	Name, Path string
	PType      ptype
}

func findPkg(b *BuildCtxt, name, cwd string) *pinfo {
	var fi os.FileInfo
	var err error
	var p string

	info := &pinfo{
		Name: name,
	}

	// Recurse backward to scan other vendor/ directories
	for wd := cwd; wd != "/"; wd = filepath.Dir(wd) {
		p = filepath.Join(wd, "vendor", name)
		if fi, err = os.Stat(p); err == nil && (fi.IsDir() || isLink(fi)) {
			info.Path = p
			info.PType = ptypeVendor
			return info
		}
	}
	// Check $GOPATH
	for _, r := range strings.Split(b.GOPATH, ":") {
		p = filepath.Join(r, "src", name)
		if fi, err = os.Stat(p); err == nil && (fi.IsDir() || isLink(fi)) {
			info.Path = p
			info.PType = ptypeGopath
			return info
		}
	}

	// Check $GOROOT
	for _, r := range strings.Split(b.GOROOT, ":") {
		p = filepath.Join(r, "src", name)
		if fi, err = os.Stat(p); err == nil && (fi.IsDir() || isLink(fi)) {
			info.Path = p
			info.PType = ptypeGoroot
			return info
		}
	}
	return info
}

func isLink(fi os.FileInfo) bool {
	return fi.Mode()&os.ModeSymlink == os.ModeSymlink
}

func walkDeps(b *BuildCtxt, base, myName string) []string {
	externalDeps := []string{}
	filepath.Walk(base, func(path string, fi os.FileInfo, err error) error {
		if excludeSubtree(path, fi) {
			if fi.IsDir() {
				return filepath.SkipDir
			}
			return nil
		}

		pkg, err := b.ImportDir(path, 0)
		if err != nil {
			return err
		}

		if pkg.Goroot {
			return nil
		}

		for _, imp := range pkg.Imports {
			//if strings.HasPrefix(imp, myName) {
			////Info("Skipping %s because it is a subpackage of %s", imp, myName)
			//continue
			//}
			if imp == myName {
				continue
			}
			externalDeps = append(externalDeps, imp)
		}

		return nil
	})
	return externalDeps
}

func excludeSubtree(path string, fi os.FileInfo) bool {
	top := filepath.Base(path)

	if !fi.IsDir() && !isLink(fi) {
		return true
	}

	// Provisionally, we'll skip vendor. We definitely
	// should skip testdata.
	if top == "vendor" || top == "testdata" {
		return true
	}

	// Skip anything that starts with _
	if strings.HasPrefix(top, "_") || (strings.HasPrefix(top, ".") && top != ".") {
		return true
	}
	return false
}
<commit_msg>Cleaning up tree.go per gofmt and go vet<commit_after>package cmd

import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"sort"
	"strings"

	"github.com/Masterminds/cookoo"
)

var ErrPkgNotFound = errors.New("package not found")

// Tree prints a tree representing dependencies.
func Tree(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
	buildContext, err := GetBuildContext()
	if err != nil {
		return nil, err
	}
	showcore := p.Get("showcore", false).(bool)
	basedir := p.Get("dir", ".").(string)
	myName := guessPackageName(buildContext, basedir)

	if basedir == "." {
		var err error
		basedir, err = os.Getwd()
		if err != nil {
			Error("Could not get working directory")
			return nil, err
		}
	}

	fmt.Println(myName)
	displayTree(buildContext, basedir, myName, 1, showcore)
	return nil, nil
}

// ListDeps lists all of the dependencies of the current project.
//
// Params:
//
// Returns:
//
func ListDeps(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
	buildContext, err := GetBuildContext()
	if err != nil {
		return nil, err
	}
	basedir := p.Get("dir", ".").(string)
	myName := guessPackageName(buildContext, basedir)

	basedir, err = filepath.Abs(basedir)
	if err != nil {
		return nil, err
	}

	direct := map[string]bool{}
	d := walkDeps(buildContext, basedir, myName)
	for _, i := range d {
		listDeps(buildContext, direct, i, basedir)
	}

	sortable := make([]string, len(direct))
	i := 0
	for k := range direct {
		sortable[i] = k
		i++
	}

	sort.Strings(sortable)

	for _, k := range sortable {
		dec := "no"
		if direct[k] {
			dec = "yes"
		}
		fmt.Printf("%s (Present: %s)\n", k, dec)
	}

	return nil, nil
}

func listDeps(b *BuildCtxt, info map[string]bool, name, path string) {
	found := findPkg(b, name, path)
	switch found.PType {
	case ptypeUnknown:
		info[name] = false
		break
	case ptypeGoroot:
		break
	default:
		info[name] = true
		for _, i := range walkDeps(b, found.Path, found.Name) {
			listDeps(b, info, i, found.Path)
		}
	}
}

func displayTree(b *BuildCtxt, basedir, myName string, level int, core bool) {
	deps := walkDeps(b, basedir, myName)
	for _, name := range deps {
		found := findPkg(b, name, basedir)
		if found.PType == ptypeUnknown {
			msg := "glide get " + found.Name
			fmt.Printf("\t%s\t(%s)\n", found.Name, msg)
			continue
		}
		if !core && found.PType == ptypeGoroot {
			continue
		}
		fmt.Print(strings.Repeat("\t", level))
		fmt.Printf("%s   (%s)\n", found.Name, found.Path)
		displayTree(b, found.Path, found.Name, level+1, core)
	}
}

type ptype int8

const (
	ptypeUnknown ptype = iota
	ptypeLocal
	ptypeVendor
	ptypeGopath
	ptypeGoroot
)

type pinfo struct {
	Name, Path string
	PType      ptype
}

func findPkg(b *BuildCtxt, name, cwd string) *pinfo {
	var fi os.FileInfo
	var err error
	var p string

	info := &pinfo{
		Name: name,
	}

	// Recurse backward to scan other vendor/ directories
	for wd := cwd; wd != "/"; wd = filepath.Dir(wd) {
		p = filepath.Join(wd, "vendor", name)
		if fi, err = os.Stat(p); err == nil && (fi.IsDir() || isLink(fi)) {
			info.Path = p
			info.PType = ptypeVendor
			return info
		}
	}
	// Check $GOPATH
	for _, r := range strings.Split(b.GOPATH, ":") {
		p = filepath.Join(r, "src", name)
		if fi, err = os.Stat(p); err == nil && (fi.IsDir() || isLink(fi)) {
			info.Path = p
			info.PType = ptypeGopath
			return info
		}
	}

	// Check $GOROOT
	for _, r := range strings.Split(b.GOROOT, ":") {
		p = filepath.Join(r, "src", name)
		if fi, err = os.Stat(p); err == nil && (fi.IsDir() || isLink(fi)) {
			info.Path = p
			info.PType = ptypeGoroot
			return info
		}
	}
	return info
}

func isLink(fi os.FileInfo) bool {
	return fi.Mode()&os.ModeSymlink == os.ModeSymlink
}

func walkDeps(b *BuildCtxt, base, myName string) []string {
	externalDeps := []string{}
	filepath.Walk(base, func(path string, fi os.FileInfo, err error) error {
		if excludeSubtree(path, fi) {
			if fi.IsDir() {
				return filepath.SkipDir
			}
			return nil
		}

		pkg, err := b.ImportDir(path, 0)
		if err != nil {
			return err
		}

		if pkg.Goroot {
			return nil
		}

		for _, imp := range pkg.Imports {
			//if strings.HasPrefix(imp, myName) {
			////Info("Skipping %s because it is a subpackage of %s", imp, myName)
			//continue
			//}
			if imp == myName {
				continue
			}
			externalDeps = append(externalDeps, imp)
		}

		return nil
	})
	return externalDeps
}

func excludeSubtree(path string, fi os.FileInfo) bool {
	top := filepath.Base(path)

	if !fi.IsDir() && !isLink(fi) {
		return true
	}

	// Provisionally, we'll skip vendor. We definitely
	// should skip testdata.
	if top == "vendor" || top == "testdata" {
		return true
	}

	// Skip anything that starts with _
	if strings.HasPrefix(top, "_") || (strings.HasPrefix(top, ".") && top != ".") {
		return true
	}
	return false
}
<|endoftext|>


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

package mat64

import (
	"testing"

	"github.com/gonum/blas/blas64"
	"gopkg.in/check.v1"
)

func (s *S) TestInner(c *check.C) {
	for i, test := range []struct {
		x []float64
		y []float64
		m [][]float64
	}{
		{
			x: []float64{5},
			y: []float64{10},
			m: [][]float64{{2}},
		},
		{
			x: []float64{5, 6, 1},
			y: []float64{10},
			m: [][]float64{{2}, {-3}, {5}},
		},
		{
			x: []float64{5},
			y: []float64{10, 15},
			m: [][]float64{{2, -3}},
		},
		{
			x: []float64{1, 5},
			y: []float64{10, 15},
			m: [][]float64{
				{2, -3},
				{4, -1},
			},
		},
		{
			x: []float64{2, 3, 9},
			y: []float64{8, 9},
			m: [][]float64{
				{2, 3},
				{4, 5},
				{6, 7},
			},
		},
		{
			x: []float64{2, 3},
			y: []float64{8, 9, 9},
			m: [][]float64{
				{2, 3, 6},
				{4, 5, 7},
			},
		},
	} {
		x := NewDense(1, len(test.x), test.x)
		m := NewDense(flatten(test.m))
		mWant := NewDense(flatten(test.m))
		y := NewDense(len(test.y), 1, test.y)

		mWant.Mul(mWant, y)
		mWant.Mul(x, mWant)

		rm, cm := mWant.Dims()
		c.Check(rm, check.Equals, 1, check.Commentf("Test %v result doesn't have 1 row", i))
		c.Check(cm, check.Equals, 1, check.Commentf("Test %v result doesn't have 1 column", i))

		want := mWant.At(0, 0)

		got := Inner(test.x, m, test.y)
		c.Check(want, check.Equals, got, check.Commentf("Test %v: want %v, got %v", i, want, got))
	}
}

func benchmarkInner(b *testing.B, m, n int) {
	x := make([]float64, m)
	randomSlice(x)
	y := make([]float64, n)
	randomSlice(y)
	data := make([]float64, m*n)
	randomSlice(data)
	for i := 0; i < b.N; i++ {
		Inner(x, &Dense{blas64.General{Rows: m, Cols: n, Stride: n, Data: data}}, y)
	}
}

func BenchmarkInnerSmSm(b *testing.B) {
	benchmarkInner(b, Sm, Sm)
}

func BenchmarkInnerMedMed(b *testing.B) {
	benchmarkInner(b, Med, Med)
}

func BenchmarkInnerLgLg(b *testing.B) {
	benchmarkInner(b, Lg, Lg)
}

func BenchmarkInnerLgSm(b *testing.B) {
	benchmarkInner(b, Lg, Sm)
}
<commit_msg>Allocate the matrix in advance and reset the timer for a fairer benchmark<commit_after>// Copyright ©2014 The gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package mat64

import (
	"testing"

	"github.com/gonum/blas/blas64"
	"gopkg.in/check.v1"
)

func (s *S) TestInner(c *check.C) {
	for i, test := range []struct {
		x []float64
		y []float64
		m [][]float64
	}{
		{
			x: []float64{5},
			y: []float64{10},
			m: [][]float64{{2}},
		},
		{
			x: []float64{5, 6, 1},
			y: []float64{10},
			m: [][]float64{{2}, {-3}, {5}},
		},
		{
			x: []float64{5},
			y: []float64{10, 15},
			m: [][]float64{{2, -3}},
		},
		{
			x: []float64{1, 5},
			y: []float64{10, 15},
			m: [][]float64{
				{2, -3},
				{4, -1},
			},
		},
		{
			x: []float64{2, 3, 9},
			y: []float64{8, 9},
			m: [][]float64{
				{2, 3},
				{4, 5},
				{6, 7},
			},
		},
		{
			x: []float64{2, 3},
			y: []float64{8, 9, 9},
			m: [][]float64{
				{2, 3, 6},
				{4, 5, 7},
			},
		},
	} {
		x := NewDense(1, len(test.x), test.x)
		m := NewDense(flatten(test.m))
		mWant := NewDense(flatten(test.m))
		y := NewDense(len(test.y), 1, test.y)

		mWant.Mul(mWant, y)
		mWant.Mul(x, mWant)

		rm, cm := mWant.Dims()
		c.Check(rm, check.Equals, 1, check.Commentf("Test %v result doesn't have 1 row", i))
		c.Check(cm, check.Equals, 1, check.Commentf("Test %v result doesn't have 1 column", i))

		want := mWant.At(0, 0)

		got := Inner(test.x, m, test.y)
		c.Check(want, check.Equals, got, check.Commentf("Test %v: want %v, got %v", i, want, got))
	}
}

func benchmarkInner(b *testing.B, m, n int) {
	x := make([]float64, m)
	randomSlice(x)
	y := make([]float64, n)
	randomSlice(y)
	data := make([]float64, m*n)
	randomSlice(data)
	mat := &Dense{blas64.General{Rows: m, Cols: n, Stride: n, Data: data}}
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		Inner(x, mat, y)
	}
}

func BenchmarkInnerSmSm(b *testing.B) {
	benchmarkInner(b, Sm, Sm)
}

func BenchmarkInnerMedMed(b *testing.B) {
	benchmarkInner(b, Med, Med)
}

func BenchmarkInnerLgLg(b *testing.B) {
	benchmarkInner(b, Lg, Lg)
}

func BenchmarkInnerLgSm(b *testing.B) {
	benchmarkInner(b, Lg, Sm)
}
<|endoftext|>


<commit_before>package modules

import (
	"encoding/json"

	"bitbucket.org/cihangirsavas/gene/schema"
	"bitbucket.org/cihangirsavas/gene/testdata"

	"testing"
)

func TestCreateModuleStructure(t *testing.T) {
	expected := []string{
		"gene/modules/name",
		"gene/modules/name/api",
		"gene/modules/name/name",
		"gene/modules/name/cmd",
		"gene/modules/name/tests",
		"gene/modules/name/errors",
		"gene/modules/name/handlers",
	}

	structure := createModuleStructure("name")

	for _, stc := range structure {
		exists := false
		for _, expt := range expected {
			if expt == stc {
				exists = true
				break
			}
		}
		if !exists {
			t.Fatalf("%s is not expected in the result set", stc)
		}
	}
}

func TestCreateModule(t *testing.T) {
	var s schema.Schema
	if err := json.Unmarshal([]byte(testdata.JSON1), &s); err != nil {
		t.Fatal(err.Error())
	}

	m := NewModule(&s)
	m.Create()
}
<commit_msg>Module: check Create function call response<commit_after>package modules

import (
	"encoding/json"

	"bitbucket.org/cihangirsavas/gene/schema"
	"bitbucket.org/cihangirsavas/gene/testdata"

	"testing"
)

func TestCreateModuleStructure(t *testing.T) {
	expected := []string{
		"gene/modules/name",
		"gene/modules/name/api",
		"gene/modules/name/name",
		"gene/modules/name/cmd",
		"gene/modules/name/cmd/name",
		"gene/modules/name/tests",
		"gene/modules/name/errors",
		"gene/modules/name/handlers",
	}

	structure := createModuleStructure("name")

	for _, stc := range structure {
		exists := false
		for _, expt := range expected {
			if expt == stc {
				exists = true
				break
			}
		}
		if !exists {
			t.Fatalf("%s is not expected in the result set", stc)
		}
	}
}

func TestCreateModule(t *testing.T) {
	var s schema.Schema
	if err := json.Unmarshal([]byte(testdata.JSON1), &s); err != nil {
		t.Fatal(err.Error())
	}

	m := NewModule(&s)
	err := m.Create()
	if err != nil {
		t.Fatal(err.Error())
	}

}
<|endoftext|>


<commit_before>package main

import (
	"crypto/tls"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"sync"
	"syscall"
	"time"

	"github.com/Sirupsen/logrus"
	mailgun "github.com/mailgun/mailgun-go"
)

const (
	defaultCIDR = "0.0.0.0/0"

	arinAPIEndpoint = "http://whois.arin.net/rest/ip/%s"

	emailSender = "k8scan@jessfraz.com"
)

var (
	timeoutPing time.Duration
	timeoutGet  time.Duration

	cidr string

	defaultPorts = intSlice{80, 443, 8001, 9001}
	ports        intSlice

	mailgunDomain  string
	mailgunAPIKey  string
	emailRecipient string

	debug bool
)

// intSlice is a slice of ints
type intSlice []int

// implement the flag interface for intSlice
func (i *intSlice) String() (out string) {
	for k, v := range *i {
		if k < len(*i)-1 {
			out += fmt.Sprintf("%d,", v)
		} else {
			out += fmt.Sprintf("%d", v)
		}
	}
	return out
}

func (i *intSlice) Set(value string) error {
	// Set the default if nothing was given.
	if len(value) <= 0 {
		*i = defaultPorts
		return nil
	}

	// Split on "," for individual ports and ranges.
	r := strings.Split(value, ",")
	for _, pr := range r {
		// Split on "-" to denote a range.
		if strings.Contains(pr, "-") {
			p := strings.SplitN(pr, "-", 2)
			begin, err := strconv.Atoi(p[0])
			if err != nil {
				return err
			}
			end, err := strconv.Atoi(p[1])
			if err != nil {
				return err
			}
			if begin > end {
				return fmt.Errorf("end port can not be greater than the beginning port: %d > %d", end, begin)
			}
			for port := begin; port <= end; port++ {
				*i = append(*i, port)
			}

			continue
		}

		// It is not a range just parse the port
		port, err := strconv.Atoi(pr)
		if err != nil {
			return err
		}
		*i = append(*i, port)
	}

	return nil
}

func init() {
	flag.DurationVar(&timeoutPing, "timeout-ping", 2*time.Second, "Timeout for checking that the port is open")
	flag.DurationVar(&timeoutGet, "timeout-get", 10*time.Second, "Timeout for getting the contents of the URL")

	flag.StringVar(&cidr, "cidr", defaultCIDR, "IP CIDR to scan")
	flag.Var(&ports, "ports", fmt.Sprintf("Ports to scan (ex. 80-443 or 80,443,8080 or 1-20,22,80-443) (default: %s)", defaultPorts.String()))

	flag.StringVar(&mailgunAPIKey, "mailgun-api-key", "", "Mailgun API Key to use for sending email (optional)")
	flag.StringVar(&mailgunDomain, "mailgun-domain", "", "Mailgun Domain to use for sending email (optional)")
	flag.StringVar(&emailRecipient, "email-recipient", "", "Recipient for email notifications (optional)")

	flag.BoolVar(&debug, "d", false, "Run in debug mode")

	flag.Usage = func() {
		flag.PrintDefaults()
	}

	flag.Parse()

	// set log level
	if debug {
		logrus.SetLevel(logrus.DebugLevel)
	}
}

func main() {
	// On ^C, or SIGTERM handle exit.
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	signal.Notify(c, syscall.SIGTERM)
	go func() {
		for sig := range c {
			logrus.Infof("Received %s, exiting.", sig.String())
			os.Exit(0)
		}
	}()

	// Set the logger to nil so we ignore messages from the Dial that don't matter.
	// See: https://github.com/golang/go/issues/19895#issuecomment-292793756
	log.SetFlags(0)
	log.SetOutput(ioutil.Discard)

	logrus.Infof("Scanning for Kubernetes Dashboards and API Servers on %s over port range %#v", cidr, ports)
	if len(mailgunDomain) > 0 && len(mailgunAPIKey) > 0 && len(emailRecipient) > 0 {
		logrus.Infof("Using Mailgun Domain %s, API Key %s to send emails to %s", mailgunDomain, mailgunAPIKey, emailRecipient)
	}
	logrus.Infof("This may take a bit...")

	startTime := time.Now()

	ip, ipnet, err := net.ParseCIDR(cidr)
	if err != nil {
		logrus.Fatal(err)
	}

	var wg sync.WaitGroup
	for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) {
		for _, port := range ports {
			wg.Add(1)
			go func(ip string, port int) {
				defer wg.Done()

				scanIP(ip, port)

			}(ip.String(), port)
		}
	}

	wg.Wait()

	since := time.Since(startTime)
	logrus.Infof("Scan took: %s", since.String())
}

func scanIP(ip string, port int) {
	// Check if the port is open.
	ok := portOpen(ip, port)
	if !ok {
		return
	}

	// Check if it's a kubernetes dashboard.
	ok, uri := isKubernetesDashboard(ip, port)
	if !ok {
		return
	}

	// Get the info for the ip address.
	info, err := getIPInfo(ip)
	if err != nil {
		logrus.Warnf("ip info err: %v", err)
	}

	fmt.Printf("%s:%d\t%s\t%s\t%s\n",
		ip, port,
		info.Net.Organization.Handle, info.Net.Organization.Name, info.Net.Organization.Reference)

	// send an email
	if len(mailgunDomain) > 0 && len(mailgunAPIKey) > 0 && len(emailRecipient) > 0 {
		if err := sendEmail(uri, ip, port, info); err != nil {
			logrus.Warn(err)
		}
	}
}

func portOpen(ip string, port int) bool {
	c, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", ip, port), timeoutPing)
	if err != nil {
		// logrus.Warnf("listen at %s:%s failed: %v", ip, port, err)
		return false
	}
	defer c.Close()

	return true
}

func isKubernetesDashboard(ip string, port int) (bool, string) {
	client := &http.Client{
		Timeout: timeoutGet,
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}

	tryAddrs := []string{
		fmt.Sprintf("http://%s:%d", ip, port),
		fmt.Sprintf("https://%s:%d", ip, port),
		fmt.Sprintf("http://%s:%d/api/", ip, port),
		fmt.Sprintf("https://%s:%d/api/", ip, port),
	}

	var (
		resp *http.Response
		err  = errors.New("not yet run")
		uri  string
	)

	for i := 0; i < len(tryAddrs) && err != nil; i++ {
		uri = tryAddrs[i]
		resp, err = client.Get(uri)
	}
	if err != nil {
		//logrus.Warnf("getting %s:%s failed: %v", ip, port, err)
		return false, ""
	}
	defer resp.Body.Close()

	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return false, ""
	}

	body := strings.ToLower(string(b))
	if (strings.Contains(body, "kubernetes") && strings.Contains(body, "dashboard")) ||
		(strings.Contains(body, `"versions"`) && strings.Contains(body, `"serverAddress`)) ||
		(strings.Contains(body, `"paths"`) && strings.Contains(body, `"/api"`)) {
		return true, uri
	}

	return false, ""
}

// ARINResponse describes the data struct that holds the response from ARIN.
type ARINResponse struct {
	Net NetJSON `json:"net,omitempty"`
}

// NetJSON holds the net data from the ARIN response.
type NetJSON struct {
	Organization OrganizationJSON `json:"orgRef,omitempty"`
}

// OrganizationJSON holds the organization data from the ARIN response.
type OrganizationJSON struct {
	Handle    string `json:"@handle,omitempty"`
	Name      string `json:"@name,omitempty"`
	Reference string `json:"$,omitempty"`
}

func getIPInfo(ip string) (b ARINResponse, err error) {
	req, err := http.NewRequest(http.MethodGet, fmt.Sprintf(arinAPIEndpoint, ip), nil)
	if err != nil {
		return b, err
	}
	req.Header.Set("Accept", "application/json")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return b, err
	}
	defer resp.Body.Close()

	if err := json.NewDecoder(resp.Body).Decode(&b); err != nil {
		return b, err
	}

	return b, nil
}

func inc(ip net.IP) {
	for j := len(ip) - 1; j >= 0; j-- {
		ip[j]++
		if ip[j] > 0 {
			break
		}
	}
}

func sendEmail(uri, ip string, port int, arinInfo ARINResponse) error {
	mailgunClient := mailgun.NewMailgun(mailgunDomain, mailgunAPIKey, "")

	msg, _, err := mailgunClient.Send(mailgunClient.NewMessage(
		/* From */ fmt.Sprintf("%s <%s>", emailSender, emailSender),
		/* Subject */ fmt.Sprintf("[k8scan]: found dashboard %s", uri),
		/* Body */ fmt.Sprintf(`Time: %s

IP: %s:%d
URL: %s

ARIN: %s
	  %s
	  %s
`,
			time.Now().Format(time.UnixDate),
			ip,
			port,
			uri,
			arinInfo.Net.Organization.Handle,
			arinInfo.Net.Organization.Name,
			arinInfo.Net.Organization.Reference,
		),
		/* To */ emailRecipient,
	))
	if err != nil {
		return fmt.Errorf("sending Mailgun message failed: response: %#v error: %v", msg, err)
	}

	return nil
}
<commit_msg>nit on default syntax<commit_after>package main

import (
	"crypto/tls"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"sync"
	"syscall"
	"time"

	"github.com/Sirupsen/logrus"
	mailgun "github.com/mailgun/mailgun-go"
)

const (
	defaultCIDR = "0.0.0.0/0"

	arinAPIEndpoint = "http://whois.arin.net/rest/ip/%s"

	emailSender = "k8scan@jessfraz.com"
)

var (
	timeoutPing time.Duration
	timeoutGet  time.Duration

	cidr string

	defaultPorts = intSlice{80, 443, 8001, 9001}
	ports        intSlice

	mailgunDomain  string
	mailgunAPIKey  string
	emailRecipient string

	debug bool
)

// intSlice is a slice of ints
type intSlice []int

// implement the flag interface for intSlice
func (i *intSlice) String() (out string) {
	for k, v := range *i {
		if k < len(*i)-1 {
			out += fmt.Sprintf("%d,", v)
		} else {
			out += fmt.Sprintf("%d", v)
		}
	}
	return out
}

func (i *intSlice) Set(value string) error {
	// Set the default if nothing was given.
	if len(value) <= 0 {
		*i = defaultPorts
		return nil
	}

	// Split on "," for individual ports and ranges.
	r := strings.Split(value, ",")
	for _, pr := range r {
		// Split on "-" to denote a range.
		if strings.Contains(pr, "-") {
			p := strings.SplitN(pr, "-", 2)
			begin, err := strconv.Atoi(p[0])
			if err != nil {
				return err
			}
			end, err := strconv.Atoi(p[1])
			if err != nil {
				return err
			}
			if begin > end {
				return fmt.Errorf("end port can not be greater than the beginning port: %d > %d", end, begin)
			}
			for port := begin; port <= end; port++ {
				*i = append(*i, port)
			}

			continue
		}

		// It is not a range just parse the port
		port, err := strconv.Atoi(pr)
		if err != nil {
			return err
		}
		*i = append(*i, port)
	}

	return nil
}

func init() {
	flag.DurationVar(&timeoutPing, "timeout-ping", 2*time.Second, "Timeout for checking that the port is open")
	flag.DurationVar(&timeoutGet, "timeout-get", 10*time.Second, "Timeout for getting the contents of the URL")

	flag.StringVar(&cidr, "cidr", defaultCIDR, "IP CIDR to scan")
	flag.Var(&ports, "ports", fmt.Sprintf("Ports to scan (ex. 80-443 or 80,443,8080 or 1-20,22,80-443) (default %q)", defaultPorts.String()))

	flag.StringVar(&mailgunAPIKey, "mailgun-api-key", "", "Mailgun API Key to use for sending email (optional)")
	flag.StringVar(&mailgunDomain, "mailgun-domain", "", "Mailgun Domain to use for sending email (optional)")
	flag.StringVar(&emailRecipient, "email-recipient", "", "Recipient for email notifications (optional)")

	flag.BoolVar(&debug, "d", false, "Run in debug mode")

	flag.Usage = func() {
		flag.PrintDefaults()
	}

	flag.Parse()

	// set log level
	if debug {
		logrus.SetLevel(logrus.DebugLevel)
	}
}

func main() {
	// On ^C, or SIGTERM handle exit.
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	signal.Notify(c, syscall.SIGTERM)
	go func() {
		for sig := range c {
			logrus.Infof("Received %s, exiting.", sig.String())
			os.Exit(0)
		}
	}()

	// Set the logger to nil so we ignore messages from the Dial that don't matter.
	// See: https://github.com/golang/go/issues/19895#issuecomment-292793756
	log.SetFlags(0)
	log.SetOutput(ioutil.Discard)

	logrus.Infof("Scanning for Kubernetes Dashboards and API Servers on %s over port range %#v", cidr, ports)
	if len(mailgunDomain) > 0 && len(mailgunAPIKey) > 0 && len(emailRecipient) > 0 {
		logrus.Infof("Using Mailgun Domain %s, API Key %s to send emails to %s", mailgunDomain, mailgunAPIKey, emailRecipient)
	}
	logrus.Infof("This may take a bit...")

	startTime := time.Now()

	ip, ipnet, err := net.ParseCIDR(cidr)
	if err != nil {
		logrus.Fatal(err)
	}

	var wg sync.WaitGroup
	for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) {
		for _, port := range ports {
			wg.Add(1)
			go func(ip string, port int) {
				defer wg.Done()

				scanIP(ip, port)

			}(ip.String(), port)
		}
	}

	wg.Wait()

	since := time.Since(startTime)
	logrus.Infof("Scan took: %s", since.String())
}

func scanIP(ip string, port int) {
	// Check if the port is open.
	ok := portOpen(ip, port)
	if !ok {
		return
	}

	// Check if it's a kubernetes dashboard.
	ok, uri := isKubernetesDashboard(ip, port)
	if !ok {
		return
	}

	// Get the info for the ip address.
	info, err := getIPInfo(ip)
	if err != nil {
		logrus.Warnf("ip info err: %v", err)
	}

	fmt.Printf("%s:%d\t%s\t%s\t%s\n",
		ip, port,
		info.Net.Organization.Handle, info.Net.Organization.Name, info.Net.Organization.Reference)

	// send an email
	if len(mailgunDomain) > 0 && len(mailgunAPIKey) > 0 && len(emailRecipient) > 0 {
		if err := sendEmail(uri, ip, port, info); err != nil {
			logrus.Warn(err)
		}
	}
}

func portOpen(ip string, port int) bool {
	c, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", ip, port), timeoutPing)
	if err != nil {
		// logrus.Warnf("listen at %s:%s failed: %v", ip, port, err)
		return false
	}
	defer c.Close()

	return true
}

func isKubernetesDashboard(ip string, port int) (bool, string) {
	client := &http.Client{
		Timeout: timeoutGet,
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}

	tryAddrs := []string{
		fmt.Sprintf("http://%s:%d", ip, port),
		fmt.Sprintf("https://%s:%d", ip, port),
		fmt.Sprintf("http://%s:%d/api/", ip, port),
		fmt.Sprintf("https://%s:%d/api/", ip, port),
	}

	var (
		resp *http.Response
		err  = errors.New("not yet run")
		uri  string
	)

	for i := 0; i < len(tryAddrs) && err != nil; i++ {
		uri = tryAddrs[i]
		resp, err = client.Get(uri)
	}
	if err != nil {
		//logrus.Warnf("getting %s:%s failed: %v", ip, port, err)
		return false, ""
	}
	defer resp.Body.Close()

	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return false, ""
	}

	body := strings.ToLower(string(b))
	if (strings.Contains(body, "kubernetes") && strings.Contains(body, "dashboard")) ||
		(strings.Contains(body, `"versions"`) && strings.Contains(body, `"serverAddress`)) ||
		(strings.Contains(body, `"paths"`) && strings.Contains(body, `"/api"`)) {
		return true, uri
	}

	return false, ""
}

// ARINResponse describes the data struct that holds the response from ARIN.
type ARINResponse struct {
	Net NetJSON `json:"net,omitempty"`
}

// NetJSON holds the net data from the ARIN response.
type NetJSON struct {
	Organization OrganizationJSON `json:"orgRef,omitempty"`
}

// OrganizationJSON holds the organization data from the ARIN response.
type OrganizationJSON struct {
	Handle    string `json:"@handle,omitempty"`
	Name      string `json:"@name,omitempty"`
	Reference string `json:"$,omitempty"`
}

func getIPInfo(ip string) (b ARINResponse, err error) {
	req, err := http.NewRequest(http.MethodGet, fmt.Sprintf(arinAPIEndpoint, ip), nil)
	if err != nil {
		return b, err
	}
	req.Header.Set("Accept", "application/json")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return b, err
	}
	defer resp.Body.Close()

	if err := json.NewDecoder(resp.Body).Decode(&b); err != nil {
		return b, err
	}

	return b, nil
}

func inc(ip net.IP) {
	for j := len(ip) - 1; j >= 0; j-- {
		ip[j]++
		if ip[j] > 0 {
			break
		}
	}
}

func sendEmail(uri, ip string, port int, arinInfo ARINResponse) error {
	mailgunClient := mailgun.NewMailgun(mailgunDomain, mailgunAPIKey, "")

	msg, _, err := mailgunClient.Send(mailgunClient.NewMessage(
		/* From */ fmt.Sprintf("%s <%s>", emailSender, emailSender),
		/* Subject */ fmt.Sprintf("[k8scan]: found dashboard %s", uri),
		/* Body */ fmt.Sprintf(`Time: %s

IP: %s:%d
URL: %s

ARIN: %s
	  %s
	  %s
`,
			time.Now().Format(time.UnixDate),
			ip,
			port,
			uri,
			arinInfo.Net.Organization.Handle,
			arinInfo.Net.Organization.Name,
			arinInfo.Net.Organization.Reference,
		),
		/* To */ emailRecipient,
	))
	if err != nil {
		return fmt.Errorf("sending Mailgun message failed: response: %#v error: %v", msg, err)
	}

	return nil
}
<|endoftext|>


<commit_before>package project

import (
	"bytes"
	"log"
	"os"
	"path/filepath"
	"strings"
	"sync"

	"github.com/getantibody/folder"
	"gopkg.in/src-d/go-git.v4"
	"gopkg.in/src-d/go-git.v4/plumbing"
)

type gitProject struct {
	URL     string
	Version string
	folder  string
	inner   string
}

// NewClonedGit is a git project that was already cloned, so, only Update
// will work here.
func NewClonedGit(home, folderName string) Project {
	return gitProject{
		folder: filepath.Join(home, folderName),
		URL:    folder.ToURL(folderName),
	}
}

const (
	branchMarker = "branch:"
	pathMarker   = "path:"
)

// NewGit A git project can be any repository in any given branch. It will
// be downloaded to the provided cwd
func NewGit(cwd, line string) Project {
	version := "master"
	inner := ""
	parts := strings.Split(line, " ")
	for _, part := range parts {
		if strings.HasPrefix(part, branchMarker) {
			version = strings.Replace(part, branchMarker, "", -1)
		}
		if strings.HasPrefix(part, pathMarker) {
			inner = strings.Replace(part, pathMarker, "", -1)
		}
	}
	repo := parts[0]
	url := "https://github.com/" + repo
	switch {
	case strings.HasPrefix(repo, "http://"):
		fallthrough
	case strings.HasPrefix(repo, "https://"):
		fallthrough
	case strings.HasPrefix(repo, "git://"):
		fallthrough
	case strings.HasPrefix(repo, "ssh://"):
		fallthrough
	case strings.HasPrefix(repo, "git@gitlab.com:"):
		fallthrough
	case strings.HasPrefix(repo, "git@github.com:"):
		url = repo
	}
	return gitProject{
		Version: version,
		URL:     url,
		folder:  filepath.Join(cwd, folder.FromURL(url)),
		inner:   inner,
	}
}

// nolint: gochecknoglobals
var locks sync.Map

func (g gitProject) Download() error {
	l, _ := locks.LoadOrStore(g.folder, &sync.Mutex{})
	lock := l.(*sync.Mutex)
	lock.Lock()
	defer lock.Unlock()
	if _, err := os.Stat(g.folder); os.IsNotExist(err) {
		var w bytes.Buffer
		if _, err := git.PlainClone(g.folder, false, &git.CloneOptions{
			URL:               g.URL,
			ReferenceName:     plumbing.NewBranchReferenceName(g.Version),
			SingleBranch:      true,
			NoCheckout:        false,
			Depth:             1,
			RecurseSubmodules: 1,
			Progress:          &w,
		}); err != nil {
			log.Println("git clone failed for", g.URL, w.String())
			return err
		}
	}
	return nil
}

func (g gitProject) Update() error {
	log.Println("updating:", g.URL)

	repo, err := git.PlainOpen(g.folder)
	if err != nil {
		return err
	}

	ref, err := repo.Head()
	if err != nil {
		return err
	}

	oldRev, err := repo.ResolveRevision(plumbing.Revision(plumbing.HEAD))
	if err != nil {
		return err
	}

	wt, err := repo.Worktree()
	if err != nil {
		return err
	}

	var w bytes.Buffer
	if err := wt.Pull(&git.PullOptions{
		RemoteName:        "origin",
		ReferenceName:     ref.Name(),
		SingleBranch:      true,
		Depth:             1,
		RecurseSubmodules: 1,
		Progress:          &w,
		Force:             true,
	}); err != nil && err != git.NoErrAlreadyUpToDate {
		log.Println("git update failed for", g.folder, g.Version, w.String())
		return err
	}

	rev, err := repo.ResolveRevision(plumbing.Revision(plumbing.HEAD))
	if err != nil {
		return err
	}

	if rev.String() != oldRev.String() {
		log.Println("updated:", g.URL, oldRev, "->", rev)
	}

	return nil
}

func (g gitProject) Path() string {
	return filepath.Join(g.folder, g.inner)
}
<commit_msg>fix: handle err object not found<commit_after>package project

import (
	"bytes"
	"log"
	"os"
	"path/filepath"
	"strings"
	"sync"

	"github.com/getantibody/folder"
	"gopkg.in/src-d/go-git.v4"
	"gopkg.in/src-d/go-git.v4/plumbing"
)

type gitProject struct {
	URL     string
	Version string
	folder  string
	inner   string
}

// NewClonedGit is a git project that was already cloned, so, only Update
// will work here.
func NewClonedGit(home, folderName string) Project {
	return gitProject{
		folder: filepath.Join(home, folderName),
		URL:    folder.ToURL(folderName),
	}
}

const (
	branchMarker = "branch:"
	pathMarker   = "path:"
)

// NewGit A git project can be any repository in any given branch. It will
// be downloaded to the provided cwd
func NewGit(cwd, line string) Project {
	version := "master"
	inner := ""
	parts := strings.Split(line, " ")
	for _, part := range parts {
		if strings.HasPrefix(part, branchMarker) {
			version = strings.Replace(part, branchMarker, "", -1)
		}
		if strings.HasPrefix(part, pathMarker) {
			inner = strings.Replace(part, pathMarker, "", -1)
		}
	}
	repo := parts[0]
	url := "https://github.com/" + repo
	switch {
	case strings.HasPrefix(repo, "http://"):
		fallthrough
	case strings.HasPrefix(repo, "https://"):
		fallthrough
	case strings.HasPrefix(repo, "git://"):
		fallthrough
	case strings.HasPrefix(repo, "ssh://"):
		fallthrough
	case strings.HasPrefix(repo, "git@gitlab.com:"):
		fallthrough
	case strings.HasPrefix(repo, "git@github.com:"):
		url = repo
	}
	return gitProject{
		Version: version,
		URL:     url,
		folder:  filepath.Join(cwd, folder.FromURL(url)),
		inner:   inner,
	}
}

// nolint: gochecknoglobals
var locks sync.Map

func (g gitProject) Download() error {
	l, _ := locks.LoadOrStore(g.folder, &sync.Mutex{})
	lock := l.(*sync.Mutex)
	lock.Lock()
	defer lock.Unlock()
	if _, err := os.Stat(g.folder); os.IsNotExist(err) {
		var w bytes.Buffer
		if _, err := git.PlainClone(g.folder, false, &git.CloneOptions{
			URL:               g.URL,
			ReferenceName:     plumbing.NewBranchReferenceName(g.Version),
			SingleBranch:      true,
			NoCheckout:        false,
			Depth:             1,
			RecurseSubmodules: 1,
			Progress:          &w,
		}); err != nil {
			log.Println("git clone failed for", g.URL, w.String())
			return err
		}
	}
	return nil
}

func (g gitProject) Update() error {
	log.Println("updating:", g.URL)

	repo, err := git.PlainOpen(g.folder)
	if err != nil {
		return err
	}

	ref, err := repo.Head()
	if err != nil {
		return err
	}

	oldRev, err := repo.ResolveRevision(plumbing.Revision(plumbing.HEAD))
	if err != nil {
		return err
	}

	wt, err := repo.Worktree()
	if err != nil {
		return err
	}

	var w bytes.Buffer
	if err := wt.Pull(&git.PullOptions{
		RemoteName:        "origin",
		ReferenceName:     ref.Name(),
		SingleBranch:      true,
		Depth:             1,
		RecurseSubmodules: 1,
		Progress:          &w,
		Force:             true,
	}); err != nil && err != git.NoErrAlreadyUpToDate {
		log.Println("git clone failed", err, g.URL, w.String())
		if err == plumbing.ErrObjectNotFound {
			log.Printf(
				"This means your local copy probably is in a funky state (maybe someone force-pushed the repo). "+
					"You can fix this by running: `rm -rf %s && antibody bundle %s`",
				g.folder,
				g.URL,
			)
		}
		return err
	}

	rev, err := repo.ResolveRevision(plumbing.Revision(plumbing.HEAD))
	if err != nil {
		return err
	}

	if rev.String() != oldRev.String() {
		log.Println("updated:", g.URL, oldRev, "->", rev)
	}

	return nil
}

func (g gitProject) Path() string {
	return filepath.Join(g.folder, g.inner)
}
<|endoftext|>


<commit_before>/*
 * Copyright 2013 Nan Deng
 *
 * 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 proto

import (
	"code.google.com/p/snappy-go/snappy"
	"crypto/aes"
	"crypto/cipher"
	"crypto/hmac"
	"crypto/sha256"
	"encoding/binary"
	"hash"
	"io"
	"sync"
)

type CommandIO struct {
	writeAuth   hash.Hash
	cryptWriter io.Writer
	readAuth    hash.Hash
	cryptReader io.Reader
	conn        io.ReadWriter

	writeLock *sync.Mutex
}

func (self *CommandIO) writeThenHmac(data []byte) (mac []byte, err error) {
	writer := self.cryptWriter
	self.writeAuth.Reset()
	var datalen uint16
	datalen = uint16(len(data))
	err = binary.Write(self.writeAuth, binary.LittleEndian, datalen)
	if err != nil {
		return
	}
	err = writen(writer, data)
	if err != nil {
		return
	}
	mac = self.writeAuth.Sum(nil)
	return
}

func (self *CommandIO) readThenHmac(data []byte) (mac []byte, err error) {
	reader := self.cryptReader
	self.readAuth.Reset()

	var datalen uint16
	datalen = uint16(len(data))
	err = binary.Write(self.readAuth, binary.LittleEndian, datalen)
	if err != nil {
		return
	}
	n, err := io.ReadFull(reader, data)
	if err != nil {
		return
	}
	if n != len(data) {
		err = io.EOF
		return
	}
	mac = self.readAuth.Sum(nil)
	return
}

func (self *CommandIO) writeHmac(mac []byte) error {
	if len(mac) == 0 {
		return nil
	}
	return writen(self.conn, mac)
}

func (self *CommandIO) readAndCmpHmac(mac []byte) error {
	if len(mac) == 0 {
		return nil
	}
	macRecved := make([]byte, self.readAuth.Size())
	n, err := io.ReadFull(self.conn, macRecved)
	if err != nil {
		return err
	}
	if n != len(macRecved) {
		return ErrCorruptedData
	}
	if !bytesEq(mac, macRecved) {
		return ErrCorruptedData
	}
	return nil
}

func (self *CommandIO) decodeCommand(data []byte, compress bool) (cmd *Command, err error) {
	decoded := data
	if compress {
		decoded, err = snappy.Decode(nil, data)
		if err != nil {
			return
		}
	}
	cmd, err = UnmarshalCommand(decoded)
	if err != nil {
		return
	}
	return
}

func (self *CommandIO) encodeCommand(cmd *Command, compress bool) (data []byte, err error) {
	bsonEncoded, err := cmd.Marshal()
	if err != nil {
		return
	}

	data = bsonEncoded
	if compress {
		data, err = snappy.Encode(nil, bsonEncoded)
		if err != nil {
			return
		}
	}
	return
}

// WriteCommand() is goroutine-safe. i.e. Multiple goroutine could write concurrently.
func (self *CommandIO) WriteCommand(cmd *Command, compress bool) error {
	var flag byte
	flag = 0
	if compress {
		flag |= cmdflag_COMPRESS
	}
	data, err := self.encodeCommand(cmd, compress)
	if err != nil {
		return err
	}
	data = append(data, flag)
	var cmdLen uint16
	cmdLen = uint16(len(data))
	if cmdLen == 0 {
		return nil
	}
	self.writeLock.Lock()
	defer self.writeLock.Unlock()
	err = binary.Write(self.conn, binary.LittleEndian, cmdLen)
	if err != nil {
		return err
	}
	mac, err := self.writeThenHmac(data)
	if err != nil {
		return err
	}
	err = self.writeHmac(mac)
	if err != nil {
		return err
	}
	return nil
}

// ReadCommand() is not goroutine-safe.
func (self *CommandIO) ReadCommand() (cmd *Command, err error) {
	var cmdLen uint16
	err = binary.Read(self.conn, binary.LittleEndian, &cmdLen)
	if err != nil {
		return
	}

	data := make([]byte, int(cmdLen))
	mac, err := self.readThenHmac(data)
	if err != nil {
		return
	}
	compress := ((data[len(data) - 1] & cmdflag_COMPRESS) != 0)
	err = self.readAndCmpHmac(mac)
	if err != nil {
		return
	}
	cmd, err = self.decodeCommand(data[:len(data) - 1], compress)
	return
}

func NewCommandIO(writeKey, writeAuthKey, readKey, readAuthKey []byte, conn io.ReadWriter) *CommandIO {
	ret := new(CommandIO)
	ret.writeAuth = hmac.New(sha256.New, writeAuthKey)
	ret.readAuth = hmac.New(sha256.New, readAuthKey)
	ret.conn = conn
	ret.writeLock = new(sync.Mutex)

	writeBlkCipher, _ := aes.NewCipher(writeKey)
	readBlkCipher, _ := aes.NewCipher(readKey)

	// IV: 0 for all. Since we change keys for each connection, letting IV=0 won't hurt.
	writeIV := make([]byte, writeBlkCipher.BlockSize())
	readIV := make([]byte, readBlkCipher.BlockSize())

	writeStream := cipher.NewCTR(writeBlkCipher, writeIV)
	readStream := cipher.NewCTR(readBlkCipher, readIV)

	// Then for each encrypted bit,
	// it will be written to both the connection and the hmac
	// We use encrypt-then-hmac scheme.
	mwriter := io.MultiWriter(conn, ret.writeAuth)
	swriter := new(cipher.StreamWriter)
	swriter.S = writeStream
	swriter.W = mwriter
	ret.cryptWriter = swriter

	// Similarly, for each bit read from the connection,
	// it will be written to the hmac as well.
	tee := io.TeeReader(conn, ret.readAuth)
	sreader := new(cipher.StreamReader)
	sreader.S = readStream
	sreader.R = tee
	ret.cryptReader = sreader
	return ret
}
<commit_msg>put the flag in the front.<commit_after>/*
 * Copyright 2013 Nan Deng
 *
 * 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 proto

import (
	"code.google.com/p/snappy-go/snappy"
	"crypto/aes"
	"crypto/cipher"
	"crypto/hmac"
	"crypto/sha256"
	"encoding/binary"
	"hash"
	"io"
	"sync"
)

type CommandIO struct {
	writeAuth   hash.Hash
	cryptWriter io.Writer
	readAuth    hash.Hash
	cryptReader io.Reader
	conn        io.ReadWriter

	writeLock *sync.Mutex
}

func (self *CommandIO) writeThenHmac(data []byte) (mac []byte, err error) {
	writer := self.cryptWriter
	self.writeAuth.Reset()
	var datalen uint16
	datalen = uint16(len(data))
	err = binary.Write(self.writeAuth, binary.LittleEndian, datalen)
	if err != nil {
		return
	}
	err = writen(writer, data)
	if err != nil {
		return
	}
	mac = self.writeAuth.Sum(nil)
	return
}

func (self *CommandIO) readThenHmac(data []byte) (mac []byte, err error) {
	reader := self.cryptReader
	self.readAuth.Reset()

	var datalen uint16
	datalen = uint16(len(data))
	err = binary.Write(self.readAuth, binary.LittleEndian, datalen)
	if err != nil {
		return
	}
	n, err := io.ReadFull(reader, data)
	if err != nil {
		return
	}
	if n != len(data) {
		err = io.EOF
		return
	}
	mac = self.readAuth.Sum(nil)
	return
}

func (self *CommandIO) writeHmac(mac []byte) error {
	if len(mac) == 0 {
		return nil
	}
	return writen(self.conn, mac)
}

func (self *CommandIO) readAndCmpHmac(mac []byte) error {
	if len(mac) == 0 {
		return nil
	}
	macRecved := make([]byte, self.readAuth.Size())
	n, err := io.ReadFull(self.conn, macRecved)
	if err != nil {
		return err
	}
	if n != len(macRecved) {
		return ErrCorruptedData
	}
	if !bytesEq(mac, macRecved) {
		return ErrCorruptedData
	}
	return nil
}

func (self *CommandIO) decodeCommand(data []byte, compress bool) (cmd *Command, err error) {
	decoded := data
	if compress {
		decoded, err = snappy.Decode(nil, data)
		if err != nil {
			return
		}
	}
	cmd, err = UnmarshalCommand(decoded)
	if err != nil {
		return
	}
	return
}

func (self *CommandIO) encodeCommand(cmd *Command, compress bool) (data []byte, err error) {
	bsonEncoded, err := cmd.Marshal()
	if err != nil {
		return
	}

	data = bsonEncoded
	if compress {
		data, err = snappy.Encode(nil, bsonEncoded)
		if err != nil {
			return
		}
	}
	return
}

// WriteCommand() is goroutine-safe. i.e. Multiple goroutine could write concurrently.
func (self *CommandIO) WriteCommand(cmd *Command, compress bool) error {
	var flag byte
	flag = 0
	if compress {
		flag |= cmdflag_COMPRESS
	}
	data, err := self.encodeCommand(cmd, compress)
	if err != nil {
		return err
	}
	data = append(data, 0)
	copy(data[1:], data[:len(data)-1])
	data[0] = flag
	var cmdLen uint16
	cmdLen = uint16(len(data))
	if cmdLen == 0 {
		return nil
	}
	self.writeLock.Lock()
	defer self.writeLock.Unlock()
	err = binary.Write(self.conn, binary.LittleEndian, cmdLen)
	if err != nil {
		return err
	}
	mac, err := self.writeThenHmac(data)
	if err != nil {
		return err
	}
	err = self.writeHmac(mac)
	if err != nil {
		return err
	}
	return nil
}

// ReadCommand() is not goroutine-safe.
func (self *CommandIO) ReadCommand() (cmd *Command, err error) {
	var cmdLen uint16
	err = binary.Read(self.conn, binary.LittleEndian, &cmdLen)
	if err != nil {
		return
	}

	data := make([]byte, int(cmdLen))
	mac, err := self.readThenHmac(data)
	if err != nil {
		return
	}
	compress := ((data[0] & cmdflag_COMPRESS) != 0)
	err = self.readAndCmpHmac(mac)
	if err != nil {
		return
	}
	cmd, err = self.decodeCommand(data[1:], compress)
	return
}

func NewCommandIO(writeKey, writeAuthKey, readKey, readAuthKey []byte, conn io.ReadWriter) *CommandIO {
	ret := new(CommandIO)
	ret.writeAuth = hmac.New(sha256.New, writeAuthKey)
	ret.readAuth = hmac.New(sha256.New, readAuthKey)
	ret.conn = conn
	ret.writeLock = new(sync.Mutex)

	writeBlkCipher, _ := aes.NewCipher(writeKey)
	readBlkCipher, _ := aes.NewCipher(readKey)

	// IV: 0 for all. Since we change keys for each connection, letting IV=0 won't hurt.
	writeIV := make([]byte, writeBlkCipher.BlockSize())
	readIV := make([]byte, readBlkCipher.BlockSize())

	writeStream := cipher.NewCTR(writeBlkCipher, writeIV)
	readStream := cipher.NewCTR(readBlkCipher, readIV)

	// Then for each encrypted bit,
	// it will be written to both the connection and the hmac
	// We use encrypt-then-hmac scheme.
	mwriter := io.MultiWriter(conn, ret.writeAuth)
	swriter := new(cipher.StreamWriter)
	swriter.S = writeStream
	swriter.W = mwriter
	ret.cryptWriter = swriter

	// Similarly, for each bit read from the connection,
	// it will be written to the hmac as well.
	tee := io.TeeReader(conn, ret.readAuth)
	sreader := new(cipher.StreamReader)
	sreader.S = readStream
	sreader.R = tee
	ret.cryptReader = sreader
	return ret
}
<|endoftext|>


<commit_before>/*
 * Copyright 2012 Nan Deng
 *
 * 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 proto

import (
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"github.com/monnand/dhkx"
	pss "github.com/monnand/rsa"
	"io"
	"net"
)

type Authenticator interface {
	Authenticate(srv, usr, token string) (bool, error)
}

// The authentication here is quite similar with, if not same as, tarsnap's auth algorithm.
//
// First, server generate a Diffie-Hellman public key, dhpub1, sign it with
// server's private key using RSASSA-PSS signing algorithm.
// Send dhpub1, its signature and a nonce to client.
// An nonce is just a sequence of random bytes.
//
// Server -- dhpub1 + sign(dhpub1) + nonce --> Client
//
// Then client generate its own Diffie-Hellman key. It now can calculate
// a key, K, using its own Diffie-Hellman key and server's DH public key.
// (According to DH key exchange algorithm)
//
// Now, we can use K to derive any key we need on server and client side.
// master key, mkey = MGF1(nonce || K, 48)
func serverKeyExchange(privKey *rsa.PrivateKey, conn net.Conn) *authResult {
	ret := new(authResult)

	group, _ := dhkx.GetGroup(dhGroupID)
	priv, _ := group.GeneratePrivateKey(nil)

	mypub := priv.Bytes()
	mypub = leftPaddingZero(mypub, dhPubkeyLen)

	salt := make([]byte, pssSaltLen)
	n, err := io.ReadFull(rand.Reader, salt)
	if err != nil || n != len(salt) {
		ret.err = ErrZeroEntropy
		return ret
	}

	sha := sha256.New()
	hashed := make([]byte, sha.Size())
	sha.Write(mypub)
	hashed = sha.Sum(hashed[:0])

	sig, err := pss.SignPSS(rand.Reader, privKey, crypto.SHA256, hashed, salt)
	if err != nil {
		ret.err = err
		return ret
	}

	siglen := (privKey.N.BitLen() + 7) / 8
	keyExPkt := make([]byte, dhPubkeyLen+siglen+nonceLen)
	copy(keyExPkt, mypub)
	copy(keyExPkt[dhPubkeyLen:], sig)
	nonce := keyExPkt[dhPubkeyLen+siglen:]
	n, err = io.ReadFull(rand.Reader, nonce)
	if err != nil || n != len(nonce) {
		ret.err = ErrZeroEntropy
		return ret
	}

	// Send to client:
	// - DH public key: g ^ x
	// - Signature of DH public key RSASSA-PSS(g ^ x)
	// - nonce
	ret.err = writen(conn, keyExPkt)
	if ret.err != nil {
		return ret
	}

	// Receive from client:
	// - Client's DH public key: g ^ y
	// - HMAC of client's DH public key: HMAC(g ^ y, clientAuthKey)
	keyExPkt = keyExPkt[:dhPubkeyLen+authKeyLen]

	// Receive the data from client
	n, err = io.ReadFull(conn, keyExPkt)
	if err != nil {
		ret.err = err
		return ret
	}
	if n != len(keyExPkt) {
		ret.err = ErrBadKeyExchangePacket
		return ret
	}

	// First, recover client's DH public key
	clientpub := dhkx.NewPublicKey(keyExPkt[:dhPubkeyLen])

	// Compute a shared key K.
	K, err := group.ComputeKey(clientpub, priv)
	if err != nil {
		ret.err = err
		return ret
	}

	// Generate keys from the shared key
	ret.ks, err = generateKeys(K.Bytes(), nonce)
	if err != nil {
		ret.err = err
		return ret
	}

	// Check client's hmac
	ret.err = ret.ks.checkClientHMAC(keyExPkt[:dhPubkeyLen], keyExPkt[dhPubkeyLen:])
	if ret.err != nil {
		return ret
	}

	// TODO username/password auth
	ret.conn = conn
	return ret
}
<commit_msg>[Mod] New interface for the key exchange<commit_after>/*
 * Copyright 2012 Nan Deng
 *
 * 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 proto

import (
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"github.com/monnand/dhkx"
	pss "github.com/monnand/rsa"
	"io"
	"net"
)

type Authenticator interface {
	Authenticate(srv, usr, token string) (bool, error)
}

// The authentication here is quite similar with, if not same as, tarsnap's auth algorithm.
//
// First, server generate a Diffie-Hellman public key, dhpub1, sign it with
// server's private key using RSASSA-PSS signing algorithm.
// Send dhpub1, its signature and a nonce to client.
// An nonce is just a sequence of random bytes.
//
// Server -- dhpub1 + sign(dhpub1) + nonce --> Client
//
// Then client generate its own Diffie-Hellman key. It now can calculate
// a key, K, using its own Diffie-Hellman key and server's DH public key.
// (According to DH key exchange algorithm)
//
// Now, we can use K to derive any key we need on server and client side.
// master key, mkey = MGF1(nonce || K, 48)
func serverKeyExchange(privKey *rsa.PrivateKey, conn net.Conn) (ks *keySet, err error) {
	group, _ := dhkx.GetGroup(dhGroupID)
	priv, _ := group.GeneratePrivateKey(nil)

	mypub := priv.Bytes()
	mypub = leftPaddingZero(mypub, dhPubkeyLen)

	salt := make([]byte, pssSaltLen)
	n, err := io.ReadFull(rand.Reader, salt)
	if err != nil || n != len(salt) {
		err = ErrZeroEntropy
		return
	}

	sha := sha256.New()
	hashed := make([]byte, sha.Size())
	sha.Write(mypub)
	hashed = sha.Sum(hashed[:0])

	sig, err := pss.SignPSS(rand.Reader, privKey, crypto.SHA256, hashed, salt)
	if err != nil {
		return
	}

	siglen := (privKey.N.BitLen() + 7) / 8
	keyExPkt := make([]byte, dhPubkeyLen+siglen+nonceLen)
	copy(keyExPkt, mypub)
	copy(keyExPkt[dhPubkeyLen:], sig)
	nonce := keyExPkt[dhPubkeyLen+siglen:]
	n, err = io.ReadFull(rand.Reader, nonce)
	if err != nil || n != len(nonce) {
		err = ErrZeroEntropy
		return
	}

	// Send to client:
	// - DH public key: g ^ x
	// - Signature of DH public key RSASSA-PSS(g ^ x)
	// - nonce
	err = writen(conn, keyExPkt)
	if err != nil {
		return
	}

	// Receive from client:
	// - Client's DH public key: g ^ y
	// - HMAC of client's DH public key: HMAC(g ^ y, clientAuthKey)
	keyExPkt = keyExPkt[:dhPubkeyLen+authKeyLen]

	// Receive the data from client
	n, err = io.ReadFull(conn, keyExPkt)
	if err != nil {
		return
	}
	if n != len(keyExPkt) {
		err = ErrBadKeyExchangePacket
		return
	}

	// First, recover client's DH public key
	clientpub := dhkx.NewPublicKey(keyExPkt[:dhPubkeyLen])

	// Compute a shared key K.
	K, err := group.ComputeKey(clientpub, priv)
	if err != nil {
		return
	}

	// Generate keys from the shared key
	ks, err = generateKeys(K.Bytes(), nonce)
	if err != nil {
		return
	}

	// Check client's hmac
	err = ks.checkClientHMAC(keyExPkt[:dhPubkeyLen], keyExPkt[dhPubkeyLen:])
	if err != nil {
		return
	}

	return
}
<|endoftext|>


<commit_before>// Package ryba is a RYe Bridge Adapater for chirp (but it sounds fishy).

package ryba

import (
	"github.com/strickyak/rye"
	"github.com/yak-labs/chirp-lang"

	. "fmt"
	R "reflect"
)

func B2T(p rye.B) chirp.T {
	var z chirp.T
	c := p.Self.Contents()
	println(Sprintf("B2T <<< %v <<< %v", c, p))

	switch t := c.(type) {
	case []rye.B:
		n := len(t)
		tt := make([]chirp.T, n, n)
		for i, e := range t {
			tt[i] = B2T(e) // Recurse.
		}
		z = chirp.MkList(tt)

	default:
		z = chirp.MkT(c)
	}

	println(Sprintf("B2T >>> %v", z))
	return z
}

func T2B(t chirp.T) rye.B {
	// Rye C_Objects and Go reflect.Values.
	if val := t.QuickReflectValue(); val.IsValid() {
		guts := val.Interface()
		if gs, ok := guts.(rye.GetSelfer); ok {
			return gs.GetSelf().B()
		}
		return rye.MkValue(val)
	}

	raw := t.Raw()
	val := R.ValueOf(raw)
	switch val.Kind() {
	case R.Invalid:
		return rye.None
	case R.Bool:
		return rye.MkBool(val.Bool())
	case R.Int:
		return rye.MkInt(int64(val.Int()))
	case R.Int8:
		return rye.MkInt(int64(val.Int()))
	case R.Int16:
		return rye.MkInt(int64(val.Int()))
	case R.Int32:
		return rye.MkInt(int64(val.Int()))
	case R.Int64:
		return rye.MkInt(int64(val.Int()))
	case R.Uint:
		return rye.MkInt(int64(val.Uint()))
	case R.Uint8:
		return rye.MkInt(int64(val.Uint()))
	case R.Uint16:
		return rye.MkInt(int64(val.Uint()))
	case R.Uint32:
		return rye.MkInt(int64(val.Uint()))
	case R.Uint64:
		return rye.MkInt(int64(val.Uint()))
	case R.Uintptr:
		return rye.MkInt(int64(val.Uint()))
	case R.Float32:
		return rye.MkFloat(float64(val.Float()))
	case R.Float64:
		return rye.MkFloat(float64(val.Float()))
	case R.Complex64:
		panic("cannot complex")
	case R.Complex128:
		panic("cannot complex")
	case R.Array:
	case R.Chan:
	case R.Func:
	case R.Interface:
	case R.Map:
	case R.Ptr:
	case R.Slice:
	case R.String:
		return rye.MkStr(val.String())
	case R.Struct:
	case R.UnsafePointer:
	}

	panic(Sprintf("T2B: Bad Kind: %v", val.Kind()))
}

func cmdRyCall(fr *chirp.Frame, argv []chirp.T) chirp.T {
	fnT, argsT := chirp.Arg1v(argv)
	//fnP := T2P(fnT)
	n := len(argsT)
	argsP := make([]rye.B, n, n)
	for i, t := range argsT {
		argsP[i] = T2B(t)
	}

	if b, ok := fnT.Raw().(rye.B); ok {
		if p, ok := b.Self.(rye.ICallV); ok {
			z := p.CallV(argsP, nil, nil, nil)
			return B2T(z)
		} else {
			panic("rycall: fn not an rye.ICallV")
		}
	} else {
		panic("rycall: fn not a rye.B")
	}
}

func init() {
	if chirp.Unsafes == nil {
		chirp.Unsafes = make(map[string]chirp.Command, 333)
	}

	chirp.Unsafes["rycall"] = cmdRyCall
	// chirp.Unsafes["rysend"] = cmdRySend
}
<commit_msg>Big conversion to M-based function calls in Rye.<commit_after>// Package ryba is a RYe Bridge Adapater for chirp (but it sounds fishy).

package ryba

import (
	"github.com/strickyak/rye"
	"github.com/yak-labs/chirp-lang"

	. "fmt"
	R "reflect"
)

func T2B(t chirp.T) rye.M {
	// Rye C_Objects and Go reflect.Values.
	if val := t.QuickReflectValue(); val.IsValid() {
		guts := val.Interface()
		if gs, ok := guts.(rye.GetSelfer); ok {
			return gs.GetSelf().M()
		}
		return rye.MkValue(val)
	}

	raw := t.Raw()
	val := R.ValueOf(raw)
	switch val.Kind() {
	case R.Invalid:
		return rye.None
	case R.Bool:
		return rye.MkBool(val.Bool())
	case R.Int:
		return rye.MkInt(int64(val.Int()))
	case R.Int8:
		return rye.MkInt(int64(val.Int()))
	case R.Int16:
		return rye.MkInt(int64(val.Int()))
	case R.Int32:
		return rye.MkInt(int64(val.Int()))
	case R.Int64:
		return rye.MkInt(int64(val.Int()))
	case R.Uint:
		return rye.MkInt(int64(val.Uint()))
	case R.Uint8:
		return rye.MkInt(int64(val.Uint()))
	case R.Uint16:
		return rye.MkInt(int64(val.Uint()))
	case R.Uint32:
		return rye.MkInt(int64(val.Uint()))
	case R.Uint64:
		return rye.MkInt(int64(val.Uint()))
	case R.Uintptr:
		return rye.MkInt(int64(val.Uint()))
	case R.Float32:
		return rye.MkFloat(float64(val.Float()))
	case R.Float64:
		return rye.MkFloat(float64(val.Float()))
	case R.Complex64:
		panic("cannot complex")
	case R.Complex128:
		panic("cannot complex")
	case R.Array:
	case R.Chan:
	case R.Func:
	case R.Interface:
	case R.Map:
	case R.Ptr:
	case R.Slice:
	case R.String:
		return rye.MkStr(val.String())
	case R.Struct:
	case R.UnsafePointer:
	}

	panic(Sprintf("T2B: Bad Kind: %v", val.Kind()))
}

func cmdRyCall(fr *chirp.Frame, argv []chirp.T) chirp.T {
	fnT, argsT := chirp.Arg1v(argv)
	n := len(argsT)

	argsVV := make([]R.Value, n)
	for i, t := range argsT {
		argsVV[i] = R.ValueOf(rye.Mk(t.Raw()))
	}

	//println(Sprintf("qqq<<< cmdRyCall: fnT %T %T %#v", fnT, fnT.Raw(), fnT.Raw()))

	var fn interface{} = fnT.Raw()
	fnV := R.ValueOf(fn)
	resultsVV := fnV.Call(argsVV)
	if len(resultsVV) != 1 {
		panic("bad len resultsVV")
	}

	//println(Sprintf("qqq>>> cmdRyCall: fnT %T %T %#v", resultsVV[0], resultsVV[0].Interface(), resultsVV[0].Interface()))

	// Note:  This may not be quite right; we used to have some extra code for slices.
	return chirp.MkT(resultsVV[0].Interface().(rye.M).Contents())
}

func init() {
	if chirp.Unsafes == nil {
		chirp.Unsafes = make(map[string]chirp.Command, 333)
	}

	chirp.Unsafes["rycall"] = cmdRyCall
	// chirp.Unsafes["rysend"] = cmdRySend
}
<|endoftext|>


<commit_before>package CloudForest

import (
	"math/rand"
)

type BalancedSampler struct {
	Cases [][]int
}

func NewBalancedSampler(catf *DenseCatFeature) (s *BalancedSampler) {
	s = &BalancedSampler{make([][]int, catf.NCats())}

	for i := 0; i < catf.NCats(); i++ {
		s.Cases = append(s.Cases, make([]int, catf.Length()))
	}

	for i, v := range catf.CatData {
		if !catf.IsMissing(i) {
			s.Cases[v] = append(s.Cases[v], i)
		}
	}
	return
}

func (s *BalancedSampler) Sample(samples *[]int, n int) {
	(*samples) = (*samples)[0:0]
	nCases := len(s.Cases)
	c := 0
	for i := 0; i < n; i++ {
		c = rand.Intn(nCases)
		(*samples) = append((*samples), s.Cases[c][rand.Intn(len(s.Cases[c]))])
	}

}

/*
SampleFirstN ensures that the first n entries in the supplied
deck are randomly drawn from all entries without replacement for use in selecting candidate
features to split on. It accepts a pointer to the deck so that it can be used repeatedly on
the same deck avoiding reallocations.
*/
func SampleFirstN(deck *[]int, n int) {
	cards := *deck
	length := len(cards)
	old := 0
	randi := 0
	for i := 0; i < n; i++ {
		old = cards[i]
		randi = i + rand.Intn(length-i)
		cards[i] = cards[randi]
		cards[randi] = old

	}
}

/*
SampleWithReplacment samples nSamples random draws from [0,totalCases) with replacement
for use in selecting cases to grow a tree from.
*/
func SampleWithReplacment(nSamples int, totalCases int) (cases []int) {
	cases = make([]int, 0, nSamples)
	for i := 0; i < nSamples; i++ {
		cases = append(cases, rand.Intn(totalCases))
	}
	return
}
<commit_msg>added support for balanced bagging<commit_after>package CloudForest

import (
	"math/rand"
)

//BalancedSampler provides for random sampelign of integers (usually case indexes)
//in a way that ensures a balanced presence of classes.
type BalancedSampler struct {
	Cases [][]int
}

//NeaBalancedSampler initalizes a balanced sampler that will evenly balance cases
//between the classes present in the provided DesnseeCatFeature.
func NewBalancedSampler(catf *DenseCatFeature) (s *BalancedSampler) {
	s = &BalancedSampler{make([][]int, catf.NCats())}

	for i := 0; i < catf.NCats(); i++ {
		s.Cases = append(s.Cases, make([]int, catf.Length()))
	}

	for i, v := range catf.CatData {
		if !catf.IsMissing(i) {
			s.Cases[v] = append(s.Cases[v], i)
		}
	}
	return
}

//Sample samples n integers in a balnced-with-replacment fashion into the provided array.
func (s *BalancedSampler) Sample(samples *[]int, n int) {
	(*samples) = (*samples)[0:0]
	nCases := len(s.Cases)
	c := 0
	for i := 0; i < n; i++ {
		c = rand.Intn(nCases)
		(*samples) = append((*samples), s.Cases[c][rand.Intn(len(s.Cases[c]))])
	}

}

/*
SampleFirstN ensures that the first n entries in the supplied
deck are randomly drawn from all entries without replacement for use in selecting candidate
features to split on. It accepts a pointer to the deck so that it can be used repeatedly on
the same deck avoiding reallocations.
*/
func SampleFirstN(deck *[]int, n int) {
	cards := *deck
	length := len(cards)
	old := 0
	randi := 0
	for i := 0; i < n; i++ {
		old = cards[i]
		randi = i + rand.Intn(length-i)
		cards[i] = cards[randi]
		cards[randi] = old

	}
}

/*
SampleWithReplacment samples nSamples random draws from [0,totalCases) with replacement
for use in selecting cases to grow a tree from.
*/
func SampleWithReplacment(nSamples int, totalCases int) (cases []int) {
	cases = make([]int, 0, nSamples)
	for i := 0; i < nSamples; i++ {
		cases = append(cases, rand.Intn(totalCases))
	}
	return
}
<|endoftext|>


<commit_before>package allyourbase

import (
	"errors"
	"fmt"
	"math"
)

func ConvertToBase(inputBase int, inputDigits []int, outputBase int) (outputDigits []int, e error) {
	if inputBase < 2 {
		return []int{}, errors.New("input base must be >= 2")
	}
	if negativeDigit(inputDigits) {
		return []int{}, errors.New("all digits must satisfy 0 <= d < input base")
	}
	base10 := getBase10Input(inputBase, inputDigits)
	if base10 == 0 {
		return []int{0}, nil
	}
	for base10 > 0 {
		digit := base10 % outputBase
		outputDigits = append([]int{digit}, outputDigits...)
		base10 = base10 / outputBase
	}
	return outputDigits, nil
}

func getBase10Input(inputBase int, inputDigits []int) (base10Input int) {
	for i, digit := range reverse(inputDigits) {
		base10Input += powInt(inputBase, i) * digit
	}
	fmt.Printf("getBase10Input(%d, %v)=%d\n", inputBase, inputDigits, base10Input)
	return base10Input
}

func negativeDigit(input []int) bool {
	for _, digit := range input {
		if digit < 0 {
			return true
		}
	}
	return false
}

func reverse(input []int) (reversed []int) {
	for i := len(input) - 1; i >= 0; i-- {
		reversed = append(reversed, input[i])
	}
	return reversed
}

func powInt(x, y int) int {
	return int(math.Pow(float64(x), float64(y)))
}
<commit_msg>Solve all your base<commit_after>package allyourbase

import (
	"errors"
	"fmt"
	"math"
)

func ConvertToBase(inputBase int, inputDigits []int, outputBase int) (outputDigits []int, e error) {
	if inputBase < 2 {
		return []int{}, errors.New("input base must be >= 2")
	}
	if outputBase < 2 {
		return []int{}, errors.New("output base must be >= 2")
	}
	if invalidDigit(inputBase, inputDigits) {
		return []int{}, errors.New("all digits must satisfy 0 <= d < input base")
	}
	base10 := getBase10Input(inputBase, inputDigits)
	if base10 == 0 {
		return []int{0}, nil
	}
	for base10 > 0 {
		digit := base10 % outputBase
		outputDigits = append([]int{digit}, outputDigits...)
		base10 = base10 / outputBase
	}
	return outputDigits, nil
}

func getBase10Input(inputBase int, inputDigits []int) (base10Input int) {
	for i, digit := range reverse(inputDigits) {
		base10Input += powInt(inputBase, i) * digit
	}
	fmt.Printf("getBase10Input(%d, %v)=%d\n", inputBase, inputDigits, base10Input)
	return base10Input
}

func invalidDigit(inputBase int, input []int) bool {
	for _, digit := range input {
		if digit < 0 {
			return true
		}
		if digit >= inputBase {
			return true
		}
	}
	return false
}

func reverse(input []int) (reversed []int) {
	for i := len(input) - 1; i >= 0; i-- {
		reversed = append(reversed, input[i])
	}
	return reversed
}

func powInt(x, y int) int {
	return int(math.Pow(float64(x), float64(y)))
}
<|endoftext|>


<commit_before>package cryptosquare

import (
	"fmt"
	"math"
	"strings"
	"unicode"
)

func Encode(plainText string) (cipherText string) {
	formatted := removeFormating(plainText)
	numCols, numRows := getRectangleDimensions(len(formatted))
	rectangle := getRectangle(formatted, numCols, numRows)
	encoded := getEncoded(rectangle, numCols, numRows)
	cipherText = strings.Join(splitEveryN(encoded, numRows), " ")
	return cipherText
}

func removeFormating(plainText string) (result string) {
	for _, r := range strings.ToLower(plainText) {
		if unicode.IsLetter(r) || unicode.IsDigit(r) {
			result += string(r)
		}
	}
	return result
}

func getRectangleDimensions(messageLength int) (numCols int, numRows int) {
	x := math.Trunc(math.Sqrt(float64(messageLength)))
	if x*x >= float64(messageLength) {
		return int(x), int(x)
	} else if (x+1)*x >= float64(messageLength) {
		return int(x + 1), int(x)
	} else {
		return int(x + 1), int(x + 1)
	}
}

func getRectangle(message string, numCols int, numRows int) (rectangle [][]rune) {
	rectangle = initializeRectangle(numCols, numRows)
	index := 0
	for row := 0; row < numRows; row++ {
		for col := 0; col < numCols; col++ {
			if index >= len(message) {
				rectangle[row][col] = ' '
			} else {
				rectangle[row][col] = []rune(message)[index]
				index += 1
			}
		}
	}
	fmt.Printf("rectangle %v\n", rectangle)
	return rectangle
}

func initializeRectangle(numCols int, numRows int) (rectangle [][]rune) {
	rectangle = make([][]rune, numRows)
	for i := range rectangle {
		rectangle[i] = make([]rune, numCols)
	}
	return rectangle
}

func getEncoded(rectangle [][]rune, numCols int, numRows int) (encoded string) {
	for col := 0; col < numCols; col++ {
		for row := 0; row < numRows; row++ {
			encoded += string(rectangle[row][col])
		}
	}
	fmt.Printf("encoded %v\n", encoded)
	return encoded
}

func splitEveryN(message string, n int) (chunked []string) {
	for i := 0; i < len(message); i += n {
		upperBound := int(math.Min(float64(len(message)), float64(i+n)))
		chunked = append(chunked, message[i:upperBound])
	}
	fmt.Printf("chunked %v\n", chunked)
	return chunked
}
<commit_msg>Remove debug logs<commit_after>package cryptosquare

import (
	"math"
	"strings"
	"unicode"
)

func Encode(plainText string) (cipherText string) {
	formatted := removeFormating(plainText)
	numCols, numRows := getRectangleDimensions(len(formatted))
	rectangle := getRectangle(formatted, numCols, numRows)
	encoded := getEncoded(rectangle, numCols, numRows)
	cipherText = strings.Join(splitEveryN(encoded, numRows), " ")
	return cipherText
}

func removeFormating(plainText string) (result string) {
	for _, r := range strings.ToLower(plainText) {
		if unicode.IsLetter(r) || unicode.IsDigit(r) {
			result += string(r)
		}
	}
	return result
}

func getRectangleDimensions(messageLength int) (numCols int, numRows int) {
	x := math.Trunc(math.Sqrt(float64(messageLength)))
	if x*x >= float64(messageLength) {
		return int(x), int(x)
	} else if (x+1)*x >= float64(messageLength) {
		return int(x + 1), int(x)
	} else {
		return int(x + 1), int(x + 1)
	}
}

func getRectangle(message string, numCols int, numRows int) (rectangle [][]rune) {
	rectangle = initializeRectangle(numCols, numRows)
	index := 0
	for row := 0; row < numRows; row++ {
		for col := 0; col < numCols; col++ {
			if index >= len(message) {
				rectangle[row][col] = ' '
			} else {
				rectangle[row][col] = []rune(message)[index]
				index += 1
			}
		}
	}
	return rectangle
}

func initializeRectangle(numCols int, numRows int) (rectangle [][]rune) {
	rectangle = make([][]rune, numRows)
	for i := range rectangle {
		rectangle[i] = make([]rune, numCols)
	}
	return rectangle
}

func getEncoded(rectangle [][]rune, numCols int, numRows int) (encoded string) {
	for col := 0; col < numCols; col++ {
		for row := 0; row < numRows; row++ {
			encoded += string(rectangle[row][col])
		}
	}
	return encoded
}

func splitEveryN(message string, n int) (chunked []string) {
	for i := 0; i < len(message); i += n {
		upperBound := int(math.Min(float64(len(message)), float64(i+n)))
		chunked = append(chunked, message[i:upperBound])
	}
	return chunked
}
<|endoftext|>


<commit_before>package config

type Config struct {
	Foo string
	Bar int
}

var EventExchangeName = "EventExchange"
<commit_msg>Social: change exchange names<commit_after>package config

type Config struct {
	Foo string
	Bar int
}

var EventExchangeName = "SocialApiEventExchange"
<|endoftext|>


<commit_before>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package updater

import (
	"io"
	"testing"
	"time"

	"github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/logger"
	"github.com/keybase/client/go/protocol"
	"golang.org/x/net/context"
)

// TestUpdateCheckerIsAsync checks to make sure if the updater is blocked in a
// prompt that checks continue. This is safe because the updater is
// singleflighted.
func TestUpdateCheckerIsAsync(t *testing.T) {
	updater, err := NewTestUpdater(t, NewDefaultTestUpdateConfig(), nil)
	if err != nil {
		t.Fatal(err)
	}

	checker := newUpdateChecker(updater, testUpdateCheckUI{}, logger.NewTestLogger(t), 50*time.Millisecond, 100*time.Millisecond)
	defer checker.Stop()
	checker.Start()

	time.Sleep(400 * time.Millisecond)

	if checker.Count() <= 2 {
		t.Fatal("Checker should have checked more than once")
	}
}

type testUpdateCheckUI struct{}

func (u testUpdateCheckUI) UpdatePrompt(_ context.Context, _ keybase1.UpdatePromptArg) (keybase1.UpdatePromptRes, error) {
	time.Sleep(400 * time.Millisecond)
	return keybase1.UpdatePromptRes{Action: keybase1.UpdateAction_UPDATE}, nil
}

func (u testUpdateCheckUI) UpdateQuit(_ context.Context) (keybase1.UpdateQuitRes, error) {
	return keybase1.UpdateQuitRes{Quit: false}, nil
}

func (u testUpdateCheckUI) GetUpdateUI() (libkb.UpdateUI, error) {
	return u, nil
}

func (u testUpdateCheckUI) AfterUpdateApply(willRestart bool) error {
	return nil
}

func (u testUpdateCheckUI) Verify(r io.Reader, signature string) error {
	return nil
}

func (u testUpdateCheckUI) UpdateAppInUse(context.Context, keybase1.UpdateAppInUseArg) (keybase1.UpdateAppInUseRes, error) {
	return keybase1.UpdateAppInUseRes{Action: keybase1.UpdateAppInUseAction_CANCEL}, nil
}
<commit_msg>Fix test after merge (update checker)<commit_after>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package updater

import (
	"io"
	"testing"
	"time"

	"github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/logger"
	"github.com/keybase/client/go/protocol"
	"golang.org/x/net/context"
)

// TestUpdateCheckerIsAsync checks to make sure if the updater is blocked in a
// prompt that checks continue. This is safe because the updater is
// singleflighted.
func TestUpdateCheckerIsAsync(t *testing.T) {
	updater, err := NewTestUpdater(t, NewDefaultTestUpdateConfig(), nil)
	if err != nil {
		t.Fatal(err)
	}

	checker := newUpdateChecker(updater, testUpdateCheckUI{}, logger.NewTestLogger(t), 50*time.Millisecond, 100*time.Millisecond)
	defer checker.Stop()
	checker.Start()

	time.Sleep(400 * time.Millisecond)

	if checker.Count() <= 2 {
		t.Fatal("Checker should have checked more than once")
	}
}

type testUpdateCheckUI struct{}

func (u testUpdateCheckUI) UpdatePrompt(_ context.Context, _ keybase1.UpdatePromptArg) (keybase1.UpdatePromptRes, error) {
	time.Sleep(400 * time.Millisecond)
	return keybase1.UpdatePromptRes{Action: keybase1.UpdateAction_UPDATE}, nil
}

func (u testUpdateCheckUI) UpdateQuit(_ context.Context, _ keybase1.UpdateQuitArg) (keybase1.UpdateQuitRes, error) {
	return keybase1.UpdateQuitRes{Quit: false}, nil
}

func (u testUpdateCheckUI) GetUpdateUI() (libkb.UpdateUI, error) {
	return u, nil
}

func (u testUpdateCheckUI) AfterUpdateApply(willRestart bool) error {
	return nil
}

func (u testUpdateCheckUI) Verify(r io.Reader, signature string) error {
	return nil
}

func (u testUpdateCheckUI) UpdateAppInUse(context.Context, keybase1.UpdateAppInUseArg) (keybase1.UpdateAppInUseRes, error) {
	return keybase1.UpdateAppInUseRes{Action: keybase1.UpdateAppInUseAction_CANCEL}, nil
}
<|endoftext|>


<commit_before>package api

import (
	"errors"
	"fmt"
	"log"
	"time"

	entities "github.com/gost/core"
	gostErrors "github.com/gost/server/errors"
	"github.com/gost/server/sensorthings/odata"
)

// PostLocation tries to add a new location
func (a *APIv1) PostLocation(location *entities.Location) (*entities.Location, []error) {
	_, err := containsMandatoryParams(location)
	if err != nil {
		return nil, err
	}

	if location.EncodingType != entities.EncodingGeoJSON.Value {
		err := errors.New("Encoding not supported. Supported encoding: " + entities.EncodingGeoJSON.Value)
		return nil, []error{err}
	}

	l, err2 := a.db.PostLocation(location)
	if err2 != nil {
		return nil, []error{err2}
	}
	l.SetAllLinks(a.config.GetExternalServerURI())
	a.sendLocationOverMQTT(nil, l, "Locations")

	return l, nil
}

// PostLocationByThing checks if the given location entity is valid and adds it to the database
// the new location will be linked to a thing if needed
func (a *APIv1) PostLocationByThing(thingID interface{}, location *entities.Location) (*entities.Location, []error) {
	var err []error
	var err2 error
	l, err := a.PostLocation(location)
	if len(err) > 0 {
		return nil, err
	}

	if thingID != nil {
		err2 = a.LinkLocation(thingID, l.ID)
		if err2 != nil {
			err3 := a.DeleteLocation(l.ID)
			if err3 != nil {
				log.Printf("Error rolling back location %v", err2)
			}

			return nil, []error{err2}
		}

		hl := &entities.HistoricalLocation{
			Thing:     &entities.Thing{},
			Locations: []*entities.Location{l},
		}

		hl.Thing.ID = thingID
		hl.Time = time.Now().UTC().Format(time.RFC3339Nano)
		hl.ContainsMandatoryParams()

		_, err = a.PostHistoricalLocation(hl)
		if len(err) > 0 {
			err2 := a.DeleteHistoricalLocation(l.ID)
			if err2 != nil {
				log.Printf("Error rolling back location %v", err2)
			}

			return nil, []error{err2}
		}
	}

	l.SetAllLinks(a.config.GetExternalServerURI())

	a.sendOverMQTT(l, fmt.Sprintf("Things(%v)/Locations", thingID))

	return l, nil
}

// GetLocation retrieves a single location by id
func (a *APIv1) GetLocation(id interface{}, qo *odata.QueryOptions, path string) (*entities.Location, error) {
	l, err := a.db.GetLocation(id, qo)
	if err != nil {
		return nil, err
	}

	a.SetLinks(l, qo)
	return l, nil
}

// GetLocations retrieves all locations from the database and returns it as and ArrayResponse
func (a *APIv1) GetLocations(qo *odata.QueryOptions, path string) (*entities.ArrayResponse, error) {
	locations, count, hasNext, err := a.db.GetLocations(qo)
	return processLocations(a, locations, qo, path, count, hasNext, err)
}

// GetLocationsByHistoricalLocation retrieves the latest locations linked to a HistoricalLocation
func (a *APIv1) GetLocationsByHistoricalLocation(hlID interface{}, qo *odata.QueryOptions, path string) (*entities.ArrayResponse, error) {
	locations, count, hasNext, err := a.db.GetLocationsByHistoricalLocation(hlID, qo)
	return processLocations(a, locations, qo, path, count, hasNext, err)
}

// GetLocationsByThing retrieves the latest locations linked to a thing
func (a *APIv1) GetLocationsByThing(thingID interface{}, qo *odata.QueryOptions, path string) (*entities.ArrayResponse, error) {
	locations, count, hasNext, err := a.db.GetLocationsByThing(thingID, qo)
	return processLocations(a, locations, qo, path, count, hasNext, err)
}

func processLocations(a *APIv1, locations []*entities.Location, qo *odata.QueryOptions, path string, count int, hasNext bool, err error) (*entities.ArrayResponse, error) {
	for idx, item := range locations {
		i := *item
		a.SetLinks(&i, qo)
		locations[idx] = &i
	}

	var data interface{} = locations
	return a.createArrayResponse(count, hasNext, path, qo, data), nil
}

// PatchLocation updates the given location in the database
func (a *APIv1) PatchLocation(id interface{}, location *entities.Location) (*entities.Location, error) {
	if location.HistoricalLocations != nil || location.Things != nil {
		return nil, gostErrors.NewBadRequestError(errors.New("Unable to deep patch Location"))
	}

	if len(location.EncodingType) != 0 {
		if location.EncodingType != entities.EncodingGeoJSON.Value {
			err := errors.New("Encoding not supported. Supported encoding: " + entities.EncodingGeoJSON.Value)
			return nil, err
		}
	}

	return a.db.PatchLocation(id, location)
}

// PutLocation updates the given thing in the database
func (a *APIv1) PutLocation(id interface{}, location *entities.Location) (*entities.Location, []error) {
	var err2 error
	putlocation, err2 := a.db.PutLocation(id, location)
	if err2 != nil {
		return nil, []error{err2}
	}

	putlocation.SetAllLinks(a.config.GetExternalServerURI())
	return putlocation, nil
}

// DeleteLocation deletes a given Location from the database
func (a *APIv1) DeleteLocation(id interface{}) error {
	return a.db.DeleteLocation(id)
}

// LinkLocation links a thing with a location in the database
func (a *APIv1) LinkLocation(thingID interface{}, locationID interface{}) error {
	err := a.db.LinkLocation(thingID, locationID)
	if err != nil {
		return gostErrors.NewBadRequestError(err)
	}
	return nil
}
<commit_msg>fix build<commit_after>package api

import (
	"errors"
	"fmt"
	"log"
	"time"

	entities "github.com/gost/core"
	gostErrors "github.com/gost/server/errors"
	"github.com/gost/server/sensorthings/odata"
)

// PostLocation tries to add a new location
func (a *APIv1) PostLocation(location *entities.Location) (*entities.Location, []error) {
	_, err := containsMandatoryParams(location)
	if err != nil {
		return nil, err
	}

	if location.EncodingType != entities.EncodingGeoJSON.Value {
		err := errors.New("Encoding not supported. Supported encoding: " + entities.EncodingGeoJSON.Value)
		return nil, []error{err}
	}

	l, err2 := a.db.PostLocation(location)
	if err2 != nil {
		return nil, []error{err2}
	}
	l.SetAllLinks(a.config.GetExternalServerURI())
	a.sendOverMQTT(l, "Locations")

	return l, nil
}

// PostLocationByThing checks if the given location entity is valid and adds it to the database
// the new location will be linked to a thing if needed
func (a *APIv1) PostLocationByThing(thingID interface{}, location *entities.Location) (*entities.Location, []error) {
	var err []error
	var err2 error
	l, err := a.PostLocation(location)
	if len(err) > 0 {
		return nil, err
	}

	if thingID != nil {
		err2 = a.LinkLocation(thingID, l.ID)
		if err2 != nil {
			err3 := a.DeleteLocation(l.ID)
			if err3 != nil {
				log.Printf("Error rolling back location %v", err2)
			}

			return nil, []error{err2}
		}

		hl := &entities.HistoricalLocation{
			Thing:     &entities.Thing{},
			Locations: []*entities.Location{l},
		}

		hl.Thing.ID = thingID
		hl.Time = time.Now().UTC().Format(time.RFC3339Nano)
		hl.ContainsMandatoryParams()

		_, err = a.PostHistoricalLocation(hl)
		if len(err) > 0 {
			err2 := a.DeleteHistoricalLocation(l.ID)
			if err2 != nil {
				log.Printf("Error rolling back location %v", err2)
			}

			return nil, []error{err2}
		}
	}

	l.SetAllLinks(a.config.GetExternalServerURI())

	a.sendOverMQTT(l, fmt.Sprintf("Things(%v)/Locations", thingID))

	return l, nil
}

// GetLocation retrieves a single location by id
func (a *APIv1) GetLocation(id interface{}, qo *odata.QueryOptions, path string) (*entities.Location, error) {
	l, err := a.db.GetLocation(id, qo)
	if err != nil {
		return nil, err
	}

	a.SetLinks(l, qo)
	return l, nil
}

// GetLocations retrieves all locations from the database and returns it as and ArrayResponse
func (a *APIv1) GetLocations(qo *odata.QueryOptions, path string) (*entities.ArrayResponse, error) {
	locations, count, hasNext, err := a.db.GetLocations(qo)
	return processLocations(a, locations, qo, path, count, hasNext, err)
}

// GetLocationsByHistoricalLocation retrieves the latest locations linked to a HistoricalLocation
func (a *APIv1) GetLocationsByHistoricalLocation(hlID interface{}, qo *odata.QueryOptions, path string) (*entities.ArrayResponse, error) {
	locations, count, hasNext, err := a.db.GetLocationsByHistoricalLocation(hlID, qo)
	return processLocations(a, locations, qo, path, count, hasNext, err)
}

// GetLocationsByThing retrieves the latest locations linked to a thing
func (a *APIv1) GetLocationsByThing(thingID interface{}, qo *odata.QueryOptions, path string) (*entities.ArrayResponse, error) {
	locations, count, hasNext, err := a.db.GetLocationsByThing(thingID, qo)
	return processLocations(a, locations, qo, path, count, hasNext, err)
}

func processLocations(a *APIv1, locations []*entities.Location, qo *odata.QueryOptions, path string, count int, hasNext bool, err error) (*entities.ArrayResponse, error) {
	for idx, item := range locations {
		i := *item
		a.SetLinks(&i, qo)
		locations[idx] = &i
	}

	var data interface{} = locations
	return a.createArrayResponse(count, hasNext, path, qo, data), nil
}

// PatchLocation updates the given location in the database
func (a *APIv1) PatchLocation(id interface{}, location *entities.Location) (*entities.Location, error) {
	if location.HistoricalLocations != nil || location.Things != nil {
		return nil, gostErrors.NewBadRequestError(errors.New("Unable to deep patch Location"))
	}

	if len(location.EncodingType) != 0 {
		if location.EncodingType != entities.EncodingGeoJSON.Value {
			err := errors.New("Encoding not supported. Supported encoding: " + entities.EncodingGeoJSON.Value)
			return nil, err
		}
	}

	return a.db.PatchLocation(id, location)
}

// PutLocation updates the given thing in the database
func (a *APIv1) PutLocation(id interface{}, location *entities.Location) (*entities.Location, []error) {
	var err2 error
	putlocation, err2 := a.db.PutLocation(id, location)
	if err2 != nil {
		return nil, []error{err2}
	}

	putlocation.SetAllLinks(a.config.GetExternalServerURI())
	return putlocation, nil
}

// DeleteLocation deletes a given Location from the database
func (a *APIv1) DeleteLocation(id interface{}) error {
	return a.db.DeleteLocation(id)
}

// LinkLocation links a thing with a location in the database
func (a *APIv1) LinkLocation(thingID interface{}, locationID interface{}) error {
	err := a.db.LinkLocation(thingID, locationID)
	if err != nil {
		return gostErrors.NewBadRequestError(err)
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"os"
	"path/filepath"
)

var pluginCachePath = filepath.Join(AppDir(), "plugin-cache.json")

// UpdatePluginCache updates all the plugins in ~/.heroku/plugin-cache.json
func UpdatePluginCache() {
	cache := FetchPluginCache()
	for _, plugin := range cache {
		cache[plugin.Name] = getPlugin(plugin.Name, false)
	}
	savePluginCache(cache)
}

// AddPluginsToCache adds/updates a set of plugins to ~/.heroku/plugin-cache.json
func AddPluginsToCache(plugins ...*Plugin) {
	cache := FetchPluginCache()
	for _, plugin := range plugins {
		cache[plugin.Name] = plugin
	}
	savePluginCache(cache)
}

func savePluginCache(cache map[string]*Plugin) {
	f, err := os.Create(pluginCachePath)
	if err != nil {
		panic(err)
	}
	if err := json.NewEncoder(f).Encode(cache); err != nil {
		panic(err)
	}
}

// FetchPluginCache returns the plugins from the cache
func FetchPluginCache() map[string]*Plugin {
	plugins := make(map[string]*Plugin, 100)
	if exists, _ := fileExists(pluginCachePath); !exists {
		return plugins
	}
	f, err := os.Open(pluginCachePath)
	if err != nil {
		return plugins
	}
	if err := json.NewDecoder(f).Decode(&plugins); err != nil {
		panic(err)
	}
	return plugins
}
<commit_msg>only add real plugins to cache<commit_after>package main

import (
	"encoding/json"
	"os"
	"path/filepath"
)

var pluginCachePath = filepath.Join(AppDir(), "plugin-cache.json")

// UpdatePluginCache updates all the plugins in ~/.heroku/plugin-cache.json
func UpdatePluginCache() {
	cache := FetchPluginCache()
	for _, plugin := range cache {
		cache[plugin.Name] = getPlugin(plugin.Name, false)
	}
	savePluginCache(cache)
}

// AddPluginsToCache adds/updates a set of plugins to ~/.heroku/plugin-cache.json
func AddPluginsToCache(plugins ...*Plugin) {
	cache := FetchPluginCache()
	for _, plugin := range plugins {
		if plugin != nil {
			cache[plugin.Name] = plugin
		}
	}
	savePluginCache(cache)
}

func savePluginCache(cache map[string]*Plugin) {
	f, err := os.Create(pluginCachePath)
	if err != nil {
		panic(err)
	}
	if err := json.NewEncoder(f).Encode(cache); err != nil {
		panic(err)
	}
}

// FetchPluginCache returns the plugins from the cache
func FetchPluginCache() map[string]*Plugin {
	plugins := make(map[string]*Plugin, 100)
	if exists, _ := fileExists(pluginCachePath); !exists {
		return plugins
	}
	f, err := os.Open(pluginCachePath)
	if err != nil {
		return plugins
	}
	if err := json.NewDecoder(f).Decode(&plugins); err != nil {
		panic(err)
	}
	return plugins
}
<|endoftext|>


<commit_before>package simra

import (
	"image"
	"image/color"

	"github.com/pankona/gomo-simra/simra/gomo"
	"github.com/pankona/gomo-simra/simra/peer"
)

// Simra is a struct that provides API interface of simra
type Simra struct {
	driver Driver
}

var simra *Simra

// GetInstance returns instance of Simra.
// It is necessary to call this function to get Simra instance
// since Simra is single instance.
func GetInstance() *Simra {
	//peer.LogDebug("IN")
	if simra == nil {
		simra = &Simra{}
	}
	//peer.LogDebug("OUT")
	return simra
}

type point struct {
	x, y int
}

func (simra *Simra) onUpdate() {
	if simra.driver != nil {
		simra.driver.Drive()
	}

	simra.collisionCheckAndNotify()
}

func (simra *Simra) onStopped() {
	peer.LogDebug("IN")
	simra.driver = nil
	peer.GetGLPeer().Finalize()
	peer.LogDebug("OUT")
}

// Start needs to call to enable all function belong to simra package.
func (simra *Simra) Start(onStart, onStop chan bool) {
	peer.LogDebug("IN")
	gomo.GetInstance().Initialize(onStart, onStop, simra.onUpdate)
	peer.GetSpriteContainer().Initialize()

	gomo.GetInstance().Start()
	peer.LogDebug("OUT")
}

// SetScene sets a driver as a scene.
// If a driver is already set, it is replaced with new one.
func (simra *Simra) SetScene(driver Driver) {
	peer.LogDebug("IN")
	peer.GetGLPeer().Reset()
	peer.GetSpriteContainer().RemoveSprites()

	simra.driver = driver
	driver.Initialize()
	peer.LogDebug("OUT")
}

// AddSprite adds a sprite to current scene.
// To call this function, SetScene must be called in advance.
// TODO: remove this function. this function is deprecated. use AddImageSprite instead.
func (simra *Simra) AddSprite(assetName string, rect image.Rectangle, s *Sprite) {
	simra.AddImageSprite(assetName, rect, s)
}

// AddImageSprite adds a sprite to current scene.
// To call this function, SetScene must be called in advance.
func (simra *Simra) AddImageSprite(assetName string, rect image.Rectangle, s *Sprite) {
	tex := peer.GetGLPeer().LoadTexture(assetName, rect)
	peer.GetSpriteContainer().AddSprite(&s.Sprite, tex)
}

// AddTextSprite adds a sprite to current scene.
// To call this function, SetScene must be called in advance.
func (simra *Simra) AddTextSprite(text string, fontsize float64, fontcolor color.RGBA, rect image.Rectangle, s *Sprite) {
	tex := peer.GetGLPeer().MakeTextureByText(text, fontsize, fontcolor, rect)
	peer.GetSpriteContainer().AddSprite(&s.Sprite, tex)
}

// RemoveSprite removes specified sprite from current scene.
// Removed sprite will be disappeared.
func (simra *Simra) RemoveSprite(s *Sprite) {
	peer.GetSpriteContainer().RemoveSprite(&s.Sprite)
}

// SetDesiredScreenSize configures virtual screen size.
// This function must be called at least once before calling Start.
func (simra *Simra) SetDesiredScreenSize(w, h float32) {
	peer.SetDesiredScreenSize(w, h)
}

// AddTouchListener registers a listener for notifying touch event.
// Event is notified when "screen" is touched.
func (simra *Simra) AddTouchListener(listener peer.TouchListener) {
	peer.GetTouchPeer().AddTouchListener(listener)
}

// RemoveTouchListener unregisters a listener for notifying touch event.
func (simra *Simra) RemoveTouchListener(listener peer.TouchListener) {
	peer.GetTouchPeer().RemoveTouchListener(listener)
}

// LogDebug prints logs.
// From simra, just call peer.LogDebug.
// This is disabled at Release Build.
func LogDebug(format string, a ...interface{}) {
	peer.LogDebug(format, a...)
}

// LogError prints logs.
// From simra, just call peer.LogError.
// This is never disabled even for Release build.
func LogError(format string, a ...interface{}) {
	peer.LogError(format, a...)
}
<commit_msg>remove and initialize touch listener on scene change<commit_after>package simra

import (
	"image"
	"image/color"

	"github.com/pankona/gomo-simra/simra/gomo"
	"github.com/pankona/gomo-simra/simra/peer"
)

// Simra is a struct that provides API interface of simra
type Simra struct {
	driver Driver
}

var simra *Simra

// GetInstance returns instance of Simra.
// It is necessary to call this function to get Simra instance
// since Simra is single instance.
func GetInstance() *Simra {
	//peer.LogDebug("IN")
	if simra == nil {
		simra = &Simra{}
	}
	//peer.LogDebug("OUT")
	return simra
}

type point struct {
	x, y int
}

func (simra *Simra) onUpdate() {
	if simra.driver != nil {
		simra.driver.Drive()
	}

	simra.collisionCheckAndNotify()
}

func (simra *Simra) onStopped() {
	peer.LogDebug("IN")
	simra.driver = nil
	peer.GetGLPeer().Finalize()
	peer.LogDebug("OUT")
}

// Start needs to call to enable all function belong to simra package.
func (simra *Simra) Start(onStart, onStop chan bool) {
	peer.LogDebug("IN")
	gomo.GetInstance().Initialize(onStart, onStop, simra.onUpdate)
	peer.GetSpriteContainer().Initialize()

	gomo.GetInstance().Start()
	peer.LogDebug("OUT")
}

// SetScene sets a driver as a scene.
// If a driver is already set, it is replaced with new one.
func (simra *Simra) SetScene(driver Driver) {
	peer.LogDebug("IN")
	peer.GetGLPeer().Reset()
	peer.GetTouchPeer().RemoveAllTouchListener()
	peer.GetSpriteContainer().RemoveSprites()

	simra.driver = driver
	peer.GetSpriteContainer().Initialize()
	driver.Initialize()
	peer.LogDebug("OUT")
}

// AddSprite adds a sprite to current scene.
// To call this function, SetScene must be called in advance.
// TODO: remove this function. this function is deprecated. use AddImageSprite instead.
func (simra *Simra) AddSprite(assetName string, rect image.Rectangle, s *Sprite) {
	simra.AddImageSprite(assetName, rect, s)
}

// AddImageSprite adds a sprite to current scene.
// To call this function, SetScene must be called in advance.
func (simra *Simra) AddImageSprite(assetName string, rect image.Rectangle, s *Sprite) {
	tex := peer.GetGLPeer().LoadTexture(assetName, rect)
	peer.GetSpriteContainer().AddSprite(&s.Sprite, tex)
}

// AddTextSprite adds a sprite to current scene.
// To call this function, SetScene must be called in advance.
func (simra *Simra) AddTextSprite(text string, fontsize float64, fontcolor color.RGBA, rect image.Rectangle, s *Sprite) {
	tex := peer.GetGLPeer().MakeTextureByText(text, fontsize, fontcolor, rect)
	peer.GetSpriteContainer().AddSprite(&s.Sprite, tex)
}

// RemoveSprite removes specified sprite from current scene.
// Removed sprite will be disappeared.
func (simra *Simra) RemoveSprite(s *Sprite) {
	peer.GetSpriteContainer().RemoveSprite(&s.Sprite)
}

// SetDesiredScreenSize configures virtual screen size.
// This function must be called at least once before calling Start.
func (simra *Simra) SetDesiredScreenSize(w, h float32) {
	peer.SetDesiredScreenSize(w, h)
}

// AddTouchListener registers a listener for notifying touch event.
// Event is notified when "screen" is touched.
func (simra *Simra) AddTouchListener(listener peer.TouchListener) {
	peer.GetTouchPeer().AddTouchListener(listener)
}

// RemoveTouchListener unregisters a listener for notifying touch event.
func (simra *Simra) RemoveTouchListener(listener peer.TouchListener) {
	peer.GetTouchPeer().RemoveTouchListener(listener)
}

// LogDebug prints logs.
// From simra, just call peer.LogDebug.
// This is disabled at Release Build.
func LogDebug(format string, a ...interface{}) {
	peer.LogDebug(format, a...)
}

// LogError prints logs.
// From simra, just call peer.LogError.
// This is never disabled even for Release build.
func LogError(format string, a ...interface{}) {
	peer.LogError(format, a...)
}
<|endoftext|>