<commit_before>// Copyright 2014 The lime Authors.
// Use of this source code is governed by a 2-clause
// BSD-style license that can be found in the LICENSE file.

package render

import (
	"github.com/quarnster/util/text"
	"reflect"
	"testing"
)

func TestViewRegionsCull(t *testing.T) {
	tests := []struct {
		regions []text.Region
		cull    text.Region
		exp     []text.Region
	}{
		{
			[]text.Region{{100, 200}},
			text.Region{0, 50},
			[]text.Region{},
		},
		{
			[]text.Region{{100, 100}},
			text.Region{100, 100},
			[]text.Region{},
		},
		{
			[]text.Region{{100, 100}},
			text.Region{95, 105},
			[]text.Region{},
		},
		{
			[]text.Region{{100, 100}},
			text.Region{95, 100},
			[]text.Region{},
		},
		{
			[]text.Region{{100, 200}},
			text.Region{150, 150},
			[]text.Region{},
		},
		{
			[]text.Region{{100, 200}},
			text.Region{90, 100},
			[]text.Region{},
		},
		{
			[]text.Region{{100, 200}},
			text.Region{100, 150},
			[]text.Region{{100, 150}},
		},
		{
			[]text.Region{{100, 200}},
			text.Region{150, 175},
			[]text.Region{{150, 175}},
		},
		{
			[]text.Region{{100, 200}},
			text.Region{0, 150},
			[]text.Region{{100, 150}},
		},
		{
			[]text.Region{{100, 200}},
			text.Region{150, 250},
			[]text.Region{{150, 200}},
		},
		{
			[]text.Region{{100, 200}},
			text.Region{0, 250},
			[]text.Region{{100, 200}},
		},
		{
			[]text.Region{{100, 200}, {300, 400}},
			text.Region{0, 500},
			[]text.Region{{100, 200}, {300, 400}},
		},
		{
			[]text.Region{{100, 200}, {300, 400}},
			text.Region{150, 350},
			[]text.Region{{150, 200}, {300, 350}},
		},
		{
			[]text.Region{{100, 200}, {300, 400}},
			text.Region{150, 250},
			[]text.Region{{150, 200}},
		},
		{
			[]text.Region{{100, 200}, {300, 400}},
			text.Region{250, 350},
			[]text.Region{{300, 350}},
		},
	}

	for i, test := range tests {
		vr := ViewRegions{}
		vr.Regions.AddAll(test.regions)

		vr.Cull(test.cull)

		r := vr.Regions.Regions()

		if !reflect.DeepEqual(r, test.exp) {
			t.Errorf("Test %d: Expected %s, but got %s", i, test.exp, r)
		}
	}
}

func TestViewRegionsClone(t *testing.T) {
	vr := ViewRegions{
		Scope: "testScope",
		Icon:  "testIcon",
		Flags: 100,
	}
	vr.Regions.AddAll([]text.Region{{0, 0}, {120, 300}, {24, 34}, {45, 40}})

	c := vr.Clone()
	if !reflect.DeepEqual(c, vr) {
		t.Errorf("Expected %+v, but got %+v", vr, c)
	}
}
<commit_msg>Add ViewRegionMap tests.<commit_after>// Copyright 2014 The lime Authors.
// Use of this source code is governed by a 2-clause
// BSD-style license that can be found in the LICENSE file.

package render

import (
	"github.com/quarnster/util/text"
	"reflect"
	"testing"
)

func TestViewRegionMapCull(t *testing.T) {
	tests := []struct {
		regionsA []text.Region
		regionsB []text.Region
		cull     text.Region
		expA     []text.Region
		expB     []text.Region
	}{
		{
			[]text.Region{},
			[]text.Region{},
			text.Region{},
			nil,
			nil,
		},
		{
			[]text.Region{{100, 200}},
			[]text.Region{},
			text.Region{},
			nil,
			nil,
		},
		{
			[]text.Region{},
			[]text.Region{},
			text.Region{0, 50},
			nil,
			nil,
		},
		{
			[]text.Region{{100, 200}},
			[]text.Region{},
			text.Region{0, 50},
			nil,
			nil,
		},
		{
			[]text.Region{{100, 200}},
			[]text.Region{{300, 400}},
			text.Region{0, 50},
			nil,
			nil,
		},
		{
			[]text.Region{{100, 200}},
			[]text.Region{{300, 400}},
			text.Region{0, 150},
			[]text.Region{{100, 150}},
			nil,
		},
		{
			[]text.Region{{100, 200}},
			[]text.Region{{300, 400}},
			text.Region{150, 350},
			[]text.Region{{150, 200}},
			[]text.Region{{300, 350}},
		},
	}

	for i, test := range tests {
		vrm := ViewRegionMap{}

		vrA := ViewRegions{}
		vrA.Regions.AddAll(test.regionsA)
		vrm["A"] = vrA

		vrB := ViewRegions{}
		vrB.Regions.AddAll(test.regionsB)
		vrm["B"] = vrB

		vrm.Cull(test.cull)

		if test.expA != nil {
			rA := vrA.Regions.Regions()

			if !reflect.DeepEqual(rA, test.expA) {
				t.Errorf("Test %d: Expected %s, but got %s", i, test.expA, rA)
			}
		} else if _, ok := vrm["A"]; ok {
			t.Errorf("Test %d: Expected %s, but got %s", i, test.expA, vrm["A"])
		}

		if test.expB != nil {
			rB := vrB.Regions.Regions()

			if !reflect.DeepEqual(rB, test.expB) {
				t.Errorf("Test %d: Expected %s, but got %s", i, test.expB, rB)
			}
		} else if _, ok := vrm["B"]; ok {
			t.Errorf("Test %d: Expected %s, but got %s", i, test.expB, vrm["B"])
		}
	}
}

func TestViewRegionsCull(t *testing.T) {
	tests := []struct {
		regions []text.Region
		cull    text.Region
		exp     []text.Region
	}{
		{
			[]text.Region{{100, 200}},
			text.Region{0, 50},
			[]text.Region{},
		},
		{
			[]text.Region{{100, 100}},
			text.Region{100, 100},
			[]text.Region{},
		},
		{
			[]text.Region{{100, 100}},
			text.Region{95, 105},
			[]text.Region{},
		},
		{
			[]text.Region{{100, 100}},
			text.Region{95, 100},
			[]text.Region{},
		},
		{
			[]text.Region{{100, 200}},
			text.Region{150, 150},
			[]text.Region{},
		},
		{
			[]text.Region{{100, 200}},
			text.Region{90, 100},
			[]text.Region{},
		},
		{
			[]text.Region{{100, 200}},
			text.Region{100, 150},
			[]text.Region{{100, 150}},
		},
		{
			[]text.Region{{100, 200}},
			text.Region{150, 175},
			[]text.Region{{150, 175}},
		},
		{
			[]text.Region{{100, 200}},
			text.Region{0, 150},
			[]text.Region{{100, 150}},
		},
		{
			[]text.Region{{100, 200}},
			text.Region{150, 250},
			[]text.Region{{150, 200}},
		},
		{
			[]text.Region{{100, 200}},
			text.Region{0, 250},
			[]text.Region{{100, 200}},
		},
		{
			[]text.Region{{100, 200}, {300, 400}},
			text.Region{0, 500},
			[]text.Region{{100, 200}, {300, 400}},
		},
		{
			[]text.Region{{100, 200}, {300, 400}},
			text.Region{150, 350},
			[]text.Region{{150, 200}, {300, 350}},
		},
		{
			[]text.Region{{100, 200}, {300, 400}},
			text.Region{150, 250},
			[]text.Region{{150, 200}},
		},
		{
			[]text.Region{{100, 200}, {300, 400}},
			text.Region{250, 350},
			[]text.Region{{300, 350}},
		},
	}

	for i, test := range tests {
		vr := ViewRegions{}
		vr.Regions.AddAll(test.regions)

		vr.Cull(test.cull)

		r := vr.Regions.Regions()

		if !reflect.DeepEqual(r, test.exp) {
			t.Errorf("Test %d: Expected %s, but got %s", i, test.exp, r)
		}
	}
}

func TestViewRegionsClone(t *testing.T) {
	vr := ViewRegions{
		Scope: "testScope",
		Icon:  "testIcon",
		Flags: 100,
	}
	vr.Regions.AddAll([]text.Region{{0, 0}, {120, 300}, {24, 34}, {45, 40}})

	c := vr.Clone()
	if !reflect.DeepEqual(c, vr) {
		t.Errorf("Expected %+v, but got %+v", vr, c)
	}
}
<|endoftext|>


<commit_before>package client

import "fmt"

// A Command is a runnable sub-command of a CLI.
type Command interface {
	Run(args []string) error
}

type BaseCommand struct {
	Name        string
	Description string
	Usage       string
	ArgsUsage   string
	Action      func(interface{}) error
}

func (c *BaseCommand) Run(args []string) error {
	return fmt.Errorf("Should not be implemented")
}
<commit_msg>Remove unnecessary command file<commit_after><|endoftext|>


<commit_before>package morningStar

import (
	"bytes"
	"github.com/ViBiOh/funds/jsonHttp"
	"log"
	"net/http"
	"regexp"
	"sync"
	"time"
)

const refreshDelayInHours = 6
const maxConcurrentFetcher = 32

var requestStatus = regexp.MustCompile(`^/status$`)
var requestList = regexp.MustCompile(`^/list$`)
var requestPerf = regexp.MustCompile(`^/(.+?)$`)

type performance struct {
	ID            string    `json:"id"`
	Isin          string    `json:"isin"`
	Label         string    `json:"label"`
	Category      string    `json:"category"`
	Rating        string    `json:"rating"`
	OneMonth      float64   `json:"1m"`
	ThreeMonths   float64   `json:"3m"`
	SixMonths     float64   `json:"6m"`
	OneYear       float64   `json:"1y"`
	VolThreeYears float64   `json:"v3y"`
	Score         float64   `json:"score"`
	Update        time.Time `json:"ts"`
}

func (perf *performance) computeScore() {
	score := (0.25 * perf.OneMonth) + (0.3 * perf.ThreeMonths) + (0.25 * perf.SixMonths) + (0.2 * perf.OneYear) - (0.1 * perf.VolThreeYears)
	perf.Score = float64(int(score*100)) / 100
}

type results struct {
	Results interface{} `json:"results"`
}

var cacheRequests = make(chan *cacheRequest, maxConcurrentFetcher)

func init() {
	go cacheServer(cacheRequests)
	go func() {
		refreshCache()
		c := time.Tick(refreshDelayInHours * time.Hour)
		for range c {
			refreshCache()
		}
	}()
}

func concurrentRetrievePerformances(ids [][]byte, wg *sync.WaitGroup, performances chan<- *performance, errors chan<- []byte) {
	tokens := make(chan int, maxConcurrentFetcher)

	clearSemaphores := func() {
		wg.Done()
		<-tokens
	}

	for _, id := range ids {
		tokens <- 1

		go func(morningStarID []byte) {
			defer clearSemaphores()
			perf, err := fetchPerformance(morningStarID)
			if err == nil {
				performances <- perf
			} else {
				errors <- morningStarID
			}
		}(id)
	}
}

func retrievePerformances(ids [][]byte) ([]*performance, [][]byte) {
	var wgFetch sync.WaitGroup
	wgFetch.Add(len(ids))

	var wgDrain sync.WaitGroup
	wgDrain.Add(2)

	performancesChan := make(chan *performance, 0)
	errorsChan := make(chan []byte, 0)

	performances := make([]*performance, 0, len(ids))
	errors := make([][]byte, 0)

	go concurrentRetrievePerformances(ids, &wgFetch, performancesChan, errorsChan)

	go func() {
		wgFetch.Wait()
		close(performancesChan)
		close(errorsChan)
	}()

	go func() {
		for perf := range performancesChan {
			performances = append(performances, perf)
		}
		wgDrain.Done()
	}()

	go func() {
		for error := range errorsChan {
			errors = append(errors, error)
		}
		wgDrain.Done()
	}()

	wgDrain.Wait()

	return performances, errors
}

func refreshCache() {
	log.Print(`Cache refresh - start`)
	defer log.Print(`Cache refresh - end`)

	performances, errors := retrievePerformances(morningStarIds)

	if len(errors) > 0 {
		log.Printf(`Errors while refreshing ids %s`, bytes.Join(errors, []byte(`, `)))
	}

	loadCache(cacheRequests, performances)
}

func retrievePerformance(morningStarID []byte) (*performance, error) {
	perf := getCache(cacheRequests, cleanID(morningStarID))
	if perf != nil {
		return perf, nil
	}

	perf, err := fetchPerformance(morningStarID)
	if err != nil {
		return nil, err
	}

	pushCache(cacheRequests, perf)
	morningStarIds = append(morningStarIds, morningStarID)

	return perf, nil
}

func performanceHandler(w http.ResponseWriter, morningStarID []byte) {
	perf, err := retrievePerformance(morningStarID)

	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	} else {
		jsonHttp.ResponseJSON(w, *perf)
	}
}

func listPerformances() []*performance {
	performances := make([]*performance, 0, len(morningStarIds))
	for perf := range listCache(cacheRequests) {
		performances = append(performances, perf)
	}

	return performances
}

func listHandler(w http.ResponseWriter, r *http.Request) {
	jsonHttp.ResponseJSON(w, results{listPerformances()})
}

func statusHandler(w http.ResponseWriter, r *http.Request) {
	if len(listPerformances()) > 0 {
		w.Write([]byte(`OK`))
	} else {
		w.Write([]byte(`KO`))
	}
}

// Handler for MorningStar request. Should be use with net/http
type Handler struct {
}

func (handler Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.Header().Add(`Access-Control-Allow-Origin`, `*`)
	w.Header().Add(`Access-Control-Allow-Headers`, `Content-Type`)
	w.Header().Add(`Access-Control-Allow-Methods`, `GET`)
	w.Header().Add(`X-Content-Type-Options`, `nosniff`)

	urlPath := []byte(r.URL.Path)

	if r.Method == http.MethodOptions {
		if requestStatus.Match(urlPath) {
			statusHandler(w, r)
		} else {
			w.Write(nil)
		}
	} else if requestList.Match(urlPath) {
		listHandler(w, r)
	} else if requestPerf.Match(urlPath) {
		performanceHandler(w, requestPerf.FindSubmatch(urlPath)[1])
	}
}
<commit_msg>Changing to health check<commit_after>package morningStar

