<commit_before>// Copyright (c) 2013 The Go Authors. All rights reserved.
// Copyright (c) 2018 Dominik Honnef. All rights reserved.

package stylecheck

import (
	"go/ast"
	"go/token"
	"strings"
	"unicode"

	"honnef.co/go/tools/lint"
	. "honnef.co/go/tools/lint/lintdsl"
)

// commonInitialisms is a set of common initialisms.
// Only add entries that are highly unlikely to be non-initialisms.
// For instance, "ID" is fine (Freudian code is rare), but "AND" is not.
var commonInitialisms = map[string]bool{
	"ACL":   true,
	"API":   true,
	"ASCII": true,
	"CPU":   true,
	"CSS":   true,
	"DNS":   true,
	"EOF":   true,
	"GUID":  true,
	"HTML":  true,
	"HTTP":  true,
	"HTTPS": true,
	"ID":    true,
	"IP":    true,
	"JSON":  true,
	"QPS":   true,
	"RAM":   true,
	"RPC":   true,
	"SLA":   true,
	"SMTP":  true,
	"SQL":   true,
	"SSH":   true,
	"TCP":   true,
	"TLS":   true,
	"TTL":   true,
	"UDP":   true,
	"UI":    true,
	"GID":   true,
	"UID":   true,
	"UUID":  true,
	"URI":   true,
	"URL":   true,
	"UTF8":  true,
	"VM":    true,
	"XML":   true,
	"XMPP":  true,
	"XSRF":  true,
	"XSS":   true,
}

// knownNameExceptions is a set of names that are known to be exempt from naming checks.
// This is usually because they are constrained by having to match names in the
// standard library.
var knownNameExceptions = map[string]bool{
	"LastInsertId": true, // must match database/sql
	"kWh":          true,
}

func (c *Checker) CheckNames(j *lint.Job) {
	// A large part of this function is copied from
	// github.com/golang/lint, Copyright (c) 2013 The Go Authors,
	// licensed under the BSD 3-clause license.

	allCaps := func(s string) bool {
		for _, r := range s {
			if !((r >= 'A' && r <= 'Z') || (r >= '0' && r <= '9') || r == '_') {
				return false
			}
		}
		return true
	}

	check := func(id *ast.Ident, thing string) {
		if id.Name == "_" {
			return
		}
		if knownNameExceptions[id.Name] {
			return
		}

		// Handle two common styles from other languages that don't belong in Go.
		if len(id.Name) >= 5 && allCaps(id.Name) && strings.Contains(id.Name, "_") {
			j.Errorf(id, "should not use ALL_CAPS in Go names; use CamelCase instead")
			return
		}

		should := lintName(id.Name)
		if id.Name == should {
			return
		}

		if len(id.Name) > 2 && strings.Contains(id.Name[1:len(id.Name)-1], "_") {
			j.Errorf(id, "should not use underscores in Go names; %s %s should be %s", thing, id.Name, should)
			return
		}
		j.Errorf(id, "%s %s should be %s", thing, id.Name, should)
	}
	checkList := func(fl *ast.FieldList, thing string) {
		if fl == nil {
			return
		}
		for _, f := range fl.List {
			for _, id := range f.Names {
				check(id, thing)
			}
		}
	}
	for _, f := range c.filterGenerated(j.Program.Files) {
		// Package names need slightly different handling than other names.
		if !strings.HasSuffix(f.Name.Name, "_test") && strings.Contains(f.Name.Name, "_") {
			j.Errorf(f, "should not use underscores in package names")
		}
		if strings.IndexFunc(f.Name.Name, unicode.IsUpper) != -1 {
			j.Errorf(f, "should not use MixedCaps in package name; %s should be %s", f.Name.Name, strings.ToLower(f.Name.Name))
		}

		ast.Inspect(f, func(node ast.Node) bool {
			switch v := node.(type) {
			case *ast.AssignStmt:
				if v.Tok != token.DEFINE {
					return true
				}
				for _, exp := range v.Lhs {
					if id, ok := exp.(*ast.Ident); ok {
						check(id, "var")
					}
				}
			case *ast.FuncDecl:
				// Functions with no body are defined elsewhere (in
				// assembly, or via go:linkname). These are likely to
				// be something very low level (such as the runtime),
				// where our rules don't apply.
				if v.Body == nil {
					return true
				}

				if IsInTest(j, v) && (strings.HasPrefix(v.Name.Name, "Example") || strings.HasPrefix(v.Name.Name, "Test") || strings.HasPrefix(v.Name.Name, "Benchmark")) {
					return true
				}

				thing := "func"
				if v.Recv != nil {
					thing = "method"
				}

				if !isTechnicallyExported(v) {
					check(v.Name, thing)
				}

				checkList(v.Type.Params, thing+" parameter")
				checkList(v.Type.Results, thing+" result")
			case *ast.GenDecl:
				if v.Tok == token.IMPORT {
					return true
				}
				var thing string
				switch v.Tok {
				case token.CONST:
					thing = "const"
				case token.TYPE:
					thing = "type"
				case token.VAR:
					thing = "var"
				}
				for _, spec := range v.Specs {
					switch s := spec.(type) {
					case *ast.TypeSpec:
						check(s.Name, thing)
					case *ast.ValueSpec:
						for _, id := range s.Names {
							check(id, thing)
						}
					}
				}
			case *ast.InterfaceType:
				// Do not check interface method names.
				// They are often constrainted by the method names of concrete types.
				for _, x := range v.Methods.List {
					ft, ok := x.Type.(*ast.FuncType)
					if !ok { // might be an embedded interface name
						continue
					}
					checkList(ft.Params, "interface method parameter")
					checkList(ft.Results, "interface method result")
				}
			case *ast.RangeStmt:
				if v.Tok == token.ASSIGN {
					return true
				}
				if id, ok := v.Key.(*ast.Ident); ok {
					check(id, "range var")
				}
				if id, ok := v.Value.(*ast.Ident); ok {
					check(id, "range var")
				}
			case *ast.StructType:
				for _, f := range v.Fields.List {
					for _, id := range f.Names {
						check(id, "struct field")
					}
				}
			}
			return true
		})
	}
}

// lintName returns a different name if it should be different.
func lintName(name string) (should string) {
	// A large part of this function is copied from
	// github.com/golang/lint, Copyright (c) 2013 The Go Authors,
	// licensed under the BSD 3-clause license.

	// Fast path for simple cases: "_" and all lowercase.
	if name == "_" {
		return name
	}
	if strings.IndexFunc(name, func(r rune) bool { return !unicode.IsLower(r) }) == -1 {
		return name
	}

	// Split camelCase at any lower->upper transition, and split on underscores.
	// Check each word for common initialisms.
	runes := []rune(name)
	w, i := 0, 0 // index of start of word, scan
	for i+1 <= len(runes) {
		eow := false // whether we hit the end of a word
		if i+1 == len(runes) {
			eow = true
		} else if runes[i+1] == '_' && i+1 != len(runes)-1 {
			// underscore; shift the remainder forward over any run of underscores
			eow = true
			n := 1
			for i+n+1 < len(runes) && runes[i+n+1] == '_' {
				n++
			}

			// Leave at most one underscore if the underscore is between two digits
			if i+n+1 < len(runes) && unicode.IsDigit(runes[i]) && unicode.IsDigit(runes[i+n+1]) {
				n--
			}

			copy(runes[i+1:], runes[i+n+1:])
			runes = runes[:len(runes)-n]
		} else if unicode.IsLower(runes[i]) && !unicode.IsLower(runes[i+1]) {
			// lower->non-lower
			eow = true
		}
		i++
		if !eow {
			continue
		}

		// [w,i) is a word.
		word := string(runes[w:i])
		if u := strings.ToUpper(word); commonInitialisms[u] {
			// Keep consistent case, which is lowercase only at the start.
			if w == 0 && unicode.IsLower(runes[w]) {
				u = strings.ToLower(u)
			}
			// All the common initialisms are ASCII,
			// so we can replace the bytes exactly.
			// TODO(dh): this won't be true once we allow custom initialisms
			copy(runes[w:], []rune(u))
		} else if w > 0 && strings.ToLower(word) == word {
			// already all lowercase, and not the first word, so uppercase the first character.
			runes[w] = unicode.ToUpper(runes[w])
		}
		w = i
	}
	return string(runes)
}

func isTechnicallyExported(f *ast.FuncDecl) bool {
	if f.Recv != nil || f.Doc == nil {
		return false
	}

	const export = "//export "
	const linkname = "//go:linkname "
	for _, c := range f.Doc.List {
		if strings.HasPrefix(c.Text, export) && len(c.Text) == len(export)+len(f.Name.Name) && c.Text[len(export):] == f.Name.Name {
			return true
		}

		if strings.HasPrefix(c.Text, linkname) {
			return true
		}
	}
	return false
}
<commit_msg>stylecheck: use config file for initialisms<commit_after>// Copyright (c) 2013 The Go Authors. All rights reserved.
// Copyright (c) 2018 Dominik Honnef. All rights reserved.

package stylecheck

import (
	"go/ast"
	"go/token"
	"strings"
	"unicode"

	"honnef.co/go/tools/lint"
	. "honnef.co/go/tools/lint/lintdsl"
)

// knownNameExceptions is a set of names that are known to be exempt from naming checks.
// This is usually because they are constrained by having to match names in the
// standard library.
var knownNameExceptions = map[string]bool{
	"LastInsertId": true, // must match database/sql
	"kWh":          true,
}

func (c *Checker) CheckNames(j *lint.Job) {
	// A large part of this function is copied from
	// github.com/golang/lint, Copyright (c) 2013 The Go Authors,
	// licensed under the BSD 3-clause license.

	allCaps := func(s string) bool {
		for _, r := range s {
			if !((r >= 'A' && r <= 'Z') || (r >= '0' && r <= '9') || r == '_') {
				return false
			}
		}
		return true
	}

	check := func(id *ast.Ident, thing string, initialisms map[string]bool) {
		if id.Name == "_" {
			return
		}
		if knownNameExceptions[id.Name] {
			return
		}

		// Handle two common styles from other languages that don't belong in Go.
		if len(id.Name) >= 5 && allCaps(id.Name) && strings.Contains(id.Name, "_") {
			j.Errorf(id, "should not use ALL_CAPS in Go names; use CamelCase instead")
			return
		}

		should := lintName(id.Name, initialisms)
		if id.Name == should {
			return
		}

		if len(id.Name) > 2 && strings.Contains(id.Name[1:len(id.Name)-1], "_") {
			j.Errorf(id, "should not use underscores in Go names; %s %s should be %s", thing, id.Name, should)
			return
		}
		j.Errorf(id, "%s %s should be %s", thing, id.Name, should)
	}
	checkList := func(fl *ast.FieldList, thing string, initialisms map[string]bool) {
		if fl == nil {
			return
		}
		for _, f := range fl.List {
			for _, id := range f.Names {
				check(id, thing, initialisms)
			}
		}
	}

	for _, pkg := range j.Program.Packages {
		initialisms := make(map[string]bool, len(pkg.Config.Stylecheck.Initialisms))
		for _, word := range pkg.Config.Stylecheck.Initialisms {
			initialisms[word] = true
		}
		for _, f := range c.filterGenerated(pkg.Info.Files) {
			// Package names need slightly different handling than other names.
			if !strings.HasSuffix(f.Name.Name, "_test") && strings.Contains(f.Name.Name, "_") {
				j.Errorf(f, "should not use underscores in package names")
			}
			if strings.IndexFunc(f.Name.Name, unicode.IsUpper) != -1 {
				j.Errorf(f, "should not use MixedCaps in package name; %s should be %s", f.Name.Name, strings.ToLower(f.Name.Name))
			}

			ast.Inspect(f, func(node ast.Node) bool {
				switch v := node.(type) {
				case *ast.AssignStmt:
					if v.Tok != token.DEFINE {
						return true
					}
					for _, exp := range v.Lhs {
						if id, ok := exp.(*ast.Ident); ok {
							check(id, "var", initialisms)
						}
					}
				case *ast.FuncDecl:
					// Functions with no body are defined elsewhere (in
					// assembly, or via go:linkname). These are likely to
					// be something very low level (such as the runtime),
					// where our rules don't apply.
					if v.Body == nil {
						return true
					}

					if IsInTest(j, v) && (strings.HasPrefix(v.Name.Name, "Example") || strings.HasPrefix(v.Name.Name, "Test") || strings.HasPrefix(v.Name.Name, "Benchmark")) {
						return true
					}

					thing := "func"
					if v.Recv != nil {
						thing = "method"
					}

					if !isTechnicallyExported(v) {
						check(v.Name, thing, initialisms)
					}

					checkList(v.Type.Params, thing+" parameter", initialisms)
					checkList(v.Type.Results, thing+" result", initialisms)
				case *ast.GenDecl:
					if v.Tok == token.IMPORT {
						return true
					}
					var thing string
					switch v.Tok {
					case token.CONST:
						thing = "const"
					case token.TYPE:
						thing = "type"
					case token.VAR:
						thing = "var"
					}
					for _, spec := range v.Specs {
						switch s := spec.(type) {
						case *ast.TypeSpec:
							check(s.Name, thing, initialisms)
						case *ast.ValueSpec:
							for _, id := range s.Names {
								check(id, thing, initialisms)
							}
						}
					}
				case *ast.InterfaceType:
					// Do not check interface method names.
					// They are often constrainted by the method names of concrete types.
					for _, x := range v.Methods.List {
						ft, ok := x.Type.(*ast.FuncType)
						if !ok { // might be an embedded interface name
							continue
						}
						checkList(ft.Params, "interface method parameter", initialisms)
						checkList(ft.Results, "interface method result", initialisms)
					}
				case *ast.RangeStmt:
					if v.Tok == token.ASSIGN {
						return true
					}
					if id, ok := v.Key.(*ast.Ident); ok {
						check(id, "range var", initialisms)
					}
					if id, ok := v.Value.(*ast.Ident); ok {
						check(id, "range var", initialisms)
					}
				case *ast.StructType:
					for _, f := range v.Fields.List {
						for _, id := range f.Names {
							check(id, "struct field", initialisms)
						}
					}
				}
				return true
			})
		}
	}
}

