<commit_before>package irc

import (
	"strconv"
	"strings"
	"time"
)

// Register a callback to a connection and event code. A callback is a function
// which takes only an Event pointer as parameter. Valid event codes are all
// IRC/CTCP commands and error/response codes. This function returns the ID of
// the registered callback for later management.
func (irc *Connection) AddCallback(eventcode string, callback func(*Event)) int {
	eventcode = strings.ToUpper(eventcode)
	id := 0
	if _, ok := irc.events[eventcode]; !ok {
		irc.events[eventcode] = make(map[int]func(*Event))
		id = 0
	} else {
		id = len(irc.events[eventcode])
	}
	irc.events[eventcode][id] = callback
	return id
}

// Remove callback i (ID) from the given event code. This functions returns
// true upon success, false if any error occurs.
func (irc *Connection) RemoveCallback(eventcode string, i int) bool {
	eventcode = strings.ToUpper(eventcode)

	if event, ok := irc.events[eventcode]; ok {
		if _, ok := event[i]; ok {
			delete(irc.events[eventcode], i)
			return true
		}
		irc.Log.Printf("Event found, but no callback found at id %d\n", i)
		return false
	}

	irc.Log.Println("Event not found")
	return false
}

// Remove all callbacks from a given event code. It returns true
// if given event code is found and cleared.
func (irc *Connection) ClearCallback(eventcode string) bool {
	eventcode = strings.ToUpper(eventcode)

	if _, ok := irc.events[eventcode]; ok {
		irc.events[eventcode] = make(map[int]func(*Event))
		return true
	}

	irc.Log.Println("Event not found")
	return false
}

// Replace callback i (ID) associated with a given event code with a new callback function.
func (irc *Connection) ReplaceCallback(eventcode string, i int, callback func(*Event)) {
	eventcode = strings.ToUpper(eventcode)

	if event, ok := irc.events[eventcode]; ok {
		if _, ok := event[i]; ok {
			event[i] = callback
			return
		}
		irc.Log.Printf("Event found, but no callback found at id %d\n", i)
	}
	irc.Log.Printf("Event not found. Use AddCallBack\n")
}

// Execute all callbacks associated with a given event.
func (irc *Connection) RunCallbacks(event *Event) {
	msg := event.Message()
	if event.Code == "PRIVMSG" && len(msg) > 2 && msg[0] == '\x01' {
		event.Code = "CTCP" //Unknown CTCP

		if i := strings.LastIndex(msg, "\x01"); i > 0 {
			msg = msg[1:i]
		} else {
			irc.Log.Printf("Invalid CTCP Message: %s\n", strconv.Quote(msg))
			return
		}

		if msg == "VERSION" {
			event.Code = "CTCP_VERSION"

		} else if msg == "TIME" {
			event.Code = "CTCP_TIME"

		} else if strings.HasPrefix(msg, "PING") {
			event.Code = "CTCP_PING"

		} else if msg == "USERINFO" {
			event.Code = "CTCP_USERINFO"

		} else if msg == "CLIENTINFO" {
			event.Code = "CTCP_CLIENTINFO"

		} else if strings.HasPrefix(msg, "ACTION") {
			event.Code = "CTCP_ACTION"
			if len(msg) > 6 {
				msg = msg[7:]
			} else {
				msg = ""
			}
		}

		event.Arguments[len(event.Arguments)-1] = msg
	}

	if callbacks, ok := irc.events[event.Code]; ok {
		if irc.VerboseCallbackHandler {
			irc.Log.Printf("%v (%v) >> %#v\n", event.Code, len(callbacks), event)
		}

		for _, callback := range callbacks {
			callback(event)
		}
	} else if irc.VerboseCallbackHandler {
		irc.Log.Printf("%v (0) >> %#v\n", event.Code, event)
	}

	if callbacks, ok := irc.events["*"]; ok {
		if irc.VerboseCallbackHandler {
			irc.Log.Printf("%v (0) >> %#v\n", event.Code, event)
		}

		for _, callback := range callbacks {
			callback(event)
		}
	}
}

// Set up some initial callbacks to handle the IRC/CTCP protocol.
func (irc *Connection) setupCallbacks() {
	irc.events = make(map[string]map[int]func(*Event))

	//Handle error events. This has to be called in a new thred to allow
	//readLoop to exit
	irc.AddCallback("ERROR", func(e *Event) { irc.Disconnect() })

	//Handle ping events
	irc.AddCallback("PING", func(e *Event) { irc.SendRaw("PONG :" + e.Message()) })

	//Version handler
	irc.AddCallback("CTCP_VERSION", func(e *Event) {
		irc.SendRawf("NOTICE %s :\x01VERSION %s\x01", e.Nick, irc.Version)
	})

	irc.AddCallback("CTCP_USERINFO", func(e *Event) {
		irc.SendRawf("NOTICE %s :\x01USERINFO %s\x01", e.Nick, irc.user)
	})

	irc.AddCallback("CTCP_CLIENTINFO", func(e *Event) {
		irc.SendRawf("NOTICE %s :\x01CLIENTINFO PING VERSION TIME USERINFO CLIENTINFO\x01", e.Nick)
	})

	irc.AddCallback("CTCP_TIME", func(e *Event) {
		ltime := time.Now()
		irc.SendRawf("NOTICE %s :\x01TIME %s\x01", e.Nick, ltime.String())
	})

	irc.AddCallback("CTCP_PING", func(e *Event) { irc.SendRawf("NOTICE %s :\x01%s\x01", e.Nick, e.Message()) })

	// 437: ERR_UNAVAILRESOURCE "<nick/channel> :Nick/channel is temporarily unavailable"
	// Add a _ to current nick. If irc.nickcurrent is empty this cannot
	// work. It has to be set somewhere first in case the nick is already
	// taken or unavailable from the beginning.
	irc.AddCallback("437", func(e *Event) {
		// If irc.nickcurrent hasn't been set yet, set to irc.nick
		if irc.nickcurrent == "" {
			irc.nickcurrent = irc.nick
		}

		if len(irc.nickcurrent) > 8 {
			irc.nickcurrent = "_" + irc.nickcurrent
		} else {
			irc.nickcurrent = irc.nickcurrent + "_"
		}
		irc.SendRawf("NICK %s", irc.nickcurrent)
	})

	// 433: ERR_NICKNAMEINUSE "<nick> :Nickname is already in use"
	// Add a _ to current nick.
	irc.AddCallback("433", func(e *Event) {
		// If irc.nickcurrent hasn't been set yet, set to irc.nick
		if irc.nickcurrent == "" {
			irc.nickcurrent = irc.nick
		}

		if len(irc.nickcurrent) > 8 {
			irc.nickcurrent = "_" + irc.nickcurrent
		} else {
			irc.nickcurrent = irc.nickcurrent + "_"
		}
		irc.SendRawf("NICK %s", irc.nickcurrent)
	})

	irc.AddCallback("PONG", func(e *Event) {
		ns, _ := strconv.ParseInt(e.Message(), 10, 64)
		delta := time.Duration(time.Now().UnixNano() - ns)
		if irc.Debug {
			irc.Log.Printf("Lag: %vs\n", delta)
		}
	})

	// NICK Define a nickname.
	// Set irc.nickcurrent to the new nick actually used in this connection.
	irc.AddCallback("NICK", func(e *Event) {
		if e.Nick == irc.nick {
			irc.nickcurrent = e.Message()
		}
	})

	// 1: RPL_WELCOME "Welcome to the Internet Relay Network <nick>!<user>@<host>"
	// Set irc.nickcurrent to the actually used nick in this connection.
	irc.AddCallback("001", func(e *Event) {
		irc.nickcurrent = e.Arguments[0]
	})
}
<commit_msg>update comment on handling error events<commit_after>package irc

import (
	"strconv"
	"strings"
	"time"
)

// Register a callback to a connection and event code. A callback is a function
// which takes only an Event pointer as parameter. Valid event codes are all
// IRC/CTCP commands and error/response codes. This function returns the ID of
// the registered callback for later management.
func (irc *Connection) AddCallback(eventcode string, callback func(*Event)) int {
	eventcode = strings.ToUpper(eventcode)
	id := 0
	if _, ok := irc.events[eventcode]; !ok {
		irc.events[eventcode] = make(map[int]func(*Event))
		id = 0
	} else {
		id = len(irc.events[eventcode])
	}
	irc.events[eventcode][id] = callback
	return id
}

// Remove callback i (ID) from the given event code. This functions returns
// true upon success, false if any error occurs.
func (irc *Connection) RemoveCallback(eventcode string, i int) bool {
	eventcode = strings.ToUpper(eventcode)

	if event, ok := irc.events[eventcode]; ok {
		if _, ok := event[i]; ok {
			delete(irc.events[eventcode], i)
			return true
		}
		irc.Log.Printf("Event found, but no callback found at id %d\n", i)
		return false
	}

	irc.Log.Println("Event not found")
	return false
}

// Remove all callbacks from a given event code. It returns true
// if given event code is found and cleared.
func (irc *Connection) ClearCallback(eventcode string) bool {
	eventcode = strings.ToUpper(eventcode)

	if _, ok := irc.events[eventcode]; ok {
		irc.events[eventcode] = make(map[int]func(*Event))
		return true
	}

	irc.Log.Println("Event not found")
	return false
}

// Replace callback i (ID) associated with a given event code with a new callback function.
func (irc *Connection) ReplaceCallback(eventcode string, i int, callback func(*Event)) {
	eventcode = strings.ToUpper(eventcode)

	if event, ok := irc.events[eventcode]; ok {
		if _, ok := event[i]; ok {
			event[i] = callback
			return
		}
		irc.Log.Printf("Event found, but no callback found at id %d\n", i)
	}
	irc.Log.Printf("Event not found. Use AddCallBack\n")
}

// Execute all callbacks associated with a given event.
func (irc *Connection) RunCallbacks(event *Event) {
	msg := event.Message()
	if event.Code == "PRIVMSG" && len(msg) > 2 && msg[0] == '\x01' {
		event.Code = "CTCP" //Unknown CTCP

		if i := strings.LastIndex(msg, "\x01"); i > 0 {
			msg = msg[1:i]
		} else {
			irc.Log.Printf("Invalid CTCP Message: %s\n", strconv.Quote(msg))
			return
		}

		if msg == "VERSION" {
			event.Code = "CTCP_VERSION"

		} else if msg == "TIME" {
			event.Code = "CTCP_TIME"

		} else if strings.HasPrefix(msg, "PING") {
			event.Code = "CTCP_PING"

		} else if msg == "USERINFO" {
			event.Code = "CTCP_USERINFO"

		} else if msg == "CLIENTINFO" {
			event.Code = "CTCP_CLIENTINFO"

		} else if strings.HasPrefix(msg, "ACTION") {
			event.Code = "CTCP_ACTION"
			if len(msg) > 6 {
				msg = msg[7:]
			} else {
				msg = ""
			}
		}

		event.Arguments[len(event.Arguments)-1] = msg
	}

	if callbacks, ok := irc.events[event.Code]; ok {
		if irc.VerboseCallbackHandler {
			irc.Log.Printf("%v (%v) >> %#v\n", event.Code, len(callbacks), event)
		}

		for _, callback := range callbacks {
			callback(event)
		}
	} else if irc.VerboseCallbackHandler {
		irc.Log.Printf("%v (0) >> %#v\n", event.Code, event)
	}

	if callbacks, ok := irc.events["*"]; ok {
		if irc.VerboseCallbackHandler {
			irc.Log.Printf("%v (0) >> %#v\n", event.Code, event)
		}

		for _, callback := range callbacks {
			callback(event)
		}
	}
}

// Set up some initial callbacks to handle the IRC/CTCP protocol.
func (irc *Connection) setupCallbacks() {
	irc.events = make(map[string]map[int]func(*Event))

	//Handle error events.
	irc.AddCallback("ERROR", func(e *Event) { irc.Disconnect() })

	//Handle ping events
	irc.AddCallback("PING", func(e *Event) { irc.SendRaw("PONG :" + e.Message()) })

	//Version handler
	irc.AddCallback("CTCP_VERSION", func(e *Event) {
		irc.SendRawf("NOTICE %s :\x01VERSION %s\x01", e.Nick, irc.Version)
	})

	irc.AddCallback("CTCP_USERINFO", func(e *Event) {
		irc.SendRawf("NOTICE %s :\x01USERINFO %s\x01", e.Nick, irc.user)
	})

	irc.AddCallback("CTCP_CLIENTINFO", func(e *Event) {
		irc.SendRawf("NOTICE %s :\x01CLIENTINFO PING VERSION TIME USERINFO CLIENTINFO\x01", e.Nick)
	})

	irc.AddCallback("CTCP_TIME", func(e *Event) {
		ltime := time.Now()
		irc.SendRawf("NOTICE %s :\x01TIME %s\x01", e.Nick, ltime.String())
	})

	irc.AddCallback("CTCP_PING", func(e *Event) { irc.SendRawf("NOTICE %s :\x01%s\x01", e.Nick, e.Message()) })

	// 437: ERR_UNAVAILRESOURCE "<nick/channel> :Nick/channel is temporarily unavailable"
	// Add a _ to current nick. If irc.nickcurrent is empty this cannot
	// work. It has to be set somewhere first in case the nick is already
	// taken or unavailable from the beginning.
	irc.AddCallback("437", func(e *Event) {
		// If irc.nickcurrent hasn't been set yet, set to irc.nick
		if irc.nickcurrent == "" {
			irc.nickcurrent = irc.nick
		}

		if len(irc.nickcurrent) > 8 {
			irc.nickcurrent = "_" + irc.nickcurrent
		} else {
			irc.nickcurrent = irc.nickcurrent + "_"
		}
		irc.SendRawf("NICK %s", irc.nickcurrent)
	})

	// 433: ERR_NICKNAMEINUSE "<nick> :Nickname is already in use"
	// Add a _ to current nick.
	irc.AddCallback("433", func(e *Event) {
		// If irc.nickcurrent hasn't been set yet, set to irc.nick
		if irc.nickcurrent == "" {
			irc.nickcurrent = irc.nick
		}

		if len(irc.nickcurrent) > 8 {
			irc.nickcurrent = "_" + irc.nickcurrent
		} else {
			irc.nickcurrent = irc.nickcurrent + "_"
		}
		irc.SendRawf("NICK %s", irc.nickcurrent)
	})

	irc.AddCallback("PONG", func(e *Event) {
		ns, _ := strconv.ParseInt(e.Message(), 10, 64)
		delta := time.Duration(time.Now().UnixNano() - ns)
		if irc.Debug {
			irc.Log.Printf("Lag: %vs\n", delta)
		}
	})

	// NICK Define a nickname.
	// Set irc.nickcurrent to the new nick actually used in this connection.
	irc.AddCallback("NICK", func(e *Event) {
		if e.Nick == irc.nick {
			irc.nickcurrent = e.Message()
		}
	})

	// 1: RPL_WELCOME "Welcome to the Internet Relay Network <nick>!<user>@<host>"
	// Set irc.nickcurrent to the actually used nick in this connection.
	irc.AddCallback("001", func(e *Event) {
		irc.nickcurrent = e.Arguments[0]
	})
}
<|endoftext|>