import (
	"bytes"
	"github.com/ViBiOh/funds/jsonHttp"
	"log"
	"net/http"
	"regexp"
	"sync"
	"time"
)

const refreshDelayInHours = 6
const maxConcurrentFetcher = 32

var healthRequest = regexp.MustCompile(`^/health$`)
var listRequest = regexp.MustCompile(`^/list$`)
var performanceRequest = regexp.MustCompile(`^/(.+?)$`)

type performance struct {
	ID            string    `json:"id"`
	Isin          string    `json:"isin"`
	Label         string    `json:"label"`
	Category      string    `json:"category"`
	Rating        string    `json:"rating"`
	OneMonth      float64   `json:"1m"`
	ThreeMonths   float64   `json:"3m"`
	SixMonths     float64   `json:"6m"`
	OneYear       float64   `json:"1y"`
	VolThreeYears float64   `json:"v3y"`
	Score         float64   `json:"score"`
	Update        time.Time `json:"ts"`
}

func (perf *performance) computeScore() {
	score := (0.25 * perf.OneMonth) + (0.3 * perf.ThreeMonths) + (0.25 * perf.SixMonths) + (0.2 * perf.OneYear) - (0.1 * perf.VolThreeYears)
	perf.Score = float64(int(score*100)) / 100
}

type results struct {
	Results interface{} `json:"results"`
}

var cacheRequests = make(chan *cacheRequest, maxConcurrentFetcher)

func init() {
	go cacheServer(cacheRequests)
	go func() {
		refreshCache()
		c := time.Tick(refreshDelayInHours * time.Hour)
		for range c {
			refreshCache()
		}
	}()
}

func concurrentRetrievePerformances(ids [][]byte, wg *sync.WaitGroup, performances chan<- *performance, errors chan<- []byte) {
	tokens := make(chan int, maxConcurrentFetcher)

	clearSemaphores := func() {
		wg.Done()
		<-tokens
	}

	for _, id := range ids {
		tokens <- 1

		go func(morningStarID []byte) {
			defer clearSemaphores()
			perf, err := fetchPerformance(morningStarID)
			if err == nil {
				performances <- perf
			} else {
				errors <- morningStarID
			}
		}(id)
	}
}

func retrievePerformances(ids [][]byte) ([]*performance, [][]byte) {
	var wgFetch sync.WaitGroup
	wgFetch.Add(len(ids))

	var wgDrain sync.WaitGroup
	wgDrain.Add(2)

	performancesChan := make(chan *performance, 0)
	errorsChan := make(chan []byte, 0)

	performances := make([]*performance, 0, len(ids))
	errors := make([][]byte, 0)

	go concurrentRetrievePerformances(ids, &wgFetch, performancesChan, errorsChan)

	go func() {
		wgFetch.Wait()
		close(performancesChan)
		close(errorsChan)
	}()

	go func() {
		for perf := range performancesChan {
			performances = append(performances, perf)
		}
		wgDrain.Done()
	}()

	go func() {
		for error := range errorsChan {
			errors = append(errors, error)
		}
		wgDrain.Done()
	}()

	wgDrain.Wait()

	return performances, errors
}

func refreshCache() {
	log.Print(`Cache refresh - start`)
	defer log.Print(`Cache refresh - end`)

	performances, errors := retrievePerformances(morningStarIds)

	if len(errors) > 0 {
		log.Printf(`Errors while refreshing ids %s`, bytes.Join(errors, []byte(`, `)))
	}

	loadCache(cacheRequests, performances)
}

func retrievePerformance(morningStarID []byte) (*performance, error) {
	perf := getCache(cacheRequests, cleanID(morningStarID))
	if perf != nil {
		return perf, nil
	}

	perf, err := fetchPerformance(morningStarID)
	if err != nil {
		return nil, err
	}

	pushCache(cacheRequests, perf)
	morningStarIds = append(morningStarIds, morningStarID)

	return perf, nil
}

func performanceHandler(w http.ResponseWriter, morningStarID []byte) {
	perf, err := retrievePerformance(morningStarID)

	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	} else {
		jsonHttp.ResponseJSON(w, *perf)
	}
}

func listPerformances() []*performance {
	performances := make([]*performance, 0, len(morningStarIds))
	for perf := range listCache(cacheRequests) {
		performances = append(performances, perf)
	}

	return performances
}

func listHandler(w http.ResponseWriter, r *http.Request) {
	jsonHttp.ResponseJSON(w, results{listPerformances()})
}

func healthHandler(w http.ResponseWriter, r *http.Request) {
	if len(listPerformances()) > 0 {
		w.WriteHeader(http.StatusOK)
	} else {
		w.WriteHeader(http.StatusServiceUnavailable)
	}
}

// Handler for MorningStar request. Should be use with net/http
type Handler struct {
}

func (handler Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.Header().Add(`Access-Control-Allow-Origin`, `*`)
	w.Header().Add(`Access-Control-Allow-Headers`, `Content-Type`)
	w.Header().Add(`Access-Control-Allow-Methods`, `GET`)
	w.Header().Add(`X-Content-Type-Options`, `nosniff`)

	if r.Method == http.MethodOptions {
		w.Write(nil)
		return
	}

	urlPath := []byte(r.URL.Path)

	if healthRequest.Match(urlPath) && r.Method == http.MethodGet {
		healthHandler(w, r)
	} else if listRequest.Match(urlPath) && r.Method == http.MethodGet {
		listHandler(w, r)
	} else if performanceRequest.Match(urlPath) && r.Method == http.MethodGet {
		performanceHandler(w, performanceRequest.FindSubmatch(urlPath)[1])
	}
}
<|endoftext|>


<commit_before>package bird

import (
	"os/exec"
	"strings"
	"sync"
	"time"
)

var ClientConf BirdConfig
var StatusConf StatusConfig
var RateLimitConf struct {
	sync.RWMutex
	Conf RateLimitConfig
}

var Cache = struct {
	sync.RWMutex
	m map[string]Parsed
}{m: make(map[string]Parsed)}

func fromCache(key string) (Parsed, bool) {
	Cache.RLock()
	val, ok := Cache.m[key]
	Cache.RUnlock()
	return val, ok
}

func toCache(key string, val Parsed) {
	val["ttl"] = time.Now().Add(5 * time.Minute)
	Cache.Lock()
	Cache.m[key] = val
	Cache.Unlock()
}

func Run(args string) ([]byte, error) {
	args = "show " + args
	argsList := strings.Split(args, " ")
	return exec.Command(ClientConf.BirdCmd, argsList...).Output()
}

func InstallRateLimitReset() {
	go func() {
		c := time.Tick(time.Second)

		for _ = range c {
			RateLimitConf.Lock()
			RateLimitConf.Conf.Reqs = RateLimitConf.Conf.Max
			RateLimitConf.Unlock()
		}
	}()
}

func checkRateLimit() bool {
	RateLimitConf.RLock()
	check := !RateLimitConf.Conf.Enabled
	RateLimitConf.RUnlock()
	if check {
		return true
	}

	RateLimitConf.RLock()
	check = RateLimitConf.Conf.Reqs < 1
	RateLimitConf.RUnlock()
	if check {
		return false
	}

	RateLimitConf.Lock()
	RateLimitConf.Conf.Reqs -= 1
	RateLimitConf.Unlock()

	return true
}

func RunAndParse(cmd string, parser func([]byte) Parsed) (Parsed, bool) {
	if val, ok := fromCache(cmd); ok {
		return val, true
	}

	if !checkRateLimit() {
		return nil, false
	}

	out, err := Run(cmd)

	if err != nil {
		// ignore errors for now
		return Parsed{}, false
	}

	parsed := parser(out)
	toCache(cmd, parsed)
	return parsed, false
}

func Status() (Parsed, bool) {
	birdStatus, ok := RunAndParse("status", parseStatus)
	status := birdStatus["status"].(Parsed)

	// Last Reconfig Timestamp source:
	var lastReconfig string
	switch StatusConf.ReconfigTimestampSource {
	case "bird":
		lastReconfig = status["last_reconfig"].(string)
		break
	case "config_modified":
		lastReconfig = lastReconfigTimestampFromFileStat(
			ClientConf.ConfigFilename,
		)
	case "config_regex":
		lastReconfig = lastReconfigTimestampFromFileContent(
			ClientConf.ConfigFilename,
			StatusConf.ReconfigTimestampMatch,
		)
	}

	status["last_reconfig"] = lastReconfig

	// Filter fields
	for _, field := range StatusConf.FilterFields {
		status[field] = nil
	}

	birdStatus["status"] = status

	return birdStatus, ok
}

func Protocols() (Parsed, bool) {
	return RunAndParse("protocols all", parseProtocols)
}

func ProtocolsBgp() (Parsed, bool) {
	p, from_cache := Protocols()
	protocols := p["protocols"].([]string)

	bgpProto := Parsed{}

	for _, v := range protocols {
		if strings.Contains(v, " BGP ") {
			key := strings.Split(v, " ")[0]
			bgpProto[key] = parseBgp(v)
		}
	}

	return Parsed{"protocols": bgpProto}, from_cache
}

func Symbols() (Parsed, bool) {
	return RunAndParse("symbols", parseSymbols)
}

func RoutesPrefixed(prefix string) (Parsed, bool) {
	return RunAndParse("route all '"+prefix+"'", parseRoutes)
}

func RoutesProto(protocol string) (Parsed, bool) {
	return RunAndParse("route protocol '"+protocol+"' all",
		parseRoutes)
}

func RoutesProtoCount(protocol string) (Parsed, bool) {
	return RunAndParse("route protocol '"+protocol+"' count",
		parseRoutesCount)
}

func RoutesFiltered(protocol string) (Parsed, bool) {
	return RunAndParse("route protocol '"+protocol+"' filtered", parseRoutes)
}

func RoutesExport(protocol string) (Parsed, bool) {
	return RunAndParse("route export '"+protocol+"' all",
		parseRoutes)
}

func RoutesExportCount(protocol string) (Parsed, bool) {
	return RunAndParse("route export '"+protocol+"' count",
		parseRoutesCount)
}

func RoutesTable(table string) (Parsed, bool) {
	return RunAndParse("route table '"+table+"' all",
		parseRoutes)
}

func RoutesTableCount(table string) (Parsed, bool) {
	return RunAndParse("route table '"+table+"' count",
		parseRoutesCount)
}

func RoutesLookupTable(net string, table string) (Parsed, bool) {
	return RunAndParse("route for '"+net+"' table '"+table+"' all",
		parseRoutes)
}

func RoutesLookupProtocol(net string, protocol string) (Parsed, bool) {
	return RunAndParse("route for '"+net+"' protocol '"+protocol+"' all",
		parseRoutes)
}
<commit_msg>add useful meta data to filtered routes<commit_after>package bird

import (
	"os/exec"
	"strings"
	"sync"
	"time"
)

var ClientConf BirdConfig
var StatusConf StatusConfig
var RateLimitConf struct {
	sync.RWMutex
	Conf RateLimitConfig
}

var Cache = struct {
	sync.RWMutex
	m map[string]Parsed
}{m: make(map[string]Parsed)}

func fromCache(key string) (Parsed, bool) {
	Cache.RLock()
	val, ok := Cache.m[key]
	Cache.RUnlock()
	return val, ok
}

func toCache(key string, val Parsed) {
	val["ttl"] = time.Now().Add(5 * time.Minute)
	Cache.Lock()
	Cache.m[key] = val
	Cache.Unlock()
}

func Run(args string) ([]byte, error) {
	args = "show " + args
	argsList := strings.Split(args, " ")
	return exec.Command(ClientConf.BirdCmd, argsList...).Output()
}

func InstallRateLimitReset() {
	go func() {
		c := time.Tick(time.Second)

		for _ = range c {
			RateLimitConf.Lock()
			RateLimitConf.Conf.Reqs = RateLimitConf.Conf.Max
			RateLimitConf.Unlock()
		}
	}()
}

func checkRateLimit() bool {
	RateLimitConf.RLock()
	check := !RateLimitConf.Conf.Enabled
	RateLimitConf.RUnlock()
	if check {
		return true
	}

	RateLimitConf.RLock()
	check = RateLimitConf.Conf.Reqs < 1
	RateLimitConf.RUnlock()
	if check {
		return false
	}

	RateLimitConf.Lock()
	RateLimitConf.Conf.Reqs -= 1
	RateLimitConf.Unlock()

	return true
}

func RunAndParse(cmd string, parser func([]byte) Parsed) (Parsed, bool) {
	if val, ok := fromCache(cmd); ok {
		return val, true
	}

	if !checkRateLimit() {
		return nil, false
	}

	out, err := Run(cmd)

	if err != nil {
		// ignore errors for now
		return Parsed{}, false
	}

	parsed := parser(out)
	toCache(cmd, parsed)
	return parsed, false
}

func Status() (Parsed, bool) {
	birdStatus, ok := RunAndParse("status", parseStatus)
	status := birdStatus["status"].(Parsed)

	// Last Reconfig Timestamp source:
	var lastReconfig string
	switch StatusConf.ReconfigTimestampSource {
	case "bird":
		lastReconfig = status["last_reconfig"].(string)
		break
	case "config_modified":
		lastReconfig = lastReconfigTimestampFromFileStat(
			ClientConf.ConfigFilename,
		)
	case "config_regex":
		lastReconfig = lastReconfigTimestampFromFileContent(
			ClientConf.ConfigFilename,
			StatusConf.ReconfigTimestampMatch,
		)
	}

	status["last_reconfig"] = lastReconfig

	// Filter fields
	for _, field := range StatusConf.FilterFields {
		status[field] = nil
	}

	birdStatus["status"] = status

	return birdStatus, ok
}

func Protocols() (Parsed, bool) {
	return RunAndParse("protocols all", parseProtocols)
}

