<commit_before>// Bindings for glib
package glib

/*
#include <stdlib.h>
#include <glib-object.h>

#cgo CFLAGS: -Wno-deprecated-declarations
#cgo pkg-config: glib-2.0 gobject-2.0 gthread-2.0
*/
import "C"

import (
	"reflect"
	"unsafe"
)

type TypeGetter interface {
	Type() Type
}

type PointerSetter interface {
	SetPtr(p Pointer)
}

// A numerical value which represents the unique identifier of a registered type
type Type C.GType

const (
	TYPE_INVALID   = Type(C.G_TYPE_INVALID)
	TYPE_NONE      = Type(C.G_TYPE_NONE)
	TYPE_INTERFACE = Type(C.G_TYPE_INTERFACE)
	TYPE_CHAR      = Type(C.G_TYPE_CHAR)
	TYPE_UCHAR     = Type(C.G_TYPE_UCHAR)
	TYPE_BOOLEAN   = Type(C.G_TYPE_BOOLEAN)
	TYPE_INT       = Type(C.G_TYPE_INT)
	TYPE_GO_INT32  = TYPE_INT
	TYPE_UINT      = Type(C.G_TYPE_UINT)
	TYPE_GO_UINT32 = TYPE_UINT
	TYPE_LONG      = Type(C.G_TYPE_LONG)
	TYPE_GO_INT    = TYPE_LONG
	TYPE_ULONG     = Type(C.G_TYPE_ULONG)
	TYPE_GO_UINT   = TYPE_ULONG
	TYPE_INT64     = Type(C.G_TYPE_INT64)
	TYPE_UINT64    = Type(C.G_TYPE_UINT64)
	TYPE_ENUM      = Type(C.G_TYPE_ENUM)
	TYPE_FLAGS     = Type(C.G_TYPE_FLAGS)
	TYPE_FLOAT     = Type(C.G_TYPE_FLOAT)
	TYPE_DOUBLE    = Type(C.G_TYPE_DOUBLE)
	TYPE_STRING    = Type(C.G_TYPE_STRING)
	TYPE_POINTER   = Type(C.G_TYPE_POINTER)
	TYPE_BOXED     = Type(C.G_TYPE_BOXED)
	TYPE_PARAM     = Type(C.G_TYPE_PARAM)
	TYPE_OBJECT    = Type(C.G_TYPE_OBJECT)
	TYPE_VARIANT   = Type(C.G_TYPE_VARIANT)
)

var TYPE_GTYPE Type

func (t Type) g() C.GType {
	return C.GType(t)
}

func (t Type) String() string {
	return C.GoString((*C.char)(C.g_type_name(t.g())))
}

func (t Type) QName() Quark {
	return Quark(C.g_type_qname(t.g()))
}

func (t Type) Type() Type {
	return TYPE_GTYPE
}

func (t Type) Value() *Value {
	v := NewValue(t.Type())
	C.g_value_set_gtype(v.g(), t.g())
	return v
}

func (t Type) Parent() Type {
	return Type(C.g_type_parent(t.g()))
}

func (t Type) Depth() int {
	return int(C.g_type_depth(t.g()))
}

// Returns the type that is derived directly from root type which is also
// a base class of t
func (t Type) NextBase(root Type) Type {
	return Type(C.g_type_next_base(t.g(), root.g()))
}

// If t type is a derivable type, check whether type is a descendant of
// it type. If t type is an glib interface, check whether type conforms
// to it.
func (t Type) IsA(it Type) bool {
	return C.g_type_is_a(t.g(), it.g()) != 0
}

var type_getter = reflect.TypeOf((*TypeGetter)(nil)).Elem()
var object_caster = reflect.TypeOf((*ObjectCaster)(nil)).Elem()

func (t Type) Match(rt reflect.Type) bool {
	if rt.Implements(object_caster) {
		return t.IsA(TYPE_OBJECT)
	}
	if rt.Implements(type_getter) {
		if rt.Kind() == reflect.Ptr {
			rt = rt.Elem()
		}
		r := reflect.New(rt).Interface().(TypeGetter).Type()
		return t.QName() == r.QName()
	}
	switch rt.Kind() {
	case reflect.Invalid:
		return t == TYPE_INVALID

	case reflect.String:
		return t == TYPE_STRING

	case reflect.Int:
		return t == TYPE_GO_INT

	case reflect.Uint:
		return t == TYPE_GO_UINT

	case reflect.Int8:
		return t == TYPE_CHAR

	case reflect.Uint8:
		return t == TYPE_UCHAR

	case reflect.Int32:
		return t == TYPE_GO_INT32

	case reflect.Uint32:
		return t == TYPE_GO_UINT32

	case reflect.Int64:
		return t == TYPE_INT64

	case reflect.Uint64:
		return t == TYPE_UINT64

	case reflect.Bool:
		return t == TYPE_BOOLEAN

	case reflect.Float32:
		return t == TYPE_FLOAT

	case reflect.Float64:
		return t == TYPE_DOUBLE

	case reflect.Ptr:
		return t == TYPE_POINTER
	}
	return false
}

func (t Type) Compatible(dst Type) bool {
	return C.g_value_type_compatible(t.g(), dst.g()) != C.gboolean(0)
}

func (t Type) Transformable(dst Type) bool {
	return C.g_value_type_transformable(t.g(), dst.g()) != C.gboolean(0)
}

// TypeOf returns the Type of the value in the i}.
func TypeOf(i interface{}) Type {
	// Types ov values that implements TypeGetter
	if o, ok := i.(TypeGetter); ok {
		return o.Type()
	}
	// Other types
	switch reflect.TypeOf(i).Kind() {
	case reflect.Invalid:
		return TYPE_INVALID

	case reflect.Bool:
		return TYPE_BOOLEAN

	case reflect.Int:
		return TYPE_GO_INT

	case reflect.Int8:
		return TYPE_CHAR

	case reflect.Int32:
		return TYPE_GO_INT32

	case reflect.Int64:
		return TYPE_INT64

	case reflect.Uint:
		return TYPE_GO_UINT

	case reflect.Uint8:
		return TYPE_UCHAR

	case reflect.Uint32:
		return TYPE_GO_UINT32

	case reflect.Uint64:
		return TYPE_UINT64

	case reflect.Float32:
		return TYPE_FLOAT

	case reflect.Float64:
		return TYPE_DOUBLE

	case reflect.Ptr:
		return TYPE_POINTER

	case reflect.String:
		return TYPE_STRING
	}
	panic("Can't map Go type to Glib type")
}

func TypeFromName(name string) Type {
	tn := C.CString(name)
	defer C.free(unsafe.Pointer(tn))
	return Type(C.g_type_from_name((*C.gchar)(tn)))
}

func init() {
	C.g_type_init()
	TYPE_GTYPE = Type(C.g_gtype_get_type())
}

type Pointer C.gpointer

func gBoolean(b bool) C.gboolean {
	if b {
		return C.TRUE
	}
	return C.FALSE
}

type Quark C.GQuark

func (q Quark) GQuark() C.GQuark {
	return C.GQuark(q)
}

func (q Quark) String() string {
	return C.GoString((*C.char)(C.g_quark_to_string(q.GQuark())))
}

func QuarkFromString(s string) Quark {
	return Quark(C.g_quark_from_static_string((*C.gchar)(C.CString(s))))
}

type Error C.GError

func (e *Error) Error() string {
	return C.GoString((*C.char)(e.message))
}

func (e *Error) GetDomain() Quark {
	return Quark(e.domain)
}

func (e *Error) GetCode() int {
	return int(e.code)
}
<commit_msg>type: add *Error.Free<commit_after>// Bindings for glib
package glib

/*
#include <stdlib.h>
#include <glib-object.h>

#cgo CFLAGS: -Wno-deprecated-declarations
#cgo pkg-config: glib-2.0 gobject-2.0 gthread-2.0
*/
import "C"

import (
	"reflect"
	"unsafe"
)

type TypeGetter interface {
	Type() Type
}

type PointerSetter interface {
	SetPtr(p Pointer)
}

// A numerical value which represents the unique identifier of a registered type
type Type C.GType

const (
	TYPE_INVALID   = Type(C.G_TYPE_INVALID)
	TYPE_NONE      = Type(C.G_TYPE_NONE)
	TYPE_INTERFACE = Type(C.G_TYPE_INTERFACE)
	TYPE_CHAR      = Type(C.G_TYPE_CHAR)
	TYPE_UCHAR     = Type(C.G_TYPE_UCHAR)
	TYPE_BOOLEAN   = Type(C.G_TYPE_BOOLEAN)
	TYPE_INT       = Type(C.G_TYPE_INT)
	TYPE_GO_INT32  = TYPE_INT
	TYPE_UINT      = Type(C.G_TYPE_UINT)
	TYPE_GO_UINT32 = TYPE_UINT
	TYPE_LONG      = Type(C.G_TYPE_LONG)
	TYPE_GO_INT    = TYPE_LONG
	TYPE_ULONG     = Type(C.G_TYPE_ULONG)
	TYPE_GO_UINT   = TYPE_ULONG
	TYPE_INT64     = Type(C.G_TYPE_INT64)
	TYPE_UINT64    = Type(C.G_TYPE_UINT64)
	TYPE_ENUM      = Type(C.G_TYPE_ENUM)
	TYPE_FLAGS     = Type(C.G_TYPE_FLAGS)
	TYPE_FLOAT     = Type(C.G_TYPE_FLOAT)
	TYPE_DOUBLE    = Type(C.G_TYPE_DOUBLE)
	TYPE_STRING    = Type(C.G_TYPE_STRING)
	TYPE_POINTER   = Type(C.G_TYPE_POINTER)
	TYPE_BOXED     = Type(C.G_TYPE_BOXED)
	TYPE_PARAM     = Type(C.G_TYPE_PARAM)
	TYPE_OBJECT    = Type(C.G_TYPE_OBJECT)
	TYPE_VARIANT   = Type(C.G_TYPE_VARIANT)
)

var TYPE_GTYPE Type

func (t Type) g() C.GType {
	return C.GType(t)
}

func (t Type) String() string {
	return C.GoString((*C.char)(C.g_type_name(t.g())))
}

func (t Type) QName() Quark {
	return Quark(C.g_type_qname(t.g()))
}

func (t Type) Type() Type {
	return TYPE_GTYPE
}

func (t Type) Value() *Value {
	v := NewValue(t.Type())
	C.g_value_set_gtype(v.g(), t.g())
	return v
}

func (t Type) Parent() Type {
	return Type(C.g_type_parent(t.g()))
}

func (t Type) Depth() int {
	return int(C.g_type_depth(t.g()))
}

// Returns the type that is derived directly from root type which is also
// a base class of t
func (t Type) NextBase(root Type) Type {
	return Type(C.g_type_next_base(t.g(), root.g()))
}

// If t type is a derivable type, check whether type is a descendant of
// it type. If t type is an glib interface, check whether type conforms
// to it.
func (t Type) IsA(it Type) bool {
	return C.g_type_is_a(t.g(), it.g()) != 0
}

var type_getter = reflect.TypeOf((*TypeGetter)(nil)).Elem()
var object_caster = reflect.TypeOf((*ObjectCaster)(nil)).Elem()

func (t Type) Match(rt reflect.Type) bool {
	if rt.Implements(object_caster) {
		return t.IsA(TYPE_OBJECT)
	}
	if rt.Implements(type_getter) {
		if rt.Kind() == reflect.Ptr {
			rt = rt.Elem()
		}
		r := reflect.New(rt).Interface().(TypeGetter).Type()
		return t.QName() == r.QName()
	}
	switch rt.Kind() {
	case reflect.Invalid:
		return t == TYPE_INVALID

	case reflect.String:
		return t == TYPE_STRING

	case reflect.Int:
		return t == TYPE_GO_INT

	case reflect.Uint:
		return t == TYPE_GO_UINT

	case reflect.Int8:
		return t == TYPE_CHAR

	case reflect.Uint8:
		return t == TYPE_UCHAR

	case reflect.Int32:
		return t == TYPE_GO_INT32

	case reflect.Uint32:
		return t == TYPE_GO_UINT32

	case reflect.Int64:
		return t == TYPE_INT64

	case reflect.Uint64:
		return t == TYPE_UINT64

	case reflect.Bool:
		return t == TYPE_BOOLEAN

	case reflect.Float32:
		return t == TYPE_FLOAT

	case reflect.Float64:
		return t == TYPE_DOUBLE

	case reflect.Ptr:
		return t == TYPE_POINTER
	}
	return false
}

func (t Type) Compatible(dst Type) bool {
	return C.g_value_type_compatible(t.g(), dst.g()) != C.gboolean(0)
}

func (t Type) Transformable(dst Type) bool {
	return C.g_value_type_transformable(t.g(), dst.g()) != C.gboolean(0)
}

// TypeOf returns the Type of the value in the i}.
func TypeOf(i interface{}) Type {
	// Types ov values that implements TypeGetter
	if o, ok := i.(TypeGetter); ok {
		return o.Type()
	}
	// Other types
	switch reflect.TypeOf(i).Kind() {
	case reflect.Invalid:
		return TYPE_INVALID

	case reflect.Bool:
		return TYPE_BOOLEAN

	case reflect.Int:
		return TYPE_GO_INT

	case reflect.Int8:
		return TYPE_CHAR

	case reflect.Int32:
		return TYPE_GO_INT32

	case reflect.Int64:
		return TYPE_INT64

	case reflect.Uint:
		return TYPE_GO_UINT

	case reflect.Uint8:
		return TYPE_UCHAR

	case reflect.Uint32:
		return TYPE_GO_UINT32

	case reflect.Uint64:
		return TYPE_UINT64

	case reflect.Float32:
		return TYPE_FLOAT

	case reflect.Float64:
		return TYPE_DOUBLE

	case reflect.Ptr:
		return TYPE_POINTER

	case reflect.String:
		return TYPE_STRING
	}
	panic("Can't map Go type to Glib type")
}