// lintName returns a different name if it should be different.
func lintName(name string, initialisms map[string]bool) (should string) {
	// A large part of this function is copied from
	// github.com/golang/lint, Copyright (c) 2013 The Go Authors,
	// licensed under the BSD 3-clause license.

	// Fast path for simple cases: "_" and all lowercase.
	if name == "_" {
		return name
	}
	if strings.IndexFunc(name, func(r rune) bool { return !unicode.IsLower(r) }) == -1 {
		return name
	}

	// Split camelCase at any lower->upper transition, and split on underscores.
	// Check each word for common initialisms.
	runes := []rune(name)
	w, i := 0, 0 // index of start of word, scan
	for i+1 <= len(runes) {
		eow := false // whether we hit the end of a word
		if i+1 == len(runes) {
			eow = true
		} else if runes[i+1] == '_' && i+1 != len(runes)-1 {
			// underscore; shift the remainder forward over any run of underscores
			eow = true
			n := 1
			for i+n+1 < len(runes) && runes[i+n+1] == '_' {
				n++
			}

			// Leave at most one underscore if the underscore is between two digits
			if i+n+1 < len(runes) && unicode.IsDigit(runes[i]) && unicode.IsDigit(runes[i+n+1]) {
				n--
			}

			copy(runes[i+1:], runes[i+n+1:])
			runes = runes[:len(runes)-n]
		} else if unicode.IsLower(runes[i]) && !unicode.IsLower(runes[i+1]) {
			// lower->non-lower
			eow = true
		}
		i++
		if !eow {
			continue
		}

		// [w,i) is a word.
		word := string(runes[w:i])
		if u := strings.ToUpper(word); initialisms[u] {
			// Keep consistent case, which is lowercase only at the start.
			if w == 0 && unicode.IsLower(runes[w]) {
				u = strings.ToLower(u)
			}
			// All the common initialisms are ASCII,
			// so we can replace the bytes exactly.
			// TODO(dh): this won't be true once we allow custom initialisms
			copy(runes[w:], []rune(u))
		} else if w > 0 && strings.ToLower(word) == word {
			// already all lowercase, and not the first word, so uppercase the first character.
			runes[w] = unicode.ToUpper(runes[w])
		}
		w = i
	}
	return string(runes)
}