func ProtocolsBgp() (Parsed, bool) {
	p, from_cache := Protocols()
	protocols := p["protocols"].([]string)

	bgpProto := Parsed{}

	for _, v := range protocols {
		if strings.Contains(v, " BGP ") {
			key := strings.Split(v, " ")[0]
			bgpProto[key] = parseBgp(v)
		}
	}

	return Parsed{"protocols": bgpProto}, from_cache
}

func Symbols() (Parsed, bool) {
	return RunAndParse("symbols", parseSymbols)
}

func RoutesPrefixed(prefix string) (Parsed, bool) {
	return RunAndParse("route all '"+prefix+"'", parseRoutes)
}

func RoutesProto(protocol string) (Parsed, bool) {
	return RunAndParse("route protocol '"+protocol+"' all",
		parseRoutes)
}

func RoutesProtoCount(protocol string) (Parsed, bool) {
	return RunAndParse("route protocol '"+protocol+"' count",
		parseRoutesCount)
}

func RoutesFiltered(protocol string) (Parsed, bool) {
	return RunAndParse("route protocol '"+protocol+"' filtered all", parseRoutes)
}

func RoutesExport(protocol string) (Parsed, bool) {
	return RunAndParse("route export '"+protocol+"' all",
		parseRoutes)
}

func RoutesExportCount(protocol string) (Parsed, bool) {
	return RunAndParse("route export '"+protocol+"' count",
		parseRoutesCount)
}

func RoutesTable(table string) (Parsed, bool) {
	return RunAndParse("route table '"+table+"' all",
		parseRoutes)
}

func RoutesTableCount(table string) (Parsed, bool) {
	return RunAndParse("route table '"+table+"' count",
		parseRoutesCount)
}

func RoutesLookupTable(net string, table string) (Parsed, bool) {
	return RunAndParse("route for '"+net+"' table '"+table+"' all",
		parseRoutes)
}

func RoutesLookupProtocol(net string, protocol string) (Parsed, bool) {
	return RunAndParse("route for '"+net+"' protocol '"+protocol+"' all",
		parseRoutes)
}
<|endoftext|>


<commit_before>// Copyright (c) 2012-2014 Jeremy Latt
// Copyright (c) 2014-2015 Edmund Huber
// Copyright (c) 2016-2017 Daniel Oaks <daniel@danieloaks.net>
// released under the MIT license

package irc

import "fmt"

const (
	// SemVer is the semantic version of Oragono.
	SemVer = "2.0.0-rc1"
)

var (
	// Commit is the current git commit.
	Commit = ""

	// Ver is the full version of Oragono, used in responses to clients.
	Ver = fmt.Sprintf("oragono-%s", SemVer)

	// maxLastArgLength is used to simply cap off the final argument when creating general messages where we need to select a limit.
	// for instance, in MONITOR lists, RPL_ISUPPORT lists, etc.
	maxLastArgLength = 400
	// maxTargets is the maximum number of targets for PRIVMSG and NOTICE.
	maxTargets = 4
)
<commit_msg>bump version to 2.0.0<commit_after>// Copyright (c) 2012-2014 Jeremy Latt
// Copyright (c) 2014-2015 Edmund Huber
// Copyright (c) 2016-2017 Daniel Oaks <daniel@danieloaks.net>
// released under the MIT license

package irc

import "fmt"

const (
	// SemVer is the semantic version of Oragono.
	SemVer = "2.0.0"
)

var (
	// Commit is the current git commit.
	Commit = ""

	// Ver is the full version of Oragono, used in responses to clients.
	Ver = fmt.Sprintf("oragono-%s", SemVer)

	// maxLastArgLength is used to simply cap off the final argument when creating general messages where we need to select a limit.
	// for instance, in MONITOR lists, RPL_ISUPPORT lists, etc.
	maxLastArgLength = 400
	// maxTargets is the maximum number of targets for PRIVMSG and NOTICE.
	maxTargets = 4
)
<|endoftext|>


<commit_before>package khukuri

import (
	"errors"
	"strconv"
	"strings"
)

const alphaBetSet = "23456789bcdfghjkmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ-_"
const base = uint64(len(alphaBetSet))

func CheckSum(id uint64) uint64 {
	numStr := strconv.FormatUint(id, 10)
	runes := []rune(numStr)
	checkSum := uint64(0)
	oddSum := uint64(0)
	evenSum := uint64(0)
	for i := len(runes) - 1; i >= 0; i-- {
		item := runes[i]
		digitNum := uint64(item - '0')
		ii := i - len(runes) + 1
		if ii%2 == 0 {
			evenSum += digitNum
		} else {
			sumOfDigits := digitSum(2 * digitNum)
			oddSum += sumOfDigits
		}
	}
	checkSum = evenSum + oddSum
	return checkSum % 10
}

func digitSum(num uint64) uint64 {
	retNum := uint64(0)
	for num > 0 {
		r := num % 10
		retNum += r
		num = num / 10
	}
	return retNum
}

func EncodeToBase(seedNumber uint64) (string, error) {
	encodedString := ""
	if seedNumber <= 0 {
		return "", errors.New("Argument cannot zero or less.")
	}
	for seedNumber > 0 {
		numAtIndex := seedNumber % base
		charAtIndex := string(alphaBetSet[numAtIndex])
		encodedString += charAtIndex
		seedNumber = seedNumber / base
	}
	return reverse(encodedString), nil
}

func reverse(s string) string {
	runes := []rune(s)
	for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
		runes[i], runes[j] = runes[j], runes[i]
	}
	return string(runes)
}

func DecodeFromBase(encodedString string) (uint64, error) {
	if len(encodedString) == 0 {
		return 0, errors.New("Argument cannot empty.")
	}
	decodedVal := uint64(0)
	for _, c := range encodedString {
		decodedVal = (decodedVal * base) + uint64(strings.Index(alphaBetSet, string(c)))
	}
	return decodedVal, nil
}
<commit_msg>Check digit calculation implemented<commit_after>package khukuri

import (
	"errors"
	"strconv"
	"strings"
)

const alphaBetSet = "23456789bcdfghjkmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ-_"
const base = uint64(len(alphaBetSet))

func CheckSum(id uint64) uint64 {
	numStr := strconv.FormatUint(id, 10)
	runes := []rune(numStr)
	checkSum := uint64(0)
	oddSum := uint64(0)
	evenSum := uint64(0)
	for i := len(runes) - 1; i >= 0; i-- {
		item := runes[i]
		digitNum := uint64(item - '0')
		ii := i - len(runes) + 1
		if ii%2 == 0 {
			evenSum += digitNum
		} else {
			sumOfDigits := digitSum(2 * digitNum)
			oddSum += sumOfDigits
		}
	}
	checkSum = evenSum + oddSum
	return checkSum % 10
}

func IsCheckSumValid(id uint64) bool {
	return CheckSum(id) == 0
}

func CalculateCheckDigit(partialId uint64) uint64 {
	checkDigit := CheckSum(partialId * 10)
	if checkDigit == 0 {
		return checkDigit
	}
	return 10 - checkDigit
}

func digitSum(num uint64) uint64 {
	retNum := uint64(0)
	for num > 0 {
		r := num % 10
		retNum += r
		num = num / 10
	}
	return retNum
}

func EncodeToBase(seedNumber uint64) (string, error) {
	encodedString := ""
	if seedNumber <= 0 {
		return "", errors.New("Argument cannot zero or less.")
	}
	for seedNumber > 0 {
		numAtIndex := seedNumber % base
		charAtIndex := string(alphaBetSet[numAtIndex])
		encodedString += charAtIndex
		seedNumber = seedNumber / base
	}
	return reverse(encodedString), nil
}

func reverse(s string) string {
	runes := []rune(s)
	for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
		runes[i], runes[j] = runes[j], runes[i]
	}
	return string(runes)
}

func DecodeFromBase(encodedString string) (uint64, error) {
	if len(encodedString) == 0 {
		return 0, errors.New("Argument cannot empty.")
	}
	decodedVal := uint64(0)
	for _, c := range encodedString {
		decodedVal = (decodedVal * base) + uint64(strings.Index(alphaBetSet, string(c)))
	}
	return decodedVal, nil
}
<|endoftext|>


<commit_before>// +build appengine js

package isatty

// IsTerminal returns true if the file descriptor is terminal which
// is always false on js and appengine classic which is a sandboxed PaaS.
func IsTerminal(fd uintptr) bool {
	return false
}

// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
// terminal. This is also always false on this environment.
func IsCygwinTerminal(fd uintptr) bool {
	return false
}
<commit_msg>Add nacl<commit_after>// +build appengine js nacl

package isatty

// IsTerminal returns true if the file descriptor is terminal which
// is always false on js and appengine classic which is a sandboxed PaaS.
func IsTerminal(fd uintptr) bool {
	return false
}

// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
// terminal. This is also always false on this environment.
func IsCygwinTerminal(fd uintptr) bool {
	return false
}
<|endoftext|>


<commit_before>package judge

import (
	"fmt"
	"github.com/duguying/judger/core"
	"github.com/gogather/com"
	"github.com/gogather/com/log"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"time"
)

var BuildStartTime int64
var BuildProcessHaveExit bool

type Compile struct {
	system        string
	buildPath     string
	userBuildPath string
	itemBuildPath string
	codeFilePath  string
	currentPath   string

	compiler_c string
	postfix_c  string

	compiler_cpp string
	postfix_cpp  string

	buildOverTime bool
}

func (this *Compile) NewCompile() {
	this.buildOverTime = false
	this.system = runtime.GOOS
	this.postfix_c = "c"
	this.postfix_cpp = "cpp"
	this.currentPath, _ = os.Getwd()

	this.buildPath = filepath.Join(this.currentPath, core.C.Get(runtime.GOOS, "buildpath"))
	this.compiler_c = filepath.Join(this.currentPath, core.C.Get(runtime.GOOS, "compiler_c"))

	log.Blueln("[current path]", this.currentPath)
	log.Blueln("[build path]", this.buildPath)
	log.Blueln("[compiler path]", this.compiler_c)
}

func (this *Compile) Run(code string, language string, id int, sid string) (string, error) {

	err := this.createDirs(id, sid)
	if err != nil {
		log.Warnln(err)
		return "", err
	} else {
		err = this.writeCode(code, id, language)
		if err != nil {
			log.Warnln(err)
			return "", err
		}
	}

	return this.itemBuildPath, this.gcc(id)

}

// 创建编译环境的目录结构
func (this *Compile) createDirs(id int, sid string) error {
	var err error
	err = nil
	this.userBuildPath = filepath.Join(this.buildPath, sid)
	if !com.PathExist(this.userBuildPath) {
		err = com.Mkdir(this.userBuildPath)
	}
	this.itemBuildPath = filepath.Join(this.userBuildPath, fmt.Sprintf("%d", id))
	if !com.PathExist(this.itemBuildPath) {
		err = com.Mkdir(this.itemBuildPath)
	}
	return err
}

// 代码写入文件
func (this *Compile) writeCode(code string, id int, language string) error {
	lang := ""
	if language == "C" {
		lang = "c"
	}
	this.codeFilePath = filepath.Join(this.itemBuildPath, fmt.Sprintf("%d.%s", id, lang))
	return com.WriteFile(this.codeFilePath, code)
}

// call gcc compiler in other os
func (this *Compile) gcc(id int) error {
	os.Chdir(this.itemBuildPath)

	var cmd *exec.Cmd

	if runtime.GOOS == "windows" {
		cmd = exec.Command("cmd", "/K",
			this.compiler_c,
			this.codeFilePath,
			this.itemBuildPath,
		)
	} else {
		cmd = exec.Command("sh",
			this.compiler_c,
			this.codeFilePath,
			this.itemBuildPath,
		)
	}

	err := cmd.Start()
	if err != nil {
		log.Warnln("Start Failed")
		log.Warnln(err)
	}

	stn := time.Now()
	BuildStartTime = stn.UnixNano()
	go checkTimer(cmd, this)
	BuildProcessHaveExit = false

	err = cmd.Wait()
	BuildProcessHaveExit = true

	if err != nil {
		log.Warnln("Wait Failed")
		log.Warnln(err)
	}

	os.Chdir(this.currentPath)

	return err
}

func checkTimer(cmd *exec.Cmd, comp *Compile) {
	for {
		// if building process hava exit normally, exit timer
		if BuildProcessHaveExit {
			log.Blueln("Building Process Exit Normally.")
			return
		}

		stn := time.Now()
		now := stn.UnixNano()
		// over 10s
		if now-BuildStartTime > 10*1000000000 {
			comp.buildOverTime = true
			log.Warnln("Building Out of Time, Terminated!")
			cmd.Process.Kill()
			return
		}
	}
}
<commit_msg>try to clean the orphan gcc<commit_after>package judge

import (
	"fmt"
	"github.com/duguying/judger/core"
	"github.com/gogather/com"
	"github.com/gogather/com/log"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"time"
)

var BuildStartTime int64
var BuildProcessHaveExit bool

type Compile struct {
	system        string
	buildPath     string
	userBuildPath string
	itemBuildPath string
	codeFilePath  string
	currentPath   string

	compiler_c string
	postfix_c  string

	compiler_cpp string
	postfix_cpp  string

	buildOverTime bool
}

func (this *Compile) NewCompile() {
	this.buildOverTime = false
	this.system = runtime.GOOS
	this.postfix_c = "c"
	this.postfix_cpp = "cpp"
	this.currentPath, _ = os.Getwd()

	this.buildPath = filepath.Join(this.currentPath, core.C.Get(runtime.GOOS, "buildpath"))
	this.compiler_c = filepath.Join(this.currentPath, core.C.Get(runtime.GOOS, "compiler_c"))

	log.Blueln("[current path]", this.currentPath)
	log.Blueln("[build path]", this.buildPath)
	log.Blueln("[compiler path]", this.compiler_c)
}

func (this *Compile) Run(code string, language string, id int, sid string) (string, error) {

	err := this.createDirs(id, sid)
	if err != nil {
		log.Warnln(err)
		return "", err
	} else {
		err = this.writeCode(code, id, language)
		if err != nil {
			log.Warnln(err)
			return "", err
		}
	}

	return this.itemBuildPath, this.gcc(id)

}