func TypeFromName(name string) Type {
	tn := C.CString(name)
	defer C.free(unsafe.Pointer(tn))
	return Type(C.g_type_from_name((*C.gchar)(tn)))
}

func init() {
	C.g_type_init()
	TYPE_GTYPE = Type(C.g_gtype_get_type())
}

type Pointer C.gpointer

func gBoolean(b bool) C.gboolean {
	if b {
		return C.TRUE
	}
	return C.FALSE
}

type Quark C.GQuark

func (q Quark) GQuark() C.GQuark {
	return C.GQuark(q)
}

func (q Quark) String() string {
	return C.GoString((*C.char)(C.g_quark_to_string(q.GQuark())))
}

func QuarkFromString(s string) Quark {
	return Quark(C.g_quark_from_static_string((*C.gchar)(C.CString(s))))
}

type Error C.GError

func (e *Error) Error() string {
	return C.GoString((*C.char)(e.message))
}

func (e *Error) GetDomain() Quark {
	return Quark(e.domain)
}

func (e *Error) GetCode() int {
	return int(e.code)
}

func (e *Error) Free() {
	C.g_error_free(e)
}
<|endoftext|>


<commit_before>package cryptopals

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"crypto/subtle"

	"github.com/d1str0/pkcs7"
)

func pkcs7Pad(message []byte) []byte {
	message = message[:len(message):len(message)]
	padded, _ := pkcs7.Pad(message, aes.BlockSize)

	return padded
}

// AesCbcEncrypt encrypts the message using given key and random IV.
// IV is prepended to the ciphertext.
func AesCbcEncrypt(message, key []byte) []byte {
	padded := pkcs7Pad(message)
	ciphertext := make([]byte, aes.BlockSize+len(padded))

	iv := ciphertext[0:aes.BlockSize]
	rand.Read(iv)

	block, _ := aes.NewCipher(key)
	mode := cipher.NewCBCEncrypter(block, iv)
	mode.CryptBlocks(ciphertext[aes.BlockSize:], padded)

	return ciphertext
}

// AesCbcDecrypt decrypts the ciphertext using given key.
// It assumes that IV is prepended to the ciphertext.
func AesCbcDecrypt(ciphertext, key []byte) []byte {
	iv := ciphertext[0:aes.BlockSize]
	message := make([]byte, len(ciphertext)-len(iv))

	block, _ := aes.NewCipher(key)
	mode := cipher.NewCBCDecrypter(block, iv)
	mode.CryptBlocks(message, ciphertext[aes.BlockSize:])
	unpadded, _ := pkcs7.Unpad(message)

	return unpadded
}

// CbcMacSign calculates CBC-MAC for a given message.
// IV and MAC are appended to the plaintext.
func CbcMacSign(message, key []byte, iv []byte) []byte {
	message = message[:len(message):len(message)]
	padded, _ := pkcs7.Pad(message, aes.BlockSize)
	ciphertext := make([]byte, len(padded))

	block, _ := aes.NewCipher(key)
	mode := cipher.NewCBCEncrypter(block, iv)
	mode.CryptBlocks(ciphertext[:], padded)

	size := len(message)
	msg := make([]byte, size+2*aes.BlockSize)
	mac := ciphertext[len(ciphertext)-aes.BlockSize:]

	copy(msg[:], message)
	copy(msg[size:], iv)
	copy(msg[size+aes.BlockSize:], mac)

	return msg
}

// CbcMacVerify verifies CBC-MAC for a given message.
// It assumes that IV and MAC are appended to the plaintext.
func CbcMacVerify(msg, key []byte) bool {
	size := len(msg) - 2*aes.BlockSize

	if size < 0 {
		return false
	}

	message := msg[0:size]
	iv := msg[size : size+aes.BlockSize]
	sig := CbcMacSign(message, key, iv)

	return subtle.ConstantTimeCompare(sig, msg) == 1
}

// CbcMacSignFixedIv calculates CBC-MAC for a given message using zero IV.
// MAC is appended to the plaintext.
func CbcMacSignFixedIv(message, key []byte) []byte {
	padded := pkcs7Pad(message)
	ciphertext := make([]byte, len(padded))

	block, _ := aes.NewCipher(key)
	iv := make([]byte, aes.BlockSize)

	mode := cipher.NewCBCEncrypter(block, iv)
	mode.CryptBlocks(ciphertext[:], padded)
	mac := ciphertext[len(ciphertext)-aes.BlockSize:]

	return append(message[:len(message):len(message)], mac...)
}

// CbcMacVerifyFixedIv verifies CBC-MAC for a given message.
// It assumes that IV is zero and MAC is appended to the plaintext.
func CbcMacVerifyFixedIv(msg, key []byte) bool {
	size := len(msg) - aes.BlockSize

	if size < 0 {
		return false
	}

	message := msg[0:size]
	sig := CbcMacSignFixedIv(message, key)

	return subtle.ConstantTimeCompare(sig, msg) == 1
}
<commit_msg>Add CbcMacHash function<commit_after>package cryptopals

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"crypto/subtle"

	"github.com/d1str0/pkcs7"
)

func pkcs7Pad(message []byte) []byte {
	message = message[:len(message):len(message)]
	padded, _ := pkcs7.Pad(message, aes.BlockSize)

	return padded
}

// AesCbcEncrypt encrypts the message using given key and random IV.
// IV is prepended to the ciphertext.
func AesCbcEncrypt(message, key []byte) []byte {
	padded := pkcs7Pad(message)
	ciphertext := make([]byte, aes.BlockSize+len(padded))

	iv := ciphertext[0:aes.BlockSize]
	rand.Read(iv)

	block, _ := aes.NewCipher(key)
	mode := cipher.NewCBCEncrypter(block, iv)
	mode.CryptBlocks(ciphertext[aes.BlockSize:], padded)

	return ciphertext
}

// AesCbcDecrypt decrypts the ciphertext using given key.
// It assumes that IV is prepended to the ciphertext.
func AesCbcDecrypt(ciphertext, key []byte) []byte {
	iv := ciphertext[0:aes.BlockSize]
	message := make([]byte, len(ciphertext)-len(iv))

	block, _ := aes.NewCipher(key)
	mode := cipher.NewCBCDecrypter(block, iv)
	mode.CryptBlocks(message, ciphertext[aes.BlockSize:])
	unpadded, _ := pkcs7.Unpad(message)

	return unpadded
}

// CbcMacHash calculates CBC-MAC hash for a given message using zero IV.
func CbcMacHash(message, key []byte) []byte {
	padded := pkcs7Pad(message)
	ciphertext := make([]byte, len(padded))

	block, _ := aes.NewCipher(key)
	iv := make([]byte, aes.BlockSize)

	mode := cipher.NewCBCEncrypter(block, iv)
	mode.CryptBlocks(ciphertext[:], padded)

	return ciphertext[len(ciphertext)-aes.BlockSize:]
}

// CbcMacSign calculates CBC-MAC for a given message.
// IV and MAC are appended to the plaintext.
func CbcMacSign(message, key []byte, iv []byte) []byte {
	message = message[:len(message):len(message)]
	padded, _ := pkcs7.Pad(message, aes.BlockSize)
	ciphertext := make([]byte, len(padded))

	block, _ := aes.NewCipher(key)
	mode := cipher.NewCBCEncrypter(block, iv)
	mode.CryptBlocks(ciphertext[:], padded)

	size := len(message)
	msg := make([]byte, size+2*aes.BlockSize)
	mac := ciphertext[len(ciphertext)-aes.BlockSize:]

	copy(msg[:], message)
	copy(msg[size:], iv)
	copy(msg[size+aes.BlockSize:], mac)

	return msg
}

// CbcMacVerify verifies CBC-MAC for a given message.
// It assumes that IV and MAC are appended to the plaintext.
func CbcMacVerify(msg, key []byte) bool {
	size := len(msg) - 2*aes.BlockSize

	if size < 0 {
		return false
	}

	message := msg[0:size]
	iv := msg[size : size+aes.BlockSize]
	sig := CbcMacSign(message, key, iv)

	return subtle.ConstantTimeCompare(sig, msg) == 1
}

// CbcMacSignFixedIv calculates CBC-MAC for a given message using zero IV.
// MAC is appended to the plaintext.
func CbcMacSignFixedIv(message, key []byte) []byte {
	return append(message[:len(message):len(message)], CbcMacHash(message, key)...)
}

// CbcMacVerifyFixedIv verifies CBC-MAC for a given message.
// It assumes that IV is zero and MAC is appended to the plaintext.
func CbcMacVerifyFixedIv(msg, key []byte) bool {
	size := len(msg) - aes.BlockSize

	if size < 0 {
		return false
	}

	message := msg[0:size]
	sig := CbcMacSignFixedIv(message, key)

	return subtle.ConstantTimeCompare(sig, msg) == 1
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net"
	"strings"
)

// Returns client authentication token from header or url params
func getClientToken(c *gin.Context) string {
	// Try fetching auth token from headers first
	token := c.Req.Header.Get("Token")

	// Try to fetch from url param if blank
	if token == "" {
		if len(c.Req.URL.Query()["token"]) > 0 {
			token = c.Req.URL.Query()["token"][0]
		}
	}

	return token
}

func RequireAuthToken() gin.HandlerFunc {
	return func(c *gin.Context) {
		token := getClientToken(c)

		if token != options.Token {
			c.Abort(401)
		}
	}
}

func renderAvailableServices(c *gin.Context) {
	names := []string{}

	for _, svc := range services {
		names = append(names, svc.Name)
	}

	c.String(200, strings.Join(names, "\n")+"\n")
}

func renderServiceEnvironments(c *gin.Context) {
	serviceName := c.Params.ByName("service")

	service, err := getService(serviceName)
	if err != nil {
		c.String(400, err.Error()+"\n")
		return
	}

	names := strings.Join(service.EnvironmentNames(), "\n") + "\n"
	c.String(200, names)
}

func renderServiceEnvironment(c *gin.Context) {
	serviceName := c.Params.ByName("service")
	envName := c.Params.ByName("env")

	environment, err := getEnvironment(serviceName, envName)

	// Respond with 400 if service does not exist
	// Todo: maybe respond with 404
	if err != nil {
		c.String(400, err.Error()+"\n")
		return
	}

	// Get remote IP address
	host, _, err := net.SplitHostPort(c.Req.RemoteAddr)

	if err != nil {
		c.String(400, err.Error()+"\n")
		return
	}

	// Check if environment has allowed hosts. Localhost is allowed.
	if host != "::1" && len(environment.Hosts) > 0 {
		// Reject requests from non-whitelisted hosts
		if environment.HostEnabled(host) == false {
			c.String(401, "Restricted\n")
			return
		}
	}

	// Check if environment has access token
	// Environment tokens DO NOT work if global access token is set
	// Global token is set with -t flag or via TOKEN env variable
	if !options.Auth && environment.Token != "" {
		token := getClientToken(c)

		if token != environment.Token {
			c.Abort(401)
			return
		}
	}

	c.String(200, environment.ToString()+"\n")
}

func startServer() {
	api := gin.Default()

	if options.Auth {
		fmt.Println("authentication enabled")
		api.Use(RequireAuthToken())
	} else {
		fmt.Println("authentication disabled")
	}

	api.GET("/", renderAvailableServices)
	api.GET("/:service", renderServiceEnvironments)
	api.GET("/:service/:env", renderServiceEnvironment)

	host := fmt.Sprintf("%s:%d", options.Host, options.Port)

	fmt.Println("starting server on", host)
	api.Run(host)
}
<commit_msg>Refactor token authentication<commit_after>package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net"
	"strings"
)

// Returns client authentication token from header or url params
func getClientToken(c *gin.Context) string {
	// Try fetching auth token from headers first
	token := c.Req.Header.Get("Token")

	// Try to fetch from url param if blank
	if token == "" {
		if len(c.Req.URL.Query()["token"]) > 0 {
			token = c.Req.URL.Query()["token"][0]
		}
	}

	return token
}

// Returns a list of all available services
func renderAvailableServices(c *gin.Context) {
	// Check if authentication is enabled
	if options.Auth {
		token := getClientToken(c)

		if token != options.Token {
			c.Abort(401)
			return
		}
	}

	names := []string{}
	for _, svc := range services {
		names = append(names, svc.Name)
	}

	c.String(200, strings.Join(names, "\n")+"\n")
}

// Returns a list of all service environments
func renderServiceEnvironments(c *gin.Context) {
	// Check if authentication is enabled
	if options.Auth {
		token := getClientToken(c)

		if token != options.Token {
			c.Abort(401)
			return
		}
	}

	serviceName := c.Params.ByName("service")
	service, err := getService(serviceName)

	if err != nil {
		c.String(400, err.Error()+"\n")
		return
	}

	names := strings.Join(service.EnvironmentNames(), "\n") + "\n"
	c.String(200, names)
}