func isTechnicallyExported(f *ast.FuncDecl) bool {
	if f.Recv != nil || f.Doc == nil {
		return false
	}

	const export = "//export "
	const linkname = "//go:linkname "
	for _, c := range f.Doc.List {
		if strings.HasPrefix(c.Text, export) && len(c.Text) == len(export)+len(f.Name.Name) && c.Text[len(export):] == f.Name.Name {
			return true
		}

		if strings.HasPrefix(c.Text, linkname) {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>package subsumption_test

import (
	. "."
	"errors"
	gomock "github.com/golang/mock/gomock"
	"testing"
)

func TestCreate(t *testing.T) {
	agent := Agent{}

	if agent.Size() != 0 {
		t.Errorf("agent.Size() should be 0")
	}
}

func TestAddBehavior(t *testing.T) {
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()

	behabior := NewMockBehavior(ctrl)
	agent := Agent{}

	agent.AddBehavior(behabior)

	if agent.Size() != 1 {
		t.Errorf("agent.Size() should be 1")
	}
}

func TestInit(t *testing.T) {
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()

	behabior := NewMockBehavior(ctrl)
	behabior.EXPECT().Init()

	agent := Agent{}
	agent.AddBehavior(behabior)

	agent.Init()
}

func TestPerform(t *testing.T) {
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()

	behabior := NewMockBehavior(ctrl)
	behabior.EXPECT().Sense().Return(true, nil)
	behabior.EXPECT().Perform().Return(true, nil)

	agent := Agent{}
	agent.AddBehavior(behabior)

	ret, err := agent.Perform()

	if err != nil {
		t.Errorf("unexpected agent.Perform() fail with : %v", err)
	}
	if ret != true {
		t.Errorf("agent.Perform() should be true because behabior is active")
	}
}

func TestSenceError(t *testing.T) {
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()

	behabior := NewMockBehavior(ctrl)
	behabior.EXPECT().Sense().Return(false, errors.New("unknown error"))

	agent := Agent{}
	agent.AddBehavior(behabior)

	ret, err := agent.Perform()

	if err != nil {
		t.Errorf("unexpected agent.Perform() fail with : %v", err)
	}
	if ret != false {
		t.Errorf("agent.Perform() should be false because no behavior is active")
	}
}
<commit_msg>add test case for Agent.Perform() with multi Behaviors<commit_after>package subsumption_test

import (
	. "."
	"errors"
	gomock "github.com/golang/mock/gomock"
	"testing"
)

func TestCreate(t *testing.T) {
	agent := Agent{}

	if agent.Size() != 0 {
		t.Errorf("agent.Size() should be 0")
	}
}

func TestAddBehavior(t *testing.T) {
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()

	behabior := NewMockBehavior(ctrl)
	agent := Agent{}

	agent.AddBehavior(behabior)

	if agent.Size() != 1 {
		t.Errorf("agent.Size() should be 1")
	}
}

func TestInit(t *testing.T) {
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()

	behabior := NewMockBehavior(ctrl)
	behabior.EXPECT().Init()

	agent := Agent{}
	agent.AddBehavior(behabior)

	agent.Init()
}

func TestPerform(t *testing.T) {
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()

	behabior := NewMockBehavior(ctrl)
	behabior.EXPECT().Sense().Return(true, nil)
	behabior.EXPECT().Perform().Return(true, nil)

	agent := Agent{}
	agent.AddBehavior(behabior)

	ret, err := agent.Perform()

	if err != nil {
		t.Errorf("unexpected agent.Perform() fail with : %v", err)
	}
	if ret != true {
		t.Errorf("agent.Perform() should be true because behabior is active")
	}
}

func TestPerformMulti(t *testing.T) {
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()

	first := NewMockBehavior(ctrl)
	first.EXPECT().Sense().Return(false, nil)

	second := NewMockBehavior(ctrl)
	second.EXPECT().Sense().Return(true, nil)
	second.EXPECT().Perform().Return(true, nil)

	agent := Agent{}
	agent.AddBehavior(first)
	agent.AddBehavior(second)

	ret, err := agent.Perform()

	if err != nil {
		t.Errorf("agent.Perform() failed with : %v", err)
	}
	if ret != true {
		t.Errorf("agent.Perform() should be false because [second] behabior is active")
	}
}

func TestSenceError(t *testing.T) {
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()

	behabior := NewMockBehavior(ctrl)
	behabior.EXPECT().Sense().Return(false, errors.New("unknown error"))

	agent := Agent{}
	agent.AddBehavior(behabior)

	ret, err := agent.Perform()

	if err != nil {
		t.Errorf("unexpected agent.Perform() fail with : %v", err)
	}
	if ret != false {
		t.Errorf("agent.Perform() should be false because no behavior is active")
	}
}
<|endoftext|>


<commit_before>package stun

import "github.com/pkg/errors"

// https://tools.ietf.org/html/rfc5389#section-15.3
// The USERNAME attribute is used for message integrity.  It identifies
// the username and password combination used in the message-integrity
// check.
//
// The value of USERNAME is a variable-length value.  It MUST contain a
// UTF-8 [RFC3629] encoded sequence of less than 513 bytes, and MUST
// have been processed using SASLprep [RFC4013].
type Username struct {
	Username string
}

const (
	usernameMaxLength = 513
)

func (u *Username) Pack(message *Message) error {
	if len([]byte(u.Username)) > usernameMaxLength {
		return errors.Errorf("invalid username length %d", len([]byte(u.Username)))
	}
	message.AddAttribute(AttrSoftware, []byte(u.Username))
	return nil
}

func (u *Username) Unpack(message *Message, rawAttribute *RawAttribute) error {
	u.Username = string(rawAttribute.Value)
	return nil
}
<commit_msg>Fix AttrUsername pack (Software -> Username key)<commit_after>package stun

import "github.com/pkg/errors"

// https://tools.ietf.org/html/rfc5389#section-15.3
// The USERNAME attribute is used for message integrity.  It identifies
// the username and password combination used in the message-integrity
// check.
//
// The value of USERNAME is a variable-length value.  It MUST contain a
// UTF-8 [RFC3629] encoded sequence of less than 513 bytes, and MUST
// have been processed using SASLprep [RFC4013].
type Username struct {
	Username string
}

const (
	usernameMaxLength = 513
)

func (u *Username) Pack(message *Message) error {
	if len([]byte(u.Username)) > usernameMaxLength {
		return errors.Errorf("invalid username length %d", len([]byte(u.Username)))
	}
	message.AddAttribute(AttrUsername, []byte(u.Username))
	return nil
}

func (u *Username) Unpack(message *Message, rawAttribute *RawAttribute) error {
	u.Username = string(rawAttribute.Value)
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/cespare/blackfriday"
	"io/ioutil"
	"os"
)

func main() {
	contents, err := ioutil.ReadFile("test.md")
	if err != nil {
		panic(err)
	}
	flags := 0
	flags |= blackfriday.HTML_COMPLETE_PAGE
	flags |= blackfriday.HTML_GITHUB_BLOCKCODE
	renderer := blackfriday.HtmlRenderer(flags, "Title!", "")

	extensions := 0
	extensions |= blackfriday.EXTENSION_FENCED_CODE
	extensions |= blackfriday.EXTENSION_TABLES
	extensions |= blackfriday.EXTENSION_NO_INTRA_EMPHASIS
	extensions |= blackfriday.EXTENSION_SPACE_HEADERS
	output := blackfriday.Markdown(contents, renderer, extensions)
	os.Stdout.Write(output)
}
<commit_msg>Get initial markdown rendering with pygments working.<commit_after>package main

import (
	"bytes"
	"github.com/cespare/blackfriday"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
)

var (
	pygmentize         = "./vendor/pygments/pygmentize"
	validLanguages     = make(map[string]struct{})
	markdownRenderer   *blackfriday.Html
	markdownExtensions int
)

func init() {
	// Get the list of valid lexers from pygments.
	rawLexerList, err := exec.Command(pygmentize, "-L", "lexers").Output()
	if err != nil {
		log.Fatalln(err)
	}
	for _, line := range bytes.Split(rawLexerList, []byte("\n")) {
		if len(line) == 0 || line[0] != '*' {
			continue
		}
		for _, l := range bytes.Split(bytes.Trim(line, "* :"), []byte(",")) {
			lexer := string(bytes.TrimSpace(l))
			if len(lexer) != 0 {
				validLanguages[lexer] = struct{}{}
			}
		}
	}

	// Set up the renderer.
	flags := 0
	flags |= blackfriday.HTML_GITHUB_BLOCKCODE
	markdownRenderer = blackfriday.HtmlRenderer(flags, "", "")
	markdownRenderer.SetBlockCodeProcessor(syntaxHighlight)

	markdownExtensions = 0
	markdownExtensions |= blackfriday.EXTENSION_FENCED_CODE
	markdownExtensions |= blackfriday.EXTENSION_TABLES
	markdownExtensions |= blackfriday.EXTENSION_NO_INTRA_EMPHASIS
	markdownExtensions |= blackfriday.EXTENSION_SPACE_HEADERS
}

func syntaxHighlight(out io.Writer, in io.Reader, language string) {
	_, ok := validLanguages[language]
	if !ok || language == "" {
		language = "text"
	}
	pygmentsCommand := exec.Command(pygmentize, "-l", language, "-f", "html")
	pygmentsCommand.Stdin = in
	pygmentsCommand.Stdout = out
	pygmentsCommand.Run()
}

func main() {
	contents, err := ioutil.ReadFile("test.md")
	if err != nil {
		panic(err)
	}
	output := blackfriday.Markdown(contents, markdownRenderer, markdownExtensions)
	os.Stdout.Write(output)
}
<|endoftext|>


<commit_before>package keystore

import (
	"crypto/rand"
	"errors"
	"fmt"
	"github.com/cossacklabs/acra/utils"
	"github.com/cossacklabs/acra/zone"
	"github.com/cossacklabs/themis/gothemis/keys"
	log "github.com/sirupsen/logrus"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"sync"
)

type FilesystemKeyStore struct {
	keys                map[string][]byte
	privateKeyDirectory string
	publicKeyDirectory  string
	directory           string
	lock                *sync.RWMutex
	encryptor           KeyEncryptor
}

func NewFilesystemKeyStore(directory string, encryptor KeyEncryptor) (*FilesystemKeyStore, error) {
	return NewFilesystemKeyStoreTwoPath(directory, directory, encryptor)
}

func NewFilesystemKeyStoreTwoPath(privateKeyFolder, publicKeyFolder string, encryptor KeyEncryptor) (*FilesystemKeyStore, error) {
	// check folder for private key
	directory, err := utils.AbsPath(privateKeyFolder)
	if err != nil {
		return nil, err
	}
	fi, err := os.Stat(directory)
	if nil == err && runtime.GOOS == "linux" && fi.Mode().Perm().String() != "-rwx------" {
		log.Errorln(" key store folder has an incorrect permissions")
		return nil, errors.New("key store folder has an incorrect permissions")
	}
	if privateKeyFolder != publicKeyFolder {
		// check folder for public key
		directory, err = utils.AbsPath(privateKeyFolder)
		if err != nil {
			return nil, err
		}
		fi, err = os.Stat(directory)
		if nil != err && !os.IsNotExist(err) {
			return nil, err
		}
	}
	return &FilesystemKeyStore{privateKeyDirectory: privateKeyFolder, publicKeyDirectory: publicKeyFolder,
		keys: make(map[string][]byte), lock: &sync.RWMutex{}, encryptor: encryptor}, nil
}

func (store *FilesystemKeyStore) generateKeyPair(filename string, clientId []byte) (*keys.Keypair, error) {
	keypair, err := keys.New(keys.KEYTYPE_EC)
	if err != nil {
		return nil, err
	}
	privateKeysFolder := filepath.Dir(store.getPrivateKeyFilePath(filename))
	err = os.MkdirAll(privateKeysFolder, 0700)
	if err != nil {
		return nil, err
	}

	publicKeysFolder := filepath.Dir(store.getPublicKeyFilePath(filename))
	err = os.MkdirAll(publicKeysFolder, 0700)
	if err != nil {
		return nil, err
	}

	encryptedPrivate, err := store.encryptor.Encrypt(keypair.Private.Value, clientId)
	if err != nil {
		return nil, err
	}
	err = ioutil.WriteFile(store.getPrivateKeyFilePath(filename), encryptedPrivate, 0600)
	if err != nil {
		return nil, err
	}
	err = ioutil.WriteFile(store.getPublicKeyFilePath(fmt.Sprintf("%s.pub", filename)), keypair.Public.Value, 0644)
	if err != nil {
		return nil, err
	}
	return keypair, nil
}

func (store *FilesystemKeyStore) generateKey(filename string, length uint8) ([]byte, error) {
	randomBytes := make([]byte, length)
	_, err := rand.Read(randomBytes)
	// Note that err == nil only if we read len(b) bytes.
	if err != nil {
		log.Error(err)
		return nil, err
	}
	dirpath := filepath.Dir(store.getPrivateKeyFilePath(filename))
	err = os.MkdirAll(dirpath, 0700)
	if err != nil {
		log.Error(err)
		return nil, err
	}
	err = ioutil.WriteFile(store.getPrivateKeyFilePath(filename), randomBytes, 0600)
	if err != nil {
		log.Error(err)
		return nil, err
	}
	return randomBytes, nil
}

func (store *FilesystemKeyStore) GenerateZoneKey() ([]byte, []byte, error) {
	/* save private key in fs, return id and public key*/
	var id []byte
	for {
		// generate until key not exists
		id = zone.GenerateZoneId()
		if !store.HasZonePrivateKey(id) {
			break
		}
	}

	keypair, err := store.generateKeyPair(getZoneKeyFilename(id), id)
	if err != nil {
		return []byte{}, []byte{}, err
	}
	store.lock.Lock()
	defer store.lock.Unlock()
	// cache key
	store.keys[getZoneKeyFilename(id)] = keypair.Private.Value
	return id, keypair.Public.Value, nil
}

func (store *FilesystemKeyStore) getPrivateKeyFilePath(filename string) string {
	return fmt.Sprintf("%s%s%s", store.privateKeyDirectory, string(os.PathSeparator), filename)
}

func (store *FilesystemKeyStore) getPublicKeyFilePath(filename string) string {
	return fmt.Sprintf("%s%s%s", store.publicKeyDirectory, string(os.PathSeparator), filename)
}

func (store *FilesystemKeyStore) GetZonePrivateKey(id []byte) (*keys.PrivateKey, error) {
	if !ValidateId(id) {
		return nil, ErrInvalidClientId
	}
	fname := getZoneKeyFilename(id)
	store.lock.Lock()
	defer store.lock.Unlock()
	key, ok := store.keys[fname]
	if ok {
		log.Debugf("load cached key: %s", fname)
		return &keys.PrivateKey{Value: key}, nil
	}
	privateKey, err := utils.LoadPrivateKey(store.getPrivateKeyFilePath(fname))
	if err != nil {
		return nil, err
	}
	if privateKey.Value, err = store.encryptor.Decrypt(privateKey.Value, id); err != nil {
		return nil, err
	}
	log.Debugf("load key from fs: %s", fname)
	store.keys[fname] = privateKey.Value
	return privateKey, nil
}

func (store *FilesystemKeyStore) HasZonePrivateKey(id []byte) bool {
	if !ValidateId(id) {
		return false
	}
	// add caching false answers. now if key doesn't exists than always checks on fs
	// it's system call and slow.
	if len(id) == 0 {
		return false
	}
	fname := getZoneKeyFilename(id)
	store.lock.RLock()
	defer store.lock.RUnlock()
	_, ok := store.keys[fname]
	if ok {
		return true
	}
	exists, _ := utils.FileExists(store.getPrivateKeyFilePath(fname))
	return exists
}

func (store *FilesystemKeyStore) GetPeerPublicKey(id []byte) (*keys.PublicKey, error) {
	if !ValidateId(id) {
		return nil, ErrInvalidClientId
	}
	fname := getPublicKeyFilename(id)
	store.lock.Lock()
	defer store.lock.Unlock()
	key, ok := store.keys[fname]
	if ok {
		log.Debugf("load cached key: %s", fname)
		return &keys.PublicKey{Value: key}, nil
	}
	publicKey, err := utils.LoadPublicKey(store.getPublicKeyFilePath(fname))
	if err != nil {
		return nil, err
	}
	log.Debugf("load key from fs: %s", fname)
	store.keys[fname] = publicKey.Value
	return publicKey, nil
}

func (store *FilesystemKeyStore) GetPrivateKey(id []byte) (*keys.PrivateKey, error) {
	if !ValidateId(id) {
		return nil, ErrInvalidClientId
	}
	fname := getServerKeyFilename(id)
	lock.Lock()
	defer lock.Unlock()
	key, ok := store.keys[fname]
	if ok {
		log.Debugf("load cached key: %s", fname)
		return &keys.PrivateKey{Value: key}, nil
	}
	privateKey, err := utils.LoadPrivateKey(store.getPrivateKeyFilePath(fname))
	if err != nil {
		return nil, err
	}
	if privateKey.Value, err = store.encryptor.Decrypt(privateKey.Value, id); err != nil {
		return nil, err
	}
	log.Debugf("load key from fs: %s", fname)
	store.keys[fname] = privateKey.Value
	return privateKey, nil
}

func (store *FilesystemKeyStore) GetServerDecryptionPrivateKey(id []byte) (*keys.PrivateKey, error) {
	if !ValidateId(id) {
		return nil, ErrInvalidClientId
	}
	fname := getServerDecryptionKeyFilename(id)
	store.lock.Lock()
	defer store.lock.Unlock()
	key, ok := store.keys[fname]
	if ok {
		log.Debugf("load cached key: %s", fname)
		return &keys.PrivateKey{Value: key}, nil
	}
	privateKey, err := utils.LoadPrivateKey(store.getPrivateKeyFilePath(fname))
	if err != nil {
		return nil, err
	}
	if privateKey.Value, err = store.encryptor.Decrypt(privateKey.Value, id); err != nil {
		return nil, err
	}
	log.Debugf("load key from fs: %s", fname)
	store.keys[fname] = privateKey.Value
	return privateKey, nil
}

func (store *FilesystemKeyStore) GenerateConnectorKeys(id []byte) error {
	if !ValidateId(id) {
		return ErrInvalidClientId
	}
	filename := getConnectorKeyFilename(id)

	_, err := store.generateKeyPair(filename, id)
	if err != nil {
		return err
	}
	return nil
}
func (store *FilesystemKeyStore) GenerateServerKeys(id []byte) error {
	if !ValidateId(id) {
		return ErrInvalidClientId
	}
	filename := getServerKeyFilename(id)
	_, err := store.generateKeyPair(filename, id)
	if err != nil {
		return err
	}
	return nil
}

// generate key pair for data encryption/decryption
func (store *FilesystemKeyStore) GenerateDataEncryptionKeys(id []byte) error {
	if !ValidateId(id) {
		return ErrInvalidClientId
	}
	_, err := store.generateKeyPair(getServerDecryptionKeyFilename(id), id)
	if err != nil {
		return err
	}
	return nil
}

// clear all cached keys
func (store *FilesystemKeyStore) Reset() {
	store.keys = make(map[string][]byte)
}

func (store *FilesystemKeyStore) GetPoisonKeyPair() (*keys.Keypair, error) {
	privatePath := store.getPrivateKeyFilePath(POISON_KEY_FILENAME)
	publicPath := store.getPublicKeyFilePath(fmt.Sprintf("%s.pub", POISON_KEY_FILENAME))
	privateExists, err := utils.FileExists(privatePath)
	if err != nil {
		return nil, err
	}
	publicExists, err := utils.FileExists(publicPath)
	if err != nil {
		return nil, err
	}
	if privateExists && publicExists {
		private, err := utils.LoadPrivateKey(privatePath)
		if err != nil {
			return nil, err
		}
		if private.Value, err = store.encryptor.Decrypt(private.Value, []byte(POISON_KEY_FILENAME)); err != nil {
			return nil, err
		}
		public, err := utils.LoadPublicKey(publicPath)
		if err != nil {
			return nil, err
		}
		return &keys.Keypair{Public: public, Private: private}, nil
	}
	log.Infoln("Generate poison key pair")
	return store.generateKeyPair(POISON_KEY_FILENAME, []byte(POISON_KEY_FILENAME))
}

func (store *FilesystemKeyStore) GetAuthKey(remove bool) ([]byte, error) {
	keyPath := store.getPrivateKeyFilePath(BASIC_AUTH_KEY_FILENAME)
	keyExists, err := utils.FileExists(keyPath)
	if err != nil {
		log.Error(err)
		return nil, err
	}
	if keyExists && !remove {
		key, err := utils.ReadFile(keyPath)
		if err != nil {
			log.Error(err)
			return nil, err
		}
		return key, nil
	}
	log.Infof("Generate basic auth key for AcraWebconfig to %v", keyPath)
	return store.generateKey(BASIC_AUTH_KEY_FILENAME, BASIC_AUTH_KEY_LENGTH)
}
<commit_msg>store encrypted keys in cache (#202)<commit_after>package keystore

import (
	"crypto/rand"
	"errors"
	"fmt"
	"github.com/cossacklabs/acra/utils"
	"github.com/cossacklabs/acra/zone"
	"github.com/cossacklabs/themis/gothemis/keys"
	log "github.com/sirupsen/logrus"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"sync"
)

type FilesystemKeyStore struct {
	keys                map[string][]byte
	privateKeyDirectory string
	publicKeyDirectory  string
	directory           string
	lock                *sync.RWMutex
	encryptor           KeyEncryptor
}

func NewFilesystemKeyStore(directory string, encryptor KeyEncryptor) (*FilesystemKeyStore, error) {
	return NewFilesystemKeyStoreTwoPath(directory, directory, encryptor)
}

func NewFilesystemKeyStoreTwoPath(privateKeyFolder, publicKeyFolder string, encryptor KeyEncryptor) (*FilesystemKeyStore, error) {
	// check folder for private key
	directory, err := utils.AbsPath(privateKeyFolder)
	if err != nil {
		return nil, err
	}
	fi, err := os.Stat(directory)
	if nil == err && runtime.GOOS == "linux" && fi.Mode().Perm().String() != "-rwx------" {
		log.Errorln(" key store folder has an incorrect permissions")
		return nil, errors.New("key store folder has an incorrect permissions")
	}
	if privateKeyFolder != publicKeyFolder {
		// check folder for public key
		directory, err = utils.AbsPath(privateKeyFolder)
		if err != nil {
			return nil, err
		}
		fi, err = os.Stat(directory)
		if nil != err && !os.IsNotExist(err) {
			return nil, err
		}
	}
	return &FilesystemKeyStore{privateKeyDirectory: privateKeyFolder, publicKeyDirectory: publicKeyFolder,
		keys: make(map[string][]byte), lock: &sync.RWMutex{}, encryptor: encryptor}, nil
}

func (store *FilesystemKeyStore) generateKeyPair(filename string, clientId []byte) (*keys.Keypair, error) {
	keypair, err := keys.New(keys.KEYTYPE_EC)
	if err != nil {
		return nil, err
	}
	privateKeysFolder := filepath.Dir(store.getPrivateKeyFilePath(filename))
	err = os.MkdirAll(privateKeysFolder, 0700)
	if err != nil {
		return nil, err
	}

	publicKeysFolder := filepath.Dir(store.getPublicKeyFilePath(filename))
	err = os.MkdirAll(publicKeysFolder, 0700)
	if err != nil {
		return nil, err
	}

	encryptedPrivate, err := store.encryptor.Encrypt(keypair.Private.Value, clientId)
	if err != nil {
		return nil, err
	}
	err = ioutil.WriteFile(store.getPrivateKeyFilePath(filename), encryptedPrivate, 0600)
	if err != nil {
		return nil, err
	}
	err = ioutil.WriteFile(store.getPublicKeyFilePath(fmt.Sprintf("%s.pub", filename)), keypair.Public.Value, 0644)
	if err != nil {
		return nil, err
	}
	return keypair, nil
}

func (store *FilesystemKeyStore) generateKey(filename string, length uint8) ([]byte, error) {
	randomBytes := make([]byte, length)
	_, err := rand.Read(randomBytes)
	// Note that err == nil only if we read len(b) bytes.
	if err != nil {
		log.Error(err)
		return nil, err
	}
	dirpath := filepath.Dir(store.getPrivateKeyFilePath(filename))
	err = os.MkdirAll(dirpath, 0700)
	if err != nil {
		log.Error(err)
		return nil, err
	}
	err = ioutil.WriteFile(store.getPrivateKeyFilePath(filename), randomBytes, 0600)
	if err != nil {
		log.Error(err)
		return nil, err
	}
	return randomBytes, nil
}

func (store *FilesystemKeyStore) GenerateZoneKey() ([]byte, []byte, error) {
	/* save private key in fs, return id and public key*/
	var id []byte
	for {
		// generate until key not exists
		id = zone.GenerateZoneId()
		if !store.HasZonePrivateKey(id) {
			break
		}
	}

	keypair, err := store.generateKeyPair(getZoneKeyFilename(id), id)
	if err != nil {
		return []byte{}, []byte{}, err
	}
	store.lock.Lock()
	defer store.lock.Unlock()
	encryptedKey, err := store.encryptor.Encrypt(keypair.Private.Value, id)
	if err != nil {
		return nil, nil, nil
	}
	utils.FillSlice(byte(0), keypair.Private.Value)
	// cache key
	store.keys[getZoneKeyFilename(id)] = encryptedKey
	return id, keypair.Public.Value, nil
}

func (store *FilesystemKeyStore) getPrivateKeyFilePath(filename string) string {
	return fmt.Sprintf("%s%s%s", store.privateKeyDirectory, string(os.PathSeparator), filename)
}

func (store *FilesystemKeyStore) getPublicKeyFilePath(filename string) string {
	return fmt.Sprintf("%s%s%s", store.publicKeyDirectory, string(os.PathSeparator), filename)
}

func (store *FilesystemKeyStore) getPrivateKeyByFilename(id []byte, filename string) (*keys.PrivateKey, error) {
	if !ValidateId(id) {
		return nil, ErrInvalidClientId
	}
	store.lock.Lock()
	defer store.lock.Unlock()
	encryptedKey, ok := store.keys[filename]
	if !ok {
		encryptedPrivateKey, err := utils.LoadPrivateKey(store.getPrivateKeyFilePath(filename))
		if err != nil {
			return nil, err
		}
		encryptedKey = encryptedPrivateKey.Value
	}

	decryptedKey, err := store.encryptor.Decrypt(encryptedKey, id)
	if err != nil {
		return nil, err
	}
	log.Debugf("load key from fs: %s", filename)
	store.keys[filename] = encryptedKey
	return &keys.PrivateKey{Value: decryptedKey}, nil
}

func (store *FilesystemKeyStore) GetZonePrivateKey(id []byte) (*keys.PrivateKey, error) {
	fname := getZoneKeyFilename(id)
	return store.getPrivateKeyByFilename(id, fname)
}

func (store *FilesystemKeyStore) HasZonePrivateKey(id []byte) bool {
	if !ValidateId(id) {
		return false
	}
	// add caching false answers. now if key doesn't exists than always checks on fs
	// it's system call and slow.
	if len(id) == 0 {
		return false
	}
	fname := getZoneKeyFilename(id)
	store.lock.RLock()
	defer store.lock.RUnlock()
	_, ok := store.keys[fname]
	if ok {
		return true
	}
	exists, _ := utils.FileExists(store.getPrivateKeyFilePath(fname))
	return exists
}

func (store *FilesystemKeyStore) GetPeerPublicKey(id []byte) (*keys.PublicKey, error) {
	if !ValidateId(id) {
		return nil, ErrInvalidClientId
	}
	fname := getPublicKeyFilename(id)
	store.lock.Lock()
	defer store.lock.Unlock()
	key, ok := store.keys[fname]
	if ok {
		log.Debugf("load cached key: %s", fname)
		return &keys.PublicKey{Value: key}, nil
	}
	publicKey, err := utils.LoadPublicKey(store.getPublicKeyFilePath(fname))
	if err != nil {
		return nil, err
	}
	log.Debugf("load key from fs: %s", fname)
	store.keys[fname] = publicKey.Value
	return publicKey, nil
}

func (store *FilesystemKeyStore) GetPrivateKey(id []byte) (*keys.PrivateKey, error) {
	fname := getServerKeyFilename(id)
	return store.getPrivateKeyByFilename(id, fname)
}

func (store *FilesystemKeyStore) GetServerDecryptionPrivateKey(id []byte) (*keys.PrivateKey, error) {
	fname := getServerDecryptionKeyFilename(id)
	return store.getPrivateKeyByFilename(id, fname)
}

func (store *FilesystemKeyStore) GenerateConnectorKeys(id []byte) error {
	if !ValidateId(id) {
		return ErrInvalidClientId
	}
	filename := getConnectorKeyFilename(id)

	_, err := store.generateKeyPair(filename, id)
	if err != nil {
		return err
	}
	return nil
}
func (store *FilesystemKeyStore) GenerateServerKeys(id []byte) error {
	if !ValidateId(id) {
		return ErrInvalidClientId
	}
	filename := getServerKeyFilename(id)
	_, err := store.generateKeyPair(filename, id)
	if err != nil {
		return err
	}
	return nil
}

// generate key pair for data encryption/decryption
func (store *FilesystemKeyStore) GenerateDataEncryptionKeys(id []byte) error {
	if !ValidateId(id) {
		return ErrInvalidClientId
	}
	_, err := store.generateKeyPair(getServerDecryptionKeyFilename(id), id)
	if err != nil {
		return err
	}
	return nil
}

// clear all cached keys
func (store *FilesystemKeyStore) Reset() {
	for _, encryptedKey := range store.keys {
		utils.FillSlice(byte(0), encryptedKey)
	}
	store.keys = make(map[string][]byte)
}

func (store *FilesystemKeyStore) GetPoisonKeyPair() (*keys.Keypair, error) {
	privatePath := store.getPrivateKeyFilePath(POISON_KEY_FILENAME)
	publicPath := store.getPublicKeyFilePath(fmt.Sprintf("%s.pub", POISON_KEY_FILENAME))
	privateExists, err := utils.FileExists(privatePath)
	if err != nil {
		return nil, err
	}
	publicExists, err := utils.FileExists(publicPath)
	if err != nil {
		return nil, err
	}
	if privateExists && publicExists {
		private, err := utils.LoadPrivateKey(privatePath)
		if err != nil {
			return nil, err
		}
		if private.Value, err = store.encryptor.Decrypt(private.Value, []byte(POISON_KEY_FILENAME)); err != nil {
			return nil, err
		}
		public, err := utils.LoadPublicKey(publicPath)
		if err != nil {
			return nil, err
		}
		return &keys.Keypair{Public: public, Private: private}, nil
	}
	log.Infoln("Generate poison key pair")
	return store.generateKeyPair(POISON_KEY_FILENAME, []byte(POISON_KEY_FILENAME))
}

func (store *FilesystemKeyStore) GetAuthKey(remove bool) ([]byte, error) {
	keyPath := store.getPrivateKeyFilePath(BASIC_AUTH_KEY_FILENAME)
	keyExists, err := utils.FileExists(keyPath)
	if err != nil {
		log.Error(err)
		return nil, err
	}
	if keyExists && !remove {
		key, err := utils.ReadFile(keyPath)
		if err != nil {
			log.Error(err)
			return nil, err
		}
		return key, nil
	}
	log.Infof("Generate basic auth key for AcraWebconfig to %v", keyPath)
	return store.generateKey(BASIC_AUTH_KEY_FILENAME, BASIC_AUTH_KEY_LENGTH)
}
<|endoftext|>


<commit_before>package cloudflare

import (
	"context"
	"fmt"
	"github.com/stretchr/testify/assert"
	"net/http"
	"testing"
)

func TestTotalTLS_GetSettings(t *testing.T) {
	setup()
	defer teardown()

	mux.HandleFunc(fmt.Sprintf("/zones/%s/acm/total_tls", testZoneID), func(w http.ResponseWriter, r *http.Request) {
		assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method)
		w.Header().Set("content-type", "application/json")
		fmt.Fprintf(w, `{
	  "success": true,
	  "errors": [],
	  "messages": [],
	  "result": {
		"enabled": true,
		"certificate_authority": "google",
		"validity_days": 90
	  }
	}`)
	})

	_, err := client.TotalTLSGet(context.Background(), ZoneIdentifier(""))
	if assert.Error(t, err) {
		assert.Equal(t, ErrMissingZoneID, err)
	}

	result, err := client.TotalTLSGet(context.Background(), ZoneIdentifier(testZoneID))
	if assert.NoError(t, err) {
		assert.Equal(t, true, result.Enabled)
		assert.Equal(t, "google", result.CertificateAuthority)
		assert.Equal(t, 90, result.ValidityDays)
	}
}

func TestTotalTLS_SetSettings(t *testing.T) {
	setup()
	defer teardown()

	mux.HandleFunc(fmt.Sprintf("/zones/%s/acm/total_tls", testZoneID), func(w http.ResponseWriter, r *http.Request) {
		assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method)
		w.Header().Set("content-type", "application/json")
		fmt.Fprintf(w, `{
  "success": true,
  "errors": [],
  "messages": [],
  "result": {
    "enabled": true,
    "certificate_authority": "google",
    "validity_days": 90
  }
}`)
	})

	_, err := client.TotalTLSSet(context.Background(), ZoneIdentifier(""), TotalTLS{})
	if assert.Error(t, err) {
		assert.Equal(t, ErrMissingZoneID, err)
	}

	result, err := client.TotalTLSSet(context.Background(), ZoneIdentifier(testZoneID), TotalTLS{CertificateAuthority: "google", Enabled: true})
	if assert.NoError(t, err) {
		assert.Equal(t, true, result.Enabled)
		assert.Equal(t, "google", result.CertificateAuthority)
		assert.Equal(t, 90, result.ValidityDays)
	}
}
<commit_msg>update method names to be <verb><noun> format<commit_after>package cloudflare

import (
	"context"
	"fmt"
	"net/http"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestTotalTLS_GetSettings(t *testing.T) {
	setup()
	defer teardown()

	mux.HandleFunc(fmt.Sprintf("/zones/%s/acm/total_tls", testZoneID), func(w http.ResponseWriter, r *http.Request) {
		assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method)
		w.Header().Set("content-type", "application/json")
		fmt.Fprintf(w, `{
	  "success": true,
	  "errors": [],
	  "messages": [],
	  "result": {
		"enabled": true,
		"certificate_authority": "google",
		"validity_days": 90
	  }
	}`)
	})

	_, err := client.GetTotalTLS(context.Background(), ZoneIdentifier(""))
	if assert.Error(t, err) {
		assert.Equal(t, ErrMissingZoneID, err)
	}

	result, err := client.GetTotalTLS(context.Background(), ZoneIdentifier(testZoneID))
	if assert.NoError(t, err) {
		assert.Equal(t, BoolPtr(true), result.Enabled)
		assert.Equal(t, "google", result.CertificateAuthority)
		assert.Equal(t, 90, result.ValidityDays)
	}
}

func TestTotalTLS_SetSettings(t *testing.T) {
	setup()
	defer teardown()

	mux.HandleFunc(fmt.Sprintf("/zones/%s/acm/total_tls", testZoneID), func(w http.ResponseWriter, r *http.Request) {
		assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method)
		w.Header().Set("content-type", "application/json")
		fmt.Fprintf(w, `{
  "success": true,
  "errors": [],
  "messages": [],
  "result": {
    "enabled": true,
    "certificate_authority": "google",
    "validity_days": 90
  }
}`)
	})

	_, err := client.SetTotalTLS(context.Background(), ZoneIdentifier(""), TotalTLS{})
	if assert.Error(t, err) {
		assert.Equal(t, ErrMissingZoneID, err)
	}

	result, err := client.SetTotalTLS(context.Background(), ZoneIdentifier(testZoneID), TotalTLS{CertificateAuthority: "google", Enabled: BoolPtr(true)})
	if assert.NoError(t, err) {
		assert.Equal(t, BoolPtr(true), result.Enabled)
		assert.Equal(t, "google", result.CertificateAuthority)
		assert.Equal(t, 90, result.ValidityDays)
	}
}
<|endoftext|>


<commit_before>package flame

import (
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestTokenMigrator(t *testing.T) {
	migrator := TokenMigrator(true)

	tester.Handler = migrator(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		assert.Equal(t, "Bearer foo", r.Header.Get("Authorization"))
		assert.Equal(t, "", r.URL.Query().Get("access_token"))

		w.Write([]byte("OK"))
	}))

	tester.Request("GET", "foo?access_token=foo", "", func(r *httptest.ResponseRecorder, rq *http.Request) {
		assert.Equal(t, "OK", r.Body.String())
	})
}