// 创建编译环境的目录结构
func (this *Compile) createDirs(id int, sid string) error {
	var err error
	err = nil
	this.userBuildPath = filepath.Join(this.buildPath, sid)
	if !com.PathExist(this.userBuildPath) {
		err = com.Mkdir(this.userBuildPath)
	}
	this.itemBuildPath = filepath.Join(this.userBuildPath, fmt.Sprintf("%d", id))
	if !com.PathExist(this.itemBuildPath) {
		err = com.Mkdir(this.itemBuildPath)
	}
	return err
}

// 代码写入文件
func (this *Compile) writeCode(code string, id int, language string) error {
	lang := ""
	if language == "C" {
		lang = "c"
	}
	this.codeFilePath = filepath.Join(this.itemBuildPath, fmt.Sprintf("%d.%s", id, lang))
	return com.WriteFile(this.codeFilePath, code)
}

// call gcc compiler in other os
func (this *Compile) gcc(id int) error {
	os.Chdir(this.itemBuildPath)

	var cmd *exec.Cmd

	if runtime.GOOS == "windows" {
		cmd = exec.Command("cmd", "/K",
			this.compiler_c,
			this.codeFilePath,
			this.itemBuildPath,
		)
	} else {
		cmd = exec.Command("sh",
			this.compiler_c,
			this.codeFilePath,
			this.itemBuildPath,
		)
	}

	err := cmd.Start()
	if err != nil {
		log.Warnln("Start Failed")
		log.Warnln(err)
	}

	stn := time.Now()
	BuildStartTime = stn.UnixNano()
	go checkTimer(cmd, this, id)
	BuildProcessHaveExit = false

	err = cmd.Wait()
	BuildProcessHaveExit = true

	if err != nil {
		log.Warnln("Wait Failed")
		log.Warnln(err)
	}

	os.Chdir(this.currentPath)

	return err
}

func checkTimer(cmd *exec.Cmd, comp *Compile, id int) {
	for {
		// if building process hava exit normally, exit timer
		if BuildProcessHaveExit {
			log.Blueln("Building Process Exit Normally.")
			return
		}

		stn := time.Now()
		now := stn.UnixNano()
		// over 10s
		if now-BuildStartTime > 10*1000000000 {
			comp.buildOverTime = true
			log.Warnln("Building Out of Time, Terminated!")
			cmd.Process.Kill()

			systemTag := com.SubString(runtime.GOOS, 0, 5)
			if systemTag == "linux" {
				// ps -ef|grep cc1|grep 5.c|awk '{print $2}'|xargs kill -9
				cleanScript := fmt.Sprintf("ps -ef|grep cc1|grep %d.c|awk '{print $2}'|xargs kill -9", id)
				cleanCmd := exec.Command("sh",
					"-c",
					cleanScript,
				)
				err := cleanCmd.Run()
				if err != nil {
					log.Warnln("clean orphan failed")
				}
			}
			return
		}
	}
}
<|endoftext|>


<commit_before>package client

import (
    "fmt"
    "sort"
    "encoding/xml"
)

type SourceType int

const SourceTypeInput       SourceType  = 0
const SourceTypeStill       SourceType  = 1
const SourceTypeDest        SourceType  = 2

func (sourceType SourceType) String() string {
    switch sourceType {
    case SourceTypeInput:
        return "input"
    case SourceTypeStill:
        return "still"
    case SourceTypeDest:
        return "dest"
    default:
        return fmt.Sprintf("%d", int(sourceType))
    }
}

type Source struct {
    ID              int         `json:"id" xml:"id,attr"`

    Name            string
    HSize           int         `json:"HSize" xml:"AOIRect>HSize"`
    VSize           int         `json:"VSize" xml:"AOIRect>VSize"`
    SrcType         SourceType

    UserKeyIndex    int

    // -1 unless Type == SourceTypeInput
    InputCfgIndex       int
    InputVideoStatus    InputVideoStatus    `json:"InputCfgVideoStatus" xml:"-"` // XXX: JSON isi different

    // -1 unless Type == SourceTypeStill
    StillIndex      int

    // -1 unless Type == SourceTypeDest
    DestIndex       int
}

type listSources struct {
    Type            int         `json:"type"`
}

const listSourcesTypeInput      = 0
const listSourcesTypeBackground = 1

// Default is to return all
func (client *Client) ListSources() (sourceList []Source, err error) {
    request := Request{
        Method:     "listSources",
        Params:     struct{}{},
    }

    if err := client.doResult(&request, &sourceList); err != nil {
        return nil, err
    } else {
        return sourceList, nil
    }
}

// XML
type SourceCol map[int]Source

func (col *SourceCol) UnmarshalXML(d *xml.Decoder, e xml.StartElement) error {
    return unmarshalXMLMap(col, d, e)
}

func (col SourceCol) MarshalJSON() ([]byte, error) {
    return marshalJSONMap(col)
}

func (col SourceCol) List() (items []Source) {
    var keys []int

    for key, _ := range col {
        keys = append(keys, key)
    }

    sort.Ints(keys)

    for _, key := range keys {
        items = append(items, col[key])
    }

    return items
}

type SrcMgr struct {
    ID              int             `xml:"id,attr"`

    SourceCol       SourceCol       `xml:"SourceCol"`
    //BGSourceCol
    InputCfgCol     InputCfgCol     `xml:"InputCfgCol"`
    //SavedInputCfgCol
}
<commit_msg>client: SourceCol.Get()<commit_after>package client

import (
    "fmt"
    "sort"
    "encoding/xml"
)

type SourceType int

const SourceTypeInput       SourceType  = 0
const SourceTypeStill       SourceType  = 1
const SourceTypeDest        SourceType  = 2

func (sourceType SourceType) String() string {
    switch sourceType {
    case SourceTypeInput:
        return "input"
    case SourceTypeStill:
        return "still"
    case SourceTypeDest:
        return "dest"
    default:
        return fmt.Sprintf("%d", int(sourceType))
    }
}

type Source struct {
    ID              int         `json:"id" xml:"id,attr"`

    Name            string
    HSize           int         `json:"HSize" xml:"AOIRect>HSize"`
    VSize           int         `json:"VSize" xml:"AOIRect>VSize"`
    SrcType         SourceType

    UserKeyIndex    int

    // -1 unless Type == SourceTypeInput
    InputCfgIndex       int
    InputVideoStatus    InputVideoStatus    `json:"InputCfgVideoStatus" xml:"-"` // XXX: JSON isi different

    // -1 unless Type == SourceTypeStill
    StillIndex      int

    // -1 unless Type == SourceTypeDest
    DestIndex       int
}

type listSources struct {
    Type            int         `json:"type"`
}

const listSourcesTypeInput      = 0
const listSourcesTypeBackground = 1

// Default is to return all
func (client *Client) ListSources() (sourceList []Source, err error) {
    request := Request{
        Method:     "listSources",
        Params:     struct{}{},
    }

    if err := client.doResult(&request, &sourceList); err != nil {
        return nil, err
    } else {
        return sourceList, nil
    }
}

// XML
type SourceCol map[int]Source

func (col *SourceCol) UnmarshalXML(d *xml.Decoder, e xml.StartElement) error {
    return unmarshalXMLMap(col, d, e)
}

func (col SourceCol) MarshalJSON() ([]byte, error) {
    return marshalJSONMap(col)
}

func (col SourceCol) Get(id int) *Source {
    if item, exists := col[id]; exists {
        return &item
    } else {
        return nil
    }
}

func (col SourceCol) List() (items []Source) {
    var keys []int

    for key, _ := range col {
        keys = append(keys, key)
    }

    sort.Ints(keys)

    for _, key := range keys {
        items = append(items, col[key])
    }

    return items
}

type SrcMgr struct {
    ID              int             `xml:"id,attr"`

    SourceCol       SourceCol       `xml:"SourceCol"`
    //BGSourceCol
    InputCfgCol     InputCfgCol     `xml:"InputCfgCol"`
    //SavedInputCfgCol
}
<|endoftext|>


<commit_before>// A primitive Prolog top level for Golog.  See golog.sh in the repository
// for recommended usage.
package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/mndrix/golog"
	"github.com/mndrix/golog/read"
	"github.com/mndrix/golog/term"
)

func main() {
	// create a Golog machine
	m := initMachine()

	// ?- do(stuff).
	in := bufio.NewReader(os.Stdin)
	for {
		warnf("?- ")

		// process the user's query
		query, err := in.ReadString('\n')
		if err == io.EOF {
			warnf("\n")
			os.Exit(0)
		}
		if err != nil {
			warnf("Trouble reading from stdin: %s\n", err)
			os.Exit(1)
		}
		goal, err := read.Term(query)
		if err != nil {
			warnf("Problem parsing the query: %s\n", err)
			continue
		}

		// execute user's query
		variables := term.Variables(goal)
		answers := m.ProveAll(goal)

		// showing 0 results is easy and fun!
		if len(answers) == 0 {
			warnf("no.\n\n")
			continue
		}

		// show each answer in turn
		if variables.Size() == 0 {
			warnf("yes.\n")
			continue
		}
		for i, answer := range answers {
			lines := make([]string, 0)
			variables.ForEach(func(name string, variable interface{}) {
				v := variable.(*term.Variable)
				val := answer.Resolve_(v)
				line := fmt.Sprintf("%s = %s", name, val)
				lines = append(lines, line)
			})

			warnf("%s", strings.Join(lines, "\n"))
			if i == len(answers)-1 {
				warnf("\t.\n\n")
			} else {
				warnf("\t;\n")
			}
		}
	}
}

// warnf generates formatted output on stderr
func warnf(format string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, format, args...)
	os.Stderr.Sync()
}

// initMachine creates a new Golog machine based on command line arguments
func initMachine() golog.Machine {
	m := golog.NewMachine()

	// are we supposed to load some code into the machine?
	if len(os.Args) > 1 {
		filename := os.Args[1]
		warnf("Opening %s ...\n", filename)
		file, err := os.Open(filename)
		if err != nil {
			warnf("Can't open file: %s\n", err)
			os.Exit(1)
		}
		m = m.Consult(file)
	}

	return m
}
<commit_msg>Use NewInteractiveMachine for golog toplevel<commit_after>// A primitive Prolog top level for Golog.  See golog.sh in the repository
// for recommended usage.
package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/mndrix/golog"
	"github.com/mndrix/golog/read"
	"github.com/mndrix/golog/term"
)

func main() {
	// create a Golog machine
	m := initMachine()

	// ?- do(stuff).
	in := bufio.NewReader(os.Stdin)
	for {
		warnf("?- ")

		// process the user's query
		query, err := in.ReadString('\n')
		if err == io.EOF {
			warnf("\n")
			os.Exit(0)
		}
		if err != nil {
			warnf("Trouble reading from stdin: %s\n", err)
			os.Exit(1)
		}
		goal, err := read.Term(query)
		if err != nil {
			warnf("Problem parsing the query: %s\n", err)
			continue
		}

		// execute user's query
		variables := term.Variables(goal)
		answers := m.ProveAll(goal)

		// showing 0 results is easy and fun!
		if len(answers) == 0 {
			warnf("no.\n\n")
			continue
		}

		// show each answer in turn
		if variables.Size() == 0 {
			warnf("yes.\n")
			continue
		}
		for i, answer := range answers {
			lines := make([]string, 0)
			variables.ForEach(func(name string, variable interface{}) {
				v := variable.(*term.Variable)
				val := answer.Resolve_(v)
				line := fmt.Sprintf("%s = %s", name, val)
				lines = append(lines, line)
			})

			warnf("%s", strings.Join(lines, "\n"))
			if i == len(answers)-1 {
				warnf("\t.\n\n")
			} else {
				warnf("\t;\n")
			}
		}
	}
}

// warnf generates formatted output on stderr
func warnf(format string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, format, args...)
	os.Stderr.Sync()
}

// initMachine creates a new Golog machine based on command line arguments
func initMachine() golog.Machine {
	m := golog.NewInteractiveMachine()

	// are we supposed to load some code into the machine?
	if len(os.Args) > 1 {
		filename := os.Args[1]
		warnf("Opening %s ...\n", filename)
		file, err := os.Open(filename)
		if err != nil {
			warnf("Can't open file: %s\n", err)
			os.Exit(1)
		}
		m = m.Consult(file)
	}

	return m
}
<|endoftext|>


<commit_before>package gerrit

import (
	"crypto/md5"
	"crypto/rand"
	"encoding/base64"
	"errors"
	"fmt"
	"io"
	"net/http"
	"strings"
)

var (
	// Returned by digestAuthHeader when the WWW-Authenticate header is missing
	ErrWWWAuthenticateHeaderMissing = errors.New("WWW-Authenticate header is missing")

	// Returned by digestAuthHeader when the WWW-Authenticate invalid
	ErrWWWAuthenticateHeaderInvalid = errors.New("WWW-Authenticate header is invalid")

	// Returned by digestAuthHeader when the WWW-Authenticate header is not 'Digest'
	ErrWWWAuthenticateHeaderNotDigest = errors.New("WWW-Authenticate header type is not Digest")
)

const (
	// HTTP Basic Authentication
	authTypeBasic = 1
	// HTTP Digest Authentication
	authTypeDigest = 2
	// HTTP Cookie Authentication
	authTypeCookie = 3
)

// AuthenticationService contains Authentication related functions.
//
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api.html#authentication
type AuthenticationService struct {
	client *Client

	// Storage for authentication
	// Username or name of cookie
	name string
	// Password or value of cookie
	secret   string
	authType int
}

// SetBasicAuth sets basic parameters for HTTP Basic auth
func (s *AuthenticationService) SetBasicAuth(username, password string) {
	s.name = username
	s.secret = password
	s.authType = authTypeBasic
}

// SetDigestAuth sets digest parameters for HTTP Digest auth.
func (s *AuthenticationService) SetDigestAuth(username, password string) {
	s.name = username
	s.secret = password
	s.authType = authTypeDigest
}