func renderServiceEnvironment(c *gin.Context) {
	serviceName := c.Params.ByName("service")
	envName := c.Params.ByName("env")

	environment, err := getEnvironment(serviceName, envName)

	// Respond with 400 if service does not exist
	// Todo: maybe respond with 404
	if err != nil {
		c.String(400, err.Error()+"\n")
		return
	}

	// Get remote IP address
	host, _, err := net.SplitHostPort(c.Req.RemoteAddr)

	if err != nil {
		c.String(400, err.Error()+"\n")
		return
	}

	// Check if environment has allowed hosts. Localhost is allowed.
	if host != "::1" && len(environment.Hosts) > 0 {
		// Reject requests from non-whitelisted hosts
		if environment.HostEnabled(host) == false {
			c.String(401, "Restricted\n")
			return
		}
	}

	// Fetch token from url param or from the header
	token := getClientToken(c)

	// Validate environment token if its set, otherwise check agains global token
	if environment.Token != "" {
		if token != environment.Token {
			c.String(401, "Restricted\n")
			return
		}
	} else {
		if options.Auth && token != options.Token {
			c.String(401, "Restricted\n")
			return
		}
	}

	c.String(200, environment.ToString()+"\n")
}

func startServer() {
	host := fmt.Sprintf("%s:%d", options.Host, options.Port)
	api := gin.Default()

	api.GET("/", renderAvailableServices)
	api.GET("/:service", renderServiceEnvironments)
	api.GET("/:service/:env", renderServiceEnvironment)

	if options.Auth {
		fmt.Println("authentication enabled")
	}

	fmt.Println("starting server on", host)
	api.Run(host)
}
<|endoftext|>


<commit_before>// Package chronos is a scheduling tool for Go based on:
//  https://github.com/carlescere/scheduler

package chronos

import (
	"sync"
	"time"
)

type Job struct {
	task   func() // Task to be scheduled
	times, // Times that it can be executed, -1 means no limit
	n int // Times that it has been executed
	aux      auxiliar   // Holds the values for following API calls
	schedule *scheduler // Scheduler to determine when to run the job
	quit,    // Channel for quitting the scheduled job
	skip chan struct{} // Channel for executing the task inmediately
	mutex sync.Mutex // Mutex to avoid concurrent executions of the same task
}

// Job construction with task assignment

func Schedule(f func()) *Job {
	return &Job{task: f, times: -1, quit: make(chan struct{}, 1),
		skip: make(chan struct{}, 1)}
}

// Defining the number of times

func (j *Job) NTimes(n int) *Job {
	j.times = n
	return j
}

func (j *Job) Once() *Job {
	return j.NTimes(1)
}

func (j *Job) Twice() *Job {
	return j.NTimes(2)
}

// Defining the period size in units

func (j *Job) Every(times ...int) *Job {
	switch len(times) {
	case 0:
		j.aux.ammount = 1
	case 1:
		j.aux.ammount = times[0]
	default:
		panic("Too many arguments in Job.Every()")
	}
	return j
}

// Defining the period's unit duration

func (j *Job) duration(d time.Duration) *Job {
	j.aux.kind = periodicKind
	j.aux.unit = d
	return j
}

func (j *Job) Nanosecond() *Job {
	return j.duration(time.Nanosecond)
}

func (j *Job) Nanoseconds() *Job {
	return j.Nanosecond()
}

func (j *Job) Microsecond() *Job {
	return j.duration(time.Microsecond)
}

func (j *Job) Microseconds() *Job {
	return j.Microsecond()
}

func (j *Job) Millisecond() *Job {
	return j.duration(time.Millisecond)
}

func (j *Job) Milliseconds() *Job {
	return j.Millisecond()
}

func (j *Job) Second() *Job {
	return j.duration(time.Second)
}

func (j *Job) Seconds() *Job {
	return j.Second()
}

func (j *Job) Minute() *Job {
	return j.duration(time.Minute)
}

func (j *Job) Minutes() *Job {
	return j.Minute()
}

func (j *Job) Hour() *Job {
	return j.duration(time.Hour)
}

func (j *Job) Hours() *Job {
	return j.Hour()
}

func (j *Job) Day() *Job {
	return j.duration(Day)
}

func (j *Job) Days() *Job {
	return j.Day()
}

func (j *Job) Week() *Job {
	return j.duration(Week)
}

func (j *Job) Weeks() *Job {
	return j.Week()
}

func (j *Job) Month() *Job {
	j.aux.kind = monthlyKind
	return j
}

func (j *Job) Months() *Job {
	return j.Month()
}

func (j *Job) Year() *Job {
	j.aux.kind = yearlyKind
	return j
}

func (j *Job) Years() *Job {
	return j.Year()
}

// Defining if it should run at the start of the cycle

func (j *Job) NotInmediately() *Job {
	j.aux.notInmediately = true
	return j
}

// Defining the starting and ending times

func (j *Job) At(t time.Time) *Job {
	j.aux.start = t
	return j
}

func (j *Job) In(d time.Duration) *Job {
	return j.At(time.Now().Add(d))
}

func (j *Job) Until(t time.Time) *Job {
	j.aux.end = t
	return j
}

// Scheduling the task

func (j *Job) Done() (error, chan struct{}, chan struct{}) {
	var (
		err      error
		schedule *scheduler
	)
	switch j.aux.kind {
	case periodicKind:
		schedule, err := newPeriodic(j.aux.start, j.aux.end, j.aux.ammount,
			j.aux.unit, j.aux.notInmediately)
	case monthlyKind:
		schedule, err := newMonthly(j.aux.start, j.aux.end, j.aux.ammount,
			j.aux.notInmediately)
	case yearlyKind:
		schedule, err := newYearly(j.aux.start, j.aux.end, j.aux.ammount,
			j.aux.notInmediately)
	}

	if err == nil {
		j.schedule = schedule

		go func(j *Job) {
			var (
				ok    bool
				next  time.Duration
				timer *time.Timer
			)
			for {
				ok, next = j.schedule.next()
				if !ok {
					return
				}
				timer = time.NewTimer(next)
				select {
				case <-j.quit:
					return
				case <-j.skip:
					go j.run()
				case <-timer.C:
					go j.run()
				}
			}
		}(j)
	}

	return err, j.skip, j.quit
}

func (j *Job) run() {
	j.mutex.Lock()
	defer j.mutex.Unlock()

	if j.times == -1 || j.n < j.times {
		j.n++
		j.task()
	}
}
<commit_msg>Dereference pointer<commit_after>// Package chronos is a scheduling tool for Go based on:
//  https://github.com/carlescere/scheduler

package chronos

import (
	"sync"
	"time"
)

type Job struct {
	task   func() // Task to be scheduled
	times, // Times that it can be executed, -1 means no limit
	n int // Times that it has been executed
	aux      auxiliar   // Holds the values for following API calls
	schedule *scheduler // Scheduler to determine when to run the job
	quit,    // Channel for quitting the scheduled job
	skip chan struct{} // Channel for executing the task inmediately
	mutex sync.Mutex // Mutex to avoid concurrent executions of the same task
}

// Job construction with task assignment

func Schedule(f func()) *Job {
	return &Job{task: f, times: -1, quit: make(chan struct{}, 1),
		skip: make(chan struct{}, 1)}
}

// Defining the number of times

func (j *Job) NTimes(n int) *Job {
	j.times = n
	return j
}

func (j *Job) Once() *Job {
	return j.NTimes(1)
}

func (j *Job) Twice() *Job {
	return j.NTimes(2)
}

// Defining the period size in units

func (j *Job) Every(times ...int) *Job {
	switch len(times) {
	case 0:
		j.aux.ammount = 1
	case 1:
		j.aux.ammount = times[0]
	default:
		panic("Too many arguments in Job.Every()")
	}
	return j
}

// Defining the period's unit duration

func (j *Job) duration(d time.Duration) *Job {
	j.aux.kind = periodicKind
	j.aux.unit = d
	return j
}

func (j *Job) Nanosecond() *Job {
	return j.duration(time.Nanosecond)
}

func (j *Job) Nanoseconds() *Job {
	return j.Nanosecond()
}

func (j *Job) Microsecond() *Job {
	return j.duration(time.Microsecond)
}

func (j *Job) Microseconds() *Job {
	return j.Microsecond()
}

func (j *Job) Millisecond() *Job {
	return j.duration(time.Millisecond)
}

func (j *Job) Milliseconds() *Job {
	return j.Millisecond()
}

func (j *Job) Second() *Job {
	return j.duration(time.Second)
}

func (j *Job) Seconds() *Job {
	return j.Second()
}

func (j *Job) Minute() *Job {
	return j.duration(time.Minute)
}

func (j *Job) Minutes() *Job {
	return j.Minute()
}

func (j *Job) Hour() *Job {
	return j.duration(time.Hour)
}

func (j *Job) Hours() *Job {
	return j.Hour()
}

func (j *Job) Day() *Job {
	return j.duration(Day)
}

func (j *Job) Days() *Job {
	return j.Day()
}

func (j *Job) Week() *Job {
	return j.duration(Week)
}

func (j *Job) Weeks() *Job {
	return j.Week()
}

func (j *Job) Month() *Job {
	j.aux.kind = monthlyKind
	return j
}

func (j *Job) Months() *Job {
	return j.Month()
}

func (j *Job) Year() *Job {
	j.aux.kind = yearlyKind
	return j
}

func (j *Job) Years() *Job {
	return j.Year()
}

// Defining if it should run at the start of the cycle

func (j *Job) NotInmediately() *Job {
	j.aux.notInmediately = true
	return j
}

// Defining the starting and ending times

func (j *Job) At(t time.Time) *Job {
	j.aux.start = t
	return j
}

func (j *Job) In(d time.Duration) *Job {
	return j.At(time.Now().Add(d))
}

func (j *Job) Until(t time.Time) *Job {
	j.aux.end = t
	return j
}

// Scheduling the task

func (j *Job) Done() (error, chan struct{}, chan struct{}) {
	var (
		err      error
		schedule *scheduler
	)
	switch j.aux.kind {
	case periodicKind:
		schedule, err := newPeriodic(j.aux.start, j.aux.end, j.aux.ammount,
			j.aux.unit, j.aux.notInmediately)
	case monthlyKind:
		schedule, err := newMonthly(j.aux.start, j.aux.end, j.aux.ammount,
			j.aux.notInmediately)
	case yearlyKind:
		schedule, err := newYearly(j.aux.start, j.aux.end, j.aux.ammount,
			j.aux.notInmediately)
	}

	if err == nil {
		j.schedule = schedule

		go func(j *Job) {
			var (
				ok    bool
				next  time.Duration
				timer *time.Timer
			)
			for {
				ok, next = *(j.schedule).next()
				if !ok {
					return
				}
				timer = time.NewTimer(next)
				select {
				case <-j.quit:
					return
				case <-j.skip:
					go j.run()
				case <-timer.C:
					go j.run()
				}
			}
		}(j)
	}

	return err, j.skip, j.quit
}

func (j *Job) run() {
	j.mutex.Lock()
	defer j.mutex.Unlock()

	if j.times == -1 || j.n < j.times {
		j.n++
		j.task()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"time"
	"net/http"
	"encoding/json"
)

const AUTH_URI = "/auth/"
const ACCOUNT_URI = "/account/"
const TASKS_URI = "/tasks/"

func main() {
	fmt.Println("hello")
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "hello") })
	http.HandleFunc(AUTH_URI, apiHandler(AUTH_URI, getAuthEndpoint()))
	//http.HandleFunc(ACCOUNT_URI, apiHandler(ACCOUNT_URI, acctIndex, acctPost, acctGet, acctPut, acctDelete))
	//http.HandleFunc(TASKS_URI, apiHandler(TASKS_URI, tasksIndex, tasksPost, tasksGet, tasksPut, tasksDelete))
	http.ListenAndServe(":8000", nil)
	fmt.Println("goodbye")
}

func apiHandler(root string, endpoint *Endpoint) func(http.ResponseWriter, *http.Request) {
	handler := func(w http.ResponseWriter, r *http.Request) {
		var data interface{}
		var error int
		var endpoint_root bool
		error = 0
		endpoint_root = (len(r.URL.Path) <= len(root))

		if endpoint_root {
			if r.Method == "GET" {
				data = endpoint.Index(r)
			} else if r.Method == "POST" {
				data = endpoint.Post(r)
			} else {
				error = 400
				data = "\"bad request\""
			}
		} else {
			id := r.URL.Path[len(root):]
			if r.Method == "GET" {
				data = endpoint.Get(r, id)
			} else if r.Method == "PUT" {
				data = endpoint.Put(r, id)
			} else if r.Method == "DELETE" {
				data = endpoint.Delete(r, id)
			} else {
				error = 400
				data = "\"bad request (not root though)\""
			}
		}
		w.Header().Set("Content-Type", "application/json")
		if error == 0 {
			jdata, _ := json.Marshal(data)
			w.Write(jdata)
		} else {
			http.Error(w, data.(string), error)
		}
	}
	return handler
}

type Endpoint struct {
	Index func(*http.Request) interface{}
	Post func(*http.Request) interface{}
	Get func(*http.Request, string) interface{}
	Put func(*http.Request, string) interface{}
	Delete func(*http.Request, string) interface{}
}

func getAuthEndpoint() *Endpoint {
	index := func(r *http.Request) interface{} {
		return "auth hello"
	}
	post := func(r *http.Request) interface{} {
		return "auth post"
	}
	get := func(r *http.Request, id string) interface{} {
		return "auth get"
	}
	put := func(r *http.Request, id string) interface{} {
		return "auth put"
	}
	delete := func(r *http.Request, id string) interface{} {
		return "auth delete"
	}
	return &Endpoint{Index:index, Post:post, Get:get, Put:put, Delete:delete}
}