func TestEnsureApplicationAndGetApplicationKey(t *testing.T) {
	tester.Clean()

	key, err := EnsureApplication(tester.Store, "Foo")
	assert.NoError(t, err)

	app := tester.FindLast(&Application{}).(*Application)
	assert.Equal(t, "Foo", app.Name)
	assert.NotEmpty(t, app.Key)
	assert.Equal(t, app.Key, key)
	assert.Empty(t, app.Secret)
	assert.NotEmpty(t, app.SecretHash)
}

func TestEnsureFirstUser(t *testing.T) {
	tester.Clean()

	err := EnsureFirstUser(tester.Store, "Foo", "foo@bar.com", "bar")
	assert.NoError(t, err)

	user := tester.FindLast(&User{}).(*User)
	assert.Equal(t, "Foo", user.Name)
	assert.Equal(t, "foo@bar.com", user.Email)
	assert.Empty(t, user.Password)
	assert.NotEmpty(t, user.PasswordHash)
}
<commit_msg>clean tester<commit_after>package flame

import (
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestTokenMigrator(t *testing.T) {
	tester.Clean()

	migrator := TokenMigrator(true)

	tester.Handler = migrator(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		assert.Equal(t, "Bearer foo", r.Header.Get("Authorization"))
		assert.Equal(t, "", r.URL.Query().Get("access_token"))

		w.Write([]byte("OK"))
	}))

	tester.Request("GET", "foo?access_token=foo", "", func(r *httptest.ResponseRecorder, rq *http.Request) {
		assert.Equal(t, "OK", r.Body.String())
	})
}