// digestAuthHeader is called by gerrit.Client.Do in the event the server
// returns 401 Unauthorized and authType was set to authTypeDigest. The
// resulting string is used to set the Authorization header before retrying
// the request.
func (s *AuthenticationService) digestAuthHeader(response *http.Response) (string, error) {
	authenticateHeader := response.Header.Get("WWW-Authenticate")
	if authenticateHeader == "" {
		return "", ErrWWWAuthenticateHeaderMissing
	}

	split := strings.SplitN(authenticateHeader, " ", 2)
	if len(split) != 2 {
		return "", ErrWWWAuthenticateHeaderInvalid
	}

	if split[0] != "Digest" {
		return "", ErrWWWAuthenticateHeaderNotDigest
	}

	// Iterate over all the fields from the WWW-Authenticate header
	// and create a map of keys and values.
	authenticate := map[string]string{}
	for _, value := range strings.Split(split[1], ",") {
		kv := strings.SplitN(value, "=", 2)
		if len(kv) != 2 {
			continue
		}

		key := strings.Trim(strings.Trim(kv[0], " "), "\"")
		value := strings.Trim(strings.Trim(kv[1], " "), "\"")
		authenticate[key] = value
	}

	// Gerrit usually responds without providing the algorithm.  According
	// to RFC2617 if no algorithm is provided then the default is to use
	// MD5. At the time this code was implemented Gerrit did not appear
	// to support other algorithms or provide a means of changing the
	// algorithm.
	if value, ok := authenticate["algorithm"]; ok {
		if value != "MD5" {
			return "", fmt.Errorf(
				"algorithm not implemented: %s", value)
		}
	}

	realmHeader := authenticate["realm"]
	qopHeader := authenticate["qop"]
	nonceHeader := authenticate["nonce"]

	// If the server does not inform us what the uri is supposed
	// to be then use the last requests's uri instead.
	if _, ok := authenticate["uri"]; !ok {
		authenticate["uri"] = response.Request.URL.Path
	}

	uriHeader := authenticate["uri"]

	// A1
	h := md5.New()
	A1 := fmt.Sprintf("%s:%s:%s", s.name, realmHeader, s.secret)
	io.WriteString(h, A1)
	HA1 := fmt.Sprintf("%x", h.Sum(nil))

	// A2
	h = md5.New()
	A2 := fmt.Sprintf("%s:%s", response.Request.Method, uriHeader)
	io.WriteString(h, A2)
	HA2 := fmt.Sprintf("%x", h.Sum(nil))

	k := make([]byte, 12)
	for bytes := 0; bytes < len(k); {
		n, err := rand.Read(k[bytes:])
		if err != nil {
			return "", fmt.Errorf("cnonce generation failed: %s", err)
		}
		bytes += n
	}
	cnonce := base64.StdEncoding.EncodeToString(k)
	digest := md5.New()
	digest.Write([]byte(strings.Join([]string{HA1, nonceHeader, "00000001", cnonce, qopHeader, HA2}, ":")))
	responseField := fmt.Sprintf("%x", digest.Sum(nil))

	return fmt.Sprintf(
		`Digest username="%s", realm="%s", nonce="%s", uri="%s", cnonce="%s", nc=00000001, qop=%s, response="%s"`,
		s.name, realmHeader, nonceHeader, uriHeader, cnonce, qopHeader, responseField), nil
}

// SetCookieAuth sets basic parameters for HTTP Cookie
func (s *AuthenticationService) SetCookieAuth(name, value string) {
	s.name = name
	s.secret = value
	s.authType = authTypeCookie
}

// HasBasicAuth checks if the auth type is HTTP Basic auth
func (s *AuthenticationService) HasBasicAuth() bool {
	return s.authType == authTypeBasic
}

// HasDigestAuth checks if the auth type is HTTP Digest based
func (s *AuthenticationService) HasDigestAuth() bool {
	return s.authType == authTypeDigest
}

// HasCookieAuth checks if the auth type is HTTP Cookie based
func (s *AuthenticationService) HasCookieAuth() bool {
	return s.authType == authTypeCookie
}

// HasAuth checks if an auth type is used
func (s *AuthenticationService) HasAuth() bool {
	return s.authType > 0
}

// ResetAuth resets all former authentification settings
func (s *AuthenticationService) ResetAuth() {
	s.name = ""
	s.secret = ""
	s.authType = 0
}
<commit_msg>fix comments above errors in authentication.go<commit_after>package gerrit

import (
	"crypto/md5"
	"crypto/rand"
	"encoding/base64"
	"errors"
	"fmt"
	"io"
	"net/http"
	"strings"
)

var (
	// ErrWWWAuthenticateHeaderMissing is returned by digestAuthHeader when the WWW-Authenticate header is missing
	ErrWWWAuthenticateHeaderMissing = errors.New("WWW-Authenticate header is missing")

	// ErrWWWAuthenticateHeaderInvalid is returned by digestAuthHeader when the WWW-Authenticate invalid
	ErrWWWAuthenticateHeaderInvalid = errors.New("WWW-Authenticate header is invalid")

	// ErrWWWAuthenticateHeaderNotDigest is returned by digestAuthHeader when the WWW-Authenticate header is not 'Digest'
	ErrWWWAuthenticateHeaderNotDigest = errors.New("WWW-Authenticate header type is not Digest")
)

const (
	// HTTP Basic Authentication
	authTypeBasic = 1
	// HTTP Digest Authentication
	authTypeDigest = 2
	// HTTP Cookie Authentication
	authTypeCookie = 3
)

// AuthenticationService contains Authentication related functions.
//
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/rest-api.html#authentication
type AuthenticationService struct {
	client *Client

	// Storage for authentication
	// Username or name of cookie
	name string
	// Password or value of cookie
	secret   string
	authType int
}

// SetBasicAuth sets basic parameters for HTTP Basic auth
func (s *AuthenticationService) SetBasicAuth(username, password string) {
	s.name = username
	s.secret = password
	s.authType = authTypeBasic
}

// SetDigestAuth sets digest parameters for HTTP Digest auth.
func (s *AuthenticationService) SetDigestAuth(username, password string) {
	s.name = username
	s.secret = password
	s.authType = authTypeDigest
}

// digestAuthHeader is called by gerrit.Client.Do in the event the server
// returns 401 Unauthorized and authType was set to authTypeDigest. The
// resulting string is used to set the Authorization header before retrying
// the request.
func (s *AuthenticationService) digestAuthHeader(response *http.Response) (string, error) {
	authenticateHeader := response.Header.Get("WWW-Authenticate")
	if authenticateHeader == "" {
		return "", ErrWWWAuthenticateHeaderMissing
	}

	split := strings.SplitN(authenticateHeader, " ", 2)
	if len(split) != 2 {
		return "", ErrWWWAuthenticateHeaderInvalid
	}

	if split[0] != "Digest" {
		return "", ErrWWWAuthenticateHeaderNotDigest
	}

	// Iterate over all the fields from the WWW-Authenticate header
	// and create a map of keys and values.
	authenticate := map[string]string{}
	for _, value := range strings.Split(split[1], ",") {
		kv := strings.SplitN(value, "=", 2)
		if len(kv) != 2 {
			continue
		}

		key := strings.Trim(strings.Trim(kv[0], " "), "\"")
		value := strings.Trim(strings.Trim(kv[1], " "), "\"")
		authenticate[key] = value
	}

	// Gerrit usually responds without providing the algorithm.  According
	// to RFC2617 if no algorithm is provided then the default is to use
	// MD5. At the time this code was implemented Gerrit did not appear
	// to support other algorithms or provide a means of changing the
	// algorithm.
	if value, ok := authenticate["algorithm"]; ok {
		if value != "MD5" {
			return "", fmt.Errorf(
				"algorithm not implemented: %s", value)
		}
	}

	realmHeader := authenticate["realm"]
	qopHeader := authenticate["qop"]
	nonceHeader := authenticate["nonce"]

	// If the server does not inform us what the uri is supposed
	// to be then use the last requests's uri instead.
	if _, ok := authenticate["uri"]; !ok {
		authenticate["uri"] = response.Request.URL.Path
	}

	uriHeader := authenticate["uri"]

	// A1
	h := md5.New()
	A1 := fmt.Sprintf("%s:%s:%s", s.name, realmHeader, s.secret)
	io.WriteString(h, A1)
	HA1 := fmt.Sprintf("%x", h.Sum(nil))

	// A2
	h = md5.New()
	A2 := fmt.Sprintf("%s:%s", response.Request.Method, uriHeader)
	io.WriteString(h, A2)
	HA2 := fmt.Sprintf("%x", h.Sum(nil))

	k := make([]byte, 12)
	for bytes := 0; bytes < len(k); {
		n, err := rand.Read(k[bytes:])
		if err != nil {
			return "", fmt.Errorf("cnonce generation failed: %s", err)
		}
		bytes += n
	}
	cnonce := base64.StdEncoding.EncodeToString(k)
	digest := md5.New()
	digest.Write([]byte(strings.Join([]string{HA1, nonceHeader, "00000001", cnonce, qopHeader, HA2}, ":")))
	responseField := fmt.Sprintf("%x", digest.Sum(nil))

	return fmt.Sprintf(
		`Digest username="%s", realm="%s", nonce="%s", uri="%s", cnonce="%s", nc=00000001, qop=%s, response="%s"`,
		s.name, realmHeader, nonceHeader, uriHeader, cnonce, qopHeader, responseField), nil
}

// SetCookieAuth sets basic parameters for HTTP Cookie
func (s *AuthenticationService) SetCookieAuth(name, value string) {
	s.name = name
	s.secret = value
	s.authType = authTypeCookie
}

// HasBasicAuth checks if the auth type is HTTP Basic auth
func (s *AuthenticationService) HasBasicAuth() bool {
	return s.authType == authTypeBasic
}

// HasDigestAuth checks if the auth type is HTTP Digest based
func (s *AuthenticationService) HasDigestAuth() bool {
	return s.authType == authTypeDigest
}

// HasCookieAuth checks if the auth type is HTTP Cookie based
func (s *AuthenticationService) HasCookieAuth() bool {
	return s.authType == authTypeCookie
}

// HasAuth checks if an auth type is used
func (s *AuthenticationService) HasAuth() bool {
	return s.authType > 0
}

// ResetAuth resets all former authentification settings
func (s *AuthenticationService) ResetAuth() {
	s.name = ""
	s.secret = ""
	s.authType = 0
}
<|endoftext|>


<commit_before>package controller

import (
	"bytes"
	"errors"
	"strconv"
	"sync"

	"github.com/tidwall/resp"
	"github.com/tidwall/tile38/controller/collection"
	"github.com/tidwall/tile38/controller/glob"
	"github.com/tidwall/tile38/controller/server"
	"github.com/tidwall/tile38/geojson"
)

const limitItems = 100
const capLimit = 100000

type outputT int

const (
	outputUnknown outputT = iota
	outputIDs
	outputObjects
	outputCount
	outputPoints
	outputHashes
	outputBounds
)

type scanWriter struct {
	mu             sync.Mutex
	c              *Controller
	wr             *bytes.Buffer
	msg            *server.Message
	col            *collection.Collection
	fmap           map[string]int
	farr           []string
	fvals          []float64
	output         outputT
	wheres         []whereT
	numberItems    uint64
	nofields       bool
	cursor         uint64
	limit          uint64
	hitLimit       bool
	once           bool
	count          uint64
	precision      uint64
	globPattern    string
	globEverything bool
	globSingle     bool
	fullFields     bool
	values         []resp.Value
	matchValues    bool
}

type ScanWriterParams struct {
	id       string
	o        geojson.Object
	fields   []float64
	distance float64
	noLock   bool
}

func (c *Controller) newScanWriter(
	wr *bytes.Buffer, msg *server.Message, key string, output outputT,
	precision uint64, globPattern string, matchValues bool,
	cursor, limit uint64, wheres []whereT, nofields bool,
) (
	*scanWriter, error,
) {
	if limit == 0 {
		limit = limitItems
	} else if limit > capLimit {
		limit = capLimit
	}
	switch output {
	default:
		return nil, errors.New("invalid output type")
	case outputIDs, outputObjects, outputCount, outputBounds, outputPoints, outputHashes:
	}
	sw := &scanWriter{
		c:           c,
		wr:          wr,
		msg:         msg,
		cursor:      cursor,
		limit:       limit,
		wheres:      wheres,
		output:      output,
		nofields:    nofields,
		precision:   precision,
		globPattern: globPattern,
		matchValues: matchValues,
	}
	if globPattern == "*" || globPattern == "" {
		sw.globEverything = true
	} else {
		if !glob.IsGlob(globPattern) {
			sw.globSingle = true
		}
	}
	sw.col = c.getCol(key)
	if sw.col != nil {
		sw.fmap = sw.col.FieldMap()
		sw.farr = sw.col.FieldArr()
	}
	sw.fvals = make([]float64, len(sw.farr))
	return sw, nil
}

func (sw *scanWriter) hasFieldsOutput() bool {
	switch sw.output {
	default:
		return false
	case outputObjects, outputPoints, outputHashes, outputBounds:
		return !sw.nofields
	}
}

func (sw *scanWriter) writeHead() {
	sw.mu.Lock()
	defer sw.mu.Unlock()
	switch sw.msg.OutputType {
	case server.JSON:
		if len(sw.farr) > 0 && sw.hasFieldsOutput() {
			sw.wr.WriteString(`,"fields":[`)
			for i, field := range sw.farr {
				if i > 0 {
					sw.wr.WriteByte(',')
				}
				sw.wr.WriteString(jsonString(field))
			}
			sw.wr.WriteByte(']')
		}
		switch sw.output {
		case outputIDs:
			sw.wr.WriteString(`,"ids":[`)
		case outputObjects:
			sw.wr.WriteString(`,"objects":[`)
		case outputPoints:
			sw.wr.WriteString(`,"points":[`)
		case outputBounds:
			sw.wr.WriteString(`,"bounds":[`)
		case outputHashes:
			sw.wr.WriteString(`,"hashes":[`)
		case outputCount:

		}
	case server.RESP:
	}
}