func acctIndex(r *http.Request) interface{} {
	return "account index"
}
func acctPost(r *http.Request) interface{} {
	return "account post"
}
func acctGet(r *http.Request, id string) interface{} {
	return "acct get"
}
func acctPut(r *http.Request, id string) interface{} {
	return "acct put"
}
func acctDelete(r *http.Request, id string) interface{} {
	return "acct delete"
}

type Account struct {
	Email string
}

func (a *Account) save() error {
	return nil
}

func (a *Account) update() error {
	return nil
}

func (a *Account) remove() error {
	return nil
}

func LoadAccount(email string) (*Account, error) {
	return &Account{Email: email}, nil
}

type Task struct {
	ID string
	Project string
	Description string
	Duration time.Duration
	Date time.Time
	Creation time.Time
}

func (t *Task) save() error {
	return nil
}

func (t *Task) update() error {
	return nil
}

func (t *Task) remove() error {
	return nil
}

func LoadTask(task_id string) (*Task, error) {
	dur, _ := time.ParseDuration("10s")
	return &Task{ID: task_id,
				 Project: "test",
				 Description: "hello world",
				 Duration: dur,
				 Date: time.Date(2013, time.November, 15, 10, 0, 0, 0, time.UTC),
				 Creation: time.Date(2013, time.November, 15, 11, 0, 0, 0, time.UTC),
				 }, nil
}

func LoadAccountTasks(account_id string) ([]*Task, error) {
	dur, _ := time.ParseDuration("10s")
	return []*Task{&Task{ID: account_id,
			 Project: "test",
			 Description: "hello world",
			 Duration: dur,
			 Date: time.Date(2013, time.November, 15, 10, 0, 0, 0, time.UTC),
			 Creation: time.Date(2013, time.November, 15, 11, 0, 0, 0, time.UTC),
			 }}, nil
}
<commit_msg>endpoing shtuff<commit_after>package main

import (
	"fmt"
	"time"
	"net/http"
	"encoding/json"
)

const AUTH_URI = "/auth/"
const ACCOUNT_URI = "/account/"
const TASKS_URI = "/tasks/"

func main() {
	fmt.Println("hello")
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "hello") })
	http.HandleFunc(AUTH_URI, apiHandler(AUTH_URI, getAuthEndpoint()))
	http.HandleFunc(ACCOUNT_URI, apiHandler(ACCOUNT_URI, getAcctEndpoint()))
	http.HandleFunc(TASKS_URI, apiHandler(TASKS_URI, getTasksEndpoint()))
	http.ListenAndServe(":8000", nil)
	fmt.Println("goodbye")
}

func apiHandler(root string, endpoint *Endpoint) func(http.ResponseWriter, *http.Request) {
	handler := func(w http.ResponseWriter, r *http.Request) {
		var data interface{}
		var error int
		var endpoint_root bool
		error = 0
		endpoint_root = (len(r.URL.Path) <= len(root))

		if endpoint_root {
			if r.Method == "GET" {
				data = endpoint.Index(r)
			} else if r.Method == "POST" {
				data = endpoint.Post(r)
			} else {
				error = 400
				data = "\"bad request\""
			}
		} else {
			id := r.URL.Path[len(root):]
			if r.Method == "GET" {
				data = endpoint.Get(r, id)
			} else if r.Method == "PUT" {
				data = endpoint.Put(r, id)
			} else if r.Method == "DELETE" {
				data = endpoint.Delete(r, id)
			} else {
				error = 400
				data = "\"bad request (not root though)\""
			}
		}
		w.Header().Set("Content-Type", "application/json")
		if error == 0 {
			jdata, _ := json.Marshal(data)
			w.Write(jdata)
		} else {
			http.Error(w, data.(string), error)
		}
	}
	return handler
}

type Endpoint struct {
	Index func(*http.Request) interface{}
	Post func(*http.Request) interface{}
	Get func(*http.Request, string) interface{}
	Put func(*http.Request, string) interface{}
	Delete func(*http.Request, string) interface{}
}

func getAuthEndpoint() *Endpoint {
	index := func(r *http.Request) interface{} {
		return "auth hello"
	}
	post := func(r *http.Request) interface{} {
		return "auth post"
	}
	get := func(r *http.Request, id string) interface{} {
		return "auth get"
	}
	put := func(r *http.Request, id string) interface{} {
		return "auth put"
	}
	delete := func(r *http.Request, id string) interface{} {
		return "auth delete"
	}
	return &Endpoint{Index:index, Post:post, Get:get, Put:put, Delete:delete}
}

func getAcctEndpoint() *Endpoint {
	index := func(r *http.Request) interface{} {
		return "acct hello"
	}
	post := func(r *http.Request) interface{} {
		return "acct post"
	}
	get := func(r *http.Request, id string) interface{} {
		return "acct get"
	}
	put := func(r *http.Request, id string) interface{} {
		return "acct put"
	}
	delete := func(r *http.Request, id string) interface{} {
		return "acct delete"
	}
	return &Endpoint{Index:index, Post:post, Get:get, Put:put, Delete:delete}
}

func getTasksEndpoint() *Endpoint {
	index := func(r *http.Request) interface{} {
		return "tasks hello"
	}
	post := func(r *http.Request) interface{} {
		return "tasks post"
	}
	get := func(r *http.Request, id string) interface{} {
		return "tasks get"
	}
	put := func(r *http.Request, id string) interface{} {
		return "tasks put"
	}
	delete := func(r *http.Request, id string) interface{} {
		return "tasks delete"
	}
	return &Endpoint{Index:index, Post:post, Get:get, Put:put, Delete:delete}
}

type Account struct {
	Email string
}

func (a *Account) save() error {
	return nil
}

func (a *Account) update() error {
	return nil
}

func (a *Account) remove() error {
	return nil
}

func LoadAccount(email string) (*Account, error) {
	return &Account{Email: email}, nil
}

type Task struct {
	ID string
	Project string
	Description string
	Duration time.Duration
	Date time.Time
	Creation time.Time
}

func (t *Task) save() error {
	return nil
}

func (t *Task) update() error {
	return nil
}

func (t *Task) remove() error {
	return nil
}

func LoadTask(task_id string) (*Task, error) {
	dur, _ := time.ParseDuration("10s")
	return &Task{ID: task_id,
				 Project: "test",
				 Description: "hello world",
				 Duration: dur,
				 Date: time.Date(2013, time.November, 15, 10, 0, 0, 0, time.UTC),
				 Creation: time.Date(2013, time.November, 15, 11, 0, 0, 0, time.UTC),
				 }, nil
}

func LoadAccountTasks(account_id string) ([]*Task, error) {
	dur, _ := time.ParseDuration("10s")
	return []*Task{&Task{ID: account_id,
			 Project: "test",
			 Description: "hello world",
			 Duration: dur,
			 Date: time.Date(2013, time.November, 15, 10, 0, 0, 0, time.UTC),
			 Creation: time.Date(2013, time.November, 15, 11, 0, 0, 0, time.UTC),
			 }}, nil
}
<|endoftext|>


<commit_before>package main

import (
	"code.google.com/p/go.net/websocket"
	"github.com/ugorji/go-msgpack"
	"net/url"
	"reflect"
	"errors"
)

const MAX_USERS_PER_LOCATION = 20

var UserCount int

type User struct {
	Socket      *websocket.Conn
	UserId      int
	Nickname    string
	Location    *Location
	MouseIsDown bool
	PositionX   int
	PositionY   int
	ColorRed    int
	ColorGreen  int
	ColorBlue   int
	UsePen      bool
}

func NewUser(ws *websocket.Conn) *User {
	Log.Println("NewUser", "want Lock")
	GlobalLock.Lock()
	Log.Println("NewUser", "got Lock")
	defer func() {
		GlobalLock.Unlock()
		Log.Println("NewUser", "released Lock")
	}()
	Log.Println("NewUser", "1")
	UserCount += 1
	user := new(User)
	Log.Println("NewUser", "2")
	user.Socket = ws
	user.UserId = UserCount
	location_url, err := url.QueryUnescape(ws.Request().RequestURI[6:])
	Log.Println("NewUser", "3")
	if err != nil {
		Log.Println("NewUser", "panic")
		panic(err)
	}
	Log.Println("NewUser", "4")
	user.Location = GetLocation(location_url)
	Log.Println("NewUser", "5")
	if len(user.Location.Users) >= MAX_USERS_PER_LOCATION {
		Log.Println("NewUser", "too much")
		user.Error("Too much users at this location, try adding #something at the end of the URL.")
		return nil
	}
	Log.Println("NewUser", "6")
	user.Location.AddUser(user)
	Log.Println("NewUser", "7")
	user.UsePen = true
	Log.Println("NewUser", "8")
	user.OnOpen()
	Log.Println("NewUser", "9")
	return user
}

func EncodeEvent(event []interface{}) []byte {
	result, err := msgpack.Marshal(event)
	if err != nil {
		panic(err)
	}
	return result
}

func (user *User) SendImage(bytes []byte) {
	if len(bytes) == 0 {
		return
	}
	err := websocket.Message.Send(user.Socket, bytes)
	if err != nil {
		Log.Printf("Couldn't send image to %d: %v\n", user.UserId, err)
		user.Socket.Close()
	}
}

func (user *User) Error(description string) {
	user.SendEvent([]interface{}{
		EventTypeError,
		description,
	})
	user.Socket.Close()
}

func (user *User) Broadcast(event []interface{}, include_myself bool) {
	//    fmt.Printf("users %v\n", user.Location.Users)
	// event.insert(1, user.UserId) ...
	event = append(event[:1], append([]interface{}{user.UserId}, event[1:]...)...)
	for _, other := range user.Location.Users {
		if other != nil {
			//            fmt.Printf("user %v\n", other)
			if !include_myself && other == user {
				continue
			}
			other.SendEvent(event)
		}
	}
}

func (user *User) MouseMove(x int, y int, duration int) {
	//    fmt.Printf("mouse move\n")
	if user.MouseIsDown {
		user.Location.DrawLine(
			user.PositionX, user.PositionY, // origin
			x, y, // destination
			duration,                                       // duration
			user.ColorRed, user.ColorGreen, user.ColorBlue, // color
			user.UsePen, // pen or eraser
		)
	}
	user.PositionX = x
	user.PositionY = y
}

func (user *User) MouseUp() {
	user.MouseIsDown = false
}

func (user *User) MouseDown() {
	user.MouseIsDown = true
}

func (user *User) ChangeTool(use_pen bool) {
	user.UsePen = use_pen
}

func (user *User) ChangeColor(red, green, blue int) {
	user.ColorRed = red
	user.ColorGreen = green
	user.ColorBlue = blue
}

func (user *User) ChangeNickname(nickname string) {
	user.Nickname = nickname
}

func ToInt(n interface{}) (result int, err error) {
	switch n.(type) {
	case int, int8, int16, int32, int64:
		result = int(reflect.ValueOf(n).Int())
	case uint, uint8, uint16, uint32, uint64:
		result = int(reflect.ValueOf(n).Uint())
	default:
		Log.Printf("ToInt, not an int: %#v ", n)
		err = errors.New("Not an int")
	}
	return result, err
}

func (user *User) GotMessage(event []interface{}) {
	event_type, err := ToInt(event[0])
	if err != nil{
		user.Socket.Close()
		return
	}
	params := event[1:]
	switch event_type {
	case EventTypeMouseMove:
		p0, err0 := ToInt(params[0])
		p1, err1 := ToInt(params[1])
		p2, err2 := ToInt(params[2])
		if err0 != nil || err1 != nil || err2 != nil {
			user.Socket.Close()
			return
		}
		user.MouseMove(p0, p1, p2)
	case EventTypeMouseUp:
		user.MouseUp()
	case EventTypeMouseDown:
		user.MouseDown()
	case EventTypeChangeTool:
		user.ChangeTool(params[0].(int8) != 0)
	case EventTypeChangeColor:
		p0, err0 := ToInt(params[0])
		p1, err1 := ToInt(params[1])
		p2, err2 := ToInt(params[2])
		if err0 != nil || err1 != nil || err2 != nil {
			user.Socket.Close()
			return
		}
		user.ChangeColor(p0, p1, p2)
	case EventTypeChangeNickname:
		user.ChangeNickname(params[0].(string))
	}
	user.Broadcast(event, true)
}

func (user *User) OnOpen() {
	// Send the list of present users to this user:
	for _, other := range user.Location.Users {
		user.SendEvent([]interface{}{
			EventTypeJoin,
			other.UserId,
			[]interface{}{other.PositionX, other.PositionY},
			[]interface{}{other.ColorRed, other.ColorGreen, other.ColorBlue},
			other.MouseIsDown,
			false, // not you
			other.Nickname,
			other.UsePen,
		})
	}
	// Send the delta between the image and now to the new user:
	user.SendEvent([]interface{}{
		EventTypeWelcome,
		user.Location.FileName,
		user.Location.GetDelta(),
	})
	// Send this new user to other users:
	event := []interface{}{
		EventTypeJoin,
		[]interface{}{user.PositionX, user.PositionY},
		[]interface{}{user.ColorRed, user.ColorGreen, user.ColorBlue},
		user.MouseIsDown,
		false, // not you
		user.Nickname,
		user.UsePen,
	}
	user.Broadcast(event, false)
	// Send this user to himself
	event = []interface{}{
		EventTypeJoin,
		user.UserId,
		[]interface{}{user.PositionX, user.PositionY},
		[]interface{}{user.ColorRed, user.ColorGreen, user.ColorBlue},
		user.MouseIsDown,
		true, // you
		user.Nickname,
		user.UsePen,
	}
	user.SendEvent(event)
}