func TestEnsureApplicationAndGetApplicationKey(t *testing.T) {
	tester.Clean()

	key, err := EnsureApplication(tester.Store, "Foo")
	assert.NoError(t, err)

	app := tester.FindLast(&Application{}).(*Application)
	assert.Equal(t, "Foo", app.Name)
	assert.NotEmpty(t, app.Key)
	assert.Equal(t, app.Key, key)
	assert.Empty(t, app.Secret)
	assert.NotEmpty(t, app.SecretHash)
}

func TestEnsureFirstUser(t *testing.T) {
	tester.Clean()

	err := EnsureFirstUser(tester.Store, "Foo", "foo@bar.com", "bar")
	assert.NoError(t, err)

	user := tester.FindLast(&User{}).(*User)
	assert.Equal(t, "Foo", user.Name)
	assert.Equal(t, "foo@bar.com", user.Email)
	assert.Empty(t, user.Password)
	assert.NotEmpty(t, user.PasswordHash)
}
<|endoftext|>


<commit_before>package torrent_center

import "github.com/bamboV/torrent"

type TrackerSearchResult struct {
	Name string
	Items []torrent.Distribution
}
<commit_msg>Added json mapping<commit_after>package torrent_center

import "github.com/bamboV/torrent"

type TrackerSearchResult struct {
	Name string `json:"name"`
	Items []torrent.Distribution `json:"items"`
}
<|endoftext|>


<commit_before>//+build !windows,!solaris

package dbus

import (
	"bytes"
	"encoding/binary"
	"errors"
	"io"
	"net"
	"syscall"
)

type oobReader struct {
	conn *net.UnixConn
	oob  []byte
	buf  [4096]byte
}

func (o *oobReader) Read(b []byte) (n int, err error) {
	n, oobn, flags, _, err := o.conn.ReadMsgUnix(b, o.buf[:])
	if err != nil {
		return n, err
	}
	if flags&syscall.MSG_CTRUNC != 0 {
		return n, errors.New("dbus: control data truncated (too many fds received)")
	}
	o.oob = append(o.oob, o.buf[:oobn]...)
	return n, nil
}

type unixTransport struct {
	*net.UnixConn
	rdr        *oobReader
	hasUnixFDs bool
}

func newUnixTransport(keys string) (transport, error) {
	var err error

	t := new(unixTransport)
	abstract := getKey(keys, "abstract")
	path := getKey(keys, "path")
	switch {
	case abstract == "" && path == "":
		return nil, errors.New("dbus: invalid address (neither path nor abstract set)")
	case abstract != "" && path == "":
		t.UnixConn, err = net.DialUnix("unix", nil, &net.UnixAddr{Name: "@" + abstract, Net: "unix"})
		if err != nil {
			return nil, err
		}
		return t, nil
	case abstract == "" && path != "":
		t.UnixConn, err = net.DialUnix("unix", nil, &net.UnixAddr{Name: path, Net: "unix"})
		if err != nil {
			return nil, err
		}
		return t, nil
	default:
		return nil, errors.New("dbus: invalid address (both path and abstract set)")
	}
}

func init() {
	transports["unix"] = newUnixTransport
}

func (t *unixTransport) EnableUnixFDs() {
	t.hasUnixFDs = true
}

func (t *unixTransport) ReadMessage() (*Message, error) {
	var (
		blen, hlen uint32
		csheader   [16]byte
		headers    []header
		order      binary.ByteOrder
		unixfds    uint32
	)
	// To be sure that all bytes of out-of-band data are read, we use a special
	// reader that uses ReadUnix on the underlying connection instead of Read
	// and gathers the out-of-band data in a buffer.
	if t.rdr == nil {
		t.rdr = &oobReader{conn: t.UnixConn}
	} else {
		t.rdr.oob = nil
	}

	// read the first 16 bytes (the part of the header that has a constant size),
	// from which we can figure out the length of the rest of the message
	if _, err := io.ReadFull(t.rdr, csheader[:]); err != nil {
		return nil, err
	}
	switch csheader[0] {
	case 'l':
		order = binary.LittleEndian
	case 'B':
		order = binary.BigEndian
	default:
		return nil, InvalidMessageError("invalid byte order")
	}
	// csheader[4:8] -> length of message body, csheader[12:16] -> length of
	// header fields (without alignment)
	binary.Read(bytes.NewBuffer(csheader[4:8]), order, &blen)
	binary.Read(bytes.NewBuffer(csheader[12:]), order, &hlen)
	if hlen%8 != 0 {
		hlen += 8 - (hlen % 8)
	}

	// decode headers and look for unix fds
	headerdata := make([]byte, hlen+4)
	copy(headerdata, csheader[12:])
	if _, err := io.ReadFull(t.rdr, headerdata[4:]); err != nil {
		return nil, err
	}
	dec := newDecoder(bytes.NewBuffer(headerdata), order, make([]int, 0))
	dec.pos = 12
	vs, err := dec.Decode(Signature{"a(yv)"})
	if err != nil {
		return nil, err
	}
	Store(vs, &headers)
	for _, v := range headers {
		if v.Field == byte(FieldUnixFDs) {
			unixfds, _ = v.Variant.value.(uint32)
		}
	}
	all := make([]byte, 16+hlen+blen)
	copy(all, csheader[:])
	copy(all[16:], headerdata[4:])
	if _, err := io.ReadFull(t.rdr, all[16+hlen:]); err != nil {
		return nil, err
	}
	if unixfds != 0 {
		if !t.hasUnixFDs {
			return nil, errors.New("dbus: got unix fds on unsupported transport")
		}
		// read the fds from the OOB data
		scms, err := syscall.ParseSocketControlMessage(t.rdr.oob)
		if err != nil {
			return nil, err
		}
		if len(scms) != 1 {
			return nil, errors.New("dbus: received more than one socket control message")
		}
		fds, err := syscall.ParseUnixRights(&scms[0])
		if err != nil {
			return nil, err
		}
		msg, err := DecodeMessageWithFDs(bytes.NewBuffer(all), fds)
		if err != nil {
			return nil, err
		}
		// substitute the values in the message body (which are indices for the
		// array receiver via OOB) with the actual values
		for i, v := range msg.Body {
			switch v.(type) {
			case UnixFDIndex:
				j := v.(UnixFDIndex)
				if uint32(j) >= unixfds {
					return nil, InvalidMessageError("invalid index for unix fd")
				}
				msg.Body[i] = UnixFD(fds[j])
			case []UnixFDIndex:
				idxArray := v.([]UnixFDIndex)
				fdArray := make([]UnixFD, len(idxArray))
				for k, j := range idxArray {
					if uint32(j) >= unixfds {
						return nil, InvalidMessageError("invalid index for unix fd")
					}
					fdArray[k] = UnixFD(fds[j])
				}
				msg.Body[i] = fdArray
			}
		}
		return msg, nil
	}
	return DecodeMessage(bytes.NewBuffer(all))
}