func (sw *scanWriter) writeFoot() {
	sw.mu.Lock()
	defer sw.mu.Unlock()
	cursor := sw.cursor + sw.numberItems
	if !sw.hitLimit {
		cursor = 0
	}
	switch sw.msg.OutputType {
	case server.JSON:
		switch sw.output {
		default:
			sw.wr.WriteByte(']')
		case outputCount:

		}
		sw.wr.WriteString(`,"count":` + strconv.FormatUint(sw.count, 10))
		sw.wr.WriteString(`,"cursor":` + strconv.FormatUint(cursor, 10))
	case server.RESP:
		sw.wr.Reset()
		var data []byte
		var err error
		if sw.output == outputCount {
			data, err = resp.IntegerValue(int(sw.count)).MarshalRESP()
		} else {
			values := []resp.Value{
				resp.IntegerValue(int(cursor)),
				resp.ArrayValue(sw.values),
			}
			data, err = resp.ArrayValue(values).MarshalRESP()
		}
		if err != nil {
			panic("Eek this is bad. Marshal resp should not fail.")
		}
		sw.wr.Write(data)
	}
}

func (sw *scanWriter) fieldMatch(fields []float64, o geojson.Object) ([]float64, bool) {
	var z float64
	var gotz bool
	if !sw.hasFieldsOutput() || sw.fullFields {
		for _, where := range sw.wheres {
			if where.field == "z" {
				if !gotz {
					z = o.CalculatedPoint().Z
				}
				if !where.match(z) {
					return sw.fvals, false
				}
				continue
			}
			var value float64
			idx, ok := sw.fmap[where.field]
			if ok {
				if len(fields) > idx {
					value = fields[idx]
				}
			}
			if !where.match(value) {
				return sw.fvals, false
			}
		}
	} else {
		for idx := range sw.farr {
			var value float64
			if len(fields) > idx {
				value = fields[idx]
			}
			sw.fvals[idx] = value
		}
		for _, where := range sw.wheres {
			if where.field == "z" {
				if !gotz {
					z = o.CalculatedPoint().Z
				}
				if !where.match(z) {
					return sw.fvals, false
				}
				continue
			}
			var value float64
			idx, ok := sw.fmap[where.field]
			if ok {
				value = sw.fvals[idx]
			}
			if !where.match(value) {
				return sw.fvals, false
			}
		}
	}
	return sw.fvals, true
}

//id string, o geojson.Object, fields []float64, noLock bool
func (sw *scanWriter) writeObject(opts ScanWriterParams) bool {
	if !opts.noLock {
		sw.mu.Lock()
		defer sw.mu.Unlock()
	}
	keepGoing := true
	if !sw.globEverything {
		if sw.globSingle {
			if sw.globPattern != opts.id {
				return true
			}
			keepGoing = false // return current object and stop iterating
		} else {
			var val string
			if sw.matchValues {
				val = opts.o.String()
			} else {
				val = opts.id
			}
			ok, _ := glob.Match(sw.globPattern, val)
			if !ok {
				return true
			}
		}
	}
	nfields, ok := sw.fieldMatch(opts.fields, opts.o)
	if !ok {
		return true
	}
	sw.count++
	if sw.count <= sw.cursor {
		return true
	}
	if sw.output == outputCount {
		return sw.count < sw.limit
	}
	switch sw.msg.OutputType {
	case server.JSON:
		var wr bytes.Buffer
		var jsfields string
		if sw.once {
			wr.WriteByte(',')
		} else {
			sw.once = true
		}
		if sw.hasFieldsOutput() {
			if sw.fullFields {
				if len(sw.fmap) > 0 {
					jsfields = `,"fields":{`
					var i int
					for field, idx := range sw.fmap {
						if len(opts.fields) > idx {
							if opts.fields[idx] != 0 {
								if i > 0 {
									jsfields += `,`
								}
								jsfields += jsonString(field) + ":" + strconv.FormatFloat(opts.fields[idx], 'f', -1, 64)
								i++
							}
						}
					}
					jsfields += `}`
				}

			} else if len(sw.farr) > 0 {
				jsfields = `,"fields":[`
				for i, field := range nfields {
					if i > 0 {
						jsfields += ","
					}
					jsfields += strconv.FormatFloat(field, 'f', -1, 64)
				}
				jsfields += `]`
			}
		}
		if sw.output == outputIDs {
			wr.WriteString(jsonString(opts.id))
		} else {
			wr.WriteString(`{"id":` + jsonString(opts.id))
			switch sw.output {
			case outputObjects:
				wr.WriteString(`,"object":` + opts.o.JSON())
			case outputPoints:
				wr.WriteString(`,"point":` + opts.o.CalculatedPoint().ExternalJSON())
			case outputHashes:
				p, err := opts.o.Geohash(int(sw.precision))
				if err != nil {
					p = ""
				}
				wr.WriteString(`,"hash":"` + p + `"`)
			case outputBounds:
				wr.WriteString(`,"bounds":` + opts.o.CalculatedBBox().ExternalJSON())
			}

			wr.WriteString(jsfields)

			if opts.distance > 0 {
				wr.WriteString(`,"distance":` + strconv.FormatFloat(opts.distance, 'f', 2, 64))
			}

			wr.WriteString(`}`)
		}
		sw.wr.Write(wr.Bytes())
	case server.RESP:
		vals := make([]resp.Value, 1, 3)
		vals[0] = resp.StringValue(opts.id)
		if sw.output == outputIDs {
			sw.values = append(sw.values, vals[0])
		} else {
			switch sw.output {
			case outputObjects:
				vals = append(vals, resp.StringValue(opts.o.String()))
			case outputPoints:
				point := opts.o.CalculatedPoint()
				if point.Z != 0 {
					vals = append(vals, resp.ArrayValue([]resp.Value{
						resp.FloatValue(point.Y),
						resp.FloatValue(point.X),
						resp.FloatValue(point.Z),
					}))
				} else {
					vals = append(vals, resp.ArrayValue([]resp.Value{
						resp.FloatValue(point.Y),
						resp.FloatValue(point.X),
					}))
				}
			case outputHashes:
				p, err := opts.o.Geohash(int(sw.precision))
				if err != nil {
					p = ""
				}
				vals = append(vals, resp.StringValue(p))
			case outputBounds:
				bbox := opts.o.CalculatedBBox()
				vals = append(vals, resp.ArrayValue([]resp.Value{
					resp.ArrayValue([]resp.Value{
						resp.FloatValue(bbox.Min.Y),
						resp.FloatValue(bbox.Min.X),
					}),
					resp.ArrayValue([]resp.Value{
						resp.FloatValue(bbox.Max.Y),
						resp.FloatValue(bbox.Max.X),
					}),
				}))
			}

			if sw.hasFieldsOutput() {
				fvs := orderFields(sw.fmap, opts.fields)
				if len(fvs) > 0 {
					fvals := make([]resp.Value, 0, len(fvs)*2)
					for i, fv := range fvs {
						fvals = append(fvals, resp.StringValue(fv.field), resp.StringValue(strconv.FormatFloat(fv.value, 'f', -1, 64)))
						i++
					}
					vals = append(vals, resp.ArrayValue(fvals))
				}
			}
			if opts.distance > 0 {
				vals = append(vals, resp.FloatValue(opts.distance))
			}

			sw.values = append(sw.values, resp.ArrayValue(vals))
		}
	}
	sw.numberItems++
	if sw.numberItems == sw.limit {
		sw.hitLimit = true
		return false
	}
	return keepGoing
}
<commit_msg>lifted limit cap<commit_after>package controller

import (
	"bytes"
	"errors"
	"math"
	"strconv"
	"sync"

	"github.com/tidwall/resp"
	"github.com/tidwall/tile38/controller/collection"
	"github.com/tidwall/tile38/controller/glob"
	"github.com/tidwall/tile38/controller/server"
	"github.com/tidwall/tile38/geojson"
)

const limitItems = 100

type outputT int

const (
	outputUnknown outputT = iota
	outputIDs
	outputObjects
	outputCount
	outputPoints
	outputHashes
	outputBounds
)

type scanWriter struct {
	mu             sync.Mutex
	c              *Controller
	wr             *bytes.Buffer
	msg            *server.Message
	col            *collection.Collection
	fmap           map[string]int
	farr           []string
	fvals          []float64
	output         outputT
	wheres         []whereT
	numberItems    uint64
	nofields       bool
	cursor         uint64
	limit          uint64
	hitLimit       bool
	once           bool
	count          uint64
	precision      uint64
	globPattern    string
	globEverything bool
	globSingle     bool
	fullFields     bool
	values         []resp.Value
	matchValues    bool
}

type ScanWriterParams struct {
	id       string
	o        geojson.Object
	fields   []float64
	distance float64
	noLock   bool
}

func (c *Controller) newScanWriter(
	wr *bytes.Buffer, msg *server.Message, key string, output outputT,
	precision uint64, globPattern string, matchValues bool,
	cursor, limit uint64, wheres []whereT, nofields bool,
) (
	*scanWriter, error,
) {
	switch output {
	default:
		return nil, errors.New("invalid output type")
	case outputIDs, outputObjects, outputCount, outputBounds, outputPoints, outputHashes:
	}
	if limit == 0 {
		if output == outputCount {
			limit = math.MaxUint64
		} else {
			limit = limitItems
		}
	}
	sw := &scanWriter{
		c:           c,
		wr:          wr,
		msg:         msg,
		cursor:      cursor,
		limit:       limit,
		wheres:      wheres,
		output:      output,
		nofields:    nofields,
		precision:   precision,
		globPattern: globPattern,
		matchValues: matchValues,
	}
	if globPattern == "*" || globPattern == "" {
		sw.globEverything = true
	} else {
		if !glob.IsGlob(globPattern) {
			sw.globSingle = true
		}
	}
	sw.col = c.getCol(key)
	if sw.col != nil {
		sw.fmap = sw.col.FieldMap()
		sw.farr = sw.col.FieldArr()
	}
	sw.fvals = make([]float64, len(sw.farr))
	return sw, nil
}

func (sw *scanWriter) hasFieldsOutput() bool {
	switch sw.output {
	default:
		return false
	case outputObjects, outputPoints, outputHashes, outputBounds:
		return !sw.nofields
	}
}

func (sw *scanWriter) writeHead() {
	sw.mu.Lock()
	defer sw.mu.Unlock()
	switch sw.msg.OutputType {
	case server.JSON:
		if len(sw.farr) > 0 && sw.hasFieldsOutput() {
			sw.wr.WriteString(`,"fields":[`)
			for i, field := range sw.farr {
				if i > 0 {
					sw.wr.WriteByte(',')
				}
				sw.wr.WriteString(jsonString(field))
			}
			sw.wr.WriteByte(']')
		}
		switch sw.output {
		case outputIDs:
			sw.wr.WriteString(`,"ids":[`)
		case outputObjects:
			sw.wr.WriteString(`,"objects":[`)
		case outputPoints:
			sw.wr.WriteString(`,"points":[`)
		case outputBounds:
			sw.wr.WriteString(`,"bounds":[`)
		case outputHashes:
			sw.wr.WriteString(`,"hashes":[`)
		case outputCount:

		}
	case server.RESP:
	}
}

func (sw *scanWriter) writeFoot() {
	sw.mu.Lock()
	defer sw.mu.Unlock()
	cursor := sw.cursor + sw.numberItems
	if !sw.hitLimit {
		cursor = 0
	}
	switch sw.msg.OutputType {
	case server.JSON:
		switch sw.output {
		default:
			sw.wr.WriteByte(']')
		case outputCount:

		}
		sw.wr.WriteString(`,"count":` + strconv.FormatUint(sw.count, 10))
		sw.wr.WriteString(`,"cursor":` + strconv.FormatUint(cursor, 10))
	case server.RESP:
		sw.wr.Reset()
		var data []byte
		var err error
		if sw.output == outputCount {
			data, err = resp.IntegerValue(int(sw.count)).MarshalRESP()
		} else {
			values := []resp.Value{
				resp.IntegerValue(int(cursor)),
				resp.ArrayValue(sw.values),
			}
			data, err = resp.ArrayValue(values).MarshalRESP()
		}
		if err != nil {
			panic("Eek this is bad. Marshal resp should not fail.")
		}
		sw.wr.Write(data)
	}
}

func (sw *scanWriter) fieldMatch(fields []float64, o geojson.Object) ([]float64, bool) {
	var z float64
	var gotz bool
	if !sw.hasFieldsOutput() || sw.fullFields {
		for _, where := range sw.wheres {
			if where.field == "z" {
				if !gotz {
					z = o.CalculatedPoint().Z
				}
				if !where.match(z) {
					return sw.fvals, false
				}
				continue
			}
			var value float64
			idx, ok := sw.fmap[where.field]
			if ok {
				if len(fields) > idx {
					value = fields[idx]
				}
			}
			if !where.match(value) {
				return sw.fvals, false
			}
		}
	} else {
		for idx := range sw.farr {
			var value float64
			if len(fields) > idx {
				value = fields[idx]
			}
			sw.fvals[idx] = value
		}
		for _, where := range sw.wheres {
			if where.field == "z" {
				if !gotz {
					z = o.CalculatedPoint().Z
				}
				if !where.match(z) {
					return sw.fvals, false
				}
				continue
			}
			var value float64
			idx, ok := sw.fmap[where.field]
			if ok {
				value = sw.fvals[idx]
			}
			if !where.match(value) {
				return sw.fvals, false
			}
		}
	}
	return sw.fvals, true
}