func (user *User) OnClose() {
	user.Broadcast([]interface{}{EventTypeLeave}, true)
	user.Location.RemoveUser(user)
}
<commit_msg>log if can't encode event<commit_after>package main

import (
	"code.google.com/p/go.net/websocket"
	"github.com/ugorji/go-msgpack"
	"net/url"
	"reflect"
	"errors"
)

const MAX_USERS_PER_LOCATION = 20

var UserCount int

type User struct {
	Socket      *websocket.Conn
	UserId      int
	Nickname    string
	Location    *Location
	MouseIsDown bool
	PositionX   int
	PositionY   int
	ColorRed    int
	ColorGreen  int
	ColorBlue   int
	UsePen      bool
}

func NewUser(ws *websocket.Conn) *User {
	Log.Println("NewUser", "want Lock")
	GlobalLock.Lock()
	Log.Println("NewUser", "got Lock")
	defer func() {
		GlobalLock.Unlock()
		Log.Println("NewUser", "released Lock")
	}()
	Log.Println("NewUser", "1")
	UserCount += 1
	user := new(User)
	Log.Println("NewUser", "2")
	user.Socket = ws
	user.UserId = UserCount
	location_url, err := url.QueryUnescape(ws.Request().RequestURI[6:])
	Log.Println("NewUser", "3")
	if err != nil {
		Log.Println("NewUser", "panic")
		panic(err)
	}
	Log.Println("NewUser", "4")
	user.Location = GetLocation(location_url)
	Log.Println("NewUser", "5")
	if len(user.Location.Users) >= MAX_USERS_PER_LOCATION {
		Log.Println("NewUser", "too much")
		user.Error("Too much users at this location, try adding #something at the end of the URL.")
		return nil
	}
	Log.Println("NewUser", "6")
	user.Location.AddUser(user)
	Log.Println("NewUser", "7")
	user.UsePen = true
	Log.Println("NewUser", "8")
	user.OnOpen()
	Log.Println("NewUser", "9")
	return user
}

func EncodeEvent(event []interface{}) []byte {
	result, err := msgpack.Marshal(event)
	if err != nil {
		Log.Printf("Couldn't encode event '%v' for user %d\n", event, user.UserId)
		panic(err)
	}
	return result
}

func (user *User) SendImage(bytes []byte) {
	if len(bytes) == 0 {
		return
	}
	err := websocket.Message.Send(user.Socket, bytes)
	if err != nil {
		Log.Printf("Couldn't send image to %d: %v\n", user.UserId, err)
		user.Socket.Close()
	}
}

func (user *User) Error(description string) {
	user.SendEvent([]interface{}{
		EventTypeError,
		description,
	})
	user.Socket.Close()
}

func (user *User) Broadcast(event []interface{}, include_myself bool) {
	//    fmt.Printf("users %v\n", user.Location.Users)
	// event.insert(1, user.UserId) ...
	event = append(event[:1], append([]interface{}{user.UserId}, event[1:]...)...)
	for _, other := range user.Location.Users {
		if other != nil {
			//            fmt.Printf("user %v\n", other)
			if !include_myself && other == user {
				continue
			}
			other.SendEvent(event)
		}
	}
}

func (user *User) MouseMove(x int, y int, duration int) {
	//    fmt.Printf("mouse move\n")
	if user.MouseIsDown {
		user.Location.DrawLine(
			user.PositionX, user.PositionY, // origin
			x, y, // destination
			duration,                                       // duration
			user.ColorRed, user.ColorGreen, user.ColorBlue, // color
			user.UsePen, // pen or eraser
		)
	}
	user.PositionX = x
	user.PositionY = y
}

func (user *User) MouseUp() {
	user.MouseIsDown = false
}

func (user *User) MouseDown() {
	user.MouseIsDown = true
}

func (user *User) ChangeTool(use_pen bool) {
	user.UsePen = use_pen
}

func (user *User) ChangeColor(red, green, blue int) {
	user.ColorRed = red
	user.ColorGreen = green
	user.ColorBlue = blue
}

func (user *User) ChangeNickname(nickname string) {
	user.Nickname = nickname
}

func ToInt(n interface{}) (result int, err error) {
	switch n.(type) {
	case int, int8, int16, int32, int64:
		result = int(reflect.ValueOf(n).Int())
	case uint, uint8, uint16, uint32, uint64:
		result = int(reflect.ValueOf(n).Uint())
	default:
		Log.Printf("ToInt, not an int: %#v ", n)
		err = errors.New("Not an int")
	}
	return result, err
}

func (user *User) GotMessage(event []interface{}) {
	event_type, err := ToInt(event[0])
	if err != nil{
		user.Socket.Close()
		return
	}
	params := event[1:]
	switch event_type {
	case EventTypeMouseMove:
		p0, err0 := ToInt(params[0])
		p1, err1 := ToInt(params[1])
		p2, err2 := ToInt(params[2])
		if err0 != nil || err1 != nil || err2 != nil {
			user.Socket.Close()
			return
		}
		user.MouseMove(p0, p1, p2)
	case EventTypeMouseUp:
		user.MouseUp()
	case EventTypeMouseDown:
		user.MouseDown()
	case EventTypeChangeTool:
		user.ChangeTool(params[0].(int8) != 0)
	case EventTypeChangeColor:
		p0, err0 := ToInt(params[0])
		p1, err1 := ToInt(params[1])
		p2, err2 := ToInt(params[2])
		if err0 != nil || err1 != nil || err2 != nil {
			user.Socket.Close()
			return
		}
		user.ChangeColor(p0, p1, p2)
	case EventTypeChangeNickname:
		user.ChangeNickname(params[0].(string))
	}
	user.Broadcast(event, true)
}

func (user *User) OnOpen() {
	// Send the list of present users to this user:
	for _, other := range user.Location.Users {
		user.SendEvent([]interface{}{
			EventTypeJoin,
			other.UserId,
			[]interface{}{other.PositionX, other.PositionY},
			[]interface{}{other.ColorRed, other.ColorGreen, other.ColorBlue},
			other.MouseIsDown,
			false, // not you
			other.Nickname,
			other.UsePen,
		})
	}
	// Send the delta between the image and now to the new user:
	user.SendEvent([]interface{}{
		EventTypeWelcome,
		user.Location.FileName,
		user.Location.GetDelta(),
	})
	// Send this new user to other users:
	event := []interface{}{
		EventTypeJoin,
		[]interface{}{user.PositionX, user.PositionY},
		[]interface{}{user.ColorRed, user.ColorGreen, user.ColorBlue},
		user.MouseIsDown,
		false, // not you
		user.Nickname,
		user.UsePen,
	}
	user.Broadcast(event, false)
	// Send this user to himself
	event = []interface{}{
		EventTypeJoin,
		user.UserId,
		[]interface{}{user.PositionX, user.PositionY},
		[]interface{}{user.ColorRed, user.ColorGreen, user.ColorBlue},
		user.MouseIsDown,
		true, // you
		user.Nickname,
		user.UsePen,
	}
	user.SendEvent(event)
}

func (user *User) OnClose() {
	user.Broadcast([]interface{}{EventTypeLeave}, true)
	user.Location.RemoveUser(user)
}
<|endoftext|>


<commit_before>package rpimonitor

type User struct {
	Name string
}
<commit_msg>Added name and interface for fetch and auth.<commit_after>package rpimonitor

import "errors"

type User struct {
	Login string
	Name  string
}

var NotFound = errors.New("User not found")

type UserManager interface {
	Fetch(login string) (User, error)
	Authenticate(login, password string) (bool, error)
}
<|endoftext|>


<commit_before>package sofa

import (
	"encoding/json"
)

// UserDocument contains all of the fields used by CouchDB to represent a
// user on the server.
type UserDocument struct {
	DocumentMetadata

	Name     string   `json:"name,omitempty"`
	Password string   `json:"password,omitempty"`
	Roles    []string `json:"roles"`
	TheType  string   `json:"type,omitempty"`
}

// Users gets a list of all users currently active on this CouchDB server
func (con *Connection) Users() ([]UserDocument, error) {
	db := con.Database("_users")

	table, err := db.AllDocuments()
	if err != nil {
		return nil, err
	}

	users := []UserDocument{}
	for _, rawUser := range table.RawDocuments() {
		user := UserDocument{}
		if err := json.Unmarshal(rawUser, &user); err != nil {
			return nil, err
		}
		users = append(users, user)
	}
	return users, nil
}

// User gets a particular UserDocument from the server by ID. A revision can
// also be specified to retrieve a particular revision of the document.
func (con *Connection) User(id string, rev string) (UserDocument, error) {
	db := con.Database("_users")

	user := UserDocument{}
	_, err := db.Get(&user, id, rev)
	if err != nil {
		return user, err
	}

	return user, nil
}
<commit_msg>Add more utility methods for _users database<commit_after>package sofa

import (
	"encoding/json"
	"errors"
	"fmt"
)

// UserDocument contains all of the fields used by CouchDB to represent a
// user on the server.
type UserDocument struct {
	DocumentMetadata

	Name    string   `json:"name"`
	Roles   []string `json:"roles"`
	TheType string   `json:"type"`

	// This field is never sent back from CouchDB (for obvious reasons)
	Password string `json:"password,omitempty"`

	// These fields are generated by CouchDB from the password provided on creation
	DerivedKey     string `json:"derived_key,omitempty"`
	Iterations     int    `json:"iterations,omitempty"`
	PasswordScheme string `json:"password_scheme,omitempty"`
	Salt           string `json:"salt,omitempty"`
}

// Users gets a list of all users currently active on this CouchDB server
func (con *Connection) Users() ([]UserDocument, error) {
	db := con.Database("_users")

	table, err := db.AllDocuments()
	if err != nil {
		return nil, err
	}

	users := []UserDocument{}
	for _, rawUser := range table.RawDocuments() {
		user := UserDocument{}
		if err := json.Unmarshal(rawUser, &user); err != nil {
			return nil, err
		}
		users = append(users, user)
	}
	return users, nil
}

// User gets a particular UserDocument from the server by name. A revision can
// also be specified to retrieve a particular revision of the document (or an
// empty string supplied to fetch the current version).
// This makes the assumption that the user exists in the 'org.couchdb.user' namespace
// but I am unaware of any situation where that is not true. If the user doesn't
// exist in this namespace it should be possible to retrieve them with UserByID.
func (con *Connection) User(name string, rev string) (UserDocument, error) {
	id := fmt.Sprintf("org.couchdb.user:%s", name)
	return con.UserByID(id, rev)
}

// UserByID gets a CouchDB user by the ID of ther user document rather than their
// name.
func (con *Connection) UserByID(id string, rev string) (UserDocument, error) {
	db := con.Database("_users")

	user := UserDocument{}
	_, err := db.Get(&user, id, rev)
	if err != nil {
		return user, err
	}

	return user, nil
}

// CreateUser creates a new document in the _users database.
func (con *Connection) CreateUser(user UserDocument) (string, error) {
	db := con.Database("_users")

	id := fmt.Sprintf("org.couchdb.user:%s", user.Name)

	// For convenience fill in the ID if it was left blank
	if user.DocumentMetadata.ID == "" {
		user.DocumentMetadata.ID = id
	}

	return db.Put(&user)
}

// DeleteUser deletes an existing user from the _users database.
func (con *Connection) DeleteUser(user UserDocument) (string, error) {
	db := con.Database("_users")

	if user.DocumentMetadata.ID == "" {
		return "", errors.New("cannot delete a user with an unknown id")
	}

	if user.DocumentMetadata.Rev == "" {
		return "", errors.New("cannot delete a user with no current rev")
	}

	return db.Delete(&user)
}
<|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"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/binary"
	"fmt"
	"time"
)

const (
	// ZeroHash is the string of all 00s
	ZeroHash = "0000000000000000000000000000000000000000000000000000000000000000"
)

var (
	RpcConfig = &RPCConfig{}
)

func entryCost(e *Entry) (int8, error) {
	p, err := e.MarshalBinary()
	if err != nil {
		return 0, err
	}

	// caulculate the length exluding the header size 35 for Milestone 1
	l := len(p) - 35

	if l > 10240 {
		return 10, fmt.Errorf("Entry cannot be larger than 10KB")
	}

	// n is the capacity of the entry payment in KB
	n := int8(l / 1024)

	if r := l % 1024; r > 0 {
		n++
	}

	if n < 1 {
		n = 1
	}
	return n, nil
}

// milliTime returns a 6 byte slice representing the unix time in milliseconds
func milliTime() (r []byte) {
	buf := new(bytes.Buffer)
	t := time.Now().UnixNano()
	m := t / 1e6
	binary.Write(buf, binary.BigEndian, m)
	return buf.Bytes()[2:]
}

// shad Double Sha256 Hash; sha256(sha256(data))
func shad(data []byte) []byte {
	h1 := sha256.Sum256(data)
	h2 := sha256.Sum256(h1[:])
	return h2[:]
}

// sha52 Sha512+Sha256 Hash; sha256(sha512(data)+data)
func sha52(data []byte) []byte {
	h1 := sha512.Sum512(data)
	h2 := sha256.Sum256(append(h1[:], data...))
	return h2[:]
}

func factoshiToFactoid(i uint64) string {
	d := i / 1e8
	r := i % 1e8
	return fmt.Sprintf("%d.%.8d", d, r)
}
<commit_msg>dont print trailing zeros<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"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/binary"
	"fmt"
	"time"
	"strings"
)