<commit_before>package log

import (
	"fmt"
	stdlog "log"
	"os"
	"sort"
	"strings"
	"time"
)

// Fields represents a map of entry level data used for structured logging.
type Fields map[string]interface{}

// Names returns field names sorted.
// map is not
func (f Fields) Names() (v []string) {
	for k := range f {
		v = append(v, k)
	}

	sort.Strings(v)
	return
}

// Get field value by name.
func (f Fields) Get(name string) interface{} {
	return f[name]
}

// Entry defines a single log entry
type Entry struct {
	logger *logger
	start  time.Time
	fields []Fields // private used; store all fields when withFields is called.  improve performance.

	Level     Level     `json:"level"`
	Message   string    `json:"message"`
	Timestamp time.Time `json:"timestamp"`
	Fields    Fields    `json:"fields"` // single map; easy to use for handlers
}

func newEntry(l *logger) Entry {
	e := Entry{}
	e.logger = l
	e.fields = l.defaultFields
	return e
}

// Debug level message.
func (e Entry) Debug(msg string) {
	e.Level = DebugLevel
	e.Message = msg
	handler(e)
}

// Debugf level message.
func (e Entry) Debugf(msg string, v ...interface{}) {
	e.Level = DebugLevel
	e.Message = fmt.Sprintf(msg, v...)
	handler(e)
}

// Info level message.
func (e Entry) Info(msg string) {
	e.Level = InfoLevel
	e.Message = msg
	handler(e)
}

// Infof level message.
func (e Entry) Infof(msg string, v ...interface{}) {
	e.Level = InfoLevel
	e.Message = fmt.Sprintf(msg, v...)
	handler(e)
}

// Warn level message.
func (e Entry) Warn(msg string) {
	e.Level = WarnLevel
	e.Message = msg
	handler(e)
}

// Warnf level message.
func (e Entry) Warnf(msg string, v ...interface{}) {
	e.Level = WarnLevel
	e.Message = fmt.Sprintf(msg, v...)
	handler(e)
}

// Error level message.
func (e Entry) Error(msg string) {
	e.Level = ErrorLevel
	e.Message = msg
	handler(e)
}

// Errorf level message.
func (e Entry) Errorf(msg string, v ...interface{}) {
	e.Level = ErrorLevel
	e.Message = fmt.Sprintf(msg, v...)
	handler(e)
}

// Panic level message.
func (e Entry) Panic(msg string) {
	e.Level = PanicLevel
	e.Message = msg
	handler(e)
	os.Exit(1)
}

// Panicf level message.
func (e Entry) Panicf(msg string, v ...interface{}) {
	e.Level = PanicLevel
	e.Message = fmt.Sprintf(msg, v...)
	handler(e)
	os.Exit(1)
}

// Fatal level message.
func (e Entry) Fatal(msg string) {
	e.Level = FatalLevel
	e.Message = msg
	handler(e)
	os.Exit(1)
}

// Fatalf level message.
func (e Entry) Fatalf(msg string, v ...interface{}) {
	e.Level = FatalLevel
	e.Message = fmt.Sprintf(msg, v...)
	handler(e)
	os.Exit(1)
}

// WithField returns a new entry with the `key` and `value` set.
func (e Entry) WithField(key string, value interface{}) Entry {
	return e.WithFields(Fields{key: value})
}

// WithFields adds the provided fields to the current entry
func (e Entry) WithFields(fields Fields) Entry {
	//f := []Fields{}
	//f = append(f, e.Fields...)
	//f = append(f, fields)

	e.fields = append(e.fields, fields)
	return e
}

// WithError returns a new entry with the "error" set to `err`.
func (e Entry) WithError(err error) Entry {
	if err == nil {
		return e
	}
	return e.WithField("error", fmt.Sprintf("%+v", err))
}

// Trace returns a new entry with a Stop method to fire off
// a corresponding completion log, useful with defer.
func (e Entry) Trace(msg string) Entry {
	e.Message = msg
	e.start = time.Now().UTC()
	return e
}

// mergedFields returns the fields list collapsed into a single map.
func (e Entry) mergedFields() Fields {
	f := Fields{}

	for _, fields := range e.fields {
		for k, v := range fields {
			f[k] = v
		}
	}

	return f
}

const (
	day  = time.Minute * 60 * 24
	year = 365 * day
)

func duration(d time.Duration) string {
	if d < day {
		return d.String()
	}

	var b strings.Builder

	if d >= year {
		years := d / year
		fmt.Fprintf(&b, "%dy", years)
		d -= years * year
	}

	days := d / day
	d -= days * day
	fmt.Fprintf(&b, "%dd%s", days, d)

	return b.String()
}

// Stop should be used with Trace, to fire off the completion message. When
// an `err` is passed the "error" field is set, and the log level is error.
func (e Entry) Stop() {
	e.WithField("duration", duration(time.Since(e.start))).Info(e.Message)
}

func handler(e Entry) {
	// I guess we don't need to lock here and the performance can be improved
	// e.logger.rwMutex.RLock()
	// defer e.logger.rwMutex.RUnlock()

	var err error
	for _, h := range e.logger.cacheLeveledHandler(e.Level) {
		e.Timestamp = time.Now().UTC()
		e.Fields = e.mergedFields()
		err = h.Log(e)
		if err != nil {
			stdlog.Printf("log: log failed: %v", err)
		}
	}
}
<commit_msg>change to use stack memory<commit_after>package log

import (
	"fmt"
	stdlog "log"
	"os"
	"sort"
	"strings"
	"time"
)

// Fields represents a map of entry level data used for structured logging.
type Fields map[string]interface{}

// Names returns field names sorted.
// map is not
func (f Fields) Names() (v []string) {
	for k := range f {
		v = append(v, k)
	}

	sort.Strings(v)
	return
}

// Get field value by name.
func (f Fields) Get(name string) interface{} {
	return f[name]
}

// Entry defines a single log entry
type Entry struct {
	logger *logger
	start  time.Time
	fields []Fields // private used; store all fields when withFields is called.  improve performance.

	Level     Level     `json:"level"`
	Message   string    `json:"message"`
	Timestamp time.Time `json:"timestamp"`
	Fields    Fields    `json:"fields"` // single map; easy to use for handlers
}

func newEntry(l *logger) Entry {
	e := Entry{}
	e.logger = l
	e.fields = l.defaultFields
	return e
}

// Debug level message.
func (e Entry) Debug(msg string) {
	e.Level = DebugLevel
	e.Message = msg
	handler(e)
}

// Debugf level message.
func (e Entry) Debugf(msg string, v ...interface{}) {
	e.Level = DebugLevel
	e.Message = fmt.Sprintf(msg, v...)
	handler(e)
}

// Info level message.
func (e Entry) Info(msg string) {
	e.Level = InfoLevel
	e.Message = msg
	handler(e)
}

// Infof level message.
func (e Entry) Infof(msg string, v ...interface{}) {
	e.Level = InfoLevel
	e.Message = fmt.Sprintf(msg, v...)
	handler(e)
}

// Warn level message.
func (e Entry) Warn(msg string) {
	e.Level = WarnLevel
	e.Message = msg
	handler(e)
}

// Warnf level message.
func (e Entry) Warnf(msg string, v ...interface{}) {
	e.Level = WarnLevel
	e.Message = fmt.Sprintf(msg, v...)
	handler(e)
}

// Error level message.
func (e Entry) Error(msg string) {
	e.Level = ErrorLevel
	e.Message = msg
	handler(e)
}

// Errorf level message.
func (e Entry) Errorf(msg string, v ...interface{}) {
	e.Level = ErrorLevel
	e.Message = fmt.Sprintf(msg, v...)
	handler(e)
}

// Panic level message.
func (e Entry) Panic(msg string) {
	e.Level = PanicLevel
	e.Message = msg
	handler(e)
	os.Exit(1)
}

// Panicf level message.
func (e Entry) Panicf(msg string, v ...interface{}) {
	e.Level = PanicLevel
	e.Message = fmt.Sprintf(msg, v...)
	handler(e)
	os.Exit(1)
}

// Fatal level message.
func (e Entry) Fatal(msg string) {
	e.Level = FatalLevel
	e.Message = msg
	handler(e)
	os.Exit(1)
}

// Fatalf level message.
func (e Entry) Fatalf(msg string, v ...interface{}) {
	e.Level = FatalLevel
	e.Message = fmt.Sprintf(msg, v...)
	handler(e)
	os.Exit(1)
}

// WithField returns a new entry with the `key` and `value` set.
func (e Entry) WithField(key string, value interface{}) Entry {
	return e.WithFields(Fields{key: value})
}

// WithFields adds the provided fields to the current entry
func (e Entry) WithFields(fields Fields) Entry {
	//f := []Fields{}
	//f = append(f, e.Fields...)
	//f = append(f, fields)

	e.fields = append(e.fields, fields)
	return e
}

// WithError returns a new entry with the "error" set to `err`.
func (e Entry) WithError(err error) Entry {
	if err == nil {
		return e
	}
	return e.WithField("error", fmt.Sprintf("%+v", err))
}

// Trace returns a new entry with a Stop method to fire off
// a corresponding completion log, useful with defer.
func (e Entry) Trace(msg string) Entry {
	e.Message = msg
	e.start = time.Now().UTC()
	return e
}

// mergedFields returns the fields list collapsed into a single map.
func (e Entry) mergedFields() Fields {
	f := Fields{}

	for _, fields := range e.fields {
		for k, v := range fields {
			f[k] = v
		}
	}

	return f
}

const (
	day  = time.Minute * 60 * 24
	year = 365 * day
)

func duration(d time.Duration) string {
	if d < day {
		return d.String()
	}

	var b strings.Builder

	if d >= year {
		years := d / year
		fmt.Fprintf(&b, "%dy", years)
		d -= years * year
	}

	days := d / day
	d -= days * day
	fmt.Fprintf(&b, "%dd%s", days, d)

	return b.String()
}

// Stop should be used with Trace, to fire off the completion message. When
// an `err` is passed the "error" field is set, and the log level is error.
func (e Entry) Stop() {
	e.WithField("duration", duration(time.Since(e.start))).Info(e.Message)
}

func handler(e Entry) {
	// I guess we don't need to lock here and the performance can be improved
	// e.logger.rwMutex.RLock()
	// defer e.logger.rwMutex.RUnlock()

	for _, h := range e.logger.cacheLeveledHandler(e.Level) {
		e.Timestamp = time.Now().UTC()
		e.Fields = e.mergedFields()
		err := h.Log(e)
		if err != nil {
			stdlog.Printf("log: log failed: %v", err)
		}
	}
}
<|endoftext|>


<commit_before>package email

import (
	"fmt"
	"net"
	"net/smtp"
	"strings"
)

// Message creates a email to be sent
type Message struct {
	To      string
	From    string
	Subject string
	Body    string
}

var (
	ports = []int{25, 2525, 587}
)

// Send sends a message to recipient(s) listed in the 'To' field of a Message
func (m Message) Send() error {
	if !strings.Contains(m.To, "@") {
		return fmt.Errorf("Invalid recipient address: <%s>", m.To)
	}

	host := strings.Split(m.To, "@")[1]
	addrs, err := net.LookupMX(host)
	if err != nil {
		return err
	}

	c, err := newClient(addrs, ports)
	if err != nil {
		return err
	}

	err = send(m, c)
	if err != nil {
		return err
	}

	return nil
}

func newClient(mx []*net.MX, ports []int) (*smtp.Client, error) {
	for i := range mx {
		for j := range ports {
			server := strings.TrimSuffix(mx[i].Host, ".")
			hostPort := fmt.Sprintf("%s:%d", server, ports[j])
			client, err := smtp.Dial(hostPort)
			if err != nil {
				if j == len(ports)-1 {
					return nil, err
				}

				continue
			}

			return client, nil
		}
	}

	return nil, fmt.Errorf("Couldn't connect to servers %v on any common port.", mx)
}