func (t *unixTransport) SendMessage(msg *Message) error {
	fdcnt, err := msg.CountFds()
	if err != nil {
		return err
	}
	if fdcnt != 0 {
		if !t.hasUnixFDs {
			return errors.New("dbus: unix fd passing not enabled")
		}
		msg.Headers[FieldUnixFDs] = MakeVariant(uint32(fdcnt))
		buf := new(bytes.Buffer)
		fds, err := msg.EncodeToWithFDs(buf, nativeEndian)
		if err != nil {
			return err
		}
		oob := syscall.UnixRights(fds...)
		n, oobn, err := t.UnixConn.WriteMsgUnix(buf.Bytes(), oob, nil)
		if err != nil {
			return err
		}
		if n != buf.Len() || oobn != len(oob) {
			return io.ErrShortWrite
		}
	} else {
		if err := msg.EncodeTo(t, nativeEndian); err != nil {
			return err
		}
	}
	return nil
}

func (t *unixTransport) SupportsUnixFDs() bool {
	return true
}
<commit_msg>fix: remove redundant type conversions<commit_after>//+build !windows,!solaris

package dbus

import (
	"bytes"
	"encoding/binary"
	"errors"
	"io"
	"net"
	"syscall"
)

type oobReader struct {
	conn *net.UnixConn
	oob  []byte
	buf  [4096]byte
}

func (o *oobReader) Read(b []byte) (n int, err error) {
	n, oobn, flags, _, err := o.conn.ReadMsgUnix(b, o.buf[:])
	if err != nil {
		return n, err
	}
	if flags&syscall.MSG_CTRUNC != 0 {
		return n, errors.New("dbus: control data truncated (too many fds received)")
	}
	o.oob = append(o.oob, o.buf[:oobn]...)
	return n, nil
}

type unixTransport struct {
	*net.UnixConn
	rdr        *oobReader
	hasUnixFDs bool
}

func newUnixTransport(keys string) (transport, error) {
	var err error

	t := new(unixTransport)
	abstract := getKey(keys, "abstract")
	path := getKey(keys, "path")
	switch {
	case abstract == "" && path == "":
		return nil, errors.New("dbus: invalid address (neither path nor abstract set)")
	case abstract != "" && path == "":
		t.UnixConn, err = net.DialUnix("unix", nil, &net.UnixAddr{Name: "@" + abstract, Net: "unix"})
		if err != nil {
			return nil, err
		}
		return t, nil
	case abstract == "" && path != "":
		t.UnixConn, err = net.DialUnix("unix", nil, &net.UnixAddr{Name: path, Net: "unix"})
		if err != nil {
			return nil, err
		}
		return t, nil
	default:
		return nil, errors.New("dbus: invalid address (both path and abstract set)")
	}
}

func init() {
	transports["unix"] = newUnixTransport
}

func (t *unixTransport) EnableUnixFDs() {
	t.hasUnixFDs = true
}

func (t *unixTransport) ReadMessage() (*Message, error) {
	var (
		blen, hlen uint32
		csheader   [16]byte
		headers    []header
		order      binary.ByteOrder
		unixfds    uint32
	)
	// To be sure that all bytes of out-of-band data are read, we use a special
	// reader that uses ReadUnix on the underlying connection instead of Read
	// and gathers the out-of-band data in a buffer.
	if t.rdr == nil {
		t.rdr = &oobReader{conn: t.UnixConn}
	} else {
		t.rdr.oob = nil
	}

	// read the first 16 bytes (the part of the header that has a constant size),
	// from which we can figure out the length of the rest of the message
	if _, err := io.ReadFull(t.rdr, csheader[:]); err != nil {
		return nil, err
	}
	switch csheader[0] {
	case 'l':
		order = binary.LittleEndian
	case 'B':
		order = binary.BigEndian
	default:
		return nil, InvalidMessageError("invalid byte order")
	}
	// csheader[4:8] -> length of message body, csheader[12:16] -> length of
	// header fields (without alignment)
	binary.Read(bytes.NewBuffer(csheader[4:8]), order, &blen)
	binary.Read(bytes.NewBuffer(csheader[12:]), order, &hlen)
	if hlen%8 != 0 {
		hlen += 8 - (hlen % 8)
	}

	// decode headers and look for unix fds
	headerdata := make([]byte, hlen+4)
	copy(headerdata, csheader[12:])
	if _, err := io.ReadFull(t.rdr, headerdata[4:]); err != nil {
		return nil, err
	}
	dec := newDecoder(bytes.NewBuffer(headerdata), order, make([]int, 0))
	dec.pos = 12
	vs, err := dec.Decode(Signature{"a(yv)"})
	if err != nil {
		return nil, err
	}
	Store(vs, &headers)
	for _, v := range headers {
		if v.Field == byte(FieldUnixFDs) {
			unixfds, _ = v.Variant.value.(uint32)
		}
	}
	all := make([]byte, 16+hlen+blen)
	copy(all, csheader[:])
	copy(all[16:], headerdata[4:])
	if _, err := io.ReadFull(t.rdr, all[16+hlen:]); err != nil {
		return nil, err
	}
	if unixfds != 0 {
		if !t.hasUnixFDs {
			return nil, errors.New("dbus: got unix fds on unsupported transport")
		}
		// read the fds from the OOB data
		scms, err := syscall.ParseSocketControlMessage(t.rdr.oob)
		if err != nil {
			return nil, err
		}
		if len(scms) != 1 {
			return nil, errors.New("dbus: received more than one socket control message")
		}
		fds, err := syscall.ParseUnixRights(&scms[0])
		if err != nil {
			return nil, err
		}
		msg, err := DecodeMessageWithFDs(bytes.NewBuffer(all), fds)
		if err != nil {
			return nil, err
		}
		// substitute the values in the message body (which are indices for the
		// array receiver via OOB) with the actual values
		for i, v := range msg.Body {
			switch index := v.(type) {
			case UnixFDIndex:
				if uint32(index) >= unixfds {
					return nil, InvalidMessageError("invalid index for unix fd")
				}
				msg.Body[i] = UnixFD(fds[index])
			case []UnixFDIndex:
				fdArray := make([]UnixFD, len(index))
				for k, j := range index {
					if uint32(j) >= unixfds {
						return nil, InvalidMessageError("invalid index for unix fd")
					}
					fdArray[k] = UnixFD(fds[j])
				}
				msg.Body[i] = fdArray
			}
		}
		return msg, nil
	}
	return DecodeMessage(bytes.NewBuffer(all))
}

func (t *unixTransport) SendMessage(msg *Message) error {
	fdcnt, err := msg.CountFds()
	if err != nil {
		return err
	}
	if fdcnt != 0 {
		if !t.hasUnixFDs {
			return errors.New("dbus: unix fd passing not enabled")
		}
		msg.Headers[FieldUnixFDs] = MakeVariant(uint32(fdcnt))
		buf := new(bytes.Buffer)
		fds, err := msg.EncodeToWithFDs(buf, nativeEndian)
		if err != nil {
			return err
		}
		oob := syscall.UnixRights(fds...)
		n, oobn, err := t.UnixConn.WriteMsgUnix(buf.Bytes(), oob, nil)
		if err != nil {
			return err
		}
		if n != buf.Len() || oobn != len(oob) {
			return io.ErrShortWrite
		}
	} else {
		if err := msg.EncodeTo(t, nativeEndian); err != nil {
			return err
		}
	}
	return nil
}

func (t *unixTransport) SupportsUnixFDs() bool {
	return true
}
<|endoftext|>


<commit_before>// http://golang.org/pkg/net/http/

package sloth

import (
  "fmt"
  "net/http"
  "net/url"
  // "time"
)

type RestError interface {
  Error() string
}

// Methods

const (
  GET    = "GET"
  POST   = "POST"
  PUT    = "PUT"
  DELETE = "DELETE"
)

type Getable   interface { Get(values url.Values)    (int, interface{}) }
type Postable  interface { Post(values url.Values)   (int, interface{}) }
type Putable   interface { Put(values url.Values)    (int, interface{}) }
type Deletable interface { Delete(values url.Values) (int, interface{}) }

func (resource *RestResource) Get(values url.Values)    (int, interface{}) { return 405, "" }
func (resource *RestResource) Put(values url.Values)    (int, interface{}) { return 405, "" }
func (resource *RestResource) Post(values url.Values)   (int, interface{}) { return 405, "" }
func (resource *RestResource) Delete(values url.Values) (int, interface{}) { return 405, "" }

// func (getable *Getable) Get(values url.Values) (int, interface{}) {
//   return 405, ""
// }

// Resources

// var _ RestfulResource = (*RestResource)(nil)

type RestfulResource interface {
  all()     (int, interface{})
  byId(int) (int, interface{})

  //MarshalContent(data interface{}) (interface{}, interface{})
  MarshalContent(data interface{}) ([]byte, error)
  RequestHandler() http.HandlerFunc
}

type RestResource struct {
  baseUrl, contentType string
}

func (resource *RestResource) MarshalContent(data interface{}) ([]byte, error) {//(interface{}, interface{}) {
  return AsBytes(data)
}

// type RestRequestInterceptor func(int, interface{})

func (resource *RestResource) RequestHandler() http.HandlerFunc {
  return func(rw http.ResponseWriter, request *http.Request) {
    var data interface{}
    var stat int

    request.ParseForm()
    method := request.Method
    values := request.Form

    // TODO - validate method

    // TODO - base on method interfaces (Getable, Postable) instead
    switch method {
    case GET:
      stat, data = resource.Get(values)
    case POST:
      stat, data = resource.Post(values)
    case PUT:
      stat, data = resource.Put(values)
    case DELETE:
      stat, data = resource.Delete(values)
    default:
      resource.AbortRequest(rw, 405)
      return
    }

    // request filter TODO
    // requestInterceptor

    content, err := resource.MarshalContent(data)

    if err != nil {
      resource.AbortRequest(rw, 500)
    }

    // FIXME - convert content to string..?
    rw.WriteHeader(stat)
    rw.Write(content)
  }
}

func (resource *RestResource) AbortRequest(rw http.ResponseWriter, statusCode int) {
  rw.WriteHeader(statusCode)
}

type RestAPI struct {
  host, base string

  resources []RestResource
}

// Services

// var _ RestfulService = (*RestService)(nil)

type RestfulService interface {
  MarshalContent(data interface{})
  RequestHandler(resource RestResource) http.HandlerFunc
}

type RestService struct {
  baseUri string
}

func (service *RestService) MarshalContent(data interface{}) ([]byte, error) {
  return AsBytes(data)
}

func (service *RestService) AddResource(resource RestResource, path string) { // TODO - make path deprecated, get it from resource
  http.HandleFunc(path, resource.RequestHandler())
}

func (service *RestService) Start(port int) {
  portStr := fmt.Sprintf(":%d", port)

  http.ListenAndServe(portStr, nil)
}

func (service *RestService) Abort(rw http.ResponseWriter, statusCode int) {
  rw.WriteHeader(statusCode)
}
<commit_msg>cleanup<commit_after>// http://golang.org/pkg/net/http/

package sloth

import (
  "fmt"
  "net/http"
  "net/url"
  // "time"
)

// Methods

const (
  GET    = "GET"
  POST   = "POST"
  PUT    = "PUT"
  DELETE = "DELETE"
)

type Getable   interface { Get(values url.Values)    (int, interface{}) }
type Postable  interface { Post(values url.Values)   (int, interface{}) }
type Putable   interface { Put(values url.Values)    (int, interface{}) }
type Deletable interface { Delete(values url.Values) (int, interface{}) }

func (resource *RestResource) Get(values url.Values)    (int, interface{}) { return 405, "" }
func (resource *RestResource) Put(values url.Values)    (int, interface{}) { return 405, "" }
func (resource *RestResource) Post(values url.Values)   (int, interface{}) { return 405, "" }
func (resource *RestResource) Delete(values url.Values) (int, interface{}) { return 405, "" }

// func (getable *Getable) Get(values url.Values) (int, interface{}) {
//   return 405, ""
// }

// Resources

// var _ RestfulResource = (*RestResource)(nil)

type RestError interface {
  Error() string
}

type RestfulResource interface {
  all()     (int, interface{})
  byId(int) (int, interface{})

  //MarshalContent(data interface{}) (interface{}, interface{})
  MarshalContent(data interface{}) ([]byte, error)
  RequestHandler() http.HandlerFunc
}

type RestResource struct {
  baseUrl, contentType string
}

func (resource *RestResource) MarshalContent(data interface{}) ([]byte, error) {//(interface{}, interface{}) {
  return AsBytes(data)
}

// type RestRequestInterceptor func(int, interface{})