//id string, o geojson.Object, fields []float64, noLock bool
func (sw *scanWriter) writeObject(opts ScanWriterParams) bool {
	if !opts.noLock {
		sw.mu.Lock()
		defer sw.mu.Unlock()
	}
	keepGoing := true
	if !sw.globEverything {
		if sw.globSingle {
			if sw.globPattern != opts.id {
				return true
			}
			keepGoing = false // return current object and stop iterating
		} else {
			var val string
			if sw.matchValues {
				val = opts.o.String()
			} else {
				val = opts.id
			}
			ok, _ := glob.Match(sw.globPattern, val)
			if !ok {
				return true
			}
		}
	}
	nfields, ok := sw.fieldMatch(opts.fields, opts.o)
	if !ok {
		return true
	}
	sw.count++
	if sw.count <= sw.cursor {
		return true
	}
	if sw.output == outputCount {
		return sw.count < sw.limit
	}
	switch sw.msg.OutputType {
	case server.JSON:
		var wr bytes.Buffer
		var jsfields string
		if sw.once {
			wr.WriteByte(',')
		} else {
			sw.once = true
		}
		if sw.hasFieldsOutput() {
			if sw.fullFields {
				if len(sw.fmap) > 0 {
					jsfields = `,"fields":{`
					var i int
					for field, idx := range sw.fmap {
						if len(opts.fields) > idx {
							if opts.fields[idx] != 0 {
								if i > 0 {
									jsfields += `,`
								}
								jsfields += jsonString(field) + ":" + strconv.FormatFloat(opts.fields[idx], 'f', -1, 64)
								i++
							}
						}
					}
					jsfields += `}`
				}

			} else if len(sw.farr) > 0 {
				jsfields = `,"fields":[`
				for i, field := range nfields {
					if i > 0 {
						jsfields += ","
					}
					jsfields += strconv.FormatFloat(field, 'f', -1, 64)
				}
				jsfields += `]`
			}
		}
		if sw.output == outputIDs {
			wr.WriteString(jsonString(opts.id))
		} else {
			wr.WriteString(`{"id":` + jsonString(opts.id))
			switch sw.output {
			case outputObjects:
				wr.WriteString(`,"object":` + opts.o.JSON())
			case outputPoints:
				wr.WriteString(`,"point":` + opts.o.CalculatedPoint().ExternalJSON())
			case outputHashes:
				p, err := opts.o.Geohash(int(sw.precision))
				if err != nil {
					p = ""
				}
				wr.WriteString(`,"hash":"` + p + `"`)
			case outputBounds:
				wr.WriteString(`,"bounds":` + opts.o.CalculatedBBox().ExternalJSON())
			}

			wr.WriteString(jsfields)

			if opts.distance > 0 {
				wr.WriteString(`,"distance":` + strconv.FormatFloat(opts.distance, 'f', 2, 64))
			}

			wr.WriteString(`}`)
		}
		sw.wr.Write(wr.Bytes())
	case server.RESP:
		vals := make([]resp.Value, 1, 3)
		vals[0] = resp.StringValue(opts.id)
		if sw.output == outputIDs {
			sw.values = append(sw.values, vals[0])
		} else {
			switch sw.output {
			case outputObjects:
				vals = append(vals, resp.StringValue(opts.o.String()))
			case outputPoints:
				point := opts.o.CalculatedPoint()
				if point.Z != 0 {
					vals = append(vals, resp.ArrayValue([]resp.Value{
						resp.FloatValue(point.Y),
						resp.FloatValue(point.X),
						resp.FloatValue(point.Z),
					}))
				} else {
					vals = append(vals, resp.ArrayValue([]resp.Value{
						resp.FloatValue(point.Y),
						resp.FloatValue(point.X),
					}))
				}
			case outputHashes:
				p, err := opts.o.Geohash(int(sw.precision))
				if err != nil {
					p = ""
				}
				vals = append(vals, resp.StringValue(p))
			case outputBounds:
				bbox := opts.o.CalculatedBBox()
				vals = append(vals, resp.ArrayValue([]resp.Value{
					resp.ArrayValue([]resp.Value{
						resp.FloatValue(bbox.Min.Y),
						resp.FloatValue(bbox.Min.X),
					}),
					resp.ArrayValue([]resp.Value{
						resp.FloatValue(bbox.Max.Y),
						resp.FloatValue(bbox.Max.X),
					}),
				}))
			}

			if sw.hasFieldsOutput() {
				fvs := orderFields(sw.fmap, opts.fields)
				if len(fvs) > 0 {
					fvals := make([]resp.Value, 0, len(fvs)*2)
					for i, fv := range fvs {
						fvals = append(fvals, resp.StringValue(fv.field), resp.StringValue(strconv.FormatFloat(fv.value, 'f', -1, 64)))
						i++
					}
					vals = append(vals, resp.ArrayValue(fvals))
				}
			}
			if opts.distance > 0 {
				vals = append(vals, resp.FloatValue(opts.distance))
			}

			sw.values = append(sw.values, resp.ArrayValue(vals))
		}
	}
	sw.numberItems++
	if sw.numberItems == sw.limit {
		sw.hitLimit = true
		return false
	}
	return keepGoing
}
<|endoftext|>


<commit_before>package controllers

import (
    "encoding/json"
    "fmt"
    "github.com/orc/db"
    "github.com/orc/sessions"
    "github.com/orc/utils"
    "html/template"
    "strconv"
)

func (c *BaseController) Handler() *Handler {
    return new(Handler)
}

type Handler struct {
    Controller
}

func (this *Handler) GetEventList() {
    this.Response.Header().Set("Access-Control-Allow-Origin", "*")
    this.Response.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
    this.Response.Header().Set("Content-type", "application/json")

    var request map[string]interface{}
    decoder := json.NewDecoder(this.Request.Body)
    err := decoder.Decode(&request)
    utils.HandleErr("[Handler] Decode :", err, this.Response)

    fields := request["fields"].([]interface{})
    tableName := request["table"].(string)

    model := GetModel(tableName)
    result, _ := model.Select(nil, "", utils.ArrayInterfaceToString(fields))

    response, err := json.Marshal(map[string]interface{}{"data": result})
    utils.HandleErr("[Handle select] json.Marshal: ", err, nil)
    fmt.Fprintf(this.Response, "%s", string(response))
}

func (this *Handler) ResetPassword() {
    if flag := sessions.CheackSession(this.Response, this.Request); !flag {
        return
    }
    this.Response.Header().Set("Access-Control-Allow-Origin", "*")
    this.Response.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
    this.Response.Header().Set("Content-type", "application/json")

    var request map[string]string
    decoder := json.NewDecoder(this.Request.Body)
    err := decoder.Decode(&request)
    utils.HandleErr("[Handler] Decode :", err, this.Response)

    id, pass, model := request["id"], request["pass"], GetModel("users")
    result, _ := model.Select([]string{"id", id}, "", []string{"salt"})
    salt := result[0].(map[string]interface{})["salt"].(string)
    hash := GetMD5Hash(pass + salt)
    model.Update([]string{"pass"}, []interface{}{hash, id}, "id=$2")

    response, err := json.Marshal(map[string]interface{}{"result": "ok"})
    utils.HandleErr("[Handle select] json.Marshal: ", err, nil)
    fmt.Fprintf(this.Response, "%s", string(response))
}

func (this *Handler) Index() {
    var data map[string]interface{}
    response := ""

    this.Response.Header().Set("Access-Control-Allow-Origin", "*")
    this.Response.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
    this.Response.Header().Set("Content-type", "application/json")

    decoder := json.NewDecoder(this.Request.Body)
    err := decoder.Decode(&data)
    utils.HandleErr("[Handler] Decode :", err, this.Response)

    switch data["action"] {
    case "register":
        login, password := data["login"].(string), data["password"].(string)
        fname, lname /*, pname*/ := data["fname"].(string), data["lname"].(string) /*, data["pname"].(string)*/
        response = this.HandleRegister(login, password, "user", fname, lname /*, pname*/)
        fmt.Fprintf(this.Response, "%s", response)
        break

    case "login":
        response = this.HandleLogin(data["login"].(string), data["password"].(string))
        fmt.Fprintf(this.Response, "%s", response)
        break

    case "logout":
        response = this.HandleLogout()
        fmt.Fprintf(this.Response, "%s", response)
        break

    case "editProfile":
        id := data["id"].(string)
        tableName := data["table"].(string)
        inf := data["data"].([]interface{})

        var fields []string
        var params []interface{}
        for _, element := range inf {
            fields = append(fields, element.(map[string]interface{})["name"].(string))
            params = append(params, element.(map[string]interface{})["value"])
        }
        params = append(params, id)
        model := GetModel(tableName)
        model.Update(fields, params, "id=$"+strconv.Itoa(len(fields)+1))

        response, err := json.Marshal(map[string]interface{}{"result": "ok"})
        utils.HandleErr("[Handle select] json.Marshal: ", err, nil)
        fmt.Fprintf(this.Response, "%s", string(response))
        break
    }
}

func (this *Handler) ShowCabinet(tableName string) {
    if flag := sessions.CheackSession(this.Response, this.Request); !flag {
        return
    }
    table := GetModel("users")
    login := sessions.GetValue("name", this.Request).(string)
    println(login)
    data, _ := table.Select([]string{"login", login}, "", []string{"role", "person_id"})

    role := data[0].(map[string]interface{})["role"].(string)
    person_id := data[0].(map[string]interface{})["person_id"].(int64)

    var model Model
    if role == "admin" {
        model = Model{Columns: db.Tables, ColNames: db.TableNames}
    } else if role == "user" {
        m := GetModel("persons")
        data, _ := m.Select([]string{"id", strconv.Itoa(int(person_id))}, "", m.GetColumns())
        model = Model{Caption: login, Table: data, Columns: m.GetColumns(), ColNames: m.GetColNames()}
    }

    tmp, err := template.ParseFiles(
        "mvc/views/"+role+".html",
        "mvc/views/header.html",
        "mvc/views/footer.html")
    utils.HandleErr("[Handler.ShowCabinet] ParseFiles: ", err, nil)
    err = tmp.ExecuteTemplate(this.Response, role, model)
    utils.HandleErr("[Handler.ShowCabinet] Execute: ", err, nil)
}
<commit_msg>controller/handler: fix error messages<commit_after>package controllers

import (
    "encoding/json"
    "fmt"
    "github.com/orc/db"
    "github.com/orc/sessions"
    "github.com/orc/utils"
    "html/template"
    "strconv"
)

func (c *BaseController) Handler() *Handler {
    return new(Handler)
}

type Handler struct {
    Controller
}

func (this *Handler) GetEventList() {
    this.Response.Header().Set("Access-Control-Allow-Origin", "*")
    this.Response.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
    this.Response.Header().Set("Content-type", "application/json")

    var request map[string]interface{}
    decoder := json.NewDecoder(this.Request.Body)
    err := decoder.Decode(&request)
    utils.HandleErr("[Handler::GetEventList] Decode :", err, this.Response)

    fields := request["fields"].([]interface{})
    tableName := request["table"].(string)

    model := GetModel(tableName)
    result, _ := model.Select(nil, "", utils.ArrayInterfaceToString(fields))

    response, err := json.Marshal(map[string]interface{}{"data": result})
    utils.HandleErr("[Handle::GetEventList] Marshal: ", err, this.Response)
    fmt.Fprintf(this.Response, "%s", string(response))
}

func (this *Handler) ResetPassword() {
    if flag := sessions.CheackSession(this.Response, this.Request); !flag {
        return
    }
    this.Response.Header().Set("Access-Control-Allow-Origin", "*")
    this.Response.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
    this.Response.Header().Set("Content-type", "application/json")

    var request map[string]string
    decoder := json.NewDecoder(this.Request.Body)
    err := decoder.Decode(&request)
    utils.HandleErr("[Handler::ResetPassword] Decode :", err, this.Response)

    id, pass, model := request["id"], request["pass"], GetModel("users")
    result, _ := model.Select([]string{"id", id}, "", []string{"salt"})
    salt := result[0].(map[string]interface{})["salt"].(string)
    hash := GetMD5Hash(pass + salt)
    model.Update([]string{"pass"}, []interface{}{hash, id}, "id=$2")

    response, err := json.Marshal(map[string]interface{}{"result": "ok"})
    utils.HandleErr("[Handle::ResetPassword] Marshal: ", err, this.Response)
    fmt.Fprintf(this.Response, "%s", string(response))
}

func (this *Handler) Index() {
    var data map[string]interface{}
    response := ""

    this.Response.Header().Set("Access-Control-Allow-Origin", "*")
    this.Response.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
    this.Response.Header().Set("Content-type", "application/json")

    decoder := json.NewDecoder(this.Request.Body)
    err := decoder.Decode(&data)
    utils.HandleErr("[Handler::Index] Decode :", err, this.Response)

    switch data["action"] {
    case "register":
        login, password := data["login"].(string), data["password"].(string)
        fname, lname := data["fname"].(string), data["lname"].(string)
        response = this.HandleRegister(login, password, "user", fname, lname)
        fmt.Fprintf(this.Response, "%s", response)
        break

    case "login":
        response = this.HandleLogin(data["login"].(string), data["password"].(string))
        fmt.Fprintf(this.Response, "%s", response)
        break

    case "logout":
        response = this.HandleLogout()
        fmt.Fprintf(this.Response, "%s", response)
        break

    case "editProfile":
        id := data["id"].(string)
        tableName := data["table"].(string)
        inf := data["data"].([]interface{})

        var fields []string
        var params []interface{}
        for _, element := range inf {
            fields = append(fields, element.(map[string]interface{})["name"].(string))
            params = append(params, element.(map[string]interface{})["value"])
        }
        params = append(params, id)
        model := GetModel(tableName)
        model.Update(fields, params, "id=$"+strconv.Itoa(len(fields)+1))

        response, err := json.Marshal(map[string]interface{}{"result": "ok"})
        utils.HandleErr("[Handle::Index] Marshal: ", err, this.Response)
        fmt.Fprintf(this.Response, "%s", string(response))
        break
    }
}

func (this *Handler) ShowCabinet(tableName string) {
    if flag := sessions.CheackSession(this.Response, this.Request); !flag {
        return
    }
    table := GetModel("users")
    login := sessions.GetValue("name", this.Request).(string)
    println(login)
    data, _ := table.Select([]string{"login", login}, "", []string{"role", "person_id"})

    role := data[0].(map[string]interface{})["role"].(string)
    person_id := data[0].(map[string]interface{})["person_id"].(int64)

    var model Model
    if role == "admin" {
        model = Model{Columns: db.Tables, ColNames: db.TableNames}
    } else if role == "user" {
        m := GetModel("persons")
        data, _ := m.Select([]string{"id", strconv.Itoa(int(person_id))}, "", m.GetColumns())
        model = Model{Caption: login, Table: data, Columns: m.GetColumns(), ColNames: m.GetColNames()}
    }

    tmp, err := template.ParseFiles(
        "mvc/views/"+role+".html",
        "mvc/views/header.html",
        "mvc/views/footer.html")
    utils.HandleErr("[Handler::ShowCabinet] ParseFiles: ", err, this.Response)
    err = tmp.ExecuteTemplate(this.Response, role, model)
    utils.HandleErr("[Handler::ShowCabinet] ExecuteTemplate: ", err, this.Response)
}
<|endoftext|>