const (
	// ZeroHash is the string of all 00s
	ZeroHash = "0000000000000000000000000000000000000000000000000000000000000000"
)

var (
	RpcConfig = &RPCConfig{}
)

func entryCost(e *Entry) (int8, error) {
	p, err := e.MarshalBinary()
	if err != nil {
		return 0, err
	}

	// caulculate the length exluding the header size 35 for Milestone 1
	l := len(p) - 35

	if l > 10240 {
		return 10, fmt.Errorf("Entry cannot be larger than 10KB")
	}

	// n is the capacity of the entry payment in KB
	n := int8(l / 1024)

	if r := l % 1024; r > 0 {
		n++
	}

	if n < 1 {
		n = 1
	}
	return n, nil
}

// milliTime returns a 6 byte slice representing the unix time in milliseconds
func milliTime() (r []byte) {
	buf := new(bytes.Buffer)
	t := time.Now().UnixNano()
	m := t / 1e6
	binary.Write(buf, binary.BigEndian, m)
	return buf.Bytes()[2:]
}

// shad Double Sha256 Hash; sha256(sha256(data))
func shad(data []byte) []byte {
	h1 := sha256.Sum256(data)
	h2 := sha256.Sum256(h1[:])
	return h2[:]
}

// sha52 Sha512+Sha256 Hash; sha256(sha512(data)+data)
func sha52(data []byte) []byte {
	h1 := sha512.Sum512(data)
	h2 := sha256.Sum256(append(h1[:], data...))
	return h2[:]
}

func factoshiToFactoid(i uint64) string {
	d := i / 1e8
	r := i % 1e8
	ds := fmt.Sprintf("%d", d)
	rs := fmt.Sprintf("%08d", r)
	rs = strings.TrimRight(rs, "0")
	if len(rs) > 0 {
		ds = ds + "."
	}
	return fmt.Sprintf("%s%s", ds, rs)
}
<|endoftext|>


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

package glh

import (
	"image"
	"image/color"
	"image/png"
	"log"
	"os"

	"github.com/go-gl/gl"
	"github.com/go-gl/glu"
)

// Used as "defer OpenGLSentinel()()" checks the gl error code on call and exit
func OpenGLSentinel() func() {
	check := func() {
		e := gl.GetError()
		if e != gl.NO_ERROR {
			s, err := glu.ErrorString(e)
			if err != nil {
				log.Panic("Invalid error code: ", err)
			}
			log.Panic("Encountered GLError: ", e, " = ", s)
		}
	}
	check()
	return check
}

// Returns w, h of viewport
func GetViewportWH() (int, int) {
	var viewport [4]int32
	gl.GetIntegerv(gl.VIEWPORT, viewport[0:3])
	return int(viewport[2]), int(viewport[3])
}

func GetViewportWHD() (float64, float64) {
	w, h := GetViewportWH()
	return float64(w), float64(h)
}

// Returns x, y in window co-ordinates at 0 in the z direction
func WindowToProj(x, y int) (float64, float64) {
	var projmat, modelmat [16]float64
	var viewport [4]int32

	gl.GetDoublev(gl.PROJECTION_MATRIX, projmat[0:15])
	gl.GetDoublev(gl.MODELVIEW_MATRIX, modelmat[0:15])

	gl.GetIntegerv(gl.VIEWPORT, viewport[0:3])
	// Need to convert so that y is at lower left
	y = int(viewport[3]) - y

	px, py, _ := glu.UnProject(float64(x), float64(y), 0,
		&modelmat, &projmat, &viewport)

	return px, py
}

// Returns x, y in window co-ordinates at 0 in the z direction
func ProjToWindow(x, y float64) (float64, float64) {
	var projmat, modelmat [16]float64
	var viewport [4]int32

	gl.GetDoublev(gl.PROJECTION_MATRIX, projmat[0:15])
	gl.GetDoublev(gl.MODELVIEW_MATRIX, modelmat[0:15])
	gl.GetIntegerv(gl.VIEWPORT, viewport[0:3])

	px, py, _ := glu.Project(float64(x), float64(y), 0,
		&modelmat, &projmat, &viewport)

	//return int(px), int(viewport[3]) - int(py)
	return px, float64(viewport[3]) - py
}

// Draws a cross on the screen with known lengths, useful for understanding
// screen dimensions
func DebugLines() {
	gl.MatrixMode(gl.PROJECTION)
	gl.PushMatrix()
	//gl.LoadIdentity()
	//gl.Ortho(-2.1, 6.1, -4, 8, 1, -1)
	gl.MatrixMode(gl.MODELVIEW)
	gl.PushMatrix()
	gl.LoadIdentity()

	gl.LoadIdentity()
	gl.LineWidth(5)
	gl.Color4f(1, 1, 0, 1)
	gl.Begin(gl.LINES)
	gl.Vertex2d(0, -1.6)
	gl.Vertex2d(0, 0.8)
	gl.Vertex2d(-0.8, 0)
	gl.Vertex2d(0.8, 0)
	gl.End()
	gl.PopMatrix()

	gl.MatrixMode(gl.PROJECTION)
	gl.PopMatrix()
	gl.MatrixMode(gl.MODELVIEW)
}

// Emit Vertices of a square with texture co-ordinates which wind anti-clockwise
func Squarei(x, y, w, h int) {
	u, v, u2, v2 := 0, 1, 1, 0

	gl.TexCoord2i(u, v)
	gl.Vertex2i(x, y)

	gl.TexCoord2i(u2, v)
	gl.Vertex2i(x+w, y)

	gl.TexCoord2i(u2, v2)
	gl.Vertex2i(x+w, y+h)

	gl.TexCoord2i(u, v2)
	gl.Vertex2i(x, y+h)
}

// Draw a Quad with integer co-ordinates (Using Squarei)
func DrawQuadi(x, y, w, h int) {
	With(Primitive{gl.QUADS}, func() {
		Squarei(x, y, w, h)
	})
}

// Same as Squarei, double co-ordinates
func Squared(x, y, w, h float64) {
	u, v, u2, v2 := 0, 1, 1, 0

	gl.TexCoord2i(u, v)
	gl.Vertex2d(x, y)

	gl.TexCoord2i(u2, v)
	gl.Vertex2d(x+w, y)

	gl.TexCoord2i(u2, v2)
	gl.Vertex2d(x+w, y+h)

	gl.TexCoord2i(u, v2)
	gl.Vertex2d(x, y+h)
}

// Same as DrawQuadi, double co-ordinates
func DrawQuadd(x, y, w, h float64) {
	With(Primitive{gl.QUADS}, func() {
		Squared(x, y, w, h)
	})
}

func CaptureToPng(filename string) {
	w, h := GetViewportWH()

	im := image.NewNRGBA(image.Rect(0, 0, w, h))
	gl.ReadBuffer(gl.BACK_LEFT)
	gl.ReadPixels(0, 0, w, h, gl.RGBA, gl.UNSIGNED_BYTE, im.Pix)

	fd, err := os.Create(filename)
	if err != nil {
		log.Panic("Err: ", err)
	}
	defer fd.Close()

	png.Encode(fd, im)
}

func ColorC(c color.Color) {
	if c == nil {
		panic("nil color passed to ColorC")
	}
	r, g, b, a := c.RGBA()
	gl.Color4us(uint16(r), uint16(g), uint16(b), uint16(a))
}
<commit_msg>Adds the 'Sizeof' function. It returns the byte size of the given OpenGL type for the current machine/GL implementation. This is necessary to reliably compute element offsets in components like vertex-, color-, normal-, texture- and index-buffers.<commit_after>// Copyright 2012 The go-gl Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package glh

import (
	"image"
	"image/color"
	"image/png"
	"log"
	"os"
	"unsafe"

	"github.com/go-gl/gl"
	"github.com/go-gl/glu"
)

// Sizeof yields the byte size for GL type specified by the given enum.
func Sizeof(gtype gl.GLenum) uint {
	switch gtype {
	case gl.BOOL:
		var v gl.GLboolean
		return uint(unsafe.Sizeof(v))

	case gl.BYTE:
		var v gl.GLbyte
		return uint(unsafe.Sizeof(v))

	case gl.UNSIGNED_BYTE:
		var v gl.GLubyte
		return uint(unsafe.Sizeof(v))

	case gl.SHORT:
		var v gl.GLshort
		return uint(unsafe.Sizeof(v))

	case gl.UNSIGNED_SHORT:
		var v gl.GLushort
		return uint(unsafe.Sizeof(v))

	case gl.INT:
		var v gl.GLint
		return uint(unsafe.Sizeof(v))

	case gl.UNSIGNED_INT:
		var v gl.GLuint
		return uint(unsafe.Sizeof(v))

	case gl.FLOAT:
		var v gl.GLfloat
		return uint(unsafe.Sizeof(v))

	case gl.DOUBLE:
		var v gl.GLdouble
		return uint(unsafe.Sizeof(v))
	}

	panic("Unsupported type")
}

// Used as "defer OpenGLSentinel()()" checks the gl error code on call and exit
func OpenGLSentinel() func() {
	check := func() {
		e := gl.GetError()
		if e != gl.NO_ERROR {
			s, err := glu.ErrorString(e)
			if err != nil {
				log.Panic("Invalid error code: ", err)
			}
			log.Panic("Encountered GLError: ", e, " = ", s)
		}
	}
	check()
	return check
}

// Returns w, h of viewport
func GetViewportWH() (int, int) {
	var viewport [4]int32
	gl.GetIntegerv(gl.VIEWPORT, viewport[0:3])
	return int(viewport[2]), int(viewport[3])
}

func GetViewportWHD() (float64, float64) {
	w, h := GetViewportWH()
	return float64(w), float64(h)
}

// Returns x, y in window co-ordinates at 0 in the z direction
func WindowToProj(x, y int) (float64, float64) {
	var projmat, modelmat [16]float64
	var viewport [4]int32

	gl.GetDoublev(gl.PROJECTION_MATRIX, projmat[0:15])
	gl.GetDoublev(gl.MODELVIEW_MATRIX, modelmat[0:15])

	gl.GetIntegerv(gl.VIEWPORT, viewport[0:3])
	// Need to convert so that y is at lower left
	y = int(viewport[3]) - y

	px, py, _ := glu.UnProject(float64(x), float64(y), 0,
		&modelmat, &projmat, &viewport)

	return px, py
}

// Returns x, y in window co-ordinates at 0 in the z direction
func ProjToWindow(x, y float64) (float64, float64) {
	var projmat, modelmat [16]float64
	var viewport [4]int32

	gl.GetDoublev(gl.PROJECTION_MATRIX, projmat[0:15])
	gl.GetDoublev(gl.MODELVIEW_MATRIX, modelmat[0:15])
	gl.GetIntegerv(gl.VIEWPORT, viewport[0:3])

	px, py, _ := glu.Project(float64(x), float64(y), 0,
		&modelmat, &projmat, &viewport)

	//return int(px), int(viewport[3]) - int(py)
	return px, float64(viewport[3]) - py
}

// Draws a cross on the screen with known lengths, useful for understanding
// screen dimensions
func DebugLines() {
	gl.MatrixMode(gl.PROJECTION)
	gl.PushMatrix()
	//gl.LoadIdentity()
	//gl.Ortho(-2.1, 6.1, -4, 8, 1, -1)
	gl.MatrixMode(gl.MODELVIEW)
	gl.PushMatrix()
	gl.LoadIdentity()

	gl.LoadIdentity()
	gl.LineWidth(5)
	gl.Color4f(1, 1, 0, 1)
	gl.Begin(gl.LINES)
	gl.Vertex2d(0, -1.6)
	gl.Vertex2d(0, 0.8)
	gl.Vertex2d(-0.8, 0)
	gl.Vertex2d(0.8, 0)
	gl.End()
	gl.PopMatrix()

	gl.MatrixMode(gl.PROJECTION)
	gl.PopMatrix()
	gl.MatrixMode(gl.MODELVIEW)
}

// Emit Vertices of a square with texture co-ordinates which wind anti-clockwise
func Squarei(x, y, w, h int) {
	u, v, u2, v2 := 0, 1, 1, 0

	gl.TexCoord2i(u, v)
	gl.Vertex2i(x, y)

	gl.TexCoord2i(u2, v)
	gl.Vertex2i(x+w, y)

	gl.TexCoord2i(u2, v2)
	gl.Vertex2i(x+w, y+h)

	gl.TexCoord2i(u, v2)
	gl.Vertex2i(x, y+h)
}

// Draw a Quad with integer co-ordinates (Using Squarei)
func DrawQuadi(x, y, w, h int) {
	With(Primitive{gl.QUADS}, func() {
		Squarei(x, y, w, h)
	})
}

// Same as Squarei, double co-ordinates
func Squared(x, y, w, h float64) {
	u, v, u2, v2 := 0, 1, 1, 0

	gl.TexCoord2i(u, v)
	gl.Vertex2d(x, y)

	gl.TexCoord2i(u2, v)
	gl.Vertex2d(x+w, y)

	gl.TexCoord2i(u2, v2)
	gl.Vertex2d(x+w, y+h)

	gl.TexCoord2i(u, v2)
	gl.Vertex2d(x, y+h)
}

// Same as DrawQuadi, double co-ordinates
func DrawQuadd(x, y, w, h float64) {
	With(Primitive{gl.QUADS}, func() {
		Squared(x, y, w, h)
	})
}