func (resource *RestResource) RequestHandler() http.HandlerFunc {
  return func(rw http.ResponseWriter, request *http.Request) {
    var data interface{}
    var stat int

    request.ParseForm()
    method := request.Method
    values := request.Form

    // TODO - validate method

    // TODO - base on method interfaces (Getable, Postable) instead
    switch method {
    case GET:
      stat, data = resource.Get(values)
    case POST:
      stat, data = resource.Post(values)
    case PUT:
      stat, data = resource.Put(values)
    case DELETE:
      stat, data = resource.Delete(values)
    default:
      resource.AbortRequest(rw, 405)
      return
    }

    // request filter TODO
    // requestInterceptor

    content, err := resource.MarshalContent(data)

    if err != nil {
      resource.AbortRequest(rw, 500)
    }

    // FIXME - convert content to string..?
    rw.WriteHeader(stat)
    rw.Write(content)
  }
}

func (resource *RestResource) AbortRequest(rw http.ResponseWriter, statusCode int) {
  rw.WriteHeader(statusCode)
}

type RestAPI struct {
  host, base string

  resources []RestResource
}

// Services

// var _ RestfulService = (*RestService)(nil)

type RestfulService interface {
  MarshalContent(data interface{})
  RequestHandler(resource RestResource) http.HandlerFunc
}

type RestService struct {
  baseUri string
}

func (service *RestService) MarshalContent(data interface{}) ([]byte, error) {
  return AsBytes(data)
}

func (service *RestService) AddResource(resource RestResource, path string) { // TODO - make path deprecated, get it from resource
  http.HandleFunc(path, resource.RequestHandler())
}

func (service *RestService) Start(port int) {
  portStr := fmt.Sprintf(":%d", port)

  http.ListenAndServe(portStr, nil)
}

func (service *RestService) Abort(rw http.ResponseWriter, statusCode int) {
  rw.WriteHeader(statusCode)
}<|endoftext|>


<commit_before>// Package pastebin is a simple modern and powerful pastebin service
package main

import (
	"crypto/sha1"
	"database/sql"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"html"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"time"

	duration "github.com/channelmeter/iso8601duration"
	// uniuri is used for easy random string generation
	"github.com/dchest/uniuri"
	// pygments is used for syntax highlighting
	"github.com/ewhal/pygments"
	// mysql driver
	_ "github.com/go-sql-driver/mysql"
	// mux is used for url routing
	"github.com/gorilla/mux"
)

type Configuration struct {
	// ADDRESS that pastebin will return links for
	Address string
	// LENGTH of paste id
	Length int
	// PORT that pastebin will listen on
	Port string
	// USERNAME for database
	Username string
	// PASS database password
	Password string
	// NAME database name
	Name string
}

var configuration Configuration

// DATABASE connection String
var DATABASE string

// Template pages
var templates = template.Must(template.ParseFiles("assets/paste.html", "assets/index.html", "assets/clone.html"))
var syntax, _ = ioutil.ReadFile("assets/syntax.html")

// Response API struct
type Response struct {
	SUCCESS bool   `json:"success"`
	STATUS  string `json:"status"`
	ID      string `json:"id"`
	TITLE   string `json:"title"`
	SHA1    string `json:"sha1"`
	URL     string `json:"url"`
	SIZE    int    `json:"size"`
	DELKEY  string `json:"delkey"`
}

// Page generation struct
type Page struct {
	Title    string
	Body     []byte
	Raw      string
	Home     string
	Download string
	Clone    string
}

// check error handling function
func Check(err error) {
	if err != nil {
		log.Println(err)
	}
}

// GenerateName uses uniuri to generate a random string that isn't in the
// database
func GenerateName() string {
	// use uniuri to generate random string
	id := uniuri.NewLen(configuration.Length)

	db, err := sql.Open("mysql", DATABASE)
	Check(err)
	defer db.Close()
	// query database if id exists and if it does call generateName again
	_, err = db.Query("select id from pastebin where id=?", id)
	if err != sql.ErrNoRows {
		GenerateName()
	}

	return id

}

// Sha1 hashes paste into a sha1 hash
func Sha1(paste string) string {
	hasher := sha1.New()

	hasher.Write([]byte(paste))
	sha := base64.URLEncoding.EncodeToString(hasher.Sum(nil))
	return sha
}

// DurationFromExpiry takes the expiry in string format and returns the duration
// that the paste will exist for
func DurationFromExpiry(expiry string) time.Duration {
	if expiry == "" {
		expiry = "P20Y"
	}
	dura, err := duration.FromString(expiry) // dura is time.Duration type
	Check(err)

	duration := dura.ToDuration()

	return duration
}

// Save function handles the saving of each paste.
// raw string is the raw paste input
// lang string is the user specified language for syntax highlighting
// title string user customized title
// expiry string duration that the paste will exist for
// Returns Response struct
func Save(raw string, lang string, title string, expiry string) Response {

	db, err := sql.Open("mysql", DATABASE)
	Check(err)
	defer db.Close()

	// hash paste data and query database to see if paste exists
	sha := Sha1(raw)
	query, err := db.Query("select id, title, hash, data, delkey from pastebin where hash=?", sha)

	if err != sql.ErrNoRows {
		for query.Next() {
			var id, title, hash, paste, delkey string
			err := query.Scan(&id, &title, &hash, &paste, &delkey)
			Check(err)
			url := configuration.Address + "/p/" + id
			return Response{true, "saved", id, title, hash, url, len(paste), delkey}
		}
	}
	id := GenerateName()
	url := configuration.Address + "/p/" + id
	if lang != "" {
		url += "/" + lang
	}

	const timeFormat = "2006-01-02 15:04:05"
	expiryTime := time.Now().Add(DurationFromExpiry(expiry)).Format(timeFormat)

	delKey := uniuri.NewLen(40)
	dataEscaped := html.EscapeString(raw)

	stmt, err := db.Prepare("INSERT INTO pastebin(id, title, hash, data, delkey, expiry) values(?,?,?,?,?,?)")
	Check(err)
	if title == "" {
		title = id
	}
	_, err = stmt.Exec(id, html.EscapeString(title), sha, dataEscaped, delKey, expiryTime)
	Check(err)

	return Response{true, "saved", id, title, sha, url, len(dataEscaped), delKey}
}

// DelHandler checks to see if delkey and pasteid exist in the database.
// if both exist and are correct the paste will be removed.
func DelHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	id := vars["pasteId"]
	delkey := r.FormValue("delkey")

	db, err := sql.Open("mysql", DATABASE)
	Check(err)
	defer db.Close()

	stmt, err := db.Prepare("delete from pastebin where delkey=? and id=?")
	Check(err)

	res, err := stmt.Exec(html.EscapeString(delkey), html.EscapeString(id))
	Check(err)

	_, err = res.RowsAffected()
	if err != sql.ErrNoRows {
		w.Header().Set("Content-Type", "application/json")
		b := Response{STATUS: "DELETED " + id}
		err := json.NewEncoder(w).Encode(b)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	}
}

// SaveHandler Handles saving pastes and outputing responses
func SaveHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	output := vars["output"]
	switch r.Method {
	case "POST":
		paste := r.FormValue("p")
		lang := r.FormValue("lang")
		title := r.FormValue("title")
		expiry := r.FormValue("expiry")
		if paste == "" {
			http.Error(w, "Empty paste", 500)
			return
		}
		b := Save(paste, lang, title, expiry)

		switch output {
		case "redirect":
			http.Redirect(w, r, b.URL, 301)

		default:
			w.Header().Set("Content-Type", "application/json")
			err := json.NewEncoder(w).Encode(b)
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}

		}
	}

}

// Highlight uses user specified input to call pygments library to highlight the
// paste
func Highlight(s string, lang string) (string, error) {

	highlight, err := pygments.Highlight(html.UnescapeString(s), html.EscapeString(lang), "html", "style=autumn,linenos=True, lineanchors=True,anchorlinenos=True,noclasses=True,", "utf-8")
	if err != nil {
		return "", err
	}
	return highlight, nil

}

// GetPaste takes pasteid and language
// queries the database and returns paste data
func GetPaste(paste string, lang string) (string, string) {
	param1 := html.EscapeString(paste)
	db, err := sql.Open("mysql", DATABASE)
	Check(err)
	defer db.Close()
	var title, s string
	var expiry string
	err = db.QueryRow("select title, data, expiry from pastebin where id=?", param1).Scan(&title, &s, &expiry)
	Check(err)
	if time.Now().Format("2006-01-02 15:04:05") >= expiry {
		stmt, err := db.Prepare("delete from pastebin where id=?")
		Check(err)
		_, err = stmt.Exec(param1)
		Check(err)
		return "Error invalid paste", ""
	}

	if err == sql.ErrNoRows {
		return "Error invalid paste", ""
	}
	if lang != "" {
		high, err := Highlight(s, lang)
		Check(err)
		return high, html.UnescapeString(title)
	}
	return html.UnescapeString(s), html.UnescapeString(title)
}

// APIHandler handles get requests of pastes
func APIHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	paste := vars["pasteId"]

	b, _ := GetPaste(paste, "")
	w.Header().Set("Content-Type", "application/json")
	err := json.NewEncoder(w).Encode(b)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

}

// PasteHandler handles the generation of paste pages with the links
func PasteHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	paste := vars["pasteId"]
	lang := vars["lang"]

	s, title := GetPaste(paste, lang)

	// button links
	link := configuration.Address + "/raw/" + paste
	download := configuration.Address + "/download/" + paste
	clone := configuration.Address + "/clone/" + paste
	// Page struct
	p := &Page{
		Title:    title,
		Body:     []byte(s),
		Raw:      link,
		Home:     configuration.Address,
		Download: download,
		Clone:    clone,
	}
	if lang == "" {

		err := templates.ExecuteTemplate(w, "paste.html", p)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}

	} else {
		fmt.Fprintf(w, string(syntax), p.Title, p.Title, s, p.Home, p.Download, p.Raw, p.Clone)

	}
}

// CloneHandler handles generating the clone pages
func CloneHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	paste := vars["pasteId"]

	s, title := GetPaste(paste, "")

	// Page links
	link := configuration.Address + "/raw/" + paste
	download := configuration.Address + "/download/" + paste
	clone := configuration.Address + "/clone/" + paste

	// Clone page struct
	p := &Page{
		Title:    title,
		Body:     []byte(s),
		Raw:      link,
		Home:     configuration.Address,
		Download: download,
		Clone:    clone,
	}
	err := templates.ExecuteTemplate(w, "clone.html", p)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}

}

// DownloadHandler forces downloads of selected pastes
func DownloadHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	paste := vars["pasteId"]
	s, _ := GetPaste(paste, "")

	// Set header to an attachment so browser will automatically download it
	w.Header().Set("Content-Disposition", "attachment; filename="+paste)
	w.Header().Set("Content-Type", r.Header.Get("Content-Type"))
	io.WriteString(w, s)

}

// RawHandler displays the pastes in text/plain format
func RawHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	paste := vars["pasteId"]
	s, _ := GetPaste(paste, "")

	w.Header().Set("Content-Type", "text/plain; charset=UTF-8; imeanit=yes")
	// simply write string to browser
	io.WriteString(w, s)

}