<commit_before>package casbin

import (
	"github.com/Knetic/govaluate"
	"log"
)

// Enforcer is the main interface for authorization enforcement and policy management.
type Enforcer struct {
	modelPath  string
	policyPath string
	model      Model
	enabled    bool
}

func (enforcer *Enforcer) Init(modelPath string, policyPath string) {
	enforcer.modelPath = modelPath
	enforcer.policyPath = policyPath
	enforcer.enabled = true

	enforcer.LoadAll()
}

func (enforcer *Enforcer) LoadAll() {
	enforcer.model = loadModel(enforcer.modelPath)
	printModel(enforcer.model)

	enforcer.LoadPolicy()
}

func (enforcer *Enforcer) LoadPolicy() {
	loadPolicy(enforcer.policyPath, enforcer.model)
	printPolicy(enforcer.model)
	buildRoleLinks(enforcer.model)
}

func (enforcer *Enforcer) SavePolicy() {
	savePolicy(enforcer.policyPath, enforcer.model)
}

func (enforcer *Enforcer) Enable(enable bool) {
	enforcer.enabled = enable
}

func (enforcer *Enforcer) Enforce(rvals ...string) bool {
	if !enforcer.enabled {
		return true
	}

	expString := enforcer.model["m"]["m"].value
	var expression *govaluate.EvaluableExpression

	functions := make(map[string]govaluate.ExpressionFunction)

	functions["keyMatch"] = func(args ...interface{}) (interface{}, error) {
		name1 := args[0].(string)
		name2 := args[1].(string)

		return (bool)(keyMatch(name1, name2)), nil
	}

	_, ok := enforcer.model["g"]
	if ok {
		for key, ast := range enforcer.model["g"] {
			rm := ast.rm
			functions[key] = func(args ...interface{}) (interface{}, error) {
				name1 := args[0].(string)
				name2 := args[1].(string)

				return (bool)(rm.hasLink(name1, name2)), nil
			}
		}
	}
	expression, _ = govaluate.NewEvaluableExpressionWithFunctions(expString, functions)

	policyResults := make([]bool, len(enforcer.model["p"]["p"].policy))

	for i, pvals := range enforcer.model["p"]["p"].policy {
		//log.Print("Policy Rule: ", pvals)

		parameters := make(map[string]interface{}, 8)
		for j, token := range enforcer.model["r"]["r"].tokens {
			parameters[token] = rvals[j]
		}
		for j, token := range enforcer.model["p"]["p"].tokens {
			parameters[token] = pvals[j]
		}

		result, _ := expression.Evaluate(parameters)
		//log.Print("Result: ", result)

		policyResults[i] = result.(bool)
	}

	//log.Print("Rule Results: ", policyResults)

	result := false
	if enforcer.model["e"]["e"].value == "some(where (p_eft == allow))" {
		result = false
		for _, res := range policyResults {
			if res {
				result = true
				break
			}
		}
	}

	log.Print("Request ", rvals, ": ", result)

	return result
}

func (enforcer *Enforcer) GetRoles(name string) []string {
	return enforcer.GetRolesForPolicyType("g", name)
}

func (enforcer *Enforcer) GetRolesForPolicyType(ptype string, name string) []string {
	return enforcer.model["g"][ptype].rm.getRoles(name)
}

func (enforcer *Enforcer) GetAllSubjects() []string {
	return getValuesForFieldInPolicy(enforcer.model, "p", "p", 0)
}

func (enforcer *Enforcer) GetAllObjects() []string {
	return getValuesForFieldInPolicy(enforcer.model, "p", "p", 1)
}

func (enforcer *Enforcer) GetAllActions() []string {
	return getValuesForFieldInPolicy(enforcer.model, "p", "p", 2)
}

func (enforcer *Enforcer) GetAllRoles() []string {
	return getValuesForFieldInPolicy(enforcer.model, "g", "g", 1)
}

func (enforcer *Enforcer) GetPolicy() [][]string {
	return enforcer.GetPolicyForPolicyType("p")
}

func (enforcer *Enforcer) GetPolicyForPolicyType(ptype string) [][]string {
	return getPolicy(enforcer.model, "p", ptype)
}

func (enforcer *Enforcer) GetFilteredPolicy(fieldIndex int, fieldValue string) [][]string {
	return enforcer.GetFilteredPolicyForPolicyType("p", fieldIndex, fieldValue)
}

func (enforcer *Enforcer) GetFilteredPolicyForPolicyType(ptype string, fieldIndex int, fieldValue string) [][]string {
	return getFilteredPolicy(enforcer.model, "p", ptype, fieldIndex, fieldValue)
}

func (enforcer *Enforcer) GetGroupingPolicy() [][]string {
	return enforcer.GetGroupingPolicyForPolicyType("g")
}

func (enforcer *Enforcer) GetGroupingPolicyForPolicyType(ptype string) [][]string {
	return getPolicy(enforcer.model, "g", ptype)
}

func (enforcer *Enforcer) AddPolicy(policy []string) {
	enforcer.AddPolicyForPolicyType("p", policy)
}

func (enforcer *Enforcer) RemovePolicy(policy []string) {
	enforcer.RemovePolicyForPolicyType("p", policy)
}

func (enforcer *Enforcer) AddPolicyForPolicyType(ptype string, policy []string) {
	addPolicy(enforcer.model, "p", ptype, policy)
}

func (enforcer *Enforcer) RemovePolicyForPolicyType(ptype string, policy []string) {
	removePolicy(enforcer.model, "p", ptype, policy)
}

func (enforcer *Enforcer) AddGroupingPolicy(policy []string) {
	enforcer.AddGroupingPolicyForPolicyType("g", policy)
	buildRoleLinks(enforcer.model)
}

func (enforcer *Enforcer) RemoveGroupingPolicy(policy []string) {
	enforcer.RemoveGroupingPolicyForPolicyType("g", policy)
	buildRoleLinks(enforcer.model)
}

func (enforcer *Enforcer) AddGroupingPolicyForPolicyType(ptype string, policy []string) {
	addPolicy(enforcer.model, "g", ptype, policy)
	buildRoleLinks(enforcer.model)
}

func (enforcer *Enforcer) RemoveGroupingPolicyForPolicyType(ptype string, policy []string) {
	removePolicy(enforcer.model, "g", ptype, policy)
	buildRoleLinks(enforcer.model)
}
<commit_msg>Add comments to the enforcer API.<commit_after>package casbin

import (
	"github.com/Knetic/govaluate"
	"log"
)

// Enforcer is the main interface for authorization enforcement and policy management.
type Enforcer struct {
	modelPath  string
	policyPath string
	model      Model
	enabled    bool
}

// Initialize an enforcer with a model file and a policy file.
func (enforcer *Enforcer) Init(modelPath string, policyPath string) {
	enforcer.modelPath = modelPath
	enforcer.policyPath = policyPath
	enforcer.enabled = true

	enforcer.LoadAll()
}

// Reload the model file and policy file, usually used when those files have been changed.
func (enforcer *Enforcer) LoadAll() {
	enforcer.model = loadModel(enforcer.modelPath)
	printModel(enforcer.model)

	enforcer.LoadPolicy()
}

// Reload the policy file only.
func (enforcer *Enforcer) LoadPolicy() {
	loadPolicy(enforcer.policyPath, enforcer.model)
	printPolicy(enforcer.model)
	buildRoleLinks(enforcer.model)
}

// Save the current policy (usually changed with casbin API) back to the policy file.
func (enforcer *Enforcer) SavePolicy() {
	savePolicy(enforcer.policyPath, enforcer.model)
}

// Change the enforcing state of casbin, when casbin is disabled, all access will be allowed by the Enforce() function.
func (enforcer *Enforcer) Enable(enable bool) {
	enforcer.enabled = enable
}

// Decide whether a "subject" can access a "object" with the operation "action", input parameters are usually: (sub, obj, act).
func (enforcer *Enforcer) Enforce(rvals ...string) bool {
	if !enforcer.enabled {
		return true
	}

	expString := enforcer.model["m"]["m"].value
	var expression *govaluate.EvaluableExpression

	functions := make(map[string]govaluate.ExpressionFunction)

	functions["keyMatch"] = func(args ...interface{}) (interface{}, error) {
		name1 := args[0].(string)
		name2 := args[1].(string)

		return (bool)(keyMatch(name1, name2)), nil
	}

	_, ok := enforcer.model["g"]
	if ok {
		for key, ast := range enforcer.model["g"] {
			rm := ast.rm
			functions[key] = func(args ...interface{}) (interface{}, error) {
				name1 := args[0].(string)
				name2 := args[1].(string)

				return (bool)(rm.hasLink(name1, name2)), nil
			}
		}
	}
	expression, _ = govaluate.NewEvaluableExpressionWithFunctions(expString, functions)

	policyResults := make([]bool, len(enforcer.model["p"]["p"].policy))

	for i, pvals := range enforcer.model["p"]["p"].policy {
		//log.Print("Policy Rule: ", pvals)

		parameters := make(map[string]interface{}, 8)
		for j, token := range enforcer.model["r"]["r"].tokens {
			parameters[token] = rvals[j]
		}
		for j, token := range enforcer.model["p"]["p"].tokens {
			parameters[token] = pvals[j]
		}

		result, _ := expression.Evaluate(parameters)
		//log.Print("Result: ", result)

		policyResults[i] = result.(bool)
	}

	//log.Print("Rule Results: ", policyResults)

	result := false
	if enforcer.model["e"]["e"].value == "some(where (p_eft == allow))" {
		result = false
		for _, res := range policyResults {
			if res {
				result = true
				break
			}
		}
	}

	log.Print("Request ", rvals, ": ", result)

	return result
}

// Get the roles assigned to a subject.
func (enforcer *Enforcer) GetRoles(name string) []string {
	return enforcer.GetRolesForPolicyType("g", name)
}

// Get the roles assigned to a subject, policy type can be specified.
func (enforcer *Enforcer) GetRolesForPolicyType(ptype string, name string) []string {
	return enforcer.model["g"][ptype].rm.getRoles(name)
}

// Get the list of subjects that show up in the current policy.
func (enforcer *Enforcer) GetAllSubjects() []string {
	return getValuesForFieldInPolicy(enforcer.model, "p", "p", 0)
}

// Get the list of objects that show up in the current policy.
func (enforcer *Enforcer) GetAllObjects() []string {
	return getValuesForFieldInPolicy(enforcer.model, "p", "p", 1)
}

// Get the list of actions that show up in the current policy.
func (enforcer *Enforcer) GetAllActions() []string {
	return getValuesForFieldInPolicy(enforcer.model, "p", "p", 2)
}

// Get the list of roles that show up in the current policy.
func (enforcer *Enforcer) GetAllRoles() []string {
	return getValuesForFieldInPolicy(enforcer.model, "g", "g", 1)
}

// Get all the authorization rules in the policy.
func (enforcer *Enforcer) GetPolicy() [][]string {
	return enforcer.GetPolicyForPolicyType("p")
}

// Get all the authorization rules in the policy, policy type can be specified.
func (enforcer *Enforcer) GetPolicyForPolicyType(ptype string) [][]string {
	return getPolicy(enforcer.model, "p", ptype)
}

// Get all the authorization rules in the policy, a field filter can be specified.
func (enforcer *Enforcer) GetFilteredPolicy(fieldIndex int, fieldValue string) [][]string {
	return enforcer.GetFilteredPolicyForPolicyType("p", fieldIndex, fieldValue)
}

// Get all the authorization rules in the policy, a field filter can be specified, policy type can be specified.
func (enforcer *Enforcer) GetFilteredPolicyForPolicyType(ptype string, fieldIndex int, fieldValue string) [][]string {
	return getFilteredPolicy(enforcer.model, "p", ptype, fieldIndex, fieldValue)
}

// Get all the role inheritance rules in the policy.
func (enforcer *Enforcer) GetGroupingPolicy() [][]string {
	return enforcer.GetGroupingPolicyForPolicyType("g")
}

// Get all the role inheritance rules in the policy, policy type can be specified.
func (enforcer *Enforcer) GetGroupingPolicyForPolicyType(ptype string) [][]string {
	return getPolicy(enforcer.model, "g", ptype)
}

// Add an authorization rule to the current policy.
func (enforcer *Enforcer) AddPolicy(policy []string) {
	enforcer.AddPolicyForPolicyType("p", policy)
}

// Remove an authorization rule from the current policy.
func (enforcer *Enforcer) RemovePolicy(policy []string) {
	enforcer.RemovePolicyForPolicyType("p", policy)
}

// Add an authorization rule to the current policy, policy type can be specified.
func (enforcer *Enforcer) AddPolicyForPolicyType(ptype string, policy []string) {
	addPolicy(enforcer.model, "p", ptype, policy)
}

// Remove an authorization rule from the current policy, policy type can be specified.
func (enforcer *Enforcer) RemovePolicyForPolicyType(ptype string, policy []string) {
	removePolicy(enforcer.model, "p", ptype, policy)
}

// Add a role inheritance rule to the current policy.
func (enforcer *Enforcer) AddGroupingPolicy(policy []string) {
	enforcer.AddGroupingPolicyForPolicyType("g", policy)
	buildRoleLinks(enforcer.model)
}

// Remove a role inheritance rule from the current policy.
func (enforcer *Enforcer) RemoveGroupingPolicy(policy []string) {
	enforcer.RemoveGroupingPolicyForPolicyType("g", policy)
	buildRoleLinks(enforcer.model)
}

// Add a role inheritance rule to the current policy, policy type can be specified.
func (enforcer *Enforcer) AddGroupingPolicyForPolicyType(ptype string, policy []string) {
	addPolicy(enforcer.model, "g", ptype, policy)
	buildRoleLinks(enforcer.model)
}

// Remove a role inheritance rule from the current policy, policy type can be specified.
func (enforcer *Enforcer) RemoveGroupingPolicyForPolicyType(ptype string, policy []string) {
	removePolicy(enforcer.model, "g", ptype, policy)
	buildRoleLinks(enforcer.model)
}
<|endoftext|>