func CaptureToPng(filename string) {
	w, h := GetViewportWH()

	im := image.NewNRGBA(image.Rect(0, 0, w, h))
	gl.ReadBuffer(gl.BACK_LEFT)
	gl.ReadPixels(0, 0, w, h, gl.RGBA, gl.UNSIGNED_BYTE, im.Pix)

	fd, err := os.Create(filename)
	if err != nil {
		log.Panic("Err: ", err)
	}
	defer fd.Close()

	png.Encode(fd, im)
}

func ColorC(c color.Color) {
	if c == nil {
		panic("nil color passed to ColorC")
	}
	r, g, b, a := c.RGBA()
	gl.Color4us(uint16(r), uint16(g), uint16(b), uint16(a))
}
<|endoftext|>


<commit_before>package ringo

import (
	"errors"
	"log"
	"net/http"
)

type App struct {
	*Router
	middlewares       []MiddlewareFunc
	handleHTTPRequest HandlerFunc
}

func NewApp() *App {
	return &App{Router: NewRouter()}
}

func (app *App) Use(middlewreFunc MiddlewareFunc) {
	app.middlewares = append(app.middlewares, middlewreFunc)
}

func (app *App) Run(addr string) error {
	log.Printf("Listening on %s, start serve HTTP", addr)
	app.initForServe()
	err := http.ListenAndServe(addr, app)
	if err != nil {
		log.Printf("%s", err)
	}
	return err
}

func (app *App) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	log.Printf("%+v", r)
	c := NewContext()
	c.Request = r
	c.ResponseWriter = newResponseWriter(w)
	app.handleHTTPRequest(c)
}

func (app *App) initForServe() {
	// use middlewares
	app.handleHTTPRequest = app.applyMiddlewares(app.defaultHandleHTTPRequest)
}

func (app *App) applyMiddlewares(handler HandlerFunc) HandlerFunc {
	for _, middleware := range app.middlewares {
		handler = middleware(handler)
	}

	return handler
}

func (app *App) defaultHandleHTTPRequest(c *Context) {
	handler, params := app.Router.MatchRoute(c.Request.URL.Path, c.Request.Method)
	c.Params = params

	if handler == nil {
		handler = handleNotFound
		log.Printf("Not found route for %s", c.RequestURI)
	}

	if !c.Rendered() {
		panic(errors.New("Empty response, missing render call in handler"))
	}
}

func handleNotFound(c *Context) {
	statusCode := http.StatusNotFound
	text := http.StatusText(statusCode)
	c.Render(statusCode, text)
}
<commit_msg>add missing handler call<commit_after>package ringo

import (
	"errors"
	"log"
	"net/http"
)

type App struct {
	*Router
	middlewares       []MiddlewareFunc
	handleHTTPRequest HandlerFunc
}

func NewApp() *App {
	return &App{Router: NewRouter()}
}

func (app *App) Use(middlewreFunc MiddlewareFunc) {
	app.middlewares = append(app.middlewares, middlewreFunc)
}

func (app *App) Run(addr string) error {
	log.Printf("Listening on %s, start serve HTTP", addr)
	app.initForServe()
	err := http.ListenAndServe(addr, app)
	if err != nil {
		log.Printf("%s", err)
	}
	return err
}

func (app *App) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	log.Printf("%+v", r)
	c := NewContext()
	c.Request = r
	c.ResponseWriter = newResponseWriter(w)
	app.handleHTTPRequest(c)
}

func (app *App) initForServe() {
	// use middlewares
	app.handleHTTPRequest = app.applyMiddlewares(app.defaultHandleHTTPRequest)
}

func (app *App) applyMiddlewares(handler HandlerFunc) HandlerFunc {
	for _, middleware := range app.middlewares {
		handler = middleware(handler)
	}

	return handler
}

func (app *App) defaultHandleHTTPRequest(c *Context) {
	handler, params := app.Router.MatchRoute(c.Request.URL.Path, c.Request.Method)
	c.Params = params

	if handler == nil {
		handler = handleNotFound
		log.Printf("Not found route for %s", c.RequestURI)
	}

	handler(c)

	if !c.Rendered() {
		panic(errors.New("Empty response, missing render call in handler"))
	}
}

func handleNotFound(c *Context) {
	statusCode := http.StatusNotFound
	text := http.StatusText(statusCode)
	c.Render(statusCode, text)
}
<|endoftext|>


<commit_before>package main

import ("fmt"
	"os"
	"bufio"
	"path/filepath"
	"strings"
	"strconv"
)

func assert(e error) {
	if e != nil {
		panic(e)
	}
}

func main() {

	fmt.Println("hello world")

	dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
	assert(err)

	files := []string{"v.in"}

	for _,v  := range files {
		readGoogleHashcodeFile(dir+"/inputs/"+v)
		writeSolution("solution_"+v)
	}

}

type Video struct {
	id int
	size int
}

/*type Endpoint struct {
	id int
	videos []Video
}*/

type Endpoint struct{
	id int
	cacheInfo []CacheInfo
	latency int
}

type CacheInfo struct{

	id int
	latency int

}

type RequestInfo struct {
	numRequest int
	idVideo int
	endpointId int
}

const MAX_CACHED_VIDEOS_SIZE = 500000

type Cache struct {
	id int
	videos []Video
}

type Requests struct {
	latency int

}

type ResultOfParse struct {
	videos []Video
	caches []CacheInfo
	requestInfo []RequestInfo
	endpoints int
	numberOfCaches int
	size int
}

func readGoogleHashcodeFile( path string) (ResultOfParse){

	file,error := os.Open(path)

	assert(error)

	reader := bufio.NewReader(file)

	line, _, error := reader.ReadLine()

	counter := 0

	numberOfVideos := 0
	numberOfEnpoints := 0
	numberOfRequest := 0
	numberOfCaches := 0
	cacheSize:= 0

	var videos  = []Video{}

	endpointCacheNumber := 0
	enpointDetailIteration := 0
	var currentEndpoint Endpoint;
	enpointNumber := 0
	var cacheInfo  = []CacheInfo{}

	enpointIteration := 0

	var requests  = []RequestInfo{}
	requestsIteration := 0

	for line != nil {
		assert(error)
		//process line
		linesplited := strings.Split(string(line), " ")

		if (counter == 0){
			//
			numberOfVideos = convertToInt(linesplited[0])
			numberOfEnpoints = convertToInt(linesplited[1])
			numberOfRequest = convertToInt(linesplited[2])
			numberOfCaches = convertToInt(linesplited[3])
			cacheSize = convertToInt(linesplited[4])

		}else if (counter == 1){
			for i := 0; i < numberOfVideos; i++ {
				videos = append(videos,Video{id:i,size:convertToInt(linesplited[i])})
			}
		}else {
			// ENDPOINTS

			if enpointIteration < numberOfEnpoints {
				if endpointCacheNumber < enpointDetailIteration {

					enpointDetailIteration = enpointDetailIteration +1
					cacheInfo = append(cacheInfo,CacheInfo{id:convertToInt(linesplited[0]),latency:convertToInt(linesplited[1])})
				}else{

					if len(cacheInfo) > 0 {
						currentEndpoint.cacheInfo = cacheInfo
					}

					currentEndpoint = Endpoint{id:enpointNumber,latency:convertToInt(linesplited[0])}
					endpointCacheNumber = convertToInt(linesplited[1])
					enpointNumber = enpointNumber +1
					enpointDetailIteration = 0
					cacheInfo  = []CacheInfo{}

					enpointIteration = enpointIteration + 1
				}
			}else {

				// REQUEST
				requests := append(requests,RequestInfo{numRequest:convertToInt(linesplited[0]),idVideo:convertToInt(linesplited[1]),endpointId:convertToInt(linesplited[2])})

				requestsIteration = requestsIteration + 1

				_ = requests

			}

		}

		counter = counter + 1
	}

	panic(requestsIteration != numberOfRequest)

	file.Close()

	return ResultOfParse{caches:cacheInfo,requestInfo:requests,videos:videos,endpoints:numberOfEnpoints,numberOfCaches:numberOfCaches,size:cacheSize}
}

func convertToInt(str string) (int){
	intRes,_ := strconv.Atoi(str)
	return intRes
}

func writeSolution(result string){

	file,err := os.Create(result)
	assert(err)

	defer file.Close()

	file.WriteString("writes\n")

	file.Sync()

}<commit_msg>first version<commit_after>package main

import ("fmt"
	"os"
	"bufio"

	"strings"
	"strconv"
)

func assert(e error) {
	if e != nil {
		panic(e)
	}
}

func main() {

	fmt.Println("hello world")

	//dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
	//assert(err)

	dir := "inputs/"

	files := []string{"v.in"}

	for _,v  := range files {
		readGoogleHashcodeFile(dir+v)
		writeSolution("solution_"+v)
	}

}

type Video struct {
	id int
	size int
}

/*type Endpoint struct {
	id int
	videos []Video
}*/

type Endpoint struct{
	id int
	cacheInfo []CacheInfo
	latency int
}

type CacheInfo struct{

	id int
	latency int

}

type RequestInfo struct {
	numRequest int
	idVideo int
	endpointId int
}

const MAX_CACHED_VIDEOS_SIZE = 500000

type Cache struct {
	id int
	videos []Video
}

type Requests struct {
	latency int

}

type ResultOfParse struct {
	videos []Video
	caches []CacheInfo
	requestInfo []RequestInfo
	endpoints int
	numberOfCaches int
	size int
}

func readGoogleHashcodeFile( path string) (ResultOfParse){

	file,error := os.Open(path)

	assert(error)

	reader := bufio.NewReader(file)

	line, _, error := reader.ReadLine()

	counter := 0

	numberOfVideos := 0
	numberOfEnpoints := 0
	numberOfRequest := 0
	numberOfCaches := 0
	cacheSize:= 0

	var videos  = []Video{}

	endpointCacheNumber := 0
	enpointDetailIteration := 0
	var currentEndpoint Endpoint;
	enpointNumber := 0
	var cacheInfo  = []CacheInfo{}

	enpointIteration := 0

	var requests  = []RequestInfo{}
	requestsIteration := 0

	for line != nil {
		assert(error)
		//process line
		linesplited := strings.Split(string(line), " ")

		if (counter == 0){
			//
			numberOfVideos = convertToInt(linesplited[0])
			numberOfEnpoints = convertToInt(linesplited[1])
			numberOfRequest = convertToInt(linesplited[2])
			numberOfCaches = convertToInt(linesplited[3])
			cacheSize = convertToInt(linesplited[4])

		}else if (counter == 1){
			for i := 0; i < numberOfVideos; i++ {
				videos = append(videos,Video{id:i,size:convertToInt(linesplited[i])})
			}
		}else {
			// ENDPOINTS

			if enpointIteration < numberOfEnpoints {
				if endpointCacheNumber < enpointDetailIteration {

					enpointDetailIteration = enpointDetailIteration +1
					cacheInfo = append(cacheInfo,CacheInfo{id:convertToInt(linesplited[0]),latency:convertToInt(linesplited[1])})
				}else{

					if len(cacheInfo) > 0 {
						currentEndpoint.cacheInfo = cacheInfo
					}

					currentEndpoint = Endpoint{id:enpointNumber,latency:convertToInt(linesplited[0])}
					endpointCacheNumber = convertToInt(linesplited[1])
					enpointNumber = enpointNumber +1
					enpointDetailIteration = 0
					cacheInfo  = []CacheInfo{}

					enpointIteration = enpointIteration + 1
				}
			}else {

				// REQUEST
				requests := append(requests,RequestInfo{numRequest:convertToInt(linesplited[0]),idVideo:convertToInt(linesplited[1]),endpointId:convertToInt(linesplited[2])})

				requestsIteration = requestsIteration + 1

				_ = requests

			}

		}

		counter = counter + 1
	}

	panic(requestsIteration != numberOfRequest)

	file.Close()

	return ResultOfParse{caches:cacheInfo,requestInfo:requests,videos:videos,endpoints:numberOfEnpoints,numberOfCaches:numberOfCaches,size:cacheSize}
}

func convertToInt(str string) (int){
	intRes,_ := strconv.Atoi(str)
	return intRes
}

func writeSolution(result string){

	file,err := os.Create(result)
	assert(err)

	defer file.Close()

	file.WriteString("writes\n")

	file.Sync()

}<|endoftext|>


<commit_before>// package warc provides primitives for reading WARC files.
package warc

import (
	"bufio"
	"bytes"
	"compress/bzip2"
	"compress/gzip"
	"fmt"
	"io"
	"io/ioutil"
	"strconv"
	"strings"
)

// Mode defines the way Reader will generate Records.
type Mode int

func (m Mode) String() string {
	switch m {
	case SequentialMode:
		return "SequentialMode"
	case AsynchronousMode:
		return "AsynchronousMode"
	}
	return ""
}

const (
	// SequentialMode means Records have to be consumed one by one and a call to
	// ReadRecord() invalidates the previous record. The benefit is that
	// Records have almost no overhead since they wrap around
	// the underlying Reader.
	SequentialMode Mode = iota
	// AsynchronousMode means calls to ReadRecord don't effect previously
	// returned Records. This mode copies the Record's content into
	// separate memory, thus bears memory overhead.
	AsynchronousMode
)

// Reader reads WARC records from WARC files.
type Reader struct {
	Mode Mode

	// Unexported fields.
	source io.ReadCloser
	reader *bufio.Reader
	record *Record
	buffer []byte
}

// Record represents a WARC record.
type Record struct {
	Header  map[string]string
	Content io.Reader
	Length  int
}

const (
	compressionNone = iota
	compressionBZIP
	compressionGZIP
)