func send(m Message, c *smtp.Client) error {
	if err := c.Mail(m.From); err != nil {
		return err
	}

	if err := c.Rcpt(m.To); err != nil {
		return err
	}

	msg, err := c.Data()
	if err != nil {
		return err
	}

	if m.Subject != "" {
		_, err = msg.Write([]byte("Subject: " + m.Subject + "\r\n"))
		if err != nil {
			return err
		}
	}

	if m.From != "" {
		_, err = msg.Write([]byte("From: " + m.From + " <" + m.From + ">\r\n"))
		if err != nil {
			return err
		}
	}

	if m.To != "" {
		_, err = msg.Write([]byte("To: " + m.To + " <" + m.To + ">\r\n"))
		if err != nil {
			return err
		}
	}

	_, err = fmt.Fprint(msg, m.Body)
	if err != nil {
		return err
	}

	err = msg.Close()
	if err != nil {
		return err
	}

	err = c.Quit()
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>simplify to/from to be more compliant with assortment of smtp servers<commit_after>package email

import (
	"fmt"
	"net"
	"net/smtp"
	"strings"
)

// Message creates a email to be sent
type Message struct {
	To      string
	From    string
	Subject string
	Body    string
}

var (
	ports = []int{25, 2525, 587}
)

// Send sends a message to recipient(s) listed in the 'To' field of a Message
func (m Message) Send() error {
	if !strings.Contains(m.To, "@") {
		return fmt.Errorf("Invalid recipient address: <%s>", m.To)
	}

	host := strings.Split(m.To, "@")[1]
	addrs, err := net.LookupMX(host)
	if err != nil {
		return err
	}

	c, err := newClient(addrs, ports)
	if err != nil {
		return err
	}

	err = send(m, c)
	if err != nil {
		return err
	}

	return nil
}

func newClient(mx []*net.MX, ports []int) (*smtp.Client, error) {
	for i := range mx {
		for j := range ports {
			server := strings.TrimSuffix(mx[i].Host, ".")
			hostPort := fmt.Sprintf("%s:%d", server, ports[j])
			client, err := smtp.Dial(hostPort)
			if err != nil {
				if j == len(ports)-1 {
					return nil, err
				}

				continue
			}

			return client, nil
		}
	}

	return nil, fmt.Errorf("Couldn't connect to servers %v on any common port.", mx)
}

func send(m Message, c *smtp.Client) error {
	if err := c.Mail(m.From); err != nil {
		return err
	}

	if err := c.Rcpt(m.To); err != nil {
		return err
	}

	msg, err := c.Data()
	if err != nil {
		return err
	}

	if m.Subject != "" {
		_, err = msg.Write([]byte("Subject: " + m.Subject + "\r\n"))
		if err != nil {
			return err
		}
	}

	if m.From != "" {
		_, err = msg.Write([]byte("From: <" + m.From + ">\r\n"))
		if err != nil {
			return err
		}
	}

	if m.To != "" {
		_, err = msg.Write([]byte("To: <" + m.To + ">\r\n"))
		if err != nil {
			return err
		}
	}

	_, err = fmt.Fprint(msg, m.Body)
	if err != nil {
		return err
	}

	err = msg.Close()
	if err != nil {
		return err
	}

	err = c.Quit()
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package utils
import (
	"reflect"
	"fmt"
)

type Tags map[string]string

func (t Tags) Get(name string) string {
	tag, ok := t[name]
	if !ok {
		panic(fmt.Sprintf("There no tag for %s", name))
	}
	return tag
}

func GetFieldsTag(o interface{}, tagname string) Tags {
	st := reflect.TypeOf(o)
	tags := make(map[string]string, st.NumField())
	for i := 0; i < st.NumField(); i++ {
		field := st.Field(i)
		value := field.Tag.Get(tagname)
		if value != "" {
			tags[field.Name] = value
		}
	}
	return tags
}
<commit_msg>Should instansiate with Tags<commit_after>package utils
import (
	"reflect"
	"fmt"
)

type Tags map[string]string

func (t Tags) Get(name string) string {
	tag, ok := t[name]
	if !ok {
		panic(fmt.Sprintf("There no tag for %s", name))
	}
	return tag
}

func GetFieldsTag(o interface{}, tagname string) Tags {
	st := reflect.TypeOf(o)
	tags := Tags{}
	for i := 0; i < st.NumField(); i++ {
		field := st.Field(i)
		value := field.Tag.Get(tagname)
		if value != "" {
			tags[field.Name] = value
		}
	}
	return tags
}
<|endoftext|>


<commit_before>/*
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package main

/* This file will handle all file related business. It will explore the file
 * system for new files and will watch files for changes. In particular, this
 * file is the gate to the files table in the database. Other components (Parser)
 * should rely on this file to know if a file was explored or not. */

import (
	"container/list"
	fsnotify "gopkg.in/fsnotify.v1"
	"log"
	"os"
	"path/filepath"
	"regexp"
	"sync"
)

var files chan string
var wg sync.WaitGroup
var watcher *fsnotify.Watcher
var writer chan *WriterDB

func uptodateFile(file string) bool {
	wr := <-writer
	defer func() { writer <- wr }()

	exist, uptodate, fi, err := wr.UptodateFile(file)

	if err != nil {
		// if there is an error with the dependency, we are going to
		// pretend everything is fine so the parser is not executed
		return true
	}

	if exist && uptodate {
		return true
	} else {
		wr.RemoveFileReferences(file)
		wr.InsertFile(file, fi)
		return false
	}
}

func processFile(parser *Parser) {
	wg.Add(1)
	defer wg.Done()

	// start exploring files
	for {
		file, ok := <-files

		if !ok {
			return
		}

		if !uptodateFile(file) {
			log.Println("parsing", file)
			parser.Parse(file)
		}
	}
}

func explorePathToParse(path string,
	visitDir func(string),
	visitC func(string)) *list.List {

	path = filepath.Clean(path)

	f, err := os.Open(path)
	if err != nil {
		log.Println(err, "opening", path, ", ignoring")
		return nil
	}
	defer f.Close()

	info, err := f.Stat()
	if err != nil {
		log.Println(err, "stating", path, ", ignoring")
		return nil
	}

	// visit file
	if !info.IsDir() {
		// ignore non-C files
		validC, _ := regexp.MatchString(`.*\.c$`, path)
		if validC {
			visitC(path)
		}
		return nil
	} else {
		visitDir(path)
	}

	// add all the files in the directory to explore
	dirFiles, err := f.Readdir(0)
	if err != nil {
		log.Println(err, " readdir ", path, ", ignoring")
		return nil
	}

	toExplore := list.New()
	for _, subf := range dirFiles {
		// ignore hidden files
		if subf.Name()[0] == '.' {
			continue
		}

		toExplore.PushBack(path + "/" + subf.Name())
	}
	return toExplore
}

func traversePath(path string, visitDir func(string), visitC func(string)) {
	toExplore := list.New()
	toExplore.PushBack(path)

	for toExplore.Len() > 0 {
		// dequeue first path
		path := toExplore.Front()
		toExplore.Remove(path)

		newDirs := explorePathToParse(
			path.Value.(string),
			visitDir,
			visitC)
		if newDirs != nil {
			toExplore.PushBackList(newDirs)
		}
	}
}

func removeFileAndReparseDepends(file string, db *WriterDB) {
	deps := db.RemoveFileDepsReferences(file)
	db.RemoveFileReferences(file)

	for _, d := range deps {
		files <- d
	}
}

func handleChange(event fsnotify.Event,
	watcher *fsnotify.Watcher,
	files chan string) {

	db := <-writer

	switch {
	case event.Op&(fsnotify.Write|fsnotify.Create|fsnotify.Chmod) != 0:
		removeFileAndReparseDepends(filepath.Clean(event.Name), db)
	case event.Op&(fsnotify.Remove|fsnotify.Rename) != 0:
		watcher.Remove(event.Name)
		removeFileAndReparseDepends(filepath.Clean(event.Name), db)
	}

	writer <- db
}

func StartFilesHandler(indexDir []string, nIndexingThreads int, parser *Parser,
	db *DBConnFactory) {

	files = make(chan string, nIndexingThreads)
	writer = make(chan *WriterDB, 1)
	writer <- db.NewWriter()

	// start threads to process files
	for i := 0; i < nIndexingThreads; i++ {
		go processFile(parser)
	}

	// start file watcher
	watcher, _ = fsnotify.NewWatcher()
	go func() {
		wg.Add(1)
		defer wg.Done()
		for {
			select {
			case event, ok := <-watcher.Events:
				if !ok {
					return
				}
				handleChange(event, watcher, files)
			case err, ok := <-watcher.Errors:
				if !ok {
					return
				}

				log.Println("watcher error: ", err)
			}
		}
	}()

	// explore all the paths in indexDir and process all files
	rd := db.NewReader()
	removedFilesSet := rd.GetSetFilesInDB()
	rd.Close()
	visitorDir := func(path string) {
		// add watcher to directory
		watcher.Add(path)
	}
	visitorC := func(path string) {
		// update set of removed files
		delete(removedFilesSet, path)
		// add watcher
		watcher.Add(path)
		// put file in channel
		files <- path
	}
	for _, path := range indexDir {
		traversePath(path, visitorDir, visitorC)
	}

	// remove from DB deleted files
	wr := <-writer
	for path := range removedFilesSet {
		wr.RemoveFileReferences(path)
	}
	writer <- wr
}

func UpdateDependency(file, dep string) bool {
	wr := <-writer
	defer func() { writer <- wr }()

	exist, uptodate, fi, err := wr.UptodateFile(dep)

	if err != nil {
		// if there is an error with the dependency, we are going to
		// pretend everything is fine so the parser move forward
		return true
	}

	if !exist {
		wr.InsertFile(dep, fi)
		watcher.Add(file)
	} else if !uptodate {
		removeFileAndReparseDepends(file, wr)
		files <- file
		return false
	}

	wr.InsertDependency(file, dep)
	return true
}

func CloseFilesHandler() {
	close(files)

	wr := <-writer
	wr.Close()
	close(writer)

	watcher.Close()

	wg.Wait()
}
<commit_msg>Fixing handling of FS watcher<commit_after>/*
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package main

/* This file will handle all file related business. It will explore the file
 * system for new files and will watch files for changes. In particular, this
 * file is the gate to the files table in the database. Other components (Parser)
 * should rely on this file to know if a file was explored or not. */

import (
	"container/list"
	fsnotify "gopkg.in/fsnotify.v1"
	"log"
	"os"
	"path/filepath"
	"regexp"
	"sync"
)

var files chan string
var wg sync.WaitGroup
var watcher *fsnotify.Watcher
var writer chan *WriterDB

func uptodateFile(file string) bool {
	wr := <-writer
	defer func() { writer <- wr }()

	exist, uptodate, fi, err := wr.UptodateFile(file)

	if err != nil {
		// if there is an error with the dependency, we are going to
		// pretend everything is fine so the parser is not executed
		return true
	}

	if exist && uptodate {
		return true
	} else {
		wr.RemoveFileReferences(file)
		wr.InsertFile(file, fi)
		return false
	}
}

func processFile(parser *Parser) {
	wg.Add(1)
	defer wg.Done()

	// start exploring files
	for {
		file, ok := <-files

		if !ok {
			return
		}

		if !uptodateFile(file) {
			log.Println("parsing", file)
			parser.Parse(file)
		}
	}
}

func explorePathToParse(path string,
	visitDir func(string),
	visitC func(string)) *list.List {

	path = filepath.Clean(path)

	f, err := os.Open(path)
	if err != nil {
		log.Println(err, "opening", path, ", ignoring")
		return nil
	}
	defer f.Close()

	info, err := f.Stat()
	if err != nil {
		log.Println(err, "stating", path, ", ignoring")
		return nil
	}

	// visit file
	if !info.IsDir() {
		// ignore non-C files
		validC, _ := regexp.MatchString(`.*\.c$`, path)
		if validC {
			visitC(path)
		}
		return nil
	} else {
		visitDir(path)
	}

	// add all the files in the directory to explore
	dirFiles, err := f.Readdir(0)
	if err != nil {
		log.Println(err, " readdir ", path, ", ignoring")
		return nil
	}

	toExplore := list.New()
	for _, subf := range dirFiles {
		// ignore hidden files
		if subf.Name()[0] == '.' {
			continue
		}

		toExplore.PushBack(path + "/" + subf.Name())
	}
	return toExplore
}

func traversePath(path string, visitDir func(string), visitC func(string)) {
	toExplore := list.New()
	toExplore.PushBack(path)

	for toExplore.Len() > 0 {
		// dequeue first path
		path := toExplore.Front()
		toExplore.Remove(path)

		newDirs := explorePathToParse(
			path.Value.(string),
			visitDir,
			visitC)
		if newDirs != nil {
			toExplore.PushBackList(newDirs)
		}
	}
}

func removeFileAndReparseDepends(file string, db *WriterDB) {
	deps := db.RemoveFileDepsReferences(file)
	db.RemoveFileReferences(file)

	for _, d := range deps {
		files <- d
	}
}

func handleFileChange(event fsnotify.Event) {

	validC, _ := regexp.MatchString(`.*\.c$`, event.Name)
	validH, _ := regexp.MatchString(`.*\.h$`, event.Name)

	switch {
	case validC:
		files <- event.Name
	case validH:
		db := <-writer
		exist, uptodate, _, err := db.UptodateFile(event.Name)

		if err != nil || (exist && !uptodate) {
			removeFileAndReparseDepends(filepath.Clean(event.Name), db)
		}

		writer <- db
	}
}

func handleDirChange(event fsnotify.Event) {
	switch {
	case event.Op&(fsnotify.Create) != 0:
		// explore the new dir
		visitorDir := func(path string) {
			// add watcher to directory
			watcher.Add(path)
		}
		visitorC := func(path string) {
			// put file in channel
			files <- path
		}
		traversePath(event.Name, visitorDir, visitorC)
	case event.Op&(fsnotify.Remove|fsnotify.Rename) != 0:
		// remove watcher from dir
		watcher.Remove(event.Name)
	}
}

func isDirectory(path string) (bool, error) {
	fi, err := os.Stat(path)
	if err != nil {
		return false, err
	} else {
		return fi.IsDir(), nil
	}
}

func handleChange(event fsnotify.Event) {

	// ignore if hidden
	if filepath.Base(event.Name)[0] == '.' {
		return
	}

	// first, we need to check if the file is a directory or not
	isDir, err := isDirectory(event.Name)
	if err != nil {
		// ignoring this event
		return
	}

	if isDir {
		handleDirChange(event)
	} else {
		handleFileChange(event)
	}
}

func StartFilesHandler(indexDir []string, nIndexingThreads int, parser *Parser,
	db *DBConnFactory) {

	files = make(chan string, nIndexingThreads)
	writer = make(chan *WriterDB, 1)
	writer <- db.NewWriter()

	// start threads to process files
	for i := 0; i < nIndexingThreads; i++ {
		go processFile(parser)
	}

	// start file watcher
	watcher, _ = fsnotify.NewWatcher()
	go func() {
		wg.Add(1)
		defer wg.Done()
		for {
			select {
			case event, ok := <-watcher.Events:
				if !ok {
					return
				}
				handleChange(event)
			case err, ok := <-watcher.Errors:
				if !ok {
					return
				}

				log.Println("watcher error: ", err)
			}
		}
	}()

	// explore all the paths in indexDir and process all files
	rd := db.NewReader()
	removedFilesSet := rd.GetSetFilesInDB()
	rd.Close()
	visitorDir := func(path string) {
		// add watcher to directory
		watcher.Add(path)
	}
	visitorC := func(path string) {
		// update set of removed files
		delete(removedFilesSet, path)
		// put file in channel
		files <- path
	}
	for _, path := range indexDir {
		traversePath(path, visitorDir, visitorC)
	}

	// remove from DB deleted files
	wr := <-writer
	for path := range removedFilesSet {
		wr.RemoveFileReferences(path)
	}
	writer <- wr
}

func UpdateDependency(file, dep string) bool {
	wr := <-writer
	defer func() { writer <- wr }()

	exist, uptodate, fi, err := wr.UptodateFile(dep)

	if err != nil {
		// if there is an error with the dependency, we are going to
		// pretend everything is fine so the parser move forward
		return true
	}

	if !exist {
		wr.InsertFile(dep, fi)
	} else if !uptodate {
		removeFileAndReparseDepends(dep, wr)
		files <- file
		return false
	}

	wr.InsertDependency(file, dep)
	return true
}

func CloseFilesHandler() {
	close(files)

	wr := <-writer
	wr.Close()
	close(writer)

	watcher.Close()

	wg.Wait()
}
<|endoftext|>


<commit_before>// Copyright 2019 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package prog

import (
	"bytes"
	"fmt"
	"math/rand"
	"sort"
	"testing"
)

func TestRotationRandom(t *testing.T) {
	target, rs, _ := initTest(t)
	for _, ncalls := range []int{10, 100, 1000, 1e9} {
		ncalls := ncalls
		rnd := rand.New(rand.NewSource(rs.Int63()))
		t.Run(fmt.Sprint(ncalls), func(t *testing.T) {
			t.Parallel()
			calls0 := selectCalls(target, rnd, ncalls)
			calls := MakeRotator(target, calls0, rnd).Select()
			for call := range calls {
				if !calls0[call] {
					t.Errorf("selected disabled syscall %v", call.Name)
				}
			}
			buf := new(bytes.Buffer)
			var array []*Syscall
			for call := range calls {
				array = append(array, call)
			}
			sort.Slice(array, func(i, j int) bool {
				return array[i].Name < array[j].Name
			})
			for _, call := range array {
				fmt.Fprintf(buf, "%v\n", call.Name)
			}
			t.Logf("calls %v->%v:\n%s", len(calls0), len(calls), buf.Bytes())
		})
	}
}

func TestRotationCoverage(t *testing.T) {
	target, rs, _ := initTest(t)
	calls := make(map[*Syscall]bool)
	counters := make(map[string]int)
	for _, call := range target.Syscalls {
		calls[call] = true
		counters[call.Name] = 0
	}
	rotator := MakeRotator(target, calls, rand.New(rs))
	for iter := 0; iter < 1e3; iter++ {
		for call := range rotator.Select() {
			counters[call.Name]++
		}
	}
	type pair struct {
		name  string
		count int
	}
	var pairs []pair
	remain := len(counters)
	for name, count := range counters {
		pairs = append(pairs, pair{name, count})
		if count != 0 {
			remain--
		}
	}
	sort.Slice(pairs, func(i, j int) bool {
		if pairs[i].count != pairs[j].count {
			return pairs[i].count > pairs[j].count
		}
		return pairs[i].name < pairs[j].name
	})
	for i, pair := range pairs {
		t.Logf("# %4d: % 4d %v", i, pair.count, pair.name)
	}
	if remain != 0 {
		t.Fatalf("uncovered syscalls: %v", remain)
	}
}

func selectCalls(target *Target, rnd *rand.Rand, ncalls int) map[*Syscall]bool {
retry:
	calls := make(map[*Syscall]bool)
	for _, call := range target.Syscalls {
		calls[call] = true
	}
	for {
		for {
			remove := 0
			switch {
			case len(calls) > ncalls+1000:
				remove = 100
			case len(calls) > ncalls+50:
				remove = 20
			case len(calls) > ncalls:
				remove = 1
			default:
				return calls
			}
			var array []*Syscall
			for call := range calls {
				array = append(array, call)
			}
			sort.Slice(array, func(i, j int) bool {
				return array[i].ID < array[j].ID
			})
			rnd.Shuffle(len(calls), func(i, j int) {
				array[i], array[j] = array[j], array[i]
			})
			for _, call := range array[:remove] {
				delete(calls, call)
			}
			calls, _ = target.transitivelyEnabled(calls)
			if len(calls) == 0 {
				goto retry
			}
		}
	}
}
<commit_msg>prog: increase number of itereations in TestRotationCoverage<commit_after>// Copyright 2019 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package prog

import (
	"bytes"
	"fmt"
	"math/rand"
	"sort"
	"testing"
)

func TestRotationRandom(t *testing.T) {
	target, rs, _ := initTest(t)
	for _, ncalls := range []int{10, 100, 1000, 1e9} {
		ncalls := ncalls
		rnd := rand.New(rand.NewSource(rs.Int63()))
		t.Run(fmt.Sprint(ncalls), func(t *testing.T) {
			t.Parallel()
			calls0 := selectCalls(target, rnd, ncalls)
			calls := MakeRotator(target, calls0, rnd).Select()
			for call := range calls {
				if !calls0[call] {
					t.Errorf("selected disabled syscall %v", call.Name)
				}
			}
			buf := new(bytes.Buffer)
			var array []*Syscall
			for call := range calls {
				array = append(array, call)
			}
			sort.Slice(array, func(i, j int) bool {
				return array[i].Name < array[j].Name
			})
			for _, call := range array {
				fmt.Fprintf(buf, "%v\n", call.Name)
			}
			t.Logf("calls %v->%v:\n%s", len(calls0), len(calls), buf.Bytes())
		})
	}
}

func TestRotationCoverage(t *testing.T) {
	target, rs, _ := initTest(t)
	calls := make(map[*Syscall]bool)
	counters := make(map[string]int)
	for _, call := range target.Syscalls {
		calls[call] = true
		counters[call.Name] = 0
	}
	rotator := MakeRotator(target, calls, rand.New(rs))
	for iter := 0; iter < 2e3; iter++ {
		for call := range rotator.Select() {
			counters[call.Name]++
		}
	}
	type pair struct {
		name  string
		count int
	}
	var pairs []pair
	remain := len(counters)
	for name, count := range counters {
		pairs = append(pairs, pair{name, count})
		if count != 0 {
			remain--
		}
	}
	sort.Slice(pairs, func(i, j int) bool {
		if pairs[i].count != pairs[j].count {
			return pairs[i].count > pairs[j].count
		}
		return pairs[i].name < pairs[j].name
	})
	for i, pair := range pairs {
		t.Logf("# %4d: % 4d %v", i, pair.count, pair.name)
	}
	if remain != 0 {
		t.Fatalf("uncovered syscalls: %v", remain)
	}
}

func selectCalls(target *Target, rnd *rand.Rand, ncalls int) map[*Syscall]bool {
retry:
	calls := make(map[*Syscall]bool)
	for _, call := range target.Syscalls {
		calls[call] = true
	}
	for {
		for {
			remove := 0
			switch {
			case len(calls) > ncalls+1000:
				remove = 100
			case len(calls) > ncalls+50:
				remove = 20
			case len(calls) > ncalls:
				remove = 1
			default:
				return calls
			}
			var array []*Syscall
			for call := range calls {
				array = append(array, call)
			}
			sort.Slice(array, func(i, j int) bool {
				return array[i].ID < array[j].ID
			})
			rnd.Shuffle(len(calls), func(i, j int) {
				array[i], array[j] = array[j], array[i]
			})
			for _, call := range array[:remove] {
				delete(calls, call)
			}
			calls, _ = target.transitivelyEnabled(calls)
			if len(calls) == 0 {
				goto retry
			}
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package factom

import (
	"bytes"
	"encoding/binary"
	"encoding/hex"
	"encoding/json"
	"fmt"
)

type Entry struct {
	ChainID string   `json:"chainid"`
	ExtIDs  [][]byte `json:"extids"`
	Content []byte   `json:"content"`
}

func (e *Entry) Hash() []byte {
	a, err := e.MarshalBinary()
	if err != nil {
		return make([]byte, 32)
	}
	return sha52(a)
}

func (e *Entry) MarshalBinary() ([]byte, error) {
	buf := new(bytes.Buffer)
	ids, err := e.MarshalExtIDsBinary()
	if err != nil {
		return buf.Bytes(), err
	}

	// Header

	// 1 byte Version
	buf.Write([]byte{0})

	// 32 byte chainid
	if p, err := hex.DecodeString(e.ChainID); err != nil {
		return buf.Bytes(), err
	} else {
		buf.Write(p)
	}

	// 2 byte size of extids
	if err := binary.Write(buf, binary.BigEndian, int16(len(ids))); err != nil {
		return buf.Bytes(), err
	}

	// Body

	// ExtIDs
	buf.Write(ids)

	// Content
	buf.Write(e.Content)

	return buf.Bytes(), nil
}

func (e *Entry) MarshalExtIDsBinary() ([]byte, error) {
	buf := new(bytes.Buffer)

	for _, v := range e.ExtIDs {
		// 2 byte length of extid
		binary.Write(buf, binary.BigEndian, int16(len(v)))
		// extid
		buf.Write(v)
	}

	return buf.Bytes(), nil
}

func (e *Entry) MarshalJSON() ([]byte, error) {
	type js struct {
		ChainID string   `json:"chainid"`
		ExtIDs  []string `json:"extids"`
		Content string   `json:"content"`
	}

	j := new(js)

	j.ChainID = e.ChainID

	for _, id := range e.ExtIDs {
		j.ExtIDs = append(j.ExtIDs, hex.EncodeToString(id))
	}

	j.Content = hex.EncodeToString(e.Content)

	return json.Marshal(j)
}

func (e *Entry) String() string {
	var s string
	s += fmt.Sprintln("ChainID:", e.ChainID)
	for _, id := range e.ExtIDs {
		s += fmt.Sprintln("ExtID:", string(id))
	}
	s += fmt.Sprintln("Content:")
	s += fmt.Sprintln(string(e.Content))
	return s
}

func (e *Entry) UnmarshalJSON(data []byte) error {
	type js struct {
		ChainID   string   `json:"chainid"`
		ChainName []string `json:"chainname"`
		ExtIDs    []string `json:"extids"`
		Content   string   `json:"content"`
	}

	j := new(js)
	if err := json.Unmarshal(data, j); err != nil {
		return err
	}

	e.ChainID = j.ChainID

	if e.ChainID == "" {
		n := new(Entry)
		for _, v := range j.ChainName {
			if p, err := hex.DecodeString(v); err != nil {
				return fmt.Errorf("Could not decode ChainName %s: %s", v, err)
			} else {
				n.ExtIDs = append(n.ExtIDs, p)
			}
		}
		m := NewChain(n)
		e.ChainID = m.ChainID
	}

	for _, v := range j.ExtIDs {
		if p, err := hex.DecodeString(v); err != nil {
			return fmt.Errorf("Could not decode ExtID %s: %s", v, err)
		} else {
			e.ExtIDs = append(e.ExtIDs, p)
		}
	}

	p, err := hex.DecodeString(j.Content)
	if err != nil {
		return fmt.Errorf("Could not decode Content %s: %s", j.Content, err)
	}
	e.Content = p

	return nil
}

// ComposeEntryCommit creates a JSON2Request to commit a new Entry via the
// factomd web api. The request includes the marshaled MessageRequest with the
// Entry Credit Signature.
func ComposeEntryCommit(e *Entry, ec *ECAddress) (*JSON2Request, error) {
	buf := new(bytes.Buffer)

	// 1 byte version
	buf.Write([]byte{0})

	// 6 byte milliTimestamp (truncated unix time)
	buf.Write(milliTime())

	// 32 byte Entry Hash
	buf.Write(e.Hash())

	// 1 byte number of entry credits to pay
	if c, err := entryCost(e); err != nil {
		return nil, err
	} else {
		buf.WriteByte(byte(c))
	}

	// 32 byte Entry Credit Address Public Key + 64 byte Signature
	sig := ec.Sign(buf.Bytes())
	buf.Write(ec.PubBytes())
	buf.Write(sig[:])

	params := entryRequest{Entry: hex.EncodeToString(buf.Bytes())}
	req := NewJSON2Request("commit-entry", APICounter(), params)

	return req, nil
}

// ComposeEntryReveal creates a JSON2Request to reveal the Entry via the factomd
// web api.
func ComposeEntryReveal(e *Entry) (*JSON2Request, error) {
	p, err := e.MarshalBinary()
	if err != nil {
		return nil, err
	}

	params := entryRequest{Entry: hex.EncodeToString(p)}
	req := NewJSON2Request("reveal-entry", APICounter(), params)

	return req, nil
}

// CommitEntry sends the signed Entry Hash and the Entry Credit public key to
// the factom network. Once the payment is verified and the network is commited
// to publishing the Entry it may be published with a call to RevealEntry.
func CommitEntry(e *Entry, ec *ECAddress) (string, error) {
	type commitResponse struct {
		Message string `json:"message"`
		TxID    string `json:"txid"`
	}

	req, err := ComposeEntryCommit(e, ec)
	if err != nil {
		return "", err
	}

	resp, err := factomdRequest(req)
	if err != nil {
		return "", err
	}
	if resp.Error != nil {
		return "", resp.Error
	}
	r := new(commitResponse)
	if err := json.Unmarshal(resp.JSONResult(), r); err != nil {
		return "", err
	}

	return r.TxID, nil
}

func RevealEntry(e *Entry) (string, error) {
	type revealResponse struct {
		Message string `json:"message"`
		Entry   string `json:"entryhash"`
	}

	req, err := ComposeEntryReveal(e)
	if err != nil {
		return "", err
	}

	resp, err := factomdRequest(req)
	if err != nil {
		return "", err
	}
	if resp.Error != nil {
		return "", resp.Error
	}

	r := new(revealResponse)
	if err := json.Unmarshal(resp.JSONResult(), r); err != nil {
		return "", err
	}
	return r.Entry, nil
}
<commit_msg>add entryhash to printouts<commit_after>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package factom

import (
	"bytes"
	"encoding/binary"
	"encoding/hex"
	"encoding/json"
	"fmt"
)

type Entry struct {
	ChainID string   `json:"chainid"`
	ExtIDs  [][]byte `json:"extids"`
	Content []byte   `json:"content"`
}

func (e *Entry) Hash() []byte {
	a, err := e.MarshalBinary()
	if err != nil {
		return make([]byte, 32)
	}
	return sha52(a)
}

func (e *Entry) MarshalBinary() ([]byte, error) {
	buf := new(bytes.Buffer)
	ids, err := e.MarshalExtIDsBinary()
	if err != nil {
		return buf.Bytes(), err
	}

	// Header

	// 1 byte Version
	buf.Write([]byte{0})

	// 32 byte chainid
	if p, err := hex.DecodeString(e.ChainID); err != nil {
		return buf.Bytes(), err
	} else {
		buf.Write(p)
	}

	// 2 byte size of extids
	if err := binary.Write(buf, binary.BigEndian, int16(len(ids))); err != nil {
		return buf.Bytes(), err
	}

	// Body

	// ExtIDs
	buf.Write(ids)

	// Content
	buf.Write(e.Content)

	return buf.Bytes(), nil
}

func (e *Entry) MarshalExtIDsBinary() ([]byte, error) {
	buf := new(bytes.Buffer)

	for _, v := range e.ExtIDs {
		// 2 byte length of extid
		binary.Write(buf, binary.BigEndian, int16(len(v)))
		// extid
		buf.Write(v)
	}

	return buf.Bytes(), nil
}

func (e *Entry) MarshalJSON() ([]byte, error) {
	type js struct {
		ChainID string   `json:"chainid"`
		ExtIDs  []string `json:"extids"`
		Content string   `json:"content"`
	}

	j := new(js)

	j.ChainID = e.ChainID

	for _, id := range e.ExtIDs {
		j.ExtIDs = append(j.ExtIDs, hex.EncodeToString(id))
	}

	j.Content = hex.EncodeToString(e.Content)

	return json.Marshal(j)
}

func (e *Entry) String() string {
	var s string
	s += fmt.Sprintf("Entryhash: %x\n", e.Hash())
	s += fmt.Sprintln("ChainID:", e.ChainID)
	for _, id := range e.ExtIDs {
		s += fmt.Sprintln("ExtID:", string(id))
	}
	s += fmt.Sprintln("Content:")
	s += fmt.Sprintln(string(e.Content))
	return s
}

func (e *Entry) UnmarshalJSON(data []byte) error {
	type js struct {
		ChainID   string   `json:"chainid"`
		ChainName []string `json:"chainname"`
		ExtIDs    []string `json:"extids"`
		Content   string   `json:"content"`
	}

	j := new(js)
	if err := json.Unmarshal(data, j); err != nil {
		return err
	}

	e.ChainID = j.ChainID

	if e.ChainID == "" {
		n := new(Entry)
		for _, v := range j.ChainName {
			if p, err := hex.DecodeString(v); err != nil {
				return fmt.Errorf("Could not decode ChainName %s: %s", v, err)
			} else {
				n.ExtIDs = append(n.ExtIDs, p)
			}
		}
		m := NewChain(n)
		e.ChainID = m.ChainID
	}

	for _, v := range j.ExtIDs {
		if p, err := hex.DecodeString(v); err != nil {
			return fmt.Errorf("Could not decode ExtID %s: %s", v, err)
		} else {
			e.ExtIDs = append(e.ExtIDs, p)
		}
	}

	p, err := hex.DecodeString(j.Content)
	if err != nil {
		return fmt.Errorf("Could not decode Content %s: %s", j.Content, err)
	}
	e.Content = p

	return nil
}

// ComposeEntryCommit creates a JSON2Request to commit a new Entry via the
// factomd web api. The request includes the marshaled MessageRequest with the
// Entry Credit Signature.
func ComposeEntryCommit(e *Entry, ec *ECAddress) (*JSON2Request, error) {
	buf := new(bytes.Buffer)

	// 1 byte version
	buf.Write([]byte{0})

	// 6 byte milliTimestamp (truncated unix time)
	buf.Write(milliTime())

	// 32 byte Entry Hash
	buf.Write(e.Hash())

	// 1 byte number of entry credits to pay
	if c, err := entryCost(e); err != nil {
		return nil, err
	} else {
		buf.WriteByte(byte(c))
	}

	// 32 byte Entry Credit Address Public Key + 64 byte Signature
	sig := ec.Sign(buf.Bytes())
	buf.Write(ec.PubBytes())
	buf.Write(sig[:])

	params := entryRequest{Entry: hex.EncodeToString(buf.Bytes())}
	req := NewJSON2Request("commit-entry", APICounter(), params)

	return req, nil
}

// ComposeEntryReveal creates a JSON2Request to reveal the Entry via the factomd
// web api.
func ComposeEntryReveal(e *Entry) (*JSON2Request, error) {
	p, err := e.MarshalBinary()
	if err != nil {
		return nil, err
	}

	params := entryRequest{Entry: hex.EncodeToString(p)}
	req := NewJSON2Request("reveal-entry", APICounter(), params)

	return req, nil
}

// CommitEntry sends the signed Entry Hash and the Entry Credit public key to
// the factom network. Once the payment is verified and the network is commited
// to publishing the Entry it may be published with a call to RevealEntry.
func CommitEntry(e *Entry, ec *ECAddress) (string, error) {
	type commitResponse struct {
		Message string `json:"message"`
		TxID    string `json:"txid"`
	}

	req, err := ComposeEntryCommit(e, ec)
	if err != nil {
		return "", err
	}

	resp, err := factomdRequest(req)
	if err != nil {
		return "", err
	}
	if resp.Error != nil {
		return "", resp.Error
	}
	r := new(commitResponse)
	if err := json.Unmarshal(resp.JSONResult(), r); err != nil {
		return "", err
	}

	return r.TxID, nil
}

func RevealEntry(e *Entry) (string, error) {
	type revealResponse struct {
		Message string `json:"message"`
		Entry   string `json:"entryhash"`
	}

	req, err := ComposeEntryReveal(e)
	if err != nil {
		return "", err
	}

	resp, err := factomdRequest(req)
	if err != nil {
		return "", err
	}
	if resp.Error != nil {
		return "", resp.Error
	}

	r := new(revealResponse)
	if err := json.Unmarshal(resp.JSONResult(), r); err != nil {
		return "", err
	}
	return r.Entry, nil
}
<|endoftext|>


<commit_before>package niso

import (
	"fmt"

	"net/url"

	"github.com/pkg/errors"
)

// ErrorCode is an OAuth2 error code
type ErrorCode string

// OAuth2 error codes (https://tools.ietf.org/html/rfc6749#section-4.1.2.1)
const (
	E_INVALID_REQUEST           ErrorCode = "invalid_request"
	E_UNAUTHORIZED_CLIENT       ErrorCode = "unauthorized_client"
	E_ACCESS_DENIED             ErrorCode = "access_denied"
	E_UNSUPPORTED_RESPONSE_TYPE ErrorCode = "unsupported_response_type"
	E_INVALID_SCOPE             ErrorCode = "invalid_scope"
	E_SERVER_ERROR              ErrorCode = "server_error"
	E_TEMPORARILY_UNAVAILABLE   ErrorCode = "temporarily_unavailable"
	E_UNSUPPORTED_GRANT_TYPE    ErrorCode = "unsupported_grant_type"
	E_INVALID_GRANT             ErrorCode = "invalid_grant"
	E_INVALID_CLIENT            ErrorCode = "invalid_client"
)

// NisoError is a wrapper around an existing error with an OAuth2 error code
type NisoError struct {
	Code ErrorCode
	Err  error

	// Human readable description of the error that occurred
	Message string

	// redirectURI is the URI to which the request will be redirected to when using WriteErrorResponse
	// as per https://tools.ietf.org/html/rfc6749#section-4.2.2.1
	redirectURI string

	// State is the state parameter to be passed directly back to the client
	state string
}

// NewNisoError creates a new NisoError for a response error code
func NewNisoError(code ErrorCode, message string) *NisoError {
	return &NisoError{
		Code:    code,
		Err:     errors.New(message),
		Message: message,
	}
}

// NewWrappedNisoError creates a new NisoError for a response error code and wraps the original error with the given description
func NewWrappedNisoError(code ErrorCode, error error, message string) *NisoError {
	return &NisoError{
		Code:    code,
		Err:     errors.Wrap(error, message),
		Message: message,
	}
}

// SetRedirectURI set redirect uri for this error to redirect to when written to a HTTP response
func (e *NisoError) SetRedirectURI(redirectURI string) {
	e.redirectURI = redirectURI
}

// SetState sets the "state" parameter to be returned to the user when this error is rendered
func (e *NisoError) SetState(state string) {
	e.state = state
}

func (e *NisoError) Error() string {
	return fmt.Sprintf("(%s) %s", e.Code, e.Err.Error())
}

// AsResponse creates a response object from this error, containing it's body or a redirect if specified
func (e *NisoError) AsResponse() *Response {
	resp := NewResponse()

	// Redirect user if needed
	loc, err := e.GetRedirectURI()
	if err != nil {
		return newInternalServerErrorResponse(
			errors.Wrap(err, "failed to redirect on error").Error(),
		)
	}
	if loc != "" {
		resp.responseType = REDIRECT
		resp.redirectURL = loc
	}

	// No redirect output error as a JSON response
	resp.StatusCode = statusCodeForError(e)
	for k, v := range e.GetResponseDict() {
		if v != "" {
			resp.Data[k] = v
		}
	}

	return resp
}

// GetRedirectURI returns location to redirect user to after processing this error, or empty string if there is none
func (e *NisoError) GetRedirectURI() (string, error) {
	if e.redirectURI == "" {
		return "", nil
	}

	u, err := url.Parse(e.redirectURI)
	if err != nil {
		return "", err
	}

	q := u.Query()
	for k, v := range e.GetResponseDict() {
		if v != "" {
			q.Set(k, v)
		}
	}

	u.RawQuery = q.Encode()
	u.Fragment = ""
	return u.String(), nil
}

// GetResponseDict returns the fields for an error response as defined in https://tools.ietf.org/html/rfc6749#section-4.2.2.1
func (e *NisoError) GetResponseDict() map[string]string {
	return map[string]string{
		"error":             string(e.Code),
		"error_description": e.Message,
		"state":             e.state,
	}
}

func toNisoError(err error) *NisoError {
	if ne, ok := err.(*NisoError); ok {
		return ne
	}

	return NewWrappedNisoError(E_SERVER_ERROR, err, "unknown error")
}

// status code to return for a given error code as per (https://tools.ietf.org/html/rfc6749#section-5.2)
func statusCodeForError(error *NisoError) int {
	if error.Code == E_SERVER_ERROR {
		return 500
	} else if error.Code == E_TEMPORARILY_UNAVAILABLE {
		return 503
	} else if error.Code == E_INVALID_CLIENT || error.Code == E_ACCESS_DENIED {
		return 401
	}

	return 400
}
<commit_msg>NewNiso error with args<commit_after>package niso

import (
	"fmt"

	"net/url"

	"github.com/pkg/errors"
)

// ErrorCode is an OAuth2 error code
type ErrorCode string

// OAuth2 error codes (https://tools.ietf.org/html/rfc6749#section-4.1.2.1)
const (
	E_INVALID_REQUEST           ErrorCode = "invalid_request"
	E_UNAUTHORIZED_CLIENT       ErrorCode = "unauthorized_client"
	E_ACCESS_DENIED             ErrorCode = "access_denied"
	E_UNSUPPORTED_RESPONSE_TYPE ErrorCode = "unsupported_response_type"
	E_INVALID_SCOPE             ErrorCode = "invalid_scope"
	E_SERVER_ERROR              ErrorCode = "server_error"
	E_TEMPORARILY_UNAVAILABLE   ErrorCode = "temporarily_unavailable"
	E_UNSUPPORTED_GRANT_TYPE    ErrorCode = "unsupported_grant_type"
	E_INVALID_GRANT             ErrorCode = "invalid_grant"
	E_INVALID_CLIENT            ErrorCode = "invalid_client"
)

// NisoError is a wrapper around an existing error with an OAuth2 error code
type NisoError struct {
	Code ErrorCode
	Err  error

	// Human readable description of the error that occurred
	Message string

	// redirectURI is the URI to which the request will be redirected to when using WriteErrorResponse
	// as per https://tools.ietf.org/html/rfc6749#section-4.2.2.1
	redirectURI string

	// State is the state parameter to be passed directly back to the client
	state string
}

// NewNisoError creates a new NisoError for a response error code
func NewNisoError(code ErrorCode, message string, args ...interface{}) *NisoError {
	return &NisoError{
		Code:    code,
		Err:     errors.Errorf(message, args...),
		Message: message,
	}
}

// NewWrappedNisoError creates a new NisoError for a response error code and wraps the original error with the given description
func NewWrappedNisoError(code ErrorCode, error error, message string, args ...interface{}) *NisoError {
	return &NisoError{
		Code:    code,
		Err:     errors.Wrapf(error, message, args...),
		Message: message,
	}
}

// SetRedirectURI set redirect uri for this error to redirect to when written to a HTTP response
func (e *NisoError) SetRedirectURI(redirectURI string) {
	e.redirectURI = redirectURI
}

// SetState sets the "state" parameter to be returned to the user when this error is rendered
func (e *NisoError) SetState(state string) {
	e.state = state
}

func (e *NisoError) Error() string {
	return fmt.Sprintf("(%s) %s", e.Code, e.Err.Error())
}

// AsResponse creates a response object from this error, containing it's body or a redirect if specified
func (e *NisoError) AsResponse() *Response {
	resp := NewResponse()

	// Redirect user if needed
	loc, err := e.GetRedirectURI()
	if err != nil {
		return newInternalServerErrorResponse(
			errors.Wrap(err, "failed to redirect on error").Error(),
		)
	}
	if loc != "" {
		resp.responseType = REDIRECT
		resp.redirectURL = loc
	}

	// No redirect output error as a JSON response
	resp.StatusCode = statusCodeForError(e)
	for k, v := range e.GetResponseDict() {
		if v != "" {
			resp.Data[k] = v
		}
	}

	return resp
}

// GetRedirectURI returns location to redirect user to after processing this error, or empty string if there is none
func (e *NisoError) GetRedirectURI() (string, error) {
	if e.redirectURI == "" {
		return "", nil
	}

	u, err := url.Parse(e.redirectURI)
	if err != nil {
		return "", err
	}

	q := u.Query()
	for k, v := range e.GetResponseDict() {
		if v != "" {
			q.Set(k, v)
		}
	}

	u.RawQuery = q.Encode()
	u.Fragment = ""
	return u.String(), nil
}

// GetResponseDict returns the fields for an error response as defined in https://tools.ietf.org/html/rfc6749#section-4.2.2.1
func (e *NisoError) GetResponseDict() map[string]string {
	return map[string]string{
		"error":             string(e.Code),
		"error_description": e.Message,
		"state":             e.state,
	}
}

func toNisoError(err error) *NisoError {
	if ne, ok := err.(*NisoError); ok {
		return ne
	}

	return NewWrappedNisoError(E_SERVER_ERROR, err, "unknown error")
}

// status code to return for a given error code as per (https://tools.ietf.org/html/rfc6749#section-5.2)
func statusCodeForError(error *NisoError) int {
	if error.Code == E_SERVER_ERROR {
		return 500
	} else if error.Code == E_TEMPORARILY_UNAVAILABLE {
		return 503
	} else if error.Code == E_INVALID_CLIENT || error.Code == E_ACCESS_DENIED {
		return 401
	}

	return 400
}
<|endoftext|>


<commit_before>package Golf

import (
	"bytes"
	"fmt"
	"html/template"
	"net/http"
)

var errorTemplate = `<!DOCTYPE HTML>

    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <title>Error: {{.Code}} {{.Title}}</title>

Error: {{.Code}} {{.Title}}

Sorry, the requested URL {{.URL}} caused an error:

{{.Message}}

{{.StackTrace}}

`

var tmpl = template.New("error")

type TemplateError struct {
	Format     string
	Parameters []interface{}
}

func (e *TemplateError) Error() string {
	return fmt.Sprintf(e.Format, e.Parameters...)
}

func Errf(format string, parameters ...interface{}) error {
	return &TemplateError{
		Format:     format,
		Parameters: parameters,
	}
}

// The default error handler
func defaultErrorHandler(ctx *Context) {
	tmpl.Parse(errorTemplate)
	var buf bytes.Buffer
	tmpl.Execute(&buf, map[string]interface{}{
		"Code":    ctx.StatusCode,
		"Title":   http.StatusText(ctx.StatusCode),
		"Message": http.StatusText(ctx.StatusCode),
	})
	ctx.Write(buf.String())
	ctx.Send()
}
<commit_msg>[refactor] Unexported templateError<commit_after>package Golf

import (
	"bytes"
	"fmt"
	"html/template"
	"net/http"
)

var errorTemplate = `<!DOCTYPE HTML>

    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <title>Error: {{.Code}} {{.Title}}</title>

Error: {{.Code}} {{.Title}}

Sorry, the requested URL {{.URL}} caused an error:

{{.Message}}

{{.StackTrace}}

`

var tmpl = template.New("error")

type templateError struct {
	Format     string
	Parameters []interface{}
}

func (e *templateError) Error() string {
	return fmt.Sprintf(e.Format, e.Parameters...)
}

func Errf(format string, parameters ...interface{}) error {
	return &templateError{
		Format:     format,
		Parameters: parameters,
	}
}

// The default error handler
func defaultErrorHandler(ctx *Context) {
	tmpl.Parse(errorTemplate)
	var buf bytes.Buffer
	tmpl.Execute(&buf, map[string]interface{}{
		"Code":    ctx.StatusCode,
		"Title":   http.StatusText(ctx.StatusCode),
		"Message": http.StatusText(ctx.StatusCode),
	})
	ctx.Write(buf.String())
	ctx.Send()
}
<|endoftext|>


<commit_before>// +build integration_tests

package websession

// Integration tests; these operate against the test app in ../../internal/testapp

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"testing"
)

var baseUrl string

func init() {
	// Get the base URL for the test app from the environment. if
	// the requisite environment variable is not set, panic.
	baseUrl = os.Getenv("GO_SANDSTORM_TEST_APP")
	if baseUrl == "" {
		panic("Integration test: GO_SANDSTORM_TEST_APP environment " +
			"variable not defined.")
	}
}

type echoBody struct {
	Method  string         `json:"method"`
	Url     *url.URL       `json:"url"`
	Headers http.Header    `json:"headers"`
	Body    []byte         `json:"body"`
	Cookies []*http.Cookie `json:"cookies"`
}

func chkfatal(t *testing.T, err error) {
	if err != nil {
		t.Fatal(err)
	}
}

func expectStatus(t *testing.T, want, got int) {
	if want != got {
		t.Fatal("Unexpected status code; expected", want, "but got", got)
	}
}

func TestBasicGetHead(t *testing.T) {
	successfulResponse := func(resp *http.Response, err error) {
		chkfatal(t, err)
		expectStatus(t, 200, resp.StatusCode)
	}
	successfulResponse(http.Get(baseUrl + "echo-request/hello"))
	successfulResponse(http.Head(baseUrl + "echo-request/hello"))
}

func TestGetCorrectInfo(t *testing.T) {

	resp, err := http.Get(baseUrl + "echo-request/hello")
	chkfatal(t, err)
	defer func() {
		if t.Failed() {
			t.Log("Response:", resp)
		}
	}()
	expectStatus(t, 200, resp.StatusCode)
	body := &echoBody{}
	err = json.NewDecoder(resp.Body).Decode(body)
	chkfatal(t, err)

	if body.Method != "GET" {
		t.Error("Wrong method:", body.Method)
	}
	if body.Url.Path != "/echo-request/hello" {
		t.Error("Wrong path:", body.Url.Path)
	}
}

func testHeader(t *testing.T, name, sendVal, wantRecvVal string) {
	req, err := http.NewRequest("GET", baseUrl+"echo-request/"+name+"-header", nil)
	chkfatal(t, err)
	req.Header.Set(name, sendVal)

	resp, err := http.DefaultClient.Do(req)
	chkfatal(t, err)
	defer func() {
		if t.Failed() {
			t.Log("Response:", resp)
		}
	}()

	expectStatus(t, 200, resp.StatusCode)
	body := &echoBody{}
	err = json.NewDecoder(resp.Body).Decode(body)
	chkfatal(t, err)
	gotRecvVal := body.Headers.Get(name)
	if gotRecvVal != wantRecvVal {
		t.Fatalf("Server did not see correct value for %s header; "+
			"wanted %q but got %q", name, wantRecvVal, gotRecvVal)
	}
}

func TestAcceptHeader(t *testing.T) {
	testHeader(t, "Accept", "application/json", "application/json; q=1")
}

func TestAcceptEncodingHeader(t *testing.T) {
	testHeader(t, "Accept-Encoding", "something-non-standard", "something-non-standard;q=1")
	testHeader(t, "Accept-Encoding", "gzip", "gzip;q=1")
	testHeader(t, "Accept-Encoding", "*;q=1", "*;q=1")
}

func TestAdditionalHeaders(t *testing.T) {
	testHeader(t, "X-Foo-Disallowed-Header", "Bar", "")
	testHeader(t, "X-Sandstorm-App-Baz", "quux", "quux")
	testHeader(t, "OC-Total-Length", "234", "234")
}

func TestETagPrecondition(t *testing.T) {
	testHeader(t, "If-Match", "*", "*")
	testHeader(t, "If-None-Match", `"foobarbaz"`, `"foobarbaz"`)
	testHeader(t, "If-None-Match", `W/"foobarbaz"`, `W/"foobarbaz"`)
	testHeader(t, "If-None-Match", `W/"foobarbaz", "quux"`, `W/"foobarbaz", "quux"`)

	// "net/http" won't magically deal with the etag header unless we use
	// http.FileSystem, so even though the following should arguably
	// return "Precondition Failed," we can ignore it to check whether the
	// header is getting through:
	testHeader(t, "If-None-Match", "*", "*")
	testHeader(t, "If-Match", `"foobarbaz"`, `"foobarbaz"`)
	testHeader(t, "If-Match", `W/"foobarbaz"`, `W/"foobarbaz"`)
	testHeader(t, "If-Match", `W/"foobarbaz", "quux"`, `W/"foobarbaz", "quux"`)
}

func TestResponseContentType(t *testing.T) {
	resp, err := http.Get(baseUrl + "echo-request/content-type")
	chkfatal(t, err)
	expectStatus(t, 200, resp.StatusCode)
	contentType := resp.Header.Get("Content-Type")
	if contentType != "application/json" {
		t.Fatalf("Expected content type application/json but got %q", contentType)
	}
}

func TestResponseContentEncoding(t *testing.T) {
	resp, err := http.Get(baseUrl + "echo-request/content-encoding")
	chkfatal(t, err)
	expectStatus(t, 200, resp.StatusCode)

	encoding := resp.Header.Get("Content-Encoding")
	if encoding != "identity" {
		t.Fatalf("Expected content encoding identity, but got %q.", encoding)
	}
}

func TestResponseContentLength(t *testing.T) {
	resp, err := http.Get(baseUrl + "content-length")
	chkfatal(t, err)
	expectStatus(t, 200, resp.StatusCode)

	contentLength := resp.Header.Get("Content-Length")
	reportLength, err := strconv.ParseUint(contentLength, 10, 64)
	chkfatal(t, err)

	body, err := ioutil.ReadAll(resp.Body)
	chkfatal(t, err)

	realLength := uint64(len(body))
	if realLength != reportLength {
		t.Fatal("Content-Header indicated a length of %d, but body was ",
			"actually %d bytes long.", reportLength, realLength)
	}
}

func TestWantStatus(t *testing.T) {
	for _, wantStatus := range []int{200, 201, 202, 204, 205} {
		resp, err := http.Get(fmt.Sprintf(
			"%secho-request/status?want-status=%d", baseUrl, wantStatus,
		))
		chkfatal(t, err)
		expectStatus(t, wantStatus, resp.StatusCode)
	}
}

func TestWantLanguage(t *testing.T) {
	for _, wantLang := range []string{"en-US", "de-DE"} {
		resp, err := http.Get(
			baseUrl + "echo-request/lang?want-lang=" + wantLang,
		)
		chkfatal(t, err)
		expectStatus(t, 200, resp.StatusCode)
		gotLang := resp.Header.Get("Content-Language")
		if wantLang != gotLang {
			t.Fatalf("Unexpected Content-Language; wanted %q but got %q.",
				wantLang, gotLang)
		}
	}
}

func TestNoOpHandler(t *testing.T) {
	resp, err := http.Get(baseUrl + "no-op-handler")
	chkfatal(t, err)
	expectStatus(t, 200, resp.StatusCode)
}

func TestETag(t *testing.T) {
	resp, err := http.Get(baseUrl + "etag")
	chkfatal(t, err)
	expectStatus(t, 200, resp.StatusCode)
	etag := resp.Header.Get("ETag")

	if etag != `"sometag"` {
		t.Errorf(`Expected ETag value "sometag", but got %q`, etag)
	}

	resp, err = http.Get(baseUrl + "etag?weak=true")
	chkfatal(t, err)
	expectStatus(t, 200, resp.StatusCode)
	etag = resp.Header.Get("ETag")

	if etag != `W/"sometag"` {
		t.Errorf(`Expected ETag value W/"sometag", but got %q`, etag)
	}
}
<commit_msg>Add a test re: NoContent responses.<commit_after>// +build integration_tests

package websession

// Integration tests; these operate against the test app in ../../internal/testapp

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"testing"
)

var baseUrl string

func init() {
	// Get the base URL for the test app from the environment. if
	// the requisite environment variable is not set, panic.
	baseUrl = os.Getenv("GO_SANDSTORM_TEST_APP")
	if baseUrl == "" {
		panic("Integration test: GO_SANDSTORM_TEST_APP environment " +
			"variable not defined.")
	}
}

type echoBody struct {
	Method  string         `json:"method"`
	Url     *url.URL       `json:"url"`
	Headers http.Header    `json:"headers"`
	Body    []byte         `json:"body"`
	Cookies []*http.Cookie `json:"cookies"`
}

func chkfatal(t *testing.T, err error) {
	if err != nil {
		t.Fatal(err)
	}
}

func expectStatus(t *testing.T, want, got int) {
	if want != got {
		t.Fatal("Unexpected status code; expected", want, "but got", got)
	}
}

func TestBasicGetHead(t *testing.T) {
	successfulResponse := func(resp *http.Response, err error) {
		chkfatal(t, err)
		expectStatus(t, 200, resp.StatusCode)
	}
	successfulResponse(http.Get(baseUrl + "echo-request/hello"))
	successfulResponse(http.Head(baseUrl + "echo-request/hello"))
}

func TestGetCorrectInfo(t *testing.T) {

	resp, err := http.Get(baseUrl + "echo-request/hello")
	chkfatal(t, err)
	defer func() {
		if t.Failed() {
			t.Log("Response:", resp)
		}
	}()
	expectStatus(t, 200, resp.StatusCode)
	body := &echoBody{}
	err = json.NewDecoder(resp.Body).Decode(body)
	chkfatal(t, err)

	if body.Method != "GET" {
		t.Error("Wrong method:", body.Method)
	}
	if body.Url.Path != "/echo-request/hello" {
		t.Error("Wrong path:", body.Url.Path)
	}
}

func testHeader(t *testing.T, name, sendVal, wantRecvVal string) {
	req, err := http.NewRequest("GET", baseUrl+"echo-request/"+name+"-header", nil)
	chkfatal(t, err)
	req.Header.Set(name, sendVal)

	resp, err := http.DefaultClient.Do(req)
	chkfatal(t, err)
	defer func() {
		if t.Failed() {
			t.Log("Response:", resp)
		}
	}()

	expectStatus(t, 200, resp.StatusCode)
	body := &echoBody{}
	err = json.NewDecoder(resp.Body).Decode(body)
	chkfatal(t, err)
	gotRecvVal := body.Headers.Get(name)
	if gotRecvVal != wantRecvVal {
		t.Fatalf("Server did not see correct value for %s header; "+
			"wanted %q but got %q", name, wantRecvVal, gotRecvVal)
	}
}

func TestAcceptHeader(t *testing.T) {
	testHeader(t, "Accept", "application/json", "application/json; q=1")
}

func TestAcceptEncodingHeader(t *testing.T) {
	testHeader(t, "Accept-Encoding", "something-non-standard", "something-non-standard;q=1")
	testHeader(t, "Accept-Encoding", "gzip", "gzip;q=1")
	testHeader(t, "Accept-Encoding", "*;q=1", "*;q=1")
}

func TestAdditionalHeaders(t *testing.T) {
	testHeader(t, "X-Foo-Disallowed-Header", "Bar", "")
	testHeader(t, "X-Sandstorm-App-Baz", "quux", "quux")
	testHeader(t, "OC-Total-Length", "234", "234")
}

func TestETagPrecondition(t *testing.T) {
	testHeader(t, "If-Match", "*", "*")
	testHeader(t, "If-None-Match", `"foobarbaz"`, `"foobarbaz"`)
	testHeader(t, "If-None-Match", `W/"foobarbaz"`, `W/"foobarbaz"`)
	testHeader(t, "If-None-Match", `W/"foobarbaz", "quux"`, `W/"foobarbaz", "quux"`)

	// "net/http" won't magically deal with the etag header unless we use
	// http.FileSystem, so even though the following should arguably
	// return "Precondition Failed," we can ignore it to check whether the
	// header is getting through:
	testHeader(t, "If-None-Match", "*", "*")
	testHeader(t, "If-Match", `"foobarbaz"`, `"foobarbaz"`)
	testHeader(t, "If-Match", `W/"foobarbaz"`, `W/"foobarbaz"`)
	testHeader(t, "If-Match", `W/"foobarbaz", "quux"`, `W/"foobarbaz", "quux"`)
}

func TestResponseContentType(t *testing.T) {
	resp, err := http.Get(baseUrl + "echo-request/content-type")
	chkfatal(t, err)
	expectStatus(t, 200, resp.StatusCode)
	contentType := resp.Header.Get("Content-Type")
	if contentType != "application/json" {
		t.Fatalf("Expected content type application/json but got %q", contentType)
	}
}

func TestResponseContentEncoding(t *testing.T) {
	resp, err := http.Get(baseUrl + "echo-request/content-encoding")
	chkfatal(t, err)
	expectStatus(t, 200, resp.StatusCode)

	encoding := resp.Header.Get("Content-Encoding")
	if encoding != "identity" {
		t.Fatalf("Expected content encoding identity, but got %q.", encoding)
	}
}

func TestResponseContentLength(t *testing.T) {
	resp, err := http.Get(baseUrl + "content-length")
	chkfatal(t, err)
	expectStatus(t, 200, resp.StatusCode)

	contentLength := resp.Header.Get("Content-Length")
	reportLength, err := strconv.ParseUint(contentLength, 10, 64)
	chkfatal(t, err)

	body, err := ioutil.ReadAll(resp.Body)
	chkfatal(t, err)

	realLength := uint64(len(body))
	if realLength != reportLength {
		t.Fatal("Content-Header indicated a length of %d, but body was ",
			"actually %d bytes long.", reportLength, realLength)
	}
}

func TestWantStatus(t *testing.T) {
	for _, wantStatus := range []int{200, 201, 202, 204, 205} {
		resp, err := http.Get(fmt.Sprintf(
			"%secho-request/status?want-status=%d", baseUrl, wantStatus,
		))
		chkfatal(t, err)
		expectStatus(t, wantStatus, resp.StatusCode)
	}
}

func TestWantLanguage(t *testing.T) {
	for _, wantLang := range []string{"en-US", "de-DE"} {
		resp, err := http.Get(
			baseUrl + "echo-request/lang?want-lang=" + wantLang,
		)
		chkfatal(t, err)
		expectStatus(t, 200, resp.StatusCode)
		gotLang := resp.Header.Get("Content-Language")
		if wantLang != gotLang {
			t.Fatalf("Unexpected Content-Language; wanted %q but got %q.",
				wantLang, gotLang)
		}
	}
}

func TestNoOpHandler(t *testing.T) {
	resp, err := http.Get(baseUrl + "no-op-handler")
	chkfatal(t, err)
	expectStatus(t, 200, resp.StatusCode)
}

func TestETag(t *testing.T) {
	resp, err := http.Get(baseUrl + "etag")
	chkfatal(t, err)
	expectStatus(t, 200, resp.StatusCode)
	etag := resp.Header.Get("ETag")

	if etag != `"sometag"` {
		t.Errorf(`Expected ETag value "sometag", but got %q`, etag)
	}

	resp, err = http.Get(baseUrl + "etag?weak=true")
	chkfatal(t, err)
	expectStatus(t, 200, resp.StatusCode)
	etag = resp.Header.Get("ETag")

	if etag != `W/"sometag"` {
		t.Errorf(`Expected ETag value W/"sometag", but got %q`, etag)
	}
}

func TestNoContentBodies(t *testing.T) {
	resp, err := http.Get(baseUrl + "echo-request/status?want-status=205")
	chkfatal(t, err)
	expectStatus(t, 205, resp.StatusCode)
	data, err := ioutil.ReadAll(resp.Body)
	chkfatal(t, err)
	if len(data) != 0 {
		t.Fatalf("No-content response returned a body: %q", data)
	}
}
<|endoftext|>


<commit_before>package linda

import (
	"flag"
	"github.com/sirupsen/logrus"
)

func init() {
	flag.StringVar(&settings.Queue, "queues", "", "queue name")
	flag.Float64Var(&settings.IntervalFloat, "interval", 5.0, "sleep interval when no jobs are found")
	flag.IntVar(&settings.Concurrency, "concurrency", 2, "the maximum number of concurrently workers")
	flag.StringVar(&settings.Connection, "connection", "redis://localhost:6379/", "the url of the broker connection")
}

func flags() error {
	if !flag.Parsed() {
		logrus.Debug("parse the flag")
		flag.Parse()
	}

	if err := settings.Interval.SetFloat(settings.IntervalFloat); err != nil {
		return err
	}

	return nil
}
<commit_msg>modify flag queues to queue add default value of queue `default`<commit_after>package linda

import (
	"flag"
	"github.com/sirupsen/logrus"
)

func init() {
	flag.StringVar(&settings.Queue, "queue", "default", "queue name")
	flag.Float64Var(&settings.IntervalFloat, "interval", 5.0, "sleep interval when no jobs are found")
	flag.IntVar(&settings.Concurrency, "concurrency", 2, "the maximum number of concurrently workers")
	flag.StringVar(&settings.Connection, "connection", "redis://localhost:6379/", "the url of the broker connection")
}

func flags() error {
	if !flag.Parsed() {
		logrus.Debug("parse the flag")
		flag.Parse()
	}

	if err := settings.Interval.SetFloat(settings.IntervalFloat); err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2015-2017 trivago GmbH
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"fmt"
	"github.com/trivago/gollum/core"
	"github.com/trivago/tgo/tflag"
	"github.com/sirupsen/logrus"
)

var (
	flagHelp           = tflag.Switch("h", "help", "Print this help message.")
	flagVersion        = tflag.Switch("v", "version", "Print version information and quit.")
	flagReport         = tflag.Switch("r", "report", "Print detailed version report and quit.")
	flagModules        = tflag.Switch("l", "list", "Print plugin information and quit.")
	flagConfigFile     = tflag.String("c", "config", "", "Use a given configuration file.")
	flagTestConfigFile = tflag.String("tc", "testconfig", "", "Test the given configuration file and exit.")
	flagLoglevel       = tflag.Int("ll", "loglevel", 1, "Set the loglevel [0-3] as in {0=Error, 1=+Warning, 2=+Info, 3=+Debug}.")
	flagNumCPU         = tflag.Int("n", "numcpu", 0, "Number of CPUs to use. Set 0 for all CPUs.")
	flagPidFile        = tflag.String("p", "pidfile", "", "Write the relayEntry id into a given file.")
	flagMetricsAddress = tflag.String("m", "metrics", "", "Address to use for metric queries. Disabled by default.")
	flagHealthCheck    = tflag.String("hc", "healthcheck", "", "Listening address ([IP]:PORT) to use for healthcheck HTTP endpoint. Disabled by default.")
	flagCPUProfile     = tflag.String("pc", "profilecpu", "", "Write CPU profiler results to a given file.")
	flagMemProfile     = tflag.String("pm", "profilemem", "", "Write heap profile results to a given file.")
	flagProfile        = tflag.Switch("ps", "profilespeed", "Write msg/sec measurements to log.")
	flagTrace          = tflag.String("tr", "trace", "", "Write trace results to a given file.")
)

func parseFlags() {
	tflag.Parse()
}

func printFlags() {
	helpMessageStr := fmt.Sprintf("Usage: gollum [OPTIONS]\n\nGollum - An n:m message multiplexer.\nVersion: %s\n\nOptions:", core.GetVersionString())
	tflag.PrintFlags(helpMessageStr)
}

func getLogrusLevel(intLevel int) logrus.Level {
	switch intLevel {
	case 0: return logrus.ErrorLevel
	case 1: return logrus.WarnLevel
	case 2: return logrus.InfoLevel
	case 3: return logrus.DebugLevel
	}
	return logrus.DebugLevel
}
<commit_msg>Revert auto-refactoring<commit_after>// Copyright 2015-2017 trivago GmbH
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"fmt"
	"github.com/trivago/gollum/core"
	"github.com/trivago/tgo/tflag"
	"github.com/sirupsen/logrus"
)

var (
	flagHelp           = tflag.Switch("h", "help", "Print this help message.")
	flagVersion        = tflag.Switch("v", "version", "Print version information and quit.")
	flagReport         = tflag.Switch("r", "report", "Print detailed version report and quit.")
	flagModules        = tflag.Switch("l", "list", "Print plugin information and quit.")
	flagConfigFile     = tflag.String("c", "config", "", "Use a given configuration file.")
	flagTestConfigFile = tflag.String("tc", "testconfig", "", "Test the given configuration file and exit.")
	flagLoglevel       = tflag.Int("ll", "loglevel", 1, "Set the loglevel [0-3] as in {0=Error, 1=+Warning, 2=+Info, 3=+Debug}.")
	flagNumCPU         = tflag.Int("n", "numcpu", 0, "Number of CPUs to use. Set 0 for all CPUs.")
	flagPidFile        = tflag.String("p", "pidfile", "", "Write the process id into a given file.")
	flagMetricsAddress = tflag.String("m", "metrics", "", "Address to use for metric queries. Disabled by default.")
	flagHealthCheck    = tflag.String("hc", "healthcheck", "", "Listening address ([IP]:PORT) to use for healthcheck HTTP endpoint. Disabled by default.")
	flagCPUProfile     = tflag.String("pc", "profilecpu", "", "Write CPU profiler results to a given file.")
	flagMemProfile     = tflag.String("pm", "profilemem", "", "Write heap profile results to a given file.")
	flagProfile        = tflag.Switch("ps", "profilespeed", "Write msg/sec measurements to log.")
	flagTrace          = tflag.String("tr", "trace", "", "Write trace results to a given file.")
)

func parseFlags() {
	tflag.Parse()
}

func printFlags() {
	helpMessageStr := fmt.Sprintf("Usage: gollum [OPTIONS]\n\nGollum - An n:m message multiplexer.\nVersion: %s\n\nOptions:", core.GetVersionString())
	tflag.PrintFlags(helpMessageStr)
}

func getLogrusLevel(intLevel int) logrus.Level {
	switch intLevel {
	case 0: return logrus.ErrorLevel
	case 1: return logrus.WarnLevel
	case 2: return logrus.InfoLevel
	case 3: return logrus.DebugLevel
	}
	return logrus.DebugLevel
}
<|endoftext|>


<commit_before>package media_library

import (
	"bytes"
	"database/sql/driver"
	"errors"
	"fmt"
	"image"
	"io"
	"mime/multipart"
	"os"
	"path"
	"path/filepath"
	"strings"

	"github.com/disintegration/imaging"
)

var ErrNotImplemented = errors.New("not implemented")

type Base struct {
	Url        string
	Valid      bool
	FileName   string
	FileHeader *multipart.FileHeader
	CropOption *CropOption
	Reader     io.Reader
}

func (b *Base) Scan(value interface{}) error {
	switch v := value.(type) {
	case []*multipart.FileHeader:
		if len(v) > 0 {
			file := v[0]
			b.FileHeader, b.FileName, b.Valid = file, file.Filename, true
		}
	case []uint8:
		b.Url, b.Valid = string(v), true
	case string:
		b.Url, b.Valid = v, true
	default:
		fmt.Errorf("unsupported driver -> Scan pair for MediaLibrary")
	}
	return nil
}

func (b Base) Value() (driver.Value, error) {
	if b.Valid {
		return b.FileName, nil
	}
	return nil, nil
}

func (b Base) URL(styles ...string) string {
	if len(styles) > 0 {
		ext := path.Ext(b.Url)
		return fmt.Sprintf("%v.%v%v", strings.TrimSuffix(b.Url, ext), styles[0], ext)
	}
	return b.Url
}

func (b Base) String() string {
	return b.URL()
}

func (b Base) GetFileName() string {
	return b.FileName
}

func (b Base) GetFileHeader() *multipart.FileHeader {
	return b.FileHeader
}

func (b Base) GetURLTemplate(option *Option) (path string) {
	if path = option.Get("url"); path == "" {
		path = "/system/{{class}}/{{primary_key}}/{{column}}/{{basename}}.{{nanotime}}.{{extension}}"
	}
	return
}

func (b *Base) SetCropOption(option *CropOption) {
	b.CropOption = option
}

func (b *Base) GetCropOption() *CropOption {
	return b.CropOption
}

func (b Base) Retrieve(url string) (*os.File, error) {
	return nil, ErrNotImplemented
}

func (b Base) Crop(ml MediaLibrary, option *Option) error {
	if file, err := ml.Retrieve(b.URL("original")); err == nil {
		if img, err := imaging.Decode(file); err == nil {
			if format, err := b.GetImageFormat(); err == nil {
				var buffer bytes.Buffer
				var cropOption = b.CropOption
				rect := image.Rect(cropOption.X, cropOption.Y, cropOption.X+cropOption.Width, cropOption.Y+cropOption.Height)
				imaging.Encode(&buffer, imaging.Crop(img, rect), *format)
				return ml.Store(b.URL(), option, &buffer)
			}
		} else {
			return err
		}
	}
	return nil
}

func (b Base) IsImage() bool {
	_, err := b.GetImageFormat()
	return err == nil
}

func (b Base) GetImageFormat() (*imaging.Format, error) {
	formats := map[string]imaging.Format{
		".jpg":  imaging.JPEG,
		".jpeg": imaging.JPEG,
		".png":  imaging.PNG,
		".tif":  imaging.TIFF,
		".tiff": imaging.TIFF,
		".bmp":  imaging.BMP,
		".gif":  imaging.GIF,
	}

	ext := strings.ToLower(filepath.Ext(b.Url))
	if f, ok := formats[ext]; ok {
		return &f, nil
	} else {
		return nil, imaging.ErrUnsupportedFormat
	}
}
<commit_msg>Don't download uncessary file<commit_after>package media_library

import (
	"bytes"
	"database/sql/driver"
	"errors"
	"fmt"
	"image"
	"io"
	"mime/multipart"
	"os"
	"path"
	"path/filepath"
	"strings"

	"github.com/disintegration/imaging"
)

var ErrNotImplemented = errors.New("not implemented")

type Base struct {
	Url        string
	Valid      bool
	FileName   string
	FileHeader *multipart.FileHeader
	CropOption *CropOption
	Reader     io.Reader
}

func (b *Base) Scan(value interface{}) error {
	switch v := value.(type) {
	case []*multipart.FileHeader:
		if len(v) > 0 {
			file := v[0]
			b.FileHeader, b.FileName, b.Valid = file, file.Filename, true
		}
	case []uint8:
		b.Url, b.Valid = string(v), true
	case string:
		b.Url, b.Valid = v, true
	default:
		fmt.Errorf("unsupported driver -> Scan pair for MediaLibrary")
	}
	return nil
}

func (b Base) Value() (driver.Value, error) {
	if b.Valid {
		return b.FileName, nil
	}
	return nil, nil
}

func (b Base) URL(styles ...string) string {
	if len(styles) > 0 {
		ext := path.Ext(b.Url)
		return fmt.Sprintf("%v.%v%v", strings.TrimSuffix(b.Url, ext), styles[0], ext)
	}
	return b.Url
}

func (b Base) String() string {
	return b.URL()
}

func (b Base) GetFileName() string {
	return b.FileName
}

func (b Base) GetFileHeader() *multipart.FileHeader {
	return b.FileHeader
}

func (b Base) GetURLTemplate(option *Option) (path string) {
	if path = option.Get("url"); path == "" {
		path = "/system/{{class}}/{{primary_key}}/{{column}}/{{basename}}.{{nanotime}}.{{extension}}"
	}
	return
}

func (b *Base) SetCropOption(option *CropOption) {
	b.CropOption = option
}

func (b *Base) GetCropOption() *CropOption {
	return b.CropOption
}

func (b Base) Retrieve(url string) (*os.File, error) {
	return nil, ErrNotImplemented
}

func (b Base) Crop(ml MediaLibrary, option *Option) error {
	var reader io.Reader
	var hasReader bool

	if ml.GetFileHeader() != nil {
		if file, err := ml.GetFileHeader().Open(); err == nil {
			reader = file
			hasReader = true
		}
	} else if file, err := ml.Retrieve(b.URL("original")); err == nil {
		reader = file
		hasReader = true
	}

	if hasReader {
		if img, err := imaging.Decode(reader); err == nil {
			if format, err := b.GetImageFormat(); err == nil {
				var buffer bytes.Buffer
				var cropOption = b.CropOption
				rect := image.Rect(cropOption.X, cropOption.Y, cropOption.X+cropOption.Width, cropOption.Y+cropOption.Height)
				imaging.Encode(&buffer, imaging.Crop(img, rect), *format)
				return ml.Store(b.URL(), option, &buffer)
			}
		} else {
			return err
		}
	}
	return nil
}

func (b Base) IsImage() bool {
	_, err := b.GetImageFormat()
	return err == nil
}

func (b Base) GetImageFormat() (*imaging.Format, error) {
	formats := map[string]imaging.Format{
		".jpg":  imaging.JPEG,
		".jpeg": imaging.JPEG,
		".png":  imaging.PNG,
		".tif":  imaging.TIFF,
		".tiff": imaging.TIFF,
		".bmp":  imaging.BMP,
		".gif":  imaging.GIF,
	}

	ext := strings.ToLower(filepath.Ext(b.Url))
	if f, ok := formats[ext]; ok {
		return &f, nil
	} else {
		return nil, imaging.ErrUnsupportedFormat
	}
}
<|endoftext|>


<commit_before>package gogame

/*
#cgo pkg-config: sdl2
#include "SDL.h"

int getEventType(SDL_Event *e) {
    return e->type;
}

int getKeyCode(SDL_Event *e) {
    return e->key.keysym.sym;
}

int isKeyRepeat(SDL_Event *e) {
    return e->key.repeat;
}

int isKeyPressed(int kcode) {
    const Uint8 *state = SDL_GetKeyboardState(NULL);
    int sc = SDL_GetScancodeFromKey(kcode);
    return state[sc];
}

*/
import "C"

const (
	K_LEFT   = C.SDLK_LEFT
	K_RIGHT  = C.SDLK_RIGHT
	K_SPACE  = C.SDLK_SPACE
	K_ESC    = C.SDLK_ESCAPE
	K_RETURN = C.SDLK_RETURN
	K_P      = C.SDLK_p
	K_I      = C.SDLK_i
)

type Event interface{}

type EventQuit interface{}

type EventUnknown interface{}

type EventKey struct {
	Code int
	Down bool
}

// Poll for pending envents. Return nil if there is no event available
func PollEvent() Event {
	var cev C.SDL_Event

	for {
		if 0 == C.SDL_PollEvent(&cev) {
			return nil
		}

		switch C.getEventType(&cev) {

		case C.SDL_QUIT:
			return new(EventQuit)

		case C.SDL_KEYDOWN:
			// Ignore repeat key events
			if C.isKeyRepeat(&cev) != 0 {
				break
			}
			kde := new(EventKey)
			kde.Code = int(C.getKeyCode(&cev))
			kde.Down = true
			return kde

		case C.SDL_KEYUP:
			kde := new(EventKey)
			kde.Code = int(C.getKeyCode(&cev))
			kde.Down = false
			return kde

		default:
			return new(EventUnknown)
		}
	}

}

// Process events. Returns true if EventQuit has appeared
func SlurpEvents() (quit bool) {
	quit = false
	for {
		ev := PollEvent()
		if ev == nil {
			return
		}
		switch ev.(type) {
		case *EventQuit:
			quit = true
		}
	}
}

// Returns true if key is pressed, false otherwise
func IsKeyPressed(kcode int) bool {
	return C.isKeyPressed(C.int(kcode)) == 1
}
<commit_msg>Added window resize event<commit_after>package gogame

/*
#cgo pkg-config: sdl2
#include "SDL.h"

int getEventType(SDL_Event *e) {
    return e->type;
}

int getKeyCode(SDL_Event *e) {
    return e->key.keysym.sym;
}

int isKeyRepeat(SDL_Event *e) {
    return e->key.repeat;
}

int isKeyPressed(int kcode) {
    const Uint8 * state = SDL_GetKeyboardState(NULL);
    int sc = SDL_GetScancodeFromKey(kcode);
    return state[sc];
}

int getWinData(SDL_Event *e, int *w, int *h) {
    if (e->window.event != SDL_WINDOWEVENT_RESIZED) {
        return 0;
    }
    *w = e->window.data1;
    *h = e->window.data2;
    return 1;
}

*/
import "C"

const (
	K_LEFT   = C.SDLK_LEFT
	K_RIGHT  = C.SDLK_RIGHT
	K_SPACE  = C.SDLK_SPACE
	K_ESC    = C.SDLK_ESCAPE
	K_RETURN = C.SDLK_RETURN
	K_P      = C.SDLK_p
	K_I      = C.SDLK_i
	K_M      = C.SDLK_m
	K_Q      = C.SDLK_q
)

type Event interface{}

type EventQuit interface{}

type EventUnknown interface{}

type EventKey struct {
	Code int
	Down bool
}

type EventResize struct {
	W, H int
}

// Poll for pending envents. Return nil if there is no event available
func PollEvent() Event {
	var cev C.SDL_Event

	for {
		if 0 == C.SDL_PollEvent(&cev) {
			return nil
		}

		switch C.getEventType(&cev) {

		case C.SDL_QUIT:
			return new(EventQuit)

		case C.SDL_KEYDOWN:
			// Ignore repeat key events
			if C.isKeyRepeat(&cev) != 0 {
				break
			}
			kde := new(EventKey)
			kde.Code = int(C.getKeyCode(&cev))
			kde.Down = true
			return kde

		case C.SDL_KEYUP:
			kde := new(EventKey)
			kde.Code = int(C.getKeyCode(&cev))
			kde.Down = false
			return kde

		case C.SDL_WINDOWEVENT:
			var w, h C.int
			if 1 == C.getWinData(&cev, &w, &h) {
				wr := new(EventResize)
				wr.W = int(w)
				wr.H = int(h)
				return wr
			}

		default:
			return new(EventUnknown)
		}
	}

}

// Process events. Returns true if EventQuit has appeared
func SlurpEvents() (quit bool) {
	quit = false
	for {
		ev := PollEvent()
		if ev == nil {
			return
		}
		switch ev.(type) {
		case *EventQuit:
			quit = true
		}
	}
}

// Returns true if key is pressed, false otherwise
func IsKeyPressed(kcode int) bool {
	return C.isKeyPressed(C.int(kcode)) == 1
}
<|endoftext|>


<commit_before>package hec

import (
	"fmt"
	"time"
)

type Event struct {
	Host       *string     `json:"host,omitempty"`
	Index      *string     `json:"index,omitempty"`
	Source     *string     `json:"source,omitempty"`
	SourceType *string     `json:"sourcetype,omitempty"`
	Time       *string     `json:"time,omitempty"`
	Event      interface{} `json:"event"`
}

func NewEvent(data interface{}) *Event {
	// Empty event is not allowed, but let HEC complain the error
	switch data.(type) {
	case *string:
		return &Event{Event: *data.(*string)}
	case string:
		return &Event{Event: data.(string)}
	default:
		return &Event{Event: data}
	}
}

func (e *Event) SetHost(host string) {
	e.Host = &host
}

func (e *Event) SetIndex(index string) {
	e.Index = &index
}

func (e *Event) SetSourceType(sourcetype string) {
	e.SourceType = &sourcetype
}

func (e *Event) SetSource(source string) {
	e.Source = &source
}

func (e *Event) SetTime(time time.Time) {
	e.Time = String(epochTime(&time))
}

func (e *Event) empty() bool {
	switch e.Event.(type) {
	case *string:
		return e.Event.(*string) == nil || *e.Event.(*string) == ""
	case string:
		return e.Event.(string) == ""
	default:
		return e.Event == nil
	}
}

func epochTime(t *time.Time) string {
	millis := t.UnixNano() / 1000000
	return fmt.Sprintf("%d.%03d", millis/1000, millis%1000)
}

func String(str string) *string {
	return &str
}
<commit_msg>Add support for Splunk indexed fields<commit_after>package hec

import (
	"fmt"
	"time"
)

type Event struct {
	Host       *string                `json:"host,omitempty"`
	Index      *string                `json:"index,omitempty"`
	Source     *string                `json:"source,omitempty"`
	SourceType *string                `json:"sourcetype,omitempty"`
	Time       *string                `json:"time,omitempty"`
	Fields     map[string]interface{} `json:"fields,omitempty"`
	Event      interface{}            `json:"event"`
}

func NewEvent(data interface{}) *Event {
	// Empty event is not allowed, but let HEC complain the error
	switch data.(type) {
	case *string:
		return &Event{Event: *data.(*string)}
	case string:
		return &Event{Event: data.(string)}
	default:
		return &Event{Event: data}
	}
}

func (e *Event) SetHost(host string) {
	e.Host = &host
}

func (e *Event) SetIndex(index string) {
	e.Index = &index
}

func (e *Event) SetSourceType(sourcetype string) {
	e.SourceType = &sourcetype
}

func (e *Event) SetSource(source string) {
	e.Source = &source
}

func (e *Event) SetTime(time time.Time) {
	e.Time = String(epochTime(&time))
}

func (e *Event) SetFields(fields map[string]interface{}) {
	e.Fields = fields
}

func (e *Event) SetField(fieldName string, val interface{}) {
	if e.Fields == nil {
		e.Fields = make(map[string]interface{})
	}

	e.Fields[fieldName] = val
}

func (e *Event) empty() bool {
	switch e.Event.(type) {
	case *string:
		return e.Event.(*string) == nil || *e.Event.(*string) == ""
	case string:
		return e.Event.(string) == ""
	default:
		return e.Event == nil
	}
}

func epochTime(t *time.Time) string {
	millis := t.UnixNano() / 1000000
	return fmt.Sprintf("%d.%03d", millis/1000, millis%1000)
}

func String(str string) *string {
	return &str
}
<|endoftext|>