// RootHandler handles generating the root page
func RootHandler(w http.ResponseWriter, r *http.Request) {
	err := templates.ExecuteTemplate(w, "index.html", &Page{})
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func main() {
	file, err := os.Open("config.json")
	if err != nil {
		panic(err)
	}
	decoder := json.NewDecoder(file)
	configuration := Configuration{}
	err = decoder.Decode(&configuration)
	if err != nil {
		panic(err)
	}

	DATABASE = configuration.Username + ":" + configuration.Password + "@/" + configuration.Name + "?charset=utf8"
	// create new mux router
	router := mux.NewRouter()

	// serverside rending stuff
	router.HandleFunc("/p/{pasteId}", PasteHandler).Methods("GET")
	router.HandleFunc("/raw/{pasteId}", RawHandler).Methods("GET")
	router.HandleFunc("/p/{pasteId}/{lang}", PasteHandler).Methods("GET")
	router.HandleFunc("/clone/{pasteId}", CloneHandler).Methods("GET")
	router.HandleFunc("/download/{pasteId}", DownloadHandler).Methods("GET")
	// api
	router.HandleFunc("/api", SaveHandler).Methods("POST")
	router.HandleFunc("/api/{output}", SaveHandler).Methods("POST")
	router.HandleFunc("/api/{pasteid}", APIHandler).Methods("GET")
	router.HandleFunc("/api/{pasteId}", DelHandler).Methods("DELETE")
	router.HandleFunc("/", RootHandler)
	err = http.ListenAndServe(configuration.Port, router)
	if err != nil {
		log.Fatal(err)
	}

}
<commit_msg>Fix up previous error<commit_after>// Package pastebin is a simple modern and powerful pastebin service
package main

import (
	"crypto/sha1"
	"database/sql"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"html"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"time"

	duration "github.com/channelmeter/iso8601duration"
	// uniuri is used for easy random string generation
	"github.com/dchest/uniuri"
	// pygments is used for syntax highlighting
	"github.com/ewhal/pygments"
	// mysql driver
	_ "github.com/go-sql-driver/mysql"
	// mux is used for url routing
	"github.com/gorilla/mux"
)

type Configuration struct {
	// ADDRESS that pastebin will return links for
	Address string
	// LENGTH of paste id
	Length int
	// PORT that pastebin will listen on
	Port string
	// USERNAME for database
	Username string
	// PASS database password
	Password string
	// NAME database name
	Name string
}

var configuration Configuration

// DATABASE connection String
var DATABASE string

// Template pages
var templates = template.Must(template.ParseFiles("assets/paste.html", "assets/index.html", "assets/clone.html"))
var syntax, _ = ioutil.ReadFile("assets/syntax.html")

// Response API struct
type Response struct {
	SUCCESS bool   `json:"success"`
	STATUS  string `json:"status"`
	ID      string `json:"id"`
	TITLE   string `json:"title"`
	SHA1    string `json:"sha1"`
	URL     string `json:"url"`
	SIZE    int    `json:"size"`
	DELKEY  string `json:"delkey"`
}

// Page generation struct
type Page struct {
	Title    string
	Body     []byte
	Raw      string
	Home     string
	Download string
	Clone    string
}

// check error handling function
func Check(err error) {
	if err != nil {
		log.Println(err)
	}
}

// GenerateName uses uniuri to generate a random string that isn't in the
// database
func GenerateName() string {
	// use uniuri to generate random string
	// hardcode this for now until I figure out why json isn't parsing correctly
	id := uniuri.NewLen(6)

	db, err := sql.Open("mysql", DATABASE)
	Check(err)
	defer db.Close()
	// query database if id exists and if it does call generateName again
	query, err = db.Query("select id from pastebin where id=?", id)
	if err != sql.ErrNoRows {
		for query.Next() {
			GenerateName()
		}
	}

	return id

}

// Sha1 hashes paste into a sha1 hash
func Sha1(paste string) string {
	hasher := sha1.New()

	hasher.Write([]byte(paste))
	sha := base64.URLEncoding.EncodeToString(hasher.Sum(nil))
	return sha
}

// DurationFromExpiry takes the expiry in string format and returns the duration
// that the paste will exist for
func DurationFromExpiry(expiry string) time.Duration {
	if expiry == "" {
		expiry = "P20Y"
	}
	dura, err := duration.FromString(expiry) // dura is time.Duration type
	Check(err)

	duration := dura.ToDuration()

	return duration
}

// Save function handles the saving of each paste.
// raw string is the raw paste input
// lang string is the user specified language for syntax highlighting
// title string user customized title
// expiry string duration that the paste will exist for
// Returns Response struct
func Save(raw string, lang string, title string, expiry string) Response {

	db, err := sql.Open("mysql", DATABASE)
	Check(err)
	defer db.Close()

	// hash paste data and query database to see if paste exists
	sha := Sha1(raw)
	query, err := db.Query("select id, title, hash, data, delkey from pastebin where hash=?", sha)

	if err != sql.ErrNoRows {
		for query.Next() {
			var id, title, hash, paste, delkey string
			err := query.Scan(&id, &title, &hash, &paste, &delkey)
			Check(err)
			url := configuration.Address + "/p/" + id
			return Response{true, "saved", id, title, hash, url, len(paste), delkey}
		}
	}
	id := GenerateName()
	url := configuration.Address + "/p/" + id
	if lang != "" {
		url += "/" + lang
	}

	const timeFormat = "2006-01-02 15:04:05"
	expiryTime := time.Now().Add(DurationFromExpiry(expiry)).Format(timeFormat)

	delKey := uniuri.NewLen(40)
	dataEscaped := html.EscapeString(raw)

	stmt, err := db.Prepare("INSERT INTO pastebin(id, title, hash, data, delkey, expiry) values(?,?,?,?,?,?)")
	Check(err)
	if title == "" {
		title = id
	}
	_, err = stmt.Exec(id, html.EscapeString(title), sha, dataEscaped, delKey, expiryTime)
	Check(err)

	return Response{true, "saved", id, title, sha, url, len(dataEscaped), delKey}
}

// DelHandler checks to see if delkey and pasteid exist in the database.
// if both exist and are correct the paste will be removed.
func DelHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	id := vars["pasteId"]
	delkey := r.FormValue("delkey")

	db, err := sql.Open("mysql", DATABASE)
	Check(err)
	defer db.Close()

	stmt, err := db.Prepare("delete from pastebin where delkey=? and id=?")
	Check(err)

	res, err := stmt.Exec(html.EscapeString(delkey), html.EscapeString(id))
	Check(err)

	_, err = res.RowsAffected()
	if err != sql.ErrNoRows {
		w.Header().Set("Content-Type", "application/json")
		b := Response{STATUS: "DELETED " + id}
		err := json.NewEncoder(w).Encode(b)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	}
}

// SaveHandler Handles saving pastes and outputing responses
func SaveHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	output := vars["output"]
	switch r.Method {
	case "POST":
		paste := r.FormValue("p")
		lang := r.FormValue("lang")
		title := r.FormValue("title")
		expiry := r.FormValue("expiry")
		if paste == "" {
			http.Error(w, "Empty paste", 500)
			return
		}
		b := Save(paste, lang, title, expiry)

		switch output {
		case "redirect":
			http.Redirect(w, r, b.URL, 301)

		default:
			w.Header().Set("Content-Type", "application/json")
			err := json.NewEncoder(w).Encode(b)
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}

		}
	}

}

// Highlight uses user specified input to call pygments library to highlight the
// paste
func Highlight(s string, lang string) (string, error) {

	highlight, err := pygments.Highlight(html.UnescapeString(s), html.EscapeString(lang), "html", "style=autumn,linenos=True, lineanchors=True,anchorlinenos=True,noclasses=True,", "utf-8")
	if err != nil {
		return "", err
	}
	return highlight, nil

}

// GetPaste takes pasteid and language
// queries the database and returns paste data
func GetPaste(paste string, lang string) (string, string) {
	param1 := html.EscapeString(paste)
	db, err := sql.Open("mysql", DATABASE)
	Check(err)
	defer db.Close()
	var title, s string
	var expiry string
	err = db.QueryRow("select title, data, expiry from pastebin where id=?", param1).Scan(&title, &s, &expiry)
	Check(err)
	if time.Now().Format("2006-01-02 15:04:05") >= expiry {
		stmt, err := db.Prepare("delete from pastebin where id=?")
		Check(err)
		_, err = stmt.Exec(param1)
		Check(err)
		return "Error invalid paste", ""
	}

	if err == sql.ErrNoRows {
		return "Error invalid paste", ""
	}
	if lang != "" {
		high, err := Highlight(s, lang)
		Check(err)
		return high, html.UnescapeString(title)
	}
	return html.UnescapeString(s), html.UnescapeString(title)
}

// APIHandler handles get requests of pastes
func APIHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	paste := vars["pasteId"]

	b, _ := GetPaste(paste, "")
	w.Header().Set("Content-Type", "application/json")
	err := json.NewEncoder(w).Encode(b)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

}

// PasteHandler handles the generation of paste pages with the links
func PasteHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	paste := vars["pasteId"]
	lang := vars["lang"]

	s, title := GetPaste(paste, lang)

	// button links
	link := configuration.Address + "/raw/" + paste
	download := configuration.Address + "/download/" + paste
	clone := configuration.Address + "/clone/" + paste
	// Page struct
	p := &Page{
		Title:    title,
		Body:     []byte(s),
		Raw:      link,
		Home:     configuration.Address,
		Download: download,
		Clone:    clone,
	}
	if lang == "" {

		err := templates.ExecuteTemplate(w, "paste.html", p)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}

	} else {
		fmt.Fprintf(w, string(syntax), p.Title, p.Title, s, p.Home, p.Download, p.Raw, p.Clone)

	}
}

// CloneHandler handles generating the clone pages
func CloneHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	paste := vars["pasteId"]

	s, title := GetPaste(paste, "")

	// Page links
	link := configuration.Address + "/raw/" + paste
	download := configuration.Address + "/download/" + paste
	clone := configuration.Address + "/clone/" + paste

	// Clone page struct
	p := &Page{
		Title:    title,
		Body:     []byte(s),
		Raw:      link,
		Home:     configuration.Address,
		Download: download,
		Clone:    clone,
	}
	err := templates.ExecuteTemplate(w, "clone.html", p)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}

}

// DownloadHandler forces downloads of selected pastes
func DownloadHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	paste := vars["pasteId"]
	s, _ := GetPaste(paste, "")

	// Set header to an attachment so browser will automatically download it
	w.Header().Set("Content-Disposition", "attachment; filename="+paste)
	w.Header().Set("Content-Type", r.Header.Get("Content-Type"))
	io.WriteString(w, s)

}

// RawHandler displays the pastes in text/plain format
func RawHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	paste := vars["pasteId"]
	s, _ := GetPaste(paste, "")

	w.Header().Set("Content-Type", "text/plain; charset=UTF-8; imeanit=yes")
	// simply write string to browser
	io.WriteString(w, s)

}

// RootHandler handles generating the root page
func RootHandler(w http.ResponseWriter, r *http.Request) {
	err := templates.ExecuteTemplate(w, "index.html", &Page{})
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func main() {
	file, err := os.Open("config.json")
	if err != nil {
		panic(err)
	}
	decoder := json.NewDecoder(file)
	err = decoder.Decode(&configuration)
	if err != nil {
		panic(err)
	}

	DATABASE = configuration.Username + ":" + configuration.Password + "@/" + configuration.Name + "?charset=utf8"
	// create new mux router
	router := mux.NewRouter()

	// serverside rending stuff
	router.HandleFunc("/p/{pasteId}", PasteHandler).Methods("GET")
	router.HandleFunc("/raw/{pasteId}", RawHandler).Methods("GET")
	router.HandleFunc("/p/{pasteId}/{lang}", PasteHandler).Methods("GET")
	router.HandleFunc("/clone/{pasteId}", CloneHandler).Methods("GET")
	router.HandleFunc("/download/{pasteId}", DownloadHandler).Methods("GET")
	// api
	router.HandleFunc("/api", SaveHandler).Methods("POST")
	router.HandleFunc("/api/{output}", SaveHandler).Methods("POST")
	router.HandleFunc("/api/{pasteid}", APIHandler).Methods("GET")
	router.HandleFunc("/api/{pasteId}", DelHandler).Methods("DELETE")
	router.HandleFunc("/", RootHandler)
	err = http.ListenAndServe(configuration.Port, router)
	if err != nil {
		log.Fatal(err)
	}

}
<|endoftext|>


<commit_before>package sum

import "github.com/docker/docker/pkg/tarsum"

var (
	// mapping for flag parsing
	tarsumVersions = map[string]tarsum.Version{
		"Version0":   tarsum.Version0,
		"Version1":   tarsum.Version1,
		"VersionDev": tarsum.VersionDev,
		"0":          tarsum.Version0,
		"1":          tarsum.Version1,
		"dev":        tarsum.VersionDev,
	}
)

func DetermineVersion(vstr string) (tarsum.Version, error) {
	for key, val := range tarsumVersions {
		if key == vstr {
			return val, nil
		}
	}
	return tarsum.Version(-1), tarsum.ErrVersionNotImplemented
}
<commit_msg>comments<commit_after>package sum

import "github.com/docker/docker/pkg/tarsum"

var (
	// mapping for flag parsing
	tarsumVersions = map[string]tarsum.Version{
		"Version0":   tarsum.Version0,
		"Version1":   tarsum.Version1,
		"VersionDev": tarsum.VersionDev,
		"0":          tarsum.Version0,
		"1":          tarsum.Version1,
		"dev":        tarsum.VersionDev,
	}
)

// DetermineVersion parses a human provided string (like a flag argument) and
// determines the tarsum.Version to return
func DetermineVersion(vstr string) (tarsum.Version, error) {
	for key, val := range tarsumVersions {
		if key == vstr {
			return val, nil
		}
	}
	return tarsum.Version(-1), tarsum.ErrVersionNotImplemented
}
<|endoftext|>