// guessCompression returns the compression type of a data stream by matching
// the first two bytes with the magic numbers of compression formats.
func guessCompression(b *bufio.Reader) (int, error) {
	magic, err := b.Peek(2)
	if err != nil {
		if err == io.EOF {
			err = nil
		}
		return compressionNone, err
	}
	switch {
	case magic[0] == 0x42 && magic[1] == 0x5a:
		return compressionBZIP, nil
	case magic[0] == 0x1f && magic[1] == 0x8b:
		return compressionGZIP, nil
	}
	return compressionNone, nil
}

// decompress automatically decompresses data streams and makes sure the result
// obeys the io.ReadCloser interface. This way callers don't need to check
// whether the underlying reader has a Close() function or not, they just call
// defer Close() on the result.
func decompress(r io.Reader) (res io.ReadCloser, err error) {
	// Create a buffered reader to peek the stream's magic number.
	dataReader := bufio.NewReader(r)
	compr, err := guessCompression(dataReader)
	if err != nil {
		return nil, err
	}
	switch compr {
	case compressionGZIP:
		gzipReader, err := gzip.NewReader(dataReader)
		if err != nil {
			return nil, err
		}
		res = gzipReader
	case compressionBZIP:
		bzipReader := bzip2.NewReader(dataReader)
		res = ioutil.NopCloser(bzipReader)
	case compressionNone:
		res = ioutil.NopCloser(dataReader)
	}
	return res, err
}

// sliceReader returns a new io.Reader for the next n bytes in source.
// If clone is true, the n bytes will be fully read from source and the
// resulting io.Reader will have its own copy of the data. Calls to the
// result's Read() function won't change the state of source.
// If clone is false, no bytes will be consumed from source and the resulting
// io.Reader will wrap itself around source. Each call to the result's Read()
// function will change the state of source.
func sliceReader(source io.Reader, size int, clone bool) (io.Reader, error) {
	reader := io.LimitReader(source, int64(size))
	if !clone {
		return reader, nil
	}
	content, err := ioutil.ReadAll(reader)
	if err != nil {
		return nil, err
	}
	return bytes.NewReader(content), nil
}

// splitKeyValue parses WARC record header fields.
func splitKeyValue(line string) (string, string) {
	parts := strings.SplitN(line, ":", 2)
	if len(parts) != 2 {
		return "", ""
	}
	return strings.ToLower(parts[0]), strings.TrimSpace(parts[1])
}

// NewReader creates a new WARC reader.
func NewReader(reader io.Reader, mode Mode) (*Reader, error) {
	source, err := decompress(reader)
	if err != nil {
		return nil, err
	}
	return &Reader{
		Mode:   mode,
		source: source,
		reader: bufio.NewReader(source),
		buffer: make([]byte, 4096),
	}, nil
}

// Close closes the reader.
func (r *Reader) Close() {
	if r.source != nil {
		r.source.Close()
		r.source = nil
		r.reader = nil
		r.record = nil
	}
}

// readLine reads the next line in the opened WARC file.
func (r *Reader) readLine() (string, error) {
	data, isPrefix, err := r.reader.ReadLine()
	if err != nil {
		return "", err
	}
	// Line was too long for the buffer.
	// TODO: rather return an error in this case? This function
	// is only used on header fields and they shouldn't exceed the buffer size
	// or should they?
	if isPrefix {
		buffer := new(bytes.Buffer)
		buffer.Write(data)
		for isPrefix {
			data, isPrefix, err = r.reader.ReadLine()
			if err != nil {
				return "", err
			}
			buffer.Write(data)
		}
		return buffer.String(), nil
	}
	return string(data), nil
}

// ReadRecord reads the next record from the opened WARC file.
func (r *Reader) ReadRecord() (*Record, error) {
	// Go to the position of the next record in the file.
	r.seekRecord()
	// Skip the record version line.
	if _, err := r.readLine(); err != nil {
		return nil, err
	}
	// Parse the record header.
	header := make(map[string]string)
	for {
		line, err := r.readLine()
		if err != nil {
			return nil, err
		}
		if line == "" {
			break
		}
		if key, value := splitKeyValue(line); key != "" {
			header[key] = value
		}
	}
	// Determine the content length and then retrieve the record content.
	length, err := strconv.Atoi(header["content-length"])
	if err != nil {
		return nil, fmt.Errorf("failed to parse field Content-Length: %v", err)
	}
	content, err := sliceReader(r.reader, length, r.Mode == AsynchronousMode)
	if err != nil {
		return nil, err
	}
	r.record = &Record{
		Header:  header,
		Content: content,
		Length:  length,
	}
	return r.record, nil
}

// seekRecord moves the Reader to the position of the next WARC record
// in the opened WARC file.
func (r *Reader) seekRecord() error {
	// No record was read yet? The r.reader must be at a start of the file and
	// thus the start of a record.
	if r.record == nil {
		return nil
	}
	// If the mode is set to SequentialMode, the underlying r.reader might be
	// anywhere inside the active record's block - depending on how much the
	// user actually consumed. So we have to make sure all content gets skipped
	// here.
	if r.Mode == SequentialMode {
		for {
			n, err := r.record.Content.Read(r.buffer)
			if n == 0 || err != nil {
				break
			}
		}
	}
	// Set to nil so it's safe to call this function several times without
	// destroying stuff.
	r.record = nil
	for i := 0; i < 2; i++ {
		line, err := r.readLine()
		if err != nil {
			return err
		}
		if line != "" {
			return fmt.Errorf("expected empty line, got %q", line)
		}
	}
	return nil
}
<commit_msg>implement Writer for WARC files<commit_after>// package warc provides primitives for reading and writing WARC files.
package warc

import (
	"bufio"
	"bytes"
	"compress/bzip2"
	"compress/gzip"
	"fmt"
	"io"
	"io/ioutil"
	"strconv"
	"strings"
)

// Mode defines the way Reader will generate Records.
type Mode int

func (m Mode) String() string {
	switch m {
	case SequentialMode:
		return "SequentialMode"
	case AsynchronousMode:
		return "AsynchronousMode"
	}
	return ""
}

const (
	// SequentialMode means Records have to be consumed one by one and a call to
	// ReadRecord() invalidates the previous record. The benefit is that
	// Records have almost no overhead since they wrap around
	// the underlying Reader.
	SequentialMode Mode = iota
	// AsynchronousMode means calls to ReadRecord don't effect previously
	// returned Records. This mode copies the Record's content into
	// separate memory, thus bears memory overhead.
	AsynchronousMode
)

// Reader reads WARC records from WARC files.
type Reader struct {
	Mode Mode

	// Unexported fields.
	source io.ReadCloser
	reader *bufio.Reader
	record *Record
	buffer []byte
}

// Writer writes WARC records to WARC files.
type Writer struct {
	// Unexported fields.
	target io.Writer
}

// Record represents a WARC record.
type Record struct {
	Header  map[string]string
	Content io.Reader
	Length  int
}

const (
	compressionNone = iota
	compressionBZIP
	compressionGZIP
)

// guessCompression returns the compression type of a data stream by matching
// the first two bytes with the magic numbers of compression formats.
func guessCompression(b *bufio.Reader) (int, error) {
	magic, err := b.Peek(2)
	if err != nil {
		if err == io.EOF {
			err = nil
		}
		return compressionNone, err
	}
	switch {
	case magic[0] == 0x42 && magic[1] == 0x5a:
		return compressionBZIP, nil
	case magic[0] == 0x1f && magic[1] == 0x8b:
		return compressionGZIP, nil
	}
	return compressionNone, nil
}

// decompress automatically decompresses data streams and makes sure the result
// obeys the io.ReadCloser interface. This way callers don't need to check
// whether the underlying reader has a Close() function or not, they just call
// defer Close() on the result.
func decompress(r io.Reader) (res io.ReadCloser, err error) {
	// Create a buffered reader to peek the stream's magic number.
	dataReader := bufio.NewReader(r)
	compr, err := guessCompression(dataReader)
	if err != nil {
		return nil, err
	}
	switch compr {
	case compressionGZIP:
		gzipReader, err := gzip.NewReader(dataReader)
		if err != nil {
			return nil, err
		}
		res = gzipReader
	case compressionBZIP:
		bzipReader := bzip2.NewReader(dataReader)
		res = ioutil.NopCloser(bzipReader)
	case compressionNone:
		res = ioutil.NopCloser(dataReader)
	}
	return res, err
}

// sliceReader returns a new io.Reader for the next n bytes in source.
// If clone is true, the n bytes will be fully read from source and the
// resulting io.Reader will have its own copy of the data. Calls to the
// result's Read() function won't change the state of source.
// If clone is false, no bytes will be consumed from source and the resulting
// io.Reader will wrap itself around source. Each call to the result's Read()
// function will change the state of source.
func sliceReader(source io.Reader, size int, clone bool) (io.Reader, error) {
	reader := io.LimitReader(source, int64(size))
	if !clone {
		return reader, nil
	}
	content, err := ioutil.ReadAll(reader)
	if err != nil {
		return nil, err
	}
	return bytes.NewReader(content), nil
}

// splitKeyValue parses WARC record header fields.
func splitKeyValue(line string) (string, string) {
	parts := strings.SplitN(line, ":", 2)
	if len(parts) != 2 {
		return "", ""
	}
	return strings.ToLower(parts[0]), strings.TrimSpace(parts[1])
}

// NewRecord creates a new WARC record.
func NewRecord() *Record {
	return &Record{
		Header: make(map[string]string),
	}
}

// NewReader creates a new WARC reader.
func NewReader(reader io.Reader, mode Mode) (*Reader, error) {
	source, err := decompress(reader)
	if err != nil {
		return nil, err
	}
	return &Reader{
		Mode:   mode,
		source: source,
		reader: bufio.NewReader(source),
		buffer: make([]byte, 4096),
	}, nil
}

// Close closes the reader.
func (r *Reader) Close() {
	if r.source != nil {
		r.source.Close()
		r.source = nil
		r.reader = nil
		r.record = nil
	}
}

// readLine reads the next line in the opened WARC file.
func (r *Reader) readLine() (string, error) {
	data, isPrefix, err := r.reader.ReadLine()
	if err != nil {
		return "", err
	}
	// Line was too long for the buffer.
	// TODO: rather return an error in this case? This function
	// is only used on header fields and they shouldn't exceed the buffer size
	// or should they?
	if isPrefix {
		buffer := new(bytes.Buffer)
		buffer.Write(data)
		for isPrefix {
			data, isPrefix, err = r.reader.ReadLine()
			if err != nil {
				return "", err
			}
			buffer.Write(data)
		}
		return buffer.String(), nil
	}
	return string(data), nil
}

// ReadRecord reads the next record from the opened WARC file.
func (r *Reader) ReadRecord() (*Record, error) {
	// Go to the position of the next record in the file.
	r.seekRecord()
	// Skip the record version line.
	if _, err := r.readLine(); err != nil {
		return nil, err
	}
	// Parse the record header.
	header := make(map[string]string)
	for {
		line, err := r.readLine()
		if err != nil {
			return nil, err
		}
		if line == "" {
			break
		}
		if key, value := splitKeyValue(line); key != "" {
			header[key] = value
		}
	}
	// Determine the content length and then retrieve the record content.
	length, err := strconv.Atoi(header["content-length"])
	if err != nil {
		return nil, fmt.Errorf("failed to parse field Content-Length: %v", err)
	}
	content, err := sliceReader(r.reader, length, r.Mode == AsynchronousMode)
	if err != nil {
		return nil, err
	}
	r.record = &Record{
		Header:  header,
		Content: content,
		Length:  length,
	}
	return r.record, nil
}

// seekRecord moves the Reader to the position of the next WARC record
// in the opened WARC file.
func (r *Reader) seekRecord() error {
	// No record was read yet? The r.reader must be at a start of the file and
	// thus the start of a record.
	if r.record == nil {
		return nil
	}
	// If the mode is set to SequentialMode, the underlying r.reader might be
	// anywhere inside the active record's block - depending on how much the
	// user actually consumed. So we have to make sure all content gets skipped
	// here.
	if r.Mode == SequentialMode {
		for {
			n, err := r.record.Content.Read(r.buffer)
			if n == 0 || err != nil {
				break
			}
		}
	}
	// Set to nil so it's safe to call this function several times without
	// destroying stuff.
	r.record = nil
	for i := 0; i < 2; i++ {
		line, err := r.readLine()
		if err != nil {
			return err
		}
		if line != "" {
			return fmt.Errorf("expected empty line, got %q", line)
		}
	}
	return nil
}

// NewWriter creates a new WARC writer.
func NewWriter(writer io.Writer) *Writer {
	return &Writer{writer}
}

// WriteRecord writes a record to the underlying WARC file.
func (w *Writer) WriteRecord(r *Record) error {
	data, err := ioutil.ReadAll(r.Content)
	if err != nil {
		return err
	}
	r.Header["content-length"] = strconv.Itoa(len(data))

	// A record consists of a version string, the record header followed by a
	// record content block and two newlines:
	// 	Version CLRF
	// 	Header-Key: Header-Value CLRF
	// 	CLRF
	// 	Content
	// 	CLRF
	// 	CLRF
	if _, err := fmt.Fprintf(w.target, "%s\r\n", "WARC/1.0"); err != nil {
		return err
	}
	for key, value := range r.Header {
		if _, err := fmt.Fprintf(w.target, "%s: %s\r\n", strings.Title(key), value); err != nil {
			return err
		}
	}
	if _, err := fmt.Fprintf(w.target, "\r\n%s\r\n\r\n", data); err != nil {
		return err
	}
	return nil
}
<|endoftext|>