<commit_before>// Copyright 2009 The Go 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 filepath implements utility routines for manipulating filename paths
// in a way compatible with the target operating system-defined file paths.
package filepath

import (
	"bytes"
	"os"
	"runtime"
	"sort"
	"strings"
)

const (
	Separator     = os.PathSeparator
	ListSeparator = os.PathListSeparator
)

// Clean returns the shortest path name equivalent to path
// by purely lexical processing.  It applies the following rules
// iteratively until no further processing can be done:
//
//	1. Replace multiple Separator elements with a single one.
//	2. Eliminate each . path name element (the current directory).
//	3. Eliminate each inner .. path name element (the parent directory)
//	   along with the non-.. element that precedes it.
//	4. Eliminate .. elements that begin a rooted path:
//	   that is, replace "/.." by "/" at the beginning of a path,
//         assuming Separator is '/'.
//
// If the result of this process is an empty string, Clean
// returns the string ".".
//
// See also Rob Pike, ``Lexical File Names in Plan 9 or
// Getting Dot-Dot right,''
// http://plan9.bell-labs.com/sys/doc/lexnames.html
func Clean(path string) string {
	vol := VolumeName(path)
	path = path[len(vol):]
	if path == "" {
		if len(vol) > 1 && vol[1] != ':' {
			// should be UNC
			return FromSlash(vol)
		}
		return vol + "."
	}
	rooted := os.IsPathSeparator(path[0])

	// Invariants:
	//	reading from path; r is index of next byte to process.
	//	writing to buf; w is index of next byte to write.
	//	dotdot is index in buf where .. must stop, either because
	//		it is the leading slash or it is a leading ../../.. prefix.
	n := len(path)
	buf := []byte(path)
	r, w, dotdot := 0, 0, 0
	if rooted {
		buf[0] = Separator
		r, w, dotdot = 1, 1, 1
	}

	for r < n {
		switch {
		case os.IsPathSeparator(path[r]):
			// empty path element
			r++
		case path[r] == '.' && (r+1 == n || os.IsPathSeparator(path[r+1])):
			// . element
			r++
		case path[r] == '.' && path[r+1] == '.' && (r+2 == n || os.IsPathSeparator(path[r+2])):
			// .. element: remove to last separator
			r += 2
			switch {
			case w > dotdot:
				// can backtrack
				w--
				for w > dotdot && !os.IsPathSeparator(buf[w]) {
					w--
				}
			case !rooted:
				// cannot backtrack, but not rooted, so append .. element.
				if w > 0 {
					buf[w] = Separator
					w++
				}
				buf[w] = '.'
				w++
				buf[w] = '.'
				w++
				dotdot = w
			}
		default:
			// real path element.
			// add slash if needed
			if rooted && w != 1 || !rooted && w != 0 {
				buf[w] = Separator
				w++
			}
			// copy element
			for ; r < n && !os.IsPathSeparator(path[r]); r++ {
				buf[w] = path[r]
				w++
			}
		}
	}

	// Turn empty string into "."
	if w == 0 {
		buf[w] = '.'
		w++
	}

	return FromSlash(vol + string(buf[0:w]))
}

// ToSlash returns the result of replacing each separator character
// in path with a slash ('/') character.
func ToSlash(path string) string {
	if Separator == '/' {
		return path
	}
	return strings.Replace(path, string(Separator), "/", -1)
}

// FromSlash returns the result of replacing each slash ('/') character
// in path with a separator character.
func FromSlash(path string) string {
	if Separator == '/' {
		return path
	}
	return strings.Replace(path, "/", string(Separator), -1)
}

// SplitList splits a list of paths joined by the OS-specific ListSeparator.
func SplitList(path string) []string {
	if path == "" {
		return []string{}
	}
	return strings.Split(path, string(ListSeparator))
}

// Split splits path immediately following the final Separator,
// separating it into a directory and file name component.
// If there is no Separator in path, Split returns an empty dir
// and file set to path.
func Split(path string) (dir, file string) {
	vol := VolumeName(path)
	i := len(path) - 1
	for i >= len(vol) && !os.IsPathSeparator(path[i]) {
		i--
	}
	return path[:i+1], path[i+1:]
}

// Join joins any number of path elements into a single path, adding
// a Separator if necessary.  All empty strings are ignored.
func Join(elem ...string) string {
	for i, e := range elem {
		if e != "" {
			return Clean(strings.Join(elem[i:], string(Separator)))
		}
	}
	return ""
}

// Ext returns the file name extension used by path.
// The extension is the suffix beginning at the final dot
// in the final element of path; it is empty if there is
// no dot.
func Ext(path string) string {
	for i := len(path) - 1; i >= 0 && !os.IsPathSeparator(path[i]); i-- {
		if path[i] == '.' {
			return path[i:]
		}
	}
	return ""
}

// EvalSymlinks returns the path name after the evaluation of any symbolic
// links.
// If path is relative it will be evaluated relative to the current directory.
func EvalSymlinks(path string) (string, os.Error) {
	if runtime.GOOS == "windows" {
		// Symlinks are not supported under windows.
		_, err := os.Lstat(path)
		if err != nil {
			return "", err
		}
		return Clean(path), nil
	}
	const maxIter = 255
	originalPath := path
	// consume path by taking each frontmost path element,
	// expanding it if it's a symlink, and appending it to b
	var b bytes.Buffer
	for n := 0; path != ""; n++ {
		if n > maxIter {
			return "", os.NewError("EvalSymlinks: too many links in " + originalPath)
		}

		// find next path component, p
		i := strings.IndexRune(path, Separator)
		var p string
		if i == -1 {
			p, path = path, ""
		} else {
			p, path = path[:i], path[i+1:]
		}

		if p == "" {
			if b.Len() == 0 {
				// must be absolute path
				b.WriteRune(Separator)
			}
			continue
		}

		fi, err := os.Lstat(b.String() + p)
		if err != nil {
			return "", err
		}
		if !fi.IsSymlink() {
			b.WriteString(p)
			if path != "" {
				b.WriteRune(Separator)
			}
			continue
		}

		// it's a symlink, put it at the front of path
		dest, err := os.Readlink(b.String() + p)
		if err != nil {
			return "", err
		}
		if IsAbs(dest) {
			b.Reset()
		}
		path = dest + string(Separator) + path
	}
	return Clean(b.String()), nil
}

// Abs returns an absolute representation of path.
// If the path is not absolute it will be joined with the current
// working directory to turn it into an absolute path.  The absolute
// path name for a given file is not guaranteed to be unique.
func Abs(path string) (string, os.Error) {
	if IsAbs(path) {
		return Clean(path), nil
	}
	wd, err := os.Getwd()
	if err != nil {
		return "", err
	}
	return Join(wd, path), nil
}

// Visitor methods are invoked for corresponding file tree entries
// visited by Walk. The parameter path is the full path of f relative
// to root.
type Visitor interface {
	VisitDir(path string, f *os.FileInfo) bool
	VisitFile(path string, f *os.FileInfo)
}

func walk(path string, f *os.FileInfo, v Visitor, errors chan<- os.Error) {
	if !f.IsDirectory() {
		v.VisitFile(path, f)
		return
	}

	if !v.VisitDir(path, f) {
		return // skip directory entries
	}

	list, err := readDir(path)
	if err != nil {
		if errors != nil {
			errors <- err
		}
	}

	for _, e := range list {
		walk(Join(path, e.Name), e, v, errors)
	}
}

// readDir reads the directory named by dirname and returns
// a list of sorted directory entries.
// Copied from io/ioutil to avoid the circular import.
func readDir(dirname string) ([]*os.FileInfo, os.Error) {
	f, err := os.Open(dirname)
	if err != nil {
		return nil, err
	}
	list, err := f.Readdir(-1)
	f.Close()
	if err != nil {
		return nil, err
	}
	fi := make(fileInfoList, len(list))
	for i := range list {
		fi[i] = &list[i]
	}
	sort.Sort(fi)
	return fi, nil
}

// A dirList implements sort.Interface.
type fileInfoList []*os.FileInfo

func (f fileInfoList) Len() int           { return len(f) }
func (f fileInfoList) Less(i, j int) bool { return f[i].Name < f[j].Name }
func (f fileInfoList) Swap(i, j int)      { f[i], f[j] = f[j], f[i] }

// Walk walks the file tree rooted at root, calling v.VisitDir or
// v.VisitFile for each directory or file in the tree, including root.
// If v.VisitDir returns false, Walk skips the directory's entries;
// otherwise it invokes itself for each directory entry in sorted order.
// An error reading a directory does not abort the Walk.
// If errors != nil, Walk sends each directory read error
// to the channel.  Otherwise Walk discards the error.
func Walk(root string, v Visitor, errors chan<- os.Error) {
	f, err := os.Lstat(root)
	if err != nil {
		if errors != nil {
			errors <- err
		}
		return // can't progress
	}
	walk(root, f, v, errors)
}

// Base returns the last element of path.
// Trailing path separators are removed before extracting the last element.
// If the path is empty, Base returns ".".
// If the path consists entirely of separators, Base returns a single separator.
func Base(path string) string {
	if path == "" {
		return "."
	}
	// Strip trailing slashes.
	for len(path) > 0 && os.IsPathSeparator(path[len(path)-1]) {
		path = path[0 : len(path)-1]
	}
	// Find the last element
	i := len(path) - 1
	for i >= 0 && !os.IsPathSeparator(path[i]) {
		i--
	}
	if i >= 0 {
		path = path[i+1:]
	}
	// If empty now, it had only slashes.
	if path == "" {
		return string(Separator)
	}
	return path
}
<commit_msg>path/filepath: fix Visitor doc<commit_after>// Copyright 2009 The Go 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 filepath implements utility routines for manipulating filename paths
// in a way compatible with the target operating system-defined file paths.
package filepath

import (
	"bytes"
	"os"
	"runtime"
	"sort"
	"strings"
)

const (
	Separator     = os.PathSeparator
	ListSeparator = os.PathListSeparator
)

// Clean returns the shortest path name equivalent to path
// by purely lexical processing.  It applies the following rules
// iteratively until no further processing can be done:
//
//	1. Replace multiple Separator elements with a single one.
//	2. Eliminate each . path name element (the current directory).
//	3. Eliminate each inner .. path name element (the parent directory)
//	   along with the non-.. element that precedes it.
//	4. Eliminate .. elements that begin a rooted path:
//	   that is, replace "/.." by "/" at the beginning of a path,
//         assuming Separator is '/'.
//
// If the result of this process is an empty string, Clean
// returns the string ".".
//
// See also Rob Pike, ``Lexical File Names in Plan 9 or
// Getting Dot-Dot right,''
// http://plan9.bell-labs.com/sys/doc/lexnames.html
func Clean(path string) string {
	vol := VolumeName(path)
	path = path[len(vol):]
	if path == "" {
		if len(vol) > 1 && vol[1] != ':' {
			// should be UNC
			return FromSlash(vol)
		}
		return vol + "."
	}
	rooted := os.IsPathSeparator(path[0])

	// Invariants:
	//	reading from path; r is index of next byte to process.
	//	writing to buf; w is index of next byte to write.
	//	dotdot is index in buf where .. must stop, either because
	//		it is the leading slash or it is a leading ../../.. prefix.
	n := len(path)
	buf := []byte(path)
	r, w, dotdot := 0, 0, 0
	if rooted {
		buf[0] = Separator
		r, w, dotdot = 1, 1, 1
	}

	for r < n {
		switch {
		case os.IsPathSeparator(path[r]):
			// empty path element
			r++
		case path[r] == '.' && (r+1 == n || os.IsPathSeparator(path[r+1])):
			// . element
			r++
		case path[r] == '.' && path[r+1] == '.' && (r+2 == n || os.IsPathSeparator(path[r+2])):
			// .. element: remove to last separator
			r += 2
			switch {
			case w > dotdot:
				// can backtrack
				w--
				for w > dotdot && !os.IsPathSeparator(buf[w]) {
					w--
				}
			case !rooted:
				// cannot backtrack, but not rooted, so append .. element.
				if w > 0 {
					buf[w] = Separator
					w++
				}
				buf[w] = '.'
				w++
				buf[w] = '.'
				w++
				dotdot = w
			}
		default:
			// real path element.
			// add slash if needed
			if rooted && w != 1 || !rooted && w != 0 {
				buf[w] = Separator
				w++
			}
			// copy element
			for ; r < n && !os.IsPathSeparator(path[r]); r++ {
				buf[w] = path[r]
				w++
			}
		}
	}

	// Turn empty string into "."
	if w == 0 {
		buf[w] = '.'
		w++
	}

	return FromSlash(vol + string(buf[0:w]))
}

// ToSlash returns the result of replacing each separator character
// in path with a slash ('/') character.
func ToSlash(path string) string {
	if Separator == '/' {
		return path
	}
	return strings.Replace(path, string(Separator), "/", -1)
}

// FromSlash returns the result of replacing each slash ('/') character
// in path with a separator character.
func FromSlash(path string) string {
	if Separator == '/' {
		return path
	}
	return strings.Replace(path, "/", string(Separator), -1)
}

// SplitList splits a list of paths joined by the OS-specific ListSeparator.
func SplitList(path string) []string {
	if path == "" {
		return []string{}
	}
	return strings.Split(path, string(ListSeparator))
}

// Split splits path immediately following the final Separator,
// separating it into a directory and file name component.
// If there is no Separator in path, Split returns an empty dir
// and file set to path.
func Split(path string) (dir, file string) {
	vol := VolumeName(path)
	i := len(path) - 1
	for i >= len(vol) && !os.IsPathSeparator(path[i]) {
		i--
	}
	return path[:i+1], path[i+1:]
}

// Join joins any number of path elements into a single path, adding
// a Separator if necessary.  All empty strings are ignored.
func Join(elem ...string) string {
	for i, e := range elem {
		if e != "" {
			return Clean(strings.Join(elem[i:], string(Separator)))
		}
	}
	return ""
}

// Ext returns the file name extension used by path.
// The extension is the suffix beginning at the final dot
// in the final element of path; it is empty if there is
// no dot.
func Ext(path string) string {
	for i := len(path) - 1; i >= 0 && !os.IsPathSeparator(path[i]); i-- {
		if path[i] == '.' {
			return path[i:]
		}
	}
	return ""
}

// EvalSymlinks returns the path name after the evaluation of any symbolic
// links.
// If path is relative it will be evaluated relative to the current directory.
func EvalSymlinks(path string) (string, os.Error) {
	if runtime.GOOS == "windows" {
		// Symlinks are not supported under windows.
		_, err := os.Lstat(path)
		if err != nil {
			return "", err
		}
		return Clean(path), nil
	}
	const maxIter = 255
	originalPath := path
	// consume path by taking each frontmost path element,
	// expanding it if it's a symlink, and appending it to b
	var b bytes.Buffer
	for n := 0; path != ""; n++ {
		if n > maxIter {
			return "", os.NewError("EvalSymlinks: too many links in " + originalPath)
		}

		// find next path component, p
		i := strings.IndexRune(path, Separator)
		var p string
		if i == -1 {
			p, path = path, ""
		} else {
			p, path = path[:i], path[i+1:]
		}

		if p == "" {
			if b.Len() == 0 {
				// must be absolute path
				b.WriteRune(Separator)
			}
			continue
		}

		fi, err := os.Lstat(b.String() + p)
		if err != nil {
			return "", err
		}
		if !fi.IsSymlink() {
			b.WriteString(p)
			if path != "" {
				b.WriteRune(Separator)
			}
			continue
		}

		// it's a symlink, put it at the front of path
		dest, err := os.Readlink(b.String() + p)
		if err != nil {
			return "", err
		}
		if IsAbs(dest) {
			b.Reset()
		}
		path = dest + string(Separator) + path
	}
	return Clean(b.String()), nil
}

// Abs returns an absolute representation of path.
// If the path is not absolute it will be joined with the current
// working directory to turn it into an absolute path.  The absolute
// path name for a given file is not guaranteed to be unique.
func Abs(path string) (string, os.Error) {
	if IsAbs(path) {
		return Clean(path), nil
	}
	wd, err := os.Getwd()
	if err != nil {
		return "", err
	}
	return Join(wd, path), nil
}

// Visitor methods are invoked for corresponding file tree entries
// visited by Walk. The provided path parameter begins with root.
type Visitor interface {
	VisitDir(path string, f *os.FileInfo) bool
	VisitFile(path string, f *os.FileInfo)
}

func walk(path string, f *os.FileInfo, v Visitor, errors chan<- os.Error) {
	if !f.IsDirectory() {
		v.VisitFile(path, f)
		return
	}

	if !v.VisitDir(path, f) {
		return // skip directory entries
	}

	list, err := readDir(path)
	if err != nil {
		if errors != nil {
			errors <- err
		}
	}

	for _, e := range list {
		walk(Join(path, e.Name), e, v, errors)
	}
}

// readDir reads the directory named by dirname and returns
// a list of sorted directory entries.
// Copied from io/ioutil to avoid the circular import.
func readDir(dirname string) ([]*os.FileInfo, os.Error) {
	f, err := os.Open(dirname)
	if err != nil {
		return nil, err
	}
	list, err := f.Readdir(-1)
	f.Close()
	if err != nil {
		return nil, err
	}
	fi := make(fileInfoList, len(list))
	for i := range list {
		fi[i] = &list[i]
	}
	sort.Sort(fi)
	return fi, nil
}

// A dirList implements sort.Interface.
type fileInfoList []*os.FileInfo

func (f fileInfoList) Len() int           { return len(f) }
func (f fileInfoList) Less(i, j int) bool { return f[i].Name < f[j].Name }
func (f fileInfoList) Swap(i, j int)      { f[i], f[j] = f[j], f[i] }

// Walk walks the file tree rooted at root, calling v.VisitDir or
// v.VisitFile for each directory or file in the tree, including root.
// If v.VisitDir returns false, Walk skips the directory's entries;
// otherwise it invokes itself for each directory entry in sorted order.
// An error reading a directory does not abort the Walk.
// If errors != nil, Walk sends each directory read error
// to the channel.  Otherwise Walk discards the error.
func Walk(root string, v Visitor, errors chan<- os.Error) {
	f, err := os.Lstat(root)
	if err != nil {
		if errors != nil {
			errors <- err
		}
		return // can't progress
	}
	walk(root, f, v, errors)
}

// Base returns the last element of path.
// Trailing path separators are removed before extracting the last element.
// If the path is empty, Base returns ".".
// If the path consists entirely of separators, Base returns a single separator.
func Base(path string) string {
	if path == "" {
		return "."
	}
	// Strip trailing slashes.
	for len(path) > 0 && os.IsPathSeparator(path[len(path)-1]) {
		path = path[0 : len(path)-1]
	}
	// Find the last element
	i := len(path) - 1
	for i >= 0 && !os.IsPathSeparator(path[i]) {
		i--
	}
	if i >= 0 {
		path = path[i+1:]
	}
	// If empty now, it had only slashes.
	if path == "" {
		return string(Separator)
	}
	return path
}
<|endoftext|>


<commit_before>// Copyright 2012 The Go 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 runtime_test

import (
	. "runtime"
	"sync"
	"testing"
	"time"
	"unsafe"
)

// See stack.h.
const (
	StackGuard = 256
	StackLimit = 128
)

// Test stack split logic by calling functions of every frame size
// from near 0 up to and beyond the default segment size (4k).
// Each of those functions reports its SP + stack limit, and then
// the test (the caller) checks that those make sense.  By not
// doing the actual checking and reporting from the suspect functions,
// we minimize the possibility of crashes during the test itself.
//
// Exhaustive test for http://golang.org/issue/3310.
// The linker used to get a few sizes near the segment size wrong:
//
// --- FAIL: TestStackSplit (0.01 seconds)
// 	stack_test.go:22: after runtime_test.stack3812: sp=0x7f7818d5d078 < limit=0x7f7818d5d080
// 	stack_test.go:22: after runtime_test.stack3816: sp=0x7f7818d5d078 < limit=0x7f7818d5d080
// 	stack_test.go:22: after runtime_test.stack3820: sp=0x7f7818d5d070 < limit=0x7f7818d5d080
// 	stack_test.go:22: after runtime_test.stack3824: sp=0x7f7818d5d070 < limit=0x7f7818d5d080
// 	stack_test.go:22: after runtime_test.stack3828: sp=0x7f7818d5d068 < limit=0x7f7818d5d080
// 	stack_test.go:22: after runtime_test.stack3832: sp=0x7f7818d5d068 < limit=0x7f7818d5d080
// 	stack_test.go:22: after runtime_test.stack3836: sp=0x7f7818d5d060 < limit=0x7f7818d5d080
// 	stack_test.go:22: after runtime_test.stack3840: sp=0x7f7818d5d060 < limit=0x7f7818d5d080
// 	stack_test.go:22: after runtime_test.stack3844: sp=0x7f7818d5d058 < limit=0x7f7818d5d080
// 	stack_test.go:22: after runtime_test.stack3848: sp=0x7f7818d5d058 < limit=0x7f7818d5d080
// 	stack_test.go:22: after runtime_test.stack3852: sp=0x7f7818d5d050 < limit=0x7f7818d5d080
// 	stack_test.go:22: after runtime_test.stack3856: sp=0x7f7818d5d050 < limit=0x7f7818d5d080
// 	stack_test.go:22: after runtime_test.stack3860: sp=0x7f7818d5d048 < limit=0x7f7818d5d080
// 	stack_test.go:22: after runtime_test.stack3864: sp=0x7f7818d5d048 < limit=0x7f7818d5d080
// FAIL
func TestStackSplit(t *testing.T) {
	for _, f := range splitTests {
		sp, guard := f()
		bottom := guard - StackGuard
		if sp < bottom+StackLimit {
			fun := FuncForPC(**(**uintptr)(unsafe.Pointer(&f)))
			t.Errorf("after %s: sp=%#x < limit=%#x (guard=%#x, bottom=%#x)",
				fun.Name(), sp, bottom+StackLimit, guard, bottom)
		}
	}
}

var Used byte

func use(buf []byte) {
	for _, c := range buf {
		Used += c
	}
}

// TestStackMem measures per-thread stack segment cache behavior.
// The test consumed up to 500MB in the past.
func TestStackMem(t *testing.T) {
	const (
		BatchSize      = 32
		BatchCount     = 256
		ArraySize      = 1024
		RecursionDepth = 128
	)
	if testing.Short() {
		return
	}
	defer GOMAXPROCS(GOMAXPROCS(BatchSize))
	s0 := new(MemStats)
	ReadMemStats(s0)
	for b := 0; b < BatchCount; b++ {
		c := make(chan bool, BatchSize)
		for i := 0; i < BatchSize; i++ {
			go func() {
				var f func(k int, a [ArraySize]byte)
				f = func(k int, a [ArraySize]byte) {
					if k == 0 {
						time.Sleep(time.Millisecond)
						return
					}
					f(k-1, a)
				}
				f(RecursionDepth, [ArraySize]byte{})
				c <- true
			}()
		}
		for i := 0; i < BatchSize; i++ {
			<-c
		}

		// The goroutines have signaled via c that they are ready to exit.
		// Give them a chance to exit by sleeping. If we don't wait, we
		// might not reuse them on the next batch.
		time.Sleep(10 * time.Millisecond)
	}
	s1 := new(MemStats)
	ReadMemStats(s1)
	consumed := s1.StackSys - s0.StackSys
	t.Logf("Consumed %vMB for stack mem", consumed>>20)
	estimate := uint64(8 * BatchSize * ArraySize * RecursionDepth) // 8 is to reduce flakiness.
	if consumed > estimate {
		t.Fatalf("Stack mem: want %v, got %v", estimate, consumed)
	}
	// Due to broken stack memory accounting (http://golang.org/issue/7468),
	// StackInuse can decrease during function execution, so we cast the values to int64.
	inuse := int64(s1.StackInuse) - int64(s0.StackInuse)
	t.Logf("Inuse %vMB for stack mem", inuse>>20)
	if inuse > 4<<20 {
		t.Fatalf("Stack inuse: want %v, got %v", 4<<20, inuse)
	}
}

// Test stack growing in different contexts.
func TestStackGrowth(t *testing.T) {
	t.Parallel()
	var wg sync.WaitGroup

	// in a normal goroutine
	wg.Add(1)
	go func() {
		defer wg.Done()
		growStack()
	}()

	// in locked goroutine
	wg.Add(1)
	go func() {
		defer wg.Done()
		LockOSThread()
		growStack()
		UnlockOSThread()
	}()

	// in finalizer
	wg.Add(1)
	go func() {
		defer wg.Done()
		done := make(chan bool)
		go func() {
			s := new(string)
			SetFinalizer(s, func(ss *string) {
				done <- true
			})
			s = nil
			done <- true
		}()
		<-done
		GC()
		select {
		case <-done:
		case <-time.After(4 * time.Second):
			t.Fatal("finalizer did not run")
		}
	}()

	wg.Wait()
}

// ... and in init
func init() {
	growStack()
}

func growStack() {
	for i := 0; i < 1<<10; i++ {
		x := 0
		growStackIter(&x, i)
		if x != i+1 {
			panic("stack is corrupted")
		}
	}
	GC()
}

// This function is not an anonimous func, so that the compiler can do escape
// analysis and place x on stack (and subsequently stack growth update the pointer).
func growStackIter(p *int, n int) {
	if n == 0 {
		*p = n + 1
		GC()
		return
	}
	*p = n + 1
	x := 0
	growStackIter(&x, n-1)
	if x != n {
		panic("stack is corrupted")
	}
}

func TestStackGrowthCallback(t *testing.T) {
	t.Parallel()
	var wg sync.WaitGroup

	// test stack growth at chan op
	wg.Add(1)
	go func() {
		defer wg.Done()
		c := make(chan int, 1)
		growStackWithCallback(func() {
			c <- 1
			<-c
		})
	}()

	// test stack growth at map op
	wg.Add(1)
	go func() {
		defer wg.Done()
		m := make(map[int]int)
		growStackWithCallback(func() {
			_, _ = m[1]
			m[1] = 1
		})
	}()

	// test stack growth at goroutine creation
	wg.Add(1)
	go func() {
		defer wg.Done()
		growStackWithCallback(func() {
			done := make(chan bool)
			go func() {
				done <- true
			}()
			<-done
		})
	}()

	wg.Wait()
}

func growStackWithCallback(cb func()) {
	var f func(n int)
	f = func(n int) {
		if n == 0 {
			cb()
			return
		}
		f(n - 1)
	}
	for i := 0; i < 1<<10; i++ {
		f(i)
	}
}

// TestDeferPtrs tests the adjustment of Defer's argument pointers (p aka &y)
// during a stack copy.
func set(p *int, x int) {
	*p = x
}
func TestDeferPtrs(t *testing.T) {
	var y int

	defer func() {
		if y != 42 {
			t.Errorf("defer's stack references were not adjusted appropriately")
		}
	}()
	defer set(&y, 42)
	growStack()
}
<commit_msg>runtime: make stack growth test shorter<commit_after>// Copyright 2012 The Go 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 runtime_test

import (
	. "runtime"
	"sync"
	"testing"
	"time"
	"unsafe"
)

// See stack.h.
const (
	StackGuard = 256
	StackLimit = 128
)

// Test stack split logic by calling functions of every frame size
// from near 0 up to and beyond the default segment size (4k).
// Each of those functions reports its SP + stack limit, and then
// the test (the caller) checks that those make sense.  By not
// doing the actual checking and reporting from the suspect functions,
// we minimize the possibility of crashes during the test itself.
//
// Exhaustive test for http://golang.org/issue/3310.
// The linker used to get a few sizes near the segment size wrong:
//
// --- FAIL: TestStackSplit (0.01 seconds)
// 	stack_test.go:22: after runtime_test.stack3812: sp=0x7f7818d5d078 < limit=0x7f7818d5d080
// 	stack_test.go:22: after runtime_test.stack3816: sp=0x7f7818d5d078 < limit=0x7f7818d5d080
// 	stack_test.go:22: after runtime_test.stack3820: sp=0x7f7818d5d070 < limit=0x7f7818d5d080
// 	stack_test.go:22: after runtime_test.stack3824: sp=0x7f7818d5d070 < limit=0x7f7818d5d080
// 	stack_test.go:22: after runtime_test.stack3828: sp=0x7f7818d5d068 < limit=0x7f7818d5d080
// 	stack_test.go:22: after runtime_test.stack3832: sp=0x7f7818d5d068 < limit=0x7f7818d5d080
// 	stack_test.go:22: after runtime_test.stack3836: sp=0x7f7818d5d060 < limit=0x7f7818d5d080
// 	stack_test.go:22: after runtime_test.stack3840: sp=0x7f7818d5d060 < limit=0x7f7818d5d080
// 	stack_test.go:22: after runtime_test.stack3844: sp=0x7f7818d5d058 < limit=0x7f7818d5d080
// 	stack_test.go:22: after runtime_test.stack3848: sp=0x7f7818d5d058 < limit=0x7f7818d5d080
// 	stack_test.go:22: after runtime_test.stack3852: sp=0x7f7818d5d050 < limit=0x7f7818d5d080
// 	stack_test.go:22: after runtime_test.stack3856: sp=0x7f7818d5d050 < limit=0x7f7818d5d080
// 	stack_test.go:22: after runtime_test.stack3860: sp=0x7f7818d5d048 < limit=0x7f7818d5d080
// 	stack_test.go:22: after runtime_test.stack3864: sp=0x7f7818d5d048 < limit=0x7f7818d5d080
// FAIL
func TestStackSplit(t *testing.T) {
	for _, f := range splitTests {
		sp, guard := f()
		bottom := guard - StackGuard
		if sp < bottom+StackLimit {
			fun := FuncForPC(**(**uintptr)(unsafe.Pointer(&f)))
			t.Errorf("after %s: sp=%#x < limit=%#x (guard=%#x, bottom=%#x)",
				fun.Name(), sp, bottom+StackLimit, guard, bottom)
		}
	}
}

var Used byte

func use(buf []byte) {
	for _, c := range buf {
		Used += c
	}
}

// TestStackMem measures per-thread stack segment cache behavior.
// The test consumed up to 500MB in the past.
func TestStackMem(t *testing.T) {
	const (
		BatchSize      = 32
		BatchCount     = 256
		ArraySize      = 1024
		RecursionDepth = 128
	)
	if testing.Short() {
		return
	}
	defer GOMAXPROCS(GOMAXPROCS(BatchSize))
	s0 := new(MemStats)
	ReadMemStats(s0)
	for b := 0; b < BatchCount; b++ {
		c := make(chan bool, BatchSize)
		for i := 0; i < BatchSize; i++ {
			go func() {
				var f func(k int, a [ArraySize]byte)
				f = func(k int, a [ArraySize]byte) {
					if k == 0 {
						time.Sleep(time.Millisecond)
						return
					}
					f(k-1, a)
				}
				f(RecursionDepth, [ArraySize]byte{})
				c <- true
			}()
		}
		for i := 0; i < BatchSize; i++ {
			<-c
		}

		// The goroutines have signaled via c that they are ready to exit.
		// Give them a chance to exit by sleeping. If we don't wait, we
		// might not reuse them on the next batch.
		time.Sleep(10 * time.Millisecond)
	}
	s1 := new(MemStats)
	ReadMemStats(s1)
	consumed := s1.StackSys - s0.StackSys
	t.Logf("Consumed %vMB for stack mem", consumed>>20)
	estimate := uint64(8 * BatchSize * ArraySize * RecursionDepth) // 8 is to reduce flakiness.
	if consumed > estimate {
		t.Fatalf("Stack mem: want %v, got %v", estimate, consumed)
	}
	// Due to broken stack memory accounting (http://golang.org/issue/7468),
	// StackInuse can decrease during function execution, so we cast the values to int64.
	inuse := int64(s1.StackInuse) - int64(s0.StackInuse)
	t.Logf("Inuse %vMB for stack mem", inuse>>20)
	if inuse > 4<<20 {
		t.Fatalf("Stack inuse: want %v, got %v", 4<<20, inuse)
	}
}

// Test stack growing in different contexts.
func TestStackGrowth(t *testing.T) {
	t.Parallel()
	var wg sync.WaitGroup

	// in a normal goroutine
	wg.Add(1)
	go func() {
		defer wg.Done()
		growStack()
	}()
	wg.Wait()

	// in locked goroutine
	wg.Add(1)
	go func() {
		defer wg.Done()
		LockOSThread()
		growStack()
		UnlockOSThread()
	}()
	wg.Wait()

	// in finalizer
	wg.Add(1)
	go func() {
		defer wg.Done()
		done := make(chan bool)
		go func() {
			s := new(string)
			SetFinalizer(s, func(ss *string) {
				growStack()
				done <- true
			})
			s = nil
			done <- true
		}()
		<-done
		GC()
		select {
		case <-done:
		case <-time.After(4 * time.Second):
			t.Fatal("finalizer did not run")
		}
	}()
	wg.Wait()
}

// ... and in init
//func init() {
//	growStack()
//}

func growStack() {
	n := 1 << 10
	if testing.Short() {
		n = 1 << 8
	}
	for i := 0; i < n; i++ {
		x := 0
		growStackIter(&x, i)
		if x != i+1 {
			panic("stack is corrupted")
		}
	}
	GC()
}

// This function is not an anonimous func, so that the compiler can do escape
// analysis and place x on stack (and subsequently stack growth update the pointer).
func growStackIter(p *int, n int) {
	if n == 0 {
		*p = n + 1
		GC()
		return
	}
	*p = n + 1
	x := 0
	growStackIter(&x, n-1)
	if x != n {
		panic("stack is corrupted")
	}
}

func TestStackGrowthCallback(t *testing.T) {
	t.Parallel()
	var wg sync.WaitGroup

	// test stack growth at chan op
	wg.Add(1)
	go func() {
		defer wg.Done()
		c := make(chan int, 1)
		growStackWithCallback(func() {
			c <- 1
			<-c
		})
	}()

	// test stack growth at map op
	wg.Add(1)
	go func() {
		defer wg.Done()
		m := make(map[int]int)
		growStackWithCallback(func() {
			_, _ = m[1]
			m[1] = 1
		})
	}()

	// test stack growth at goroutine creation
	wg.Add(1)
	go func() {
		defer wg.Done()
		growStackWithCallback(func() {
			done := make(chan bool)
			go func() {
				done <- true
			}()
			<-done
		})
	}()

	wg.Wait()
}

func growStackWithCallback(cb func()) {
	var f func(n int)
	f = func(n int) {
		if n == 0 {
			cb()
			return
		}
		f(n - 1)
	}
	for i := 0; i < 1<<10; i++ {
		f(i)
	}
}

// TestDeferPtrs tests the adjustment of Defer's argument pointers (p aka &y)
// during a stack copy.
func set(p *int, x int) {
	*p = x
}
func TestDeferPtrs(t *testing.T) {
	var y int

	defer func() {
		if y != 42 {
			t.Errorf("defer's stack references were not adjusted appropriately")
		}
	}()
	defer set(&y, 42)
	growStack()
}
<|endoftext|>


<commit_before>package mmail

import (
	"errors"
	"sync"
)

// ErrEmptyUID error when is empty UID stored or invalid UIDVALIDITY
var ErrEmptyUID = errors.New("Empty UID stored or invalid UIDVALIDITY")
var ErrUIDValidityZero = errors.New("uidvalidity need to be greater than zero")

// UIDCache is a cache of uid for account + mailbox
type UIDCache interface {
	// GetNextUID returns the next uid for the uidvalidity, if empty or is an invalid uidvalidity returns ErrEmptyUID
	GetNextUID(uidvalidity uint32) (uint32, error)

	// SaveNextUID stores the uid and uidvalidity
	SaveNextUID(uidvalidity, uid uint32) error
}

type uidCacheMem struct {
	uidvalidity uint32
	next        uint32
	lock        sync.RWMutex
}

// GetNextUID returns the next uid for the uidvalidity, if empty or is an invalid uidvalidity returns ErrEmptyUID
func (u *uidCacheMem) GetNextUID(uidvalidity uint32) (uint32, error) {
	u.lock.RLock()
	defer u.lock.RUnlock()

	if uidvalidity == 0 {
		return 0, ErrUIDValidityZero
	}

	if u.uidvalidity != uidvalidity {
		return 0, ErrEmptyUID
	}

	return u.next, nil
}

// SaveNextUID stores the uid and uidvalidity
func (u *uidCacheMem) SaveNextUID(uidvalidity, uid uint32) error {
	u.lock.Lock()
	defer u.lock.Unlock()

	if uidvalidity == 0 {
		return ErrUIDValidityZero
	}
	u.uidvalidity = uidvalidity
	u.next = uid

	return nil
}
<commit_msg>add comment  to ErrUIDValidityZero<commit_after>package mmail

import (
	"errors"
	"sync"
)

// ErrEmptyUID error when is empty UID stored or invalid UIDVALIDITY
var ErrEmptyUID = errors.New("Empty UID stored or invalid UIDVALIDITY")

// ErrUIDValidityZero error when UIDVALIDITY is zero
var ErrUIDValidityZero = errors.New("uidvalidity need to be greater than zero")

// UIDCache is a cache of uid for account + mailbox
type UIDCache interface {
	// GetNextUID returns the next uid for the uidvalidity, if empty or is an invalid uidvalidity returns ErrEmptyUID
	GetNextUID(uidvalidity uint32) (uint32, error)

	// SaveNextUID stores the uid and uidvalidity
	SaveNextUID(uidvalidity, uid uint32) error
}

type uidCacheMem struct {
	uidvalidity uint32
	next        uint32
	lock        sync.RWMutex
}

// GetNextUID returns the next uid for the uidvalidity, if empty or is an invalid uidvalidity returns ErrEmptyUID
func (u *uidCacheMem) GetNextUID(uidvalidity uint32) (uint32, error) {
	u.lock.RLock()
	defer u.lock.RUnlock()

	if uidvalidity == 0 {
		return 0, ErrUIDValidityZero
	}

	if u.uidvalidity != uidvalidity {
		return 0, ErrEmptyUID
	}

	return u.next, nil
}

// SaveNextUID stores the uid and uidvalidity
func (u *uidCacheMem) SaveNextUID(uidvalidity, uid uint32) error {
	u.lock.Lock()
	defer u.lock.Unlock()

	if uidvalidity == 0 {
		return ErrUIDValidityZero
	}
	u.uidvalidity = uidvalidity
	u.next = uid

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"os"
	"os/exec"
)

func main() {
	if len(os.Args) != 2 {
		println("usage: used_imports path/to/some/file.go")
		os.Exit(1)
	}

	cmd := exec.Command("go", "build", os.Args[1])
	stderr, err := cmd.StderrPipe()
	if err != nil {
		println("fatal error getting stderr pipe")
		os.Exit(2)
	}

	cmd.Start()
	r := bufio.NewReader(stderr)
	for {
		line, _, err := r.ReadLine()
		if err != nil {
			break
		}
		println(string(line))
	}

	return
}
<commit_msg>Print out unused imports one at a time<commit_after>package main

import (
	"bufio"
	"os"
	"os/exec"
	"regexp"
)

func main() {
	if len(os.Args) != 2 {
		println("usage: used_imports path/to/some/file.go")
		os.Exit(1)
	}

	cmd := exec.Command("go", "build", os.Args[1])
	stderr, err := cmd.StderrPipe()
	if err != nil {
		println("fatal error getting stderr pipe")
		os.Exit(2)
	}

	cmd.Start()
	r := bufio.NewReader(stderr)
	importRegex := regexp.MustCompile("imported and not used: \"(.*)\"")
	for {
		line, _, err := r.ReadLine()
		if err != nil {
			break
		}

		matches := importRegex.FindAllStringSubmatch(string(line), 1)
		if matches == nil {
			continue
		}

		println(matches[0][1])
	}
	return
}
<|endoftext|>


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

package oglematchers

import (
)

// Return a matcher that matches non-nil pointers whose pointee matches the
// wrapped matcher.
func Pointee(m Matcher) Matcher {
	return Not(m)
}
<commit_msg>Implemented Pointee.<commit_after>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package oglematchers

import (
	"fmt"
	"reflect"
)

// Return a matcher that matches non-nil pointers whose pointee matches the
// wrapped matcher.
func Pointee(m Matcher) Matcher {
	return Not(m)
}

type pointeeMatcher struct {
	wrapped Matcher
}

func (m *pointeeMatcher) Matches(c interface{}) (err error) {
	// Make sure the candidate is of the appropriate type.
	cv := reflect.ValueOf(c)
	if !cv.IsValid() || cv.Kind() != reflect.Ptr {
		return NewFatalError("which is not a pointer")
	}

	// Make sure the candidate is non-nil.
	if cv.IsNil() {
		return fmt.Errorf("")
	}

	// Defer to the wrapped matcher.
	return m.wrapped.Matches(cv.Elem())
}

func (m *pointeeMatcher) Description() string {
	return fmt.Sprintf("pointee(%s)", m.wrapped.Description())
}
<|endoftext|>


<commit_before>package notes

import (
	"fmt"
	"regexp"
	"strconv"
	"strings"
	"time"
)

// These functions parser a plain text content formatted with org-mode
// and return Notes

var noteTitleReg = regexp.MustCompile("(?m)^(\\*{1,3} .+\\n)")
var separator = "@@@@\n"
var separatorReg = regexp.MustCompile("(?m)^@@@@\\n")

//var dateReg = regexp.MustCompile("\\<\\d{4}-\\d{2}-\\d{2} .{3}( \\d{2}:\\d{2})?\\>")

var stampReg = regexp.MustCompile("\\<[^\\>]+\\>")
var dateReg = regexp.MustCompile("\\<\\d{4}-\\d{2}-\\d{2} .{3}\\>")
var hourDateReg = regexp.MustCompile("\\<\\d{4}-\\d{2}-\\d{2} .{3} \\d{2}:\\d{2}\\>")
var repetitionReg = regexp.MustCompile("\\<\\d{4}-\\d{2}-\\d{2} .{3}( \\d{2}:\\d{2})?( [\\+\\-]?\\d+[a-z])+\\>")
var anniversaryReg = regexp.MustCompile("\\%\\%\\(diary-anniversary \\d{1,2} \\d{1,2} \\d{4}\\)(.*)")

var yearMonthDayReg = regexp.MustCompile("\\d{4}-\\d{2}-\\d{2}")
var monthDayAnniversaryReg = regexp.MustCompile("\\d{1,2} \\d{1,2} \\d{4}")
var hourMinReg = regexp.MustCompile("\\d{2}:\\d{2}")

// Parse string content in org mode and recover notes from it
func Parse(content string) []Note {
	notes := make([]Note, 0)

	content = noteTitleReg.ReplaceAllString(content, separator+"$1")
	rawNotes := separatorReg.Split(content, -1)

	for _, rnote := range rawNotes {
		note := NewNote()
		note.Title = parseTitle(rnote)
		note.Body = parseBody(rnote)
		note.Stamps = parseStamps(rnote)

		notes = append(notes, *note)
	}

	return notes
}

func parseTitle(orgnote string) string {
	title := noteTitleReg.FindString(orgnote)
	prefix := regexp.MustCompile("(?m)^\\*+( TODO| DONE)?( \\[#(A|B|C)\\])?")
	return strings.Trim(prefix.ReplaceAllString(title, ""), " \n\t")
}

func parseBody(orgnote string) string {

	body := orgnote

	if anniversaryReg.MatchString(body) {
		mdy := strings.Fields(monthDayAnniversaryReg.FindString(body))
		if len(mdy) < 3 {
			return body
		}
		ymd := fmt.Sprintf("%s-%02s-%02s", mdy[2], mdy[0], mdy[1])
		t, err := time.Parse("2006-01-02", ymd)
		if err != nil {
			return body
		}

		body = anniversaryReg.ReplaceAllString(orgnote, "$1")
		y := int(time.Since(t).Hours() / 8760)
		body = strings.Replace(body, "%d", fmt.Sprintf("%d", y), 1)
		body = fmt.Sprintf("%s\n", body)
	}

	body = noteTitleReg.ReplaceAllString(body, "")
	body = dateReg.ReplaceAllString(body, "")
	body = hourDateReg.ReplaceAllString(body, "")

	return strings.Trim(body, " \n\t")
}

func parseStamps(orgnote string) []time.Time {

	times := make([]time.Time, 0)

	// extract normal stamp with hour or not or with period
	rawTimes := stampReg.FindAllString(orgnote, -1)
	for _, rt := range rawTimes {
		if dateReg.MatchString(rt) {
			ymd := yearMonthDayReg.FindString(rt)
			t, err := time.Parse("2006-01-02", ymd)
			if err == nil {
				times = append(times, t)
			}
			continue
		}

		if hourDateReg.MatchString(rt) || repetitionReg.MatchString(rt) {
			ymd := yearMonthDayReg.FindString(rt)
			hm := hourMinReg.FindString(rt)
			t, err := time.Parse("2006-01-02 15:04", ymd+" "+hm)
			if err == nil {
				times = append(times, t)
			}
			continue
		}

	}

	// extract anniversary dates format
	rawTimes = anniversaryReg.FindAllString(orgnote, -1)
	for _, rt := range rawTimes {
		mdy := strings.Fields(monthDayAnniversaryReg.FindString(rt))
		if len(mdy) < 3 {
			continue
		}
		year := time.Now().Year()
		ymd := fmt.Sprintf("%d-%02s-%02s", year, mdy[0], mdy[1])
		t, err := time.Parse("2006-01-02", ymd)
		if err == nil {
			times = append(times, t)
		}
	}

	return times
}

/*
func parseStamps(orgnote string) []time.Time {

	times := make([]time.Time, 0)
	rawTimes := dateReg.FindAllString(orgnote, -1)

	for _, rt := range rawTimes {
		r := regexp.MustCompile(" [a-záéíóú]{3}")
		rt = r.ReplaceAllString(rt, "")
		var t time.Time
		var err error
		if strings.Contains(rt, ":") {
			t, err = time.Parse("<2006-01-02 15:04>", rt)
		} else {
			// If the stamp has not hour is dangerous for
			// datesInSameDay() function that we save it
			// as 00:00. For that reason we add a second after
			// the midnight

			t, err = time.Parse("<2006-01-02>", rt)
			t = t.Add(time.Second)
		}
		if err == nil {
			times = append(times, t)
		}
	}

	return times
}
*/

/*
 HTML conversion
*/

var head1Reg = regexp.MustCompile("(?m)^\\* (?P.+)\\n")
var head2Reg = regexp.MustCompile("(?m)^\\*\\* (?P.+)\\n")
var linkReg = regexp.MustCompile("\\[\\[(?P<url>[^\\]]+)\\]\\[(?P<text>[^\\]]+)\\]\\]")
var imgLinkReg = regexp.MustCompile("\\[\\[file:\\.\\./img/(?P[^\\]]+)\\]\\[file:\\.\\./img/(?P<thumb>[^\\]]+)\\]\\]")
var imgReg = regexp.MustCompile("\\[\\[\\.\\./img/(?P<src>[^\\]]+)\\]\\]")

var codeReg = regexp.MustCompile("(?m)^\\#\\+BEGIN_SRC \\w*\\n(?P(?s)[^\\#]+)^\\#\\+END_SRC\\n")
var codeHeaderReg = regexp.MustCompile("(?m)^\\#\\+BEGIN_SRC \\w*\\n")
var codeFooterReg = regexp.MustCompile("(?m)^\\#\\+END_SRC\\n")

var quoteReg = regexp.MustCompile("(?m)^\\#\\+BEGIN_QUOTE\\s*\\n(?P(?s)[^\\#]+)^\\#\\+END_QUOTE\\n")
var quoteHeaderReg = regexp.MustCompile("(?m)^\\#\\+BEGIN_QUOTE\\s*\\n")
var quoteFooterReg = regexp.MustCompile("(?m)^\\#\\+END_QUOTE\\n")

var centerReg = regexp.MustCompile("(?m)^\\#\\+BEGIN_CENTER\\s*\\n(?P(?s)[^\\#]+)^\\#\\+END_CENTER\\n")
var centerHeaderReg = regexp.MustCompile("(?m)^\\#\\+BEGIN_CENTER\\s*\\n")
var centerFooterReg = regexp.MustCompile("(?m)^\\#\\+END_CENTER\\n")

var parReg = regexp.MustCompile("\\n\\n+(?P<text>[^\\n]+)")
var allPropsReg = regexp.MustCompile(":PROPERTIES:(?s).+:END:")
var rawHTML = regexp.MustCompile("\\]+\\>")

//estilos de texto
var boldReg = regexp.MustCompile("(?P<prefix>[\\s|\\W]+)\\*(?P<text>[^\\s][^\\*]+)\\*(?P<suffix>[\\s|\\W]*)")
var italicReg = regexp.MustCompile("(?P<prefix>[\\s])/(?P<text>[^\\s][^/]+)/(?P<suffix>[^A-Za-z0-9]*)")
var ulineReg = regexp.MustCompile("(?P<prefix>[\\s|\\W]+)_(?P<text>[^\\s][^_]+)_(?P<suffix>[\\s|\\W]*)")
var codeLineReg = regexp.MustCompile("(?P<prefix>[\\s|\\W]+)=(?P<text>[^\\s][^\\=]+)=(?P<suffix>[\\s|\\W]*)")
var strikeReg = regexp.MustCompile("(?P<prefix>[\\s|[\\W]+)\\+(?P<text>[^\\s][^\\+]+)\\+(?P<suffix>[\\s|\\W]*)")

// listas
var ulistItemReg = regexp.MustCompile("(?m)^\\s*[\\+|\\-]\\s+(?P<item>[^\\-|\\+|\\n+]+)")
var olistItemReg = regexp.MustCompile("(?m)^\\s*[0-9]+\\.\\s+(?P<item>[^\\-|\\+|\\n+]+)")

//var ulistItemReg = regexp.MustCompile("(?m)^\\s*[\\+|\\-]\\s+(?P<item>[^\\-|\\+]+)$")
//var olistItemReg = regexp.MustCompile("(?m)^\\s*[0-9]+\\.\\s+(?P<item>[^\\-|\\+]+)$")

//var ulistReg = regexp.MustCompile("(?P<items>(\\<uli-begin\\>[^\\<]+\\<uli-end\\>)+)")
//var olistReg = regexp.MustCompile("(?P<items>(\\<oli-begin\\>[^\\<]+\\<oli-end\\>)+)")
var ulistReg = regexp.MustCompile("(?s)(?P<items>(\\<uli-begin\\>.+\\<uli-end\\>)+)")
var olistReg = regexp.MustCompile("(?s)(?P<items>(\\<oli-begin\\>.+\\<oli-end\\>)+)")

func Org2HTML(content []byte, url string) string {

	// First remove all HTML raw tags for security
	out := rawHTML.ReplaceAll(content, []byte(""))

	// headings (h1 is not admit in the post body)
	out = head1Reg.ReplaceAll(out, []byte(""))
	out = head2Reg.ReplaceAll(out, []byte("
$head
\n"))

	// images
	out = imgReg.ReplaceAll(out, []byte(""))
	out = imgLinkReg.ReplaceAll(out, []byte(""))
	out = linkReg.ReplaceAll(out, []byte("$text"))

	// Extract blocks codes
	codeBlocks, out := extractBlocks(string(out),
		codeReg,
		codeHeaderReg,
		codeFooterReg,
		"code")

	quoteBlocks, out := extractBlocks(string(out),
		quoteReg,
		quoteHeaderReg,
		quoteFooterReg,
		"quote")

	out = centerReg.ReplaceAll(out, []byte("$cite\n"))
	out = parReg.ReplaceAll(out, []byte("\n\n
$text"))
	out = allPropsReg.ReplaceAll(out, []byte("\n"))

	// font styles
	out = italicReg.ReplaceAll(out, []byte("$prefix$text$suffix"))
	out = boldReg.ReplaceAll(out, []byte("$prefix$text$suffix"))
	out = ulineReg.ReplaceAll(out, []byte("$prefix$text$suffix"))
	out = codeLineReg.ReplaceAll(out, []byte("$prefix$text$suffix"))
	out = strikeReg.ReplaceAll(out, []byte("$prefix<s>$text</s>$suffix"))

	// List with fake tags for items
	out = ulistItemReg.ReplaceAll(out, []byte("<uli-begin>$item<uli-end>"))
	out = ulistReg.ReplaceAll(out, []byte("
\n$items
\n"))
	out = olistItemReg.ReplaceAll(out, []byte("<fake-oli>$item</fake-oli>\n"))
	out = olistReg.ReplaceAll(out, []byte("
\n$items
\n"))

	// Removing fake items tags
	sout := string(out)
	sout = strings.Replace(sout, "<uli-begin>", "
", -1)
	sout = strings.Replace(sout, "<uli-end>", "
\n", -1)
	sout = strings.Replace(sout, "<oli-begin>", "
", -1)
	sout = strings.Replace(sout, "<oli-end>", "
\n", -1)

	// Reinsert block codes
	sout = insertBlocks(sout, codeBlocks, "
", "
", "code")
	sout = insertBlocks(sout, quoteBlocks, "
", "
", "quote")

	return sout
}

func extractBlocks(src string, fullReg, headerReg, footerReg *regexp.Regexp, name string) ([][]byte, []byte) {
	out := []byte(src)
	blocks := fullReg.FindAll(out, -1)
	for i := range blocks {
		bstring := string(blocks[i])
		blocks[i] = headerReg.ReplaceAll(blocks[i], []byte("\n"))
		blocks[i] = footerReg.ReplaceAll(blocks[i], []byte("\n"))
		out = []byte(strings.Replace(string(out), bstring, "block"+name+":"+strconv.Itoa(i)+"\n", 1))
	}

	return blocks, out
}

func insertBlocks(src string, blocks [][]byte, header, footer, name string) string {
	s := src
	for i := range blocks {
		bstring := string(blocks[i])
		s = strings.Replace(s, "block"+name+":"+strconv.Itoa(i)+"\n",
			header+bstring+footer+"\n", 1)
	}

	return s
}
<commit_msg>fix error on org parsing<commit_after>package notes

import (
	"fmt"
	"regexp"
	"strconv"
	"strings"
	"time"
)

// These functions parser a plain text content formatted with org-mode
// and return Notes

var noteTitleReg = regexp.MustCompile("(?m)^(\\*{1,3} .+\\n)")
var separator = "@@@@\n"
var separatorReg = regexp.MustCompile("(?m)^@@@@\\n")

var stampReg = regexp.MustCompile("\\<[^\\>]+\\>")
var dateReg = regexp.MustCompile("\\<\\d{4}-\\d{2}-\\d{2} .{3}\\>")
var hourDateReg = regexp.MustCompile("\\<\\d{4}-\\d{2}-\\d{2} .{3} \\d{2}:\\d{2}\\>")
var repetitionReg = regexp.MustCompile("\\<\\d{4}-\\d{2}-\\d{2} .{3}( \\d{2}:\\d{2})?( [\\+\\-]?\\d+[a-z])+\\>")
var anniversaryReg = regexp.MustCompile("\\%\\%\\(diary-anniversary \\d{1,2} \\d{1,2} \\d{4}\\)(.*)")
var deadlineReg = regexp.MustCompile("(?s)DEADLINE:.+:END:")

var yearMonthDayReg = regexp.MustCompile("\\d{4}-\\d{2}-\\d{2}")
var monthDayAnniversaryReg = regexp.MustCompile("\\d{1,2} \\d{1,2} \\d{4}")
var hourMinReg = regexp.MustCompile("\\d{2}:\\d{2}")

// Parse string content in org mode and recover notes from it
func Parse(content string) []Note {
	notes := make([]Note, 0)

	content = noteTitleReg.ReplaceAllString(content, separator+"$1")
	rawNotes := separatorReg.Split(content, -1)

	for _, rnote := range rawNotes {
		note := NewNote()
		note.Title = parseTitle(rnote)
		note.Body = parseBody(rnote)
		note.Stamps = parseStamps(rnote)

		notes = append(notes, *note)
	}

	return notes
}

// Clean the title of the note
func parseTitle(orgnote string) string {
	title := noteTitleReg.FindString(orgnote)
	prefix := regexp.MustCompile("(?m)^\\*+( TODO| DONE)?( \\[#(A|B|C)\\])?")
	return strings.Trim(prefix.ReplaceAllString(title, ""), " \n\t")
}

// Extract and clean the body note. If the body content a
// %%(diary-anniversary d m year) function it calculates the
// difference and print the number in the body
func parseBody(orgnote string) string {

	body := orgnote

	if anniversaryReg.MatchString(body) {
		mdy := strings.Fields(monthDayAnniversaryReg.FindString(body))
		if len(mdy) < 3 {
			return body
		}
		ymd := fmt.Sprintf("%s-%02s-%02s", mdy[2], mdy[0], mdy[1])
		ymd2 := fmt.Sprintf("%d-%02s-%02s", time.Now().Year(), mdy[0], mdy[1])
		t, err := time.Parse("2006-01-02", ymd)
		t2, err := time.Parse("2006-01-02", ymd2)
		if err != nil {
			return body
		}

		body = anniversaryReg.ReplaceAllString(orgnote, "$1")
		diffYears := int(t2.Sub(t).Hours() / 8760)
		body = strings.Replace(body, "%d", fmt.Sprintf("%d", diffYears), 1)
		body = fmt.Sprintf("%s\n", body)
	}

	body = deadlineReg.ReplaceAllString(body, "")
	body = noteTitleReg.ReplaceAllString(body, "")
	body = dateReg.ReplaceAllString(body, "")
	body = hourDateReg.ReplaceAllString(body, "")

	return strings.Trim(body, " \n\t")
}

// Extract the stamps of the note in several formats: <day-month-year>,
// <day-month-year weekday hour:min> and <day-month-year weekday hour:min repetition>.
// If the stamp has not hour is dangerous for
// datesInSameDay() function that we save it as 00:00. For that reason we
// add a second after the midnight

func parseStamps(orgnote string) []time.Time {

	times := make([]time.Time, 0)

	// extract normal stamp with hour or not or with period
	rawTimes := stampReg.FindAllString(orgnote, -1)
	for _, rt := range rawTimes {
		if dateReg.MatchString(rt) {
			ymd := yearMonthDayReg.FindString(rt)
			t, err := time.Parse("2006-01-02", ymd)
			t = t.Add(time.Second)
			if err == nil {
				times = append(times, t)
			}
			continue
		}

		if hourDateReg.MatchString(rt) || repetitionReg.MatchString(rt) {
			ymd := yearMonthDayReg.FindString(rt)
			hm := hourMinReg.FindString(rt)
			var t time.Time
			var err error
			if hm != "" {
				t, err = time.Parse("2006-01-02 15:04", ymd+" "+hm)
			} else {
				t, err = time.Parse("2006-01-02", ymd)
				t = t.Add(time.Second)
			}
			if err == nil {
				times = append(times, t)
			}
			continue
		}

	}

	// extract anniversary dates format
	rawTimes = anniversaryReg.FindAllString(orgnote, -1)
	for _, rt := range rawTimes {
		mdy := strings.Fields(monthDayAnniversaryReg.FindString(rt))
		if len(mdy) < 3 {
			continue
		}
		year := time.Now().Year()
		ymd := fmt.Sprintf("%d-%02s-%02s", year, mdy[0], mdy[1])
		t, err := time.Parse("2006-01-02", ymd)
		t = t.Add(time.Second)
		if err == nil {
			times = append(times, t)
		}
	}

	return times
}

/*
 HTML conversion
*/

var head1Reg = regexp.MustCompile("(?m)^\\* (?P.+)\\n")
var head2Reg = regexp.MustCompile("(?m)^\\*\\* (?P.+)\\n")
var linkReg = regexp.MustCompile("\\[\\[(?P<url>[^\\]]+)\\]\\[(?P<text>[^\\]]+)\\]\\]")
var imgLinkReg = regexp.MustCompile("\\[\\[file:\\.\\./img/(?P[^\\]]+)\\]\\[file:\\.\\./img/(?P<thumb>[^\\]]+)\\]\\]")
var imgReg = regexp.MustCompile("\\[\\[\\.\\./img/(?P<src>[^\\]]+)\\]\\]")

var codeReg = regexp.MustCompile("(?m)^\\#\\+BEGIN_SRC \\w*\\n(?P(?s)[^\\#]+)^\\#\\+END_SRC\\n")
var codeHeaderReg = regexp.MustCompile("(?m)^\\#\\+BEGIN_SRC \\w*\\n")
var codeFooterReg = regexp.MustCompile("(?m)^\\#\\+END_SRC\\n")

var quoteReg = regexp.MustCompile("(?m)^\\#\\+BEGIN_QUOTE\\s*\\n(?P(?s)[^\\#]+)^\\#\\+END_QUOTE\\n")
var quoteHeaderReg = regexp.MustCompile("(?m)^\\#\\+BEGIN_QUOTE\\s*\\n")
var quoteFooterReg = regexp.MustCompile("(?m)^\\#\\+END_QUOTE\\n")

var centerReg = regexp.MustCompile("(?m)^\\#\\+BEGIN_CENTER\\s*\\n(?P(?s)[^\\#]+)^\\#\\+END_CENTER\\n")
var centerHeaderReg = regexp.MustCompile("(?m)^\\#\\+BEGIN_CENTER\\s*\\n")
var centerFooterReg = regexp.MustCompile("(?m)^\\#\\+END_CENTER\\n")

var parReg = regexp.MustCompile("\\n\\n+(?P<text>[^\\n]+)")
var allPropsReg = regexp.MustCompile(":PROPERTIES:(?s).+:END:")
var rawHTML = regexp.MustCompile("\\]+\\>")

//estilos de texto
var boldReg = regexp.MustCompile("(?P<prefix>[\\s|\\W]+)\\*(?P<text>[^\\s][^\\*]+)\\*(?P<suffix>[\\s|\\W]*)")
var italicReg = regexp.MustCompile("(?P<prefix>[\\s])/(?P<text>[^\\s][^/]+)/(?P<suffix>[^A-Za-z0-9]*)")
var ulineReg = regexp.MustCompile("(?P<prefix>[\\s|\\W]+)_(?P<text>[^\\s][^_]+)_(?P<suffix>[\\s|\\W]*)")
var codeLineReg = regexp.MustCompile("(?P<prefix>[\\s|\\W]+)=(?P<text>[^\\s][^\\=]+)=(?P<suffix>[\\s|\\W]*)")
var strikeReg = regexp.MustCompile("(?P<prefix>[\\s|[\\W]+)\\+(?P<text>[^\\s][^\\+]+)\\+(?P<suffix>[\\s|\\W]*)")

// listas
var ulistItemReg = regexp.MustCompile("(?m)^\\s*[\\+|\\-]\\s+(?P<item>[^\\-|\\+|\\n+]+)")
var olistItemReg = regexp.MustCompile("(?m)^\\s*[0-9]+\\.\\s+(?P<item>[^\\-|\\+|\\n+]+)")

//var ulistItemReg = regexp.MustCompile("(?m)^\\s*[\\+|\\-]\\s+(?P<item>[^\\-|\\+]+)$")
//var olistItemReg = regexp.MustCompile("(?m)^\\s*[0-9]+\\.\\s+(?P<item>[^\\-|\\+]+)$")

//var ulistReg = regexp.MustCompile("(?P<items>(\\<uli-begin\\>[^\\<]+\\<uli-end\\>)+)")
//var olistReg = regexp.MustCompile("(?P<items>(\\<oli-begin\\>[^\\<]+\\<oli-end\\>)+)")
var ulistReg = regexp.MustCompile("(?s)(?P<items>(\\<uli-begin\\>.+\\<uli-end\\>)+)")
var olistReg = regexp.MustCompile("(?s)(?P<items>(\\<oli-begin\\>.+\\<oli-end\\>)+)")

func Org2HTML(content []byte, url string) string {

	// First remove all HTML raw tags for security
	out := rawHTML.ReplaceAll(content, []byte(""))

	// headings (h1 is not admit in the post body)
	out = head1Reg.ReplaceAll(out, []byte(""))
	out = head2Reg.ReplaceAll(out, []byte("
$head
\n"))

	// images
	out = imgReg.ReplaceAll(out, []byte(""))
	out = imgLinkReg.ReplaceAll(out, []byte(""))
	out = linkReg.ReplaceAll(out, []byte("$text"))

	// Extract blocks codes
	codeBlocks, out := extractBlocks(string(out),
		codeReg,
		codeHeaderReg,
		codeFooterReg,
		"code")

	quoteBlocks, out := extractBlocks(string(out),
		quoteReg,
		quoteHeaderReg,
		quoteFooterReg,
		"quote")

	out = centerReg.ReplaceAll(out, []byte("$cite\n"))
	out = parReg.ReplaceAll(out, []byte("\n\n
$text"))
	out = allPropsReg.ReplaceAll(out, []byte("\n"))

	// font styles
	out = italicReg.ReplaceAll(out, []byte("$prefix$text$suffix"))
	out = boldReg.ReplaceAll(out, []byte("$prefix$text$suffix"))
	out = ulineReg.ReplaceAll(out, []byte("$prefix$text$suffix"))
	out = codeLineReg.ReplaceAll(out, []byte("$prefix$text$suffix"))
	out = strikeReg.ReplaceAll(out, []byte("$prefix<s>$text</s>$suffix"))

	// List with fake tags for items
	out = ulistItemReg.ReplaceAll(out, []byte("<uli-begin>$item<uli-end>"))
	out = ulistReg.ReplaceAll(out, []byte("
\n$items
\n"))
	out = olistItemReg.ReplaceAll(out, []byte("<fake-oli>$item</fake-oli>\n"))
	out = olistReg.ReplaceAll(out, []byte("
\n$items
\n"))

	// Removing fake items tags
	sout := string(out)
	sout = strings.Replace(sout, "<uli-begin>", "
", -1)
	sout = strings.Replace(sout, "<uli-end>", "
\n", -1)
	sout = strings.Replace(sout, "<oli-begin>", "
", -1)
	sout = strings.Replace(sout, "<oli-end>", "
\n", -1)

	// Reinsert block codes
	sout = insertBlocks(sout, codeBlocks, "
", "
", "code")
	sout = insertBlocks(sout, quoteBlocks, "
", "
", "quote")

	return sout
}

func extractBlocks(src string, fullReg, headerReg, footerReg *regexp.Regexp, name string) ([][]byte, []byte) {
	out := []byte(src)
	blocks := fullReg.FindAll(out, -1)
	for i := range blocks {
		bstring := string(blocks[i])
		blocks[i] = headerReg.ReplaceAll(blocks[i], []byte("\n"))
		blocks[i] = footerReg.ReplaceAll(blocks[i], []byte("\n"))
		out = []byte(strings.Replace(string(out), bstring, "block"+name+":"+strconv.Itoa(i)+"\n", 1))
	}

	return blocks, out
}

func insertBlocks(src string, blocks [][]byte, header, footer, name string) string {
	s := src
	for i := range blocks {
		bstring := string(blocks[i])
		s = strings.Replace(s, "block"+name+":"+strconv.Itoa(i)+"\n",
			header+bstring+footer+"\n", 1)
	}

	return s
}
<|endoftext|>


<commit_before>package transport

import (
	"crypto/hmac"
	"crypto/rand"
	"crypto/sha256"
	"crypto/subtle"
	"errors"
	"hash"
	"io"
	"strconv"
	"time"

	pond "github.com/unixninja92/Div-III-Server/protos"
	"github.com/golang/protobuf/proto"
	"golang.org/x/crypto/curve25519"
	"golang.org/x/crypto/nacl/secretbox"
)

// blockSize is the size of the blocks of data that we'll send and receive when
// working in streaming mode. Each block is prefixed by two length bytes (which
// aren't counted in blockSize) and includes secretbox.Overhead bytes of MAC
// tag (which are).
const blockSize = 4096 - 2

type Conn struct {
	conn                     io.ReadWriteCloser
	isServer                 bool
	identity, identityPublic [32]byte
	Peer                     [32]byte

	writeKey, readKey           [32]byte
	writeKeyValid, readKeyValid bool
	writeSequence, readSequence [24]byte

	// readBuffer is used to receive bytes from the network when this Conn
	// is used to stream data.
	readBuffer []byte
	// decryptBuffer is used to store decrypted payloads when this Conn is
	// used to stream data and the caller's buffer isn't large enough to
	// decrypt into directly.
	decryptBuffer []byte
	// readPending aliases into decryptBuffer when a partial decryption had
	// to be returned to a caller because of buffer size limitations.
	readPending []byte

	// writeBuffer is used to hold encrypted payloads when this Conn is
	// used for streaming data.
	writeBuffer []byte
}

func NewServer(conn io.ReadWriteCloser, identity *[32]byte) *Conn {
	c := &Conn{
		conn:     conn,
		isServer: true,
	}
	copy(c.identity[:], identity[:])
	return c
}

func NewClient(conn io.ReadWriteCloser, myIdentity, myIdentityPublic, serverPublic *[32]byte) *Conn {
	c := &Conn{
		conn: conn,
	}
	copy(c.identity[:], myIdentity[:])
	copy(c.identityPublic[:], myIdentityPublic[:])
	copy(c.Peer[:], serverPublic[:])
	return c
}

func incSequence(seq *[24]byte) {
	n := uint32(1)

	for i := 0; i < 8; i++ {
		n += uint32(seq[i])
		seq[i] = byte(n)
		n >>= 8
	}
}

type deadlineable interface {
	SetDeadline(time.Time)
}

func (c *Conn) SetDeadline(t time.Time) {
	if d, ok := c.conn.(deadlineable); ok {
		d.SetDeadline(t)
	}
}

func (c *Conn) Read(out []byte) (n int, err error) {
	if len(c.readPending) > 0 {
		n = copy(out, c.readPending)
		c.readPending = c.readPending[n:]
		return
	}

	if c.readBuffer == nil {
		c.readBuffer = make([]byte, blockSize+2)
	}

	if _, err := io.ReadFull(c.conn, c.readBuffer[:2]); err != nil {
		return 0, err
	}
	n = int(c.readBuffer[0]) | int(c.readBuffer[1])<<8
	if n > len(c.readBuffer) {
		return 0, errors.New("transport: peer's message too large for Read")
	}
	if _, err := io.ReadFull(c.conn, c.readBuffer[:n]); err != nil {
		return 0, err
	}

	var ok bool
	if len(out) >= n-secretbox.Overhead {
		// We can decrypt directly into the output buffer.
		out, ok = secretbox.Open(out[:0], c.readBuffer[:n], &c.readSequence, &c.readKey)
		n = len(out)
	} else {
		// We need to decrypt into a side buffer and copy a prefix of
		// the result into the caller's buffer.
		c.decryptBuffer, ok = secretbox.Open(c.decryptBuffer[:0], c.readBuffer[:n], &c.readSequence, &c.readKey)
		n = copy(out, c.decryptBuffer)
		c.readPending = c.decryptBuffer[n:]
	}
	incSequence(&c.readSequence)
	if !ok {
		c.readPending = c.readPending[:0]
		return 0, errors.New("transport: bad MAC")
	}

	return
}

func (c *Conn) Write(buf []byte) (n int, err error) {
	if c.writeBuffer == nil {
		c.writeBuffer = make([]byte, blockSize+2)
	}

	for len(buf) > 0 {
		m := len(buf)
		if m > blockSize-secretbox.Overhead {
			m = blockSize - secretbox.Overhead
		}
		l := len(secretbox.Seal(c.writeBuffer[2:2], buf[:m], &c.writeSequence, &c.writeKey))
		c.writeBuffer[0] = byte(l)
		c.writeBuffer[1] = byte(l >> 8)
		if _, err = c.conn.Write(c.writeBuffer[:2+l]); err != nil {
			return n, err
		}
		n += m
		buf = buf[m:]
		incSequence(&c.writeSequence)
	}

	return
}

func (c *Conn) ReadProto(out proto.Message) error {
	buf := make([]byte, pond.TransportSize+4+secretbox.Overhead)
	n, err := c.read(buf)
	if err != nil {
		return err
	}
	if n != pond.TransportSize+4 {
		return errors.New("transport: message wrong length")
	}

	n = int(buf[3]) | int(buf[2])<<8 | int(buf[1])<<12 | int(buf[0])<<16
	buf = buf[4:]
	if n > len(buf) {
		return errors.New("transport: corrupt message")
	}
	return proto.Unmarshal(buf[:n], out)
}

func (c *Conn) WriteProto(msg proto.Message) error {
	data, err := proto.Marshal(msg)
	if err != nil {
		return err
	}
	if len(data) > pond.TransportSize {
		return errors.New("transport: message too large")
	}

	buf := make([]byte, pond.TransportSize+4)
	buf[3] = byte(len(data))
	buf[2] = byte(len(data) >> 8)
	buf[1] = byte(len(data) >> 12)
	buf[0] = byte(len(data) >> 16)
	copy(buf[4:], data)
	_, err = c.write(buf)
	return err
}

func (c *Conn) Close() (err error) {
	if !c.isServer {
		_, err = c.write(nil)
	}

	if closeErr := c.conn.Close(); err == nil {
		err = closeErr
	}

	return
}

func (c *Conn) WaitForClose() error {
	if !c.isServer {
		panic("non-server waited for connection close")
	}
	n, err := c.read(make([]byte, 128))
	if err != nil {
		return err
	}
	if n != 0 {
		return errors.New("transport: non-close message received when expecting close")
	}

	return nil
}

func (c *Conn) read(data []byte) (n int, err error) {
	var lengthBytes [4]byte

	if _, err := io.ReadFull(c.conn, lengthBytes[:]); err != nil {
		return 0, err
	}

	theirLength := int(lengthBytes[3]) + int(lengthBytes[2])<<8 + int(lengthBytes[1])<<12 + int(lengthBytes[0])<<16
	if theirLength > len(data) {
		return 0, errors.New("tranport: given buffer too small (" + strconv.Itoa(len(data)) + " vs " + strconv.Itoa(theirLength) + ")")
	}

	data = data[:theirLength]
	if _, err := io.ReadFull(c.conn, data); err != nil {
		return 0, err
	}

	decrypted, err := c.decrypt(data)
	if err != nil {
		return 0, err
	}
	copy(data, decrypted)

	return len(decrypted), nil
}

func (c *Conn) write(data []byte) (n int, err error) {
	encrypted := c.encrypt(data)

	var lengthBytes [4]byte
	lengthBytes[3] = byte(len(encrypted))
	lengthBytes[2] = byte(len(encrypted) >> 8)
	lengthBytes[1] = byte(len(encrypted) >> 12)
	lengthBytes[0] = byte(len(encrypted) >> 16)

	if _, err := c.conn.Write(lengthBytes[:]); err != nil {
		return 0, err
	}
	if _, err := c.conn.Write(encrypted); err != nil {
		return 0, err
	}

	return len(data), nil
}

func (c *Conn) encrypt(data []byte) []byte {
	if !c.writeKeyValid {
		return data
	}

	encrypted := secretbox.Seal(nil, data, &c.writeSequence, &c.writeKey)
	incSequence(&c.writeSequence)
	return encrypted
}

func (c *Conn) decrypt(data []byte) ([]byte, error) {
	if !c.readKeyValid {
		return data, nil
	}

	decrypted, ok := secretbox.Open(nil, data, &c.readSequence, &c.readKey)
	incSequence(&c.readSequence)
	if !ok {
		return nil, errors.New("transport: bad MAC")
	}
	return decrypted, nil
}

var serverKeysMagic = []byte("server keys snap")
var clientKeysMagic = []byte("client keys snap")

func (c *Conn) setupKeys(ephemeralShared *[32]byte) {
	var writeMagic, readMagic []byte
	if c.isServer {
		writeMagic, readMagic = serverKeysMagic, clientKeysMagic
	} else {
		writeMagic, readMagic = clientKeysMagic, serverKeysMagic
	}

	h := sha256.New()
	h.Write(writeMagic)
	h.Write(ephemeralShared[:])
	h.Sum(c.writeKey[:0])
	c.writeKeyValid = true

	h.Reset()
	h.Write(readMagic)
	h.Write(ephemeralShared[:])
	h.Sum(c.readKey[:0])
	c.readKeyValid = true
}

var serverProofMagic = []byte("server proof snap")
var clientProofMagic = []byte("client proof snap")

var shortMessageError = errors.New("transport: received short handshake message")

func (c *Conn) Handshake() error {
	var ephemeralPrivate, ephemeralPublic, ephemeralShared [32]byte
	if _, err := io.ReadFull(rand.Reader, ephemeralPrivate[:]); err != nil {
		return err
	}
	curve25519.ScalarBaseMult(&ephemeralPublic, &ephemeralPrivate)

	if _, err := c.write(ephemeralPublic[:]); err != nil {
		return err
	}

	var theirEphemeralPublic [32]byte
	if n, err := c.read(theirEphemeralPublic[:]); err != nil || n != len(theirEphemeralPublic) {
		if err == nil {
			err = shortMessageError
		}
		return err
	}

	handshakeHash := sha256.New()
	if c.isServer {
		handshakeHash.Write(theirEphemeralPublic[:])
		handshakeHash.Write(ephemeralPublic[:])
	} else {
		handshakeHash.Write(ephemeralPublic[:])
		handshakeHash.Write(theirEphemeralPublic[:])
	}

	curve25519.ScalarMult(&ephemeralShared, &ephemeralPrivate, &theirEphemeralPublic)
	c.setupKeys(&ephemeralShared)

	if c.isServer {
		return c.handshakeServer(handshakeHash, &theirEphemeralPublic)
	}
	return c.handshakeClient(handshakeHash, &ephemeralPrivate)
}

func (c *Conn) handshakeClient(handshakeHash hash.Hash, ephemeralPrivate *[32]byte) error {
	var ephemeralIdentityShared [32]byte
	curve25519.ScalarMult(&ephemeralIdentityShared, ephemeralPrivate, &c.Peer)

	digest := handshakeHash.Sum(nil)
	h := hmac.New(sha256.New, ephemeralIdentityShared[:])
	h.Write(serverProofMagic)
	h.Write(digest)
	digest = h.Sum(digest[:0])

	digestReceived := make([]byte, len(digest)+secretbox.Overhead)
	n, err := c.read(digestReceived)
	if err != nil {
		return err
	}
	if n != len(digest) {
		return shortMessageError
	}
	digestReceived = digestReceived[:n]

	if subtle.ConstantTimeCompare(digest, digestReceived) != 1 {
		return errors.New("transport: server identity incorrect")
	}

	var identityShared [32]byte
	curve25519.ScalarMult(&identityShared, &c.identity, &c.Peer)

	handshakeHash.Write(digest)
	digest = handshakeHash.Sum(digest[:0])

	h = hmac.New(sha256.New, identityShared[:])
	h.Write(clientProofMagic)
	h.Write(digest)

	finalMessage := make([]byte, 32+sha256.Size)
	copy(finalMessage, c.identityPublic[:])
	h.Sum(finalMessage[32:32])

	if _, err := c.write(finalMessage); err != nil {
		return err
	}

	return nil
}

func (c *Conn) handshakeServer(handshakeHash hash.Hash, theirEphemeralPublic *[32]byte) error {
	var ephemeralIdentityShared [32]byte
	curve25519.ScalarMult(&ephemeralIdentityShared, &c.identity, theirEphemeralPublic)

	digest := handshakeHash.Sum(nil)
	h := hmac.New(sha256.New, ephemeralIdentityShared[:])
	h.Write(serverProofMagic)
	h.Write(digest)
	digest = h.Sum(digest[:0])

	if _, err := c.write(digest); err != nil {
		return err
	}

	handshakeHash.Write(digest)
	digest = handshakeHash.Sum(digest[:0])

	finalMessage := make([]byte, 32+sha256.Size+secretbox.Overhead)
	n, err := c.read(finalMessage)
	if err != nil {
		return err
	}
	if n != 32+sha256.Size {
		return shortMessageError
	}
	finalMessage = finalMessage[:n]

	copy(c.Peer[:], finalMessage[:32])
	var identityShared [32]byte
	curve25519.ScalarMult(&identityShared, &c.identity, &c.Peer)

	h = hmac.New(sha256.New, identityShared[:])
	h.Write(clientProofMagic)
	h.Write(digest)
	digest = h.Sum(digest[:0])

	if subtle.ConstantTimeCompare(digest, finalMessage[32:]) != 1 {
		return errors.New("transport: bad proof from client")
	}

	return nil
}
<commit_msg>But actually fixed length transport issues??<commit_after>package transport

import (
	"crypto/hmac"
	"crypto/rand"
	"crypto/sha256"
	"crypto/subtle"
	"errors"
	"hash"
	"io"
	"strconv"
	"time"

	pond "github.com/unixninja92/Div-III-Server/protos"
	"github.com/golang/protobuf/proto"
	"golang.org/x/crypto/curve25519"
	"golang.org/x/crypto/nacl/secretbox"
)

// blockSize is the size of the blocks of data that we'll send and receive when
// working in streaming mode. Each block is prefixed by two length bytes (which
// aren't counted in blockSize) and includes secretbox.Overhead bytes of MAC
// tag (which are).
const blockSize = 4096 - 4

type Conn struct {
	conn                     io.ReadWriteCloser
	isServer                 bool
	identity, identityPublic [32]byte
	Peer                     [32]byte

	writeKey, readKey           [32]byte
	writeKeyValid, readKeyValid bool
	writeSequence, readSequence [24]byte

	// readBuffer is used to receive bytes from the network when this Conn
	// is used to stream data.
	readBuffer []byte
	// decryptBuffer is used to store decrypted payloads when this Conn is
	// used to stream data and the caller's buffer isn't large enough to
	// decrypt into directly.
	decryptBuffer []byte
	// readPending aliases into decryptBuffer when a partial decryption had
	// to be returned to a caller because of buffer size limitations.
	readPending []byte

	// writeBuffer is used to hold encrypted payloads when this Conn is
	// used for streaming data.
	writeBuffer []byte
}

func NewServer(conn io.ReadWriteCloser, identity *[32]byte) *Conn {
	c := &Conn{
		conn:     conn,
		isServer: true,
	}
	copy(c.identity[:], identity[:])
	return c
}

func NewClient(conn io.ReadWriteCloser, myIdentity, myIdentityPublic, serverPublic *[32]byte) *Conn {
	c := &Conn{
		conn: conn,
	}
	copy(c.identity[:], myIdentity[:])
	copy(c.identityPublic[:], myIdentityPublic[:])
	copy(c.Peer[:], serverPublic[:])
	return c
}

func incSequence(seq *[24]byte) {
	n := uint32(1)

	for i := 0; i < 8; i++ {
		n += uint32(seq[i])
		seq[i] = byte(n)
		n >>= 8
	}
}

type deadlineable interface {
	SetDeadline(time.Time)
}

func (c *Conn) SetDeadline(t time.Time) {
	if d, ok := c.conn.(deadlineable); ok {
		d.SetDeadline(t)
	}
}

func (c *Conn) Read(out []byte) (n int, err error) {
	if len(c.readPending) > 0 {
		n = copy(out, c.readPending)
		c.readPending = c.readPending[n:]
		return
	}

	if c.readBuffer == nil {
		c.readBuffer = make([]byte, blockSize+4)
	}

	if _, err := io.ReadFull(c.conn, c.readBuffer[:4]); err != nil {
		return 0, err
	}
	n = int(c.readBuffer[3]) | int(c.readBuffer[2])<<8  | int(c.readBuffer[1])<<12 | int(c.readBuffer[0])<<16
	if n > len(c.readBuffer) {
		return 0, errors.New("transport: peer's message too large for Read")
	}
	if _, err := io.ReadFull(c.conn, c.readBuffer[:n]); err != nil {
		return 0, err
	}

	var ok bool
	if len(out) >= n-secretbox.Overhead {
		// We can decrypt directly into the output buffer.
		out, ok = secretbox.Open(out[:0], c.readBuffer[:n], &c.readSequence, &c.readKey)
		n = len(out)
	} else {
		// We need to decrypt into a side buffer and copy a prefix of
		// the result into the caller's buffer.
		c.decryptBuffer, ok = secretbox.Open(c.decryptBuffer[:0], c.readBuffer[:n], &c.readSequence, &c.readKey)
		n = copy(out, c.decryptBuffer)
		c.readPending = c.decryptBuffer[n:]
	}
	incSequence(&c.readSequence)
	if !ok {
		c.readPending = c.readPending[:0]
		return 0, errors.New("transport: bad MAC")
	}

	return
}

func (c *Conn) Write(buf []byte) (n int, err error) {
	if c.writeBuffer == nil {
		c.writeBuffer = make([]byte, blockSize+4)
	}

	for len(buf) > 0 {
		m := len(buf)
		if m > blockSize-secretbox.Overhead {
			m = blockSize - secretbox.Overhead
		}
		l := len(secretbox.Seal(c.writeBuffer[4:4], buf[:m], &c.writeSequence, &c.writeKey))
		c.writeBuffer[3] = byte(l)
		c.writeBuffer[2] = byte(l >> 8)
		c.writeBuffer[1] = byte(l >> 12)
		c.writeBuffer[0] = byte(l >> 16)
		if _, err = c.conn.Write(c.writeBuffer[:4+l]); err != nil {
			return n, err
		}
		n += m
		buf = buf[m:]
		incSequence(&c.writeSequence)
	}

	return
}

func (c *Conn) ReadProto(out proto.Message) error {
	buf := make([]byte, pond.TransportSize+4+secretbox.Overhead)
	n, err := c.read(buf)
	if err != nil {
		return err
	}
	if n != pond.TransportSize+4 {
		return errors.New("transport: message wrong length")
	}

	n = int(buf[3]) | int(buf[2])<<8 | int(buf[1])<<12 | int(buf[0])<<16
	buf = buf[4:]
	if n > len(buf) {
		return errors.New("transport: corrupt message")
	}
	return proto.Unmarshal(buf[:n], out)
}

func (c *Conn) WriteProto(msg proto.Message) error {
	data, err := proto.Marshal(msg)
	if err != nil {
		return err
	}
	if len(data) > pond.TransportSize {
		return errors.New("transport: message too large")
	}

	buf := make([]byte, pond.TransportSize+4)
	buf[3] = byte(len(data))
	buf[2] = byte(len(data) >> 8)
	buf[1] = byte(len(data) >> 12)
	buf[0] = byte(len(data) >> 16)
	copy(buf[4:], data)
	_, err = c.write(buf)
	return err
}

func (c *Conn) Close() (err error) {
	if !c.isServer {
		_, err = c.write(nil)
	}

	if closeErr := c.conn.Close(); err == nil {
		err = closeErr
	}

	return
}

func (c *Conn) WaitForClose() error {
	if !c.isServer {
		panic("non-server waited for connection close")
	}
	n, err := c.read(make([]byte, 128))
	if err != nil {
		return err
	}
	if n != 0 {
		return errors.New("transport: non-close message received when expecting close")
	}

	return nil
}

func (c *Conn) read(data []byte) (n int, err error) {
	var lengthBytes [4]byte

	if _, err := io.ReadFull(c.conn, lengthBytes[:]); err != nil {
		return 0, err
	}

	theirLength := int(lengthBytes[3]) + int(lengthBytes[2])<<8 + int(lengthBytes[1])<<12 + int(lengthBytes[0])<<16
	if theirLength > len(data) {
		return 0, errors.New("tranport: given buffer too small (" + strconv.Itoa(len(data)) + " vs " + strconv.Itoa(theirLength) + ")")
	}

	data = data[:theirLength]
	if _, err := io.ReadFull(c.conn, data); err != nil {
		return 0, err
	}

	decrypted, err := c.decrypt(data)
	if err != nil {
		return 0, err
	}
	copy(data, decrypted)

	return len(decrypted), nil
}

func (c *Conn) write(data []byte) (n int, err error) {
	encrypted := c.encrypt(data)

	var lengthBytes [4]byte
	lengthBytes[3] = byte(len(encrypted))
	lengthBytes[2] = byte(len(encrypted) >> 8)
	lengthBytes[1] = byte(len(encrypted) >> 12)
	lengthBytes[0] = byte(len(encrypted) >> 16)

	if _, err := c.conn.Write(lengthBytes[:]); err != nil {
		return 0, err
	}
	if _, err := c.conn.Write(encrypted); err != nil {
		return 0, err
	}

	return len(data), nil
}

func (c *Conn) encrypt(data []byte) []byte {
	if !c.writeKeyValid {
		return data
	}

	encrypted := secretbox.Seal(nil, data, &c.writeSequence, &c.writeKey)
	incSequence(&c.writeSequence)
	return encrypted
}

func (c *Conn) decrypt(data []byte) ([]byte, error) {
	if !c.readKeyValid {
		return data, nil
	}

	decrypted, ok := secretbox.Open(nil, data, &c.readSequence, &c.readKey)
	incSequence(&c.readSequence)
	if !ok {
		return nil, errors.New("transport: bad MAC")
	}
	return decrypted, nil
}

var serverKeysMagic = []byte("server keys snap")
var clientKeysMagic = []byte("client keys snap")

func (c *Conn) setupKeys(ephemeralShared *[32]byte) {
	var writeMagic, readMagic []byte
	if c.isServer {
		writeMagic, readMagic = serverKeysMagic, clientKeysMagic
	} else {
		writeMagic, readMagic = clientKeysMagic, serverKeysMagic
	}

	h := sha256.New()
	h.Write(writeMagic)
	h.Write(ephemeralShared[:])
	h.Sum(c.writeKey[:0])
	c.writeKeyValid = true

	h.Reset()
	h.Write(readMagic)
	h.Write(ephemeralShared[:])
	h.Sum(c.readKey[:0])
	c.readKeyValid = true
}

var serverProofMagic = []byte("server proof snap")
var clientProofMagic = []byte("client proof snap")

var shortMessageError = errors.New("transport: received short handshake message")

func (c *Conn) Handshake() error {
	var ephemeralPrivate, ephemeralPublic, ephemeralShared [32]byte
	if _, err := io.ReadFull(rand.Reader, ephemeralPrivate[:]); err != nil {
		return err
	}
	curve25519.ScalarBaseMult(&ephemeralPublic, &ephemeralPrivate)

	if _, err := c.write(ephemeralPublic[:]); err != nil {
		return err
	}

	var theirEphemeralPublic [32]byte
	if n, err := c.read(theirEphemeralPublic[:]); err != nil || n != len(theirEphemeralPublic) {
		if err == nil {
			err = shortMessageError
		}
		return err
	}

	handshakeHash := sha256.New()
	if c.isServer {
		handshakeHash.Write(theirEphemeralPublic[:])
		handshakeHash.Write(ephemeralPublic[:])
	} else {
		handshakeHash.Write(ephemeralPublic[:])
		handshakeHash.Write(theirEphemeralPublic[:])
	}

	curve25519.ScalarMult(&ephemeralShared, &ephemeralPrivate, &theirEphemeralPublic)
	c.setupKeys(&ephemeralShared)

	if c.isServer {
		return c.handshakeServer(handshakeHash, &theirEphemeralPublic)
	}
	return c.handshakeClient(handshakeHash, &ephemeralPrivate)
}

func (c *Conn) handshakeClient(handshakeHash hash.Hash, ephemeralPrivate *[32]byte) error {
	var ephemeralIdentityShared [32]byte
	curve25519.ScalarMult(&ephemeralIdentityShared, ephemeralPrivate, &c.Peer)

	digest := handshakeHash.Sum(nil)
	h := hmac.New(sha256.New, ephemeralIdentityShared[:])
	h.Write(serverProofMagic)
	h.Write(digest)
	digest = h.Sum(digest[:0])

	digestReceived := make([]byte, len(digest)+secretbox.Overhead)
	n, err := c.read(digestReceived)
	if err != nil {
		return err
	}
	if n != len(digest) {
		return shortMessageError
	}
	digestReceived = digestReceived[:n]

	if subtle.ConstantTimeCompare(digest, digestReceived) != 1 {
		return errors.New("transport: server identity incorrect")
	}

	var identityShared [32]byte
	curve25519.ScalarMult(&identityShared, &c.identity, &c.Peer)

	handshakeHash.Write(digest)
	digest = handshakeHash.Sum(digest[:0])

	h = hmac.New(sha256.New, identityShared[:])
	h.Write(clientProofMagic)
	h.Write(digest)

	finalMessage := make([]byte, 32+sha256.Size)
	copy(finalMessage, c.identityPublic[:])
	h.Sum(finalMessage[32:32])

	if _, err := c.write(finalMessage); err != nil {
		return err
	}

	return nil
}

func (c *Conn) handshakeServer(handshakeHash hash.Hash, theirEphemeralPublic *[32]byte) error {
	var ephemeralIdentityShared [32]byte
	curve25519.ScalarMult(&ephemeralIdentityShared, &c.identity, theirEphemeralPublic)

	digest := handshakeHash.Sum(nil)
	h := hmac.New(sha256.New, ephemeralIdentityShared[:])
	h.Write(serverProofMagic)
	h.Write(digest)
	digest = h.Sum(digest[:0])

	if _, err := c.write(digest); err != nil {
		return err
	}

	handshakeHash.Write(digest)
	digest = handshakeHash.Sum(digest[:0])

	finalMessage := make([]byte, 32+sha256.Size+secretbox.Overhead)
	n, err := c.read(finalMessage)
	if err != nil {
		return err
	}
	if n != 32+sha256.Size {
		return shortMessageError
	}
	finalMessage = finalMessage[:n]

	copy(c.Peer[:], finalMessage[:32])
	var identityShared [32]byte
	curve25519.ScalarMult(&identityShared, &c.identity, &c.Peer)

	h = hmac.New(sha256.New, identityShared[:])
	h.Write(clientProofMagic)
	h.Write(digest)
	digest = h.Sum(digest[:0])

	if subtle.ConstantTimeCompare(digest, finalMessage[32:]) != 1 {
		return errors.New("transport: bad proof from client")
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/microcosm-cc/bluemonday"
	"github.com/russross/blackfriday"
	"io/ioutil"
	"os"
	// "path/filepath"
	"encoding/json"
	"strings"
)

// For holding our post's configuration settings
type Config struct {
	Title string `json:"title`
	Date  string `json:"date`
}

func main() {

	// root := "./content"
	// err := filepath.Walk(root, visit)
	// fmt.Printf("filepath.Walk() returned %v\n", err)
	// os.Exit(1)

	// Note: index 0 contains the program path, so I'm excluding it from what gets passed in
	inputFile, outputFile := dealWithArgs(os.Args[1:])

	title, date := getPostConfigsJson(&inputFile)

	fmt.Println("postTitle: " + title)
	fmt.Println("postDate: " + date)
	fmt.Println("Leaving off here")
	// os.Exit(1)

	content := getContent(&inputFile)

	topHTML, bottomHTML := getSharedMarkup()

	combinedOutput := buildCombinedOutput(topHTML, content, bottomHTML)

	finalOutput := interpolateConfigVals(combinedOutput, &title)

	writeOutputFile(finalOutput, &outputFile)

	fmt.Println("Program finished, check result.")
}

func dealWithArgs(args []string) (string, string) {
	// args := os.Args[1:] // Reason: index 0 contains the program path
	if len(args) != 2 {
		fmt.Println("ERROR: Wrong number of arguments provided. We're expecting:")
		fmt.Println("1. Input file")
		fmt.Println("2. Output file")
		os.Exit(1)
	}
	inputFile := args[0]
	outputFile := args[1]

	return inputFile, outputFile
}

func writeOutputFile(finalOutput []byte, outputFile *string) bool {
	// Write our output to an HTML file
	err := ioutil.WriteFile("./content/"+*outputFile, finalOutput, 0644)
	check(err)
	return true
}

// ...into the output
func interpolateConfigVals(combinedOutput []byte, title *string) []byte {
	str := string(combinedOutput[:])
	str = strings.Replace(str, "{{title}}", *title, -1)
	return []byte(str)
}

func buildCombinedOutput(topHTML []byte, content []byte, bottomHTML []byte) []byte {
	// Incrementally building a singular byte array via append()
	combinedOutput := append(topHTML[:], content[:]...)
	combinedOutput = append(combinedOutput, bottomHTML[:]...)
	return combinedOutput
}

func getSharedMarkup() ([]byte, []byte) {

	// Get the shared markup pieces
	topHTML, err := ioutil.ReadFile("./shared_markup/top.html")
	check(err)
	bottomHTML, err := ioutil.ReadFile("./shared_markup/bottom.html")
	check(err)

	return topHTML, bottomHTML
}

func getContent(inputFile *string) []byte {

	// Get the Markdown input
	rawInput, err := ioutil.ReadFile("./content/" + *inputFile)
	check(err)

	// Convert and sanitize our content
	unsafe := blackfriday.MarkdownCommon(rawInput)
	content := bluemonday.UGCPolicy().SanitizeBytes(unsafe)

	return content
}

func getPostConfigsJson(inputFile *string) (string, string) {
	// Get the configs for this page:
	// First read the post's corresponding .json file
	configPath := "./content/" + strings.Replace(*inputFile, ".md", "", 1) + ".json"
	configJson, err := ioutil.ReadFile(configPath)
	check(err)

	// Then parse out our relevant config values for later use
	var config Config
	err = json.Unmarshal(configJson, &config)
	check(err)

	return config.Title, config.Date
}

func visit(path string, f os.FileInfo, err error) error {
	fmt.Printf("Visited: %s\n", path)
	return nil
}

func check(e error) {
	if e != nil {
		panic(e)
	}
}
<commit_msg>Now interpolating the date into the post content<commit_after>package main

import (
	"fmt"
	"github.com/microcosm-cc/bluemonday"
	"github.com/russross/blackfriday"
	"io/ioutil"
	"os"
	// "path/filepath"
	"encoding/json"
	"strings"
)

// For holding our post's configuration settings
type Config struct {
	Title string `json:"title`
	Date  string `json:"date`
}

func main() {

	// root := "./content"
	// err := filepath.Walk(root, visit)
	// fmt.Printf("filepath.Walk() returned %v\n", err)
	// os.Exit(1)

	// Note: index 0 contains the program path, so I'm excluding it from what gets passed in
	inputFile, outputFile := dealWithArgs(os.Args[1:])

	title, date := getPostConfigsJson(&inputFile)

	fmt.Println("postTitle: " + title)
	fmt.Println("postDate: " + date)
	fmt.Println("Leaving off here")
	// os.Exit(1)

	content := getContent(&inputFile)

	topHTML, bottomHTML := getSharedMarkup()

	combinedOutput := buildCombinedOutput(topHTML, content, bottomHTML)

	finalOutput := interpolateConfigVals(combinedOutput, &title, &date)

	writeOutputFile(finalOutput, &outputFile)

	fmt.Println("Program finished, check result.")
}

func dealWithArgs(args []string) (string, string) {
	// args := os.Args[1:] // Reason: index 0 contains the program path
	if len(args) != 2 {
		fmt.Println("ERROR: Wrong number of arguments provided. We're expecting:")
		fmt.Println("1. Input file")
		fmt.Println("2. Output file")
		os.Exit(1)
	}
	inputFile := args[0]
	outputFile := args[1]

	return inputFile, outputFile
}

func writeOutputFile(finalOutput []byte, outputFile *string) bool {
	// Write our output to an HTML file
	err := ioutil.WriteFile("./content/"+*outputFile, finalOutput, 0644)
	check(err)
	return true
}

// ...into the output
func interpolateConfigVals(combinedOutput []byte, title *string, date *string) []byte {
	str := string(combinedOutput[:])
	str = strings.Replace(str, "{{title}}", *title, -1)
	str = strings.Replace(str, "{{date}}", *date, -1)
	return []byte(str)
}

func buildCombinedOutput(topHTML []byte, content []byte, bottomHTML []byte) []byte {
	// Incrementally building a singular byte array via append()
	combinedOutput := append(topHTML[:], content[:]...)
	combinedOutput = append(combinedOutput, bottomHTML[:]...)
	return combinedOutput
}

func getSharedMarkup() ([]byte, []byte) {

	// Get the shared markup pieces
	topHTML, err := ioutil.ReadFile("./shared_markup/top.html")
	check(err)
	bottomHTML, err := ioutil.ReadFile("./shared_markup/bottom.html")
	check(err)

	return topHTML, bottomHTML
}

func getContent(inputFile *string) []byte {

	// Get the Markdown input
	rawInput, err := ioutil.ReadFile("./content/" + *inputFile)
	check(err)

	// Convert and sanitize our content
	unsafe := blackfriday.MarkdownCommon(rawInput)
	content := bluemonday.UGCPolicy().SanitizeBytes(unsafe)

	return content
}

func getPostConfigsJson(inputFile *string) (string, string) {
	// Get the configs for this page:
	// First read the post's corresponding .json file
	configPath := "./content/" + strings.Replace(*inputFile, ".md", "", 1) + ".json"
	configJson, err := ioutil.ReadFile(configPath)
	check(err)

	// Then parse out our relevant config values for later use
	var config Config
	err = json.Unmarshal(configJson, &config)
	check(err)

	return config.Title, config.Date
}

func visit(path string, f os.FileInfo, err error) error {
	fmt.Printf("Visited: %s\n", path)
	return nil
}

func check(e error) {
	if e != nil {
		panic(e)
	}
}
<|endoftext|>


<commit_before>package shell

import (
	"flag"
	"github.com/chrislusf/seaweedfs/weed/pb/master_pb"
	"io"
	"log"
	"time"

	"github.com/chrislusf/seaweedfs/weed/storage/needle"
)

func init() {
	Commands = append(Commands, &commandVolumeDeleteEmpty{})
}

type commandVolumeDeleteEmpty struct {
}

func (c *commandVolumeDeleteEmpty) Name() string {
	return "volume.deleteEmpty"
}

func (c *commandVolumeDeleteEmpty) Help() string {
	return `delete empty volumes from all volume servers

	volume.deleteEmpty -quietFor=24h

	This command deletes all empty volumes from one volume server.

`
}

func (c *commandVolumeDeleteEmpty) Do(args []string, commandEnv *CommandEnv, writer io.Writer) (err error) {

	if err = commandEnv.confirmIsLocked(); err != nil {
		return
	}

	volDeleteCommand := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
	quietPeriod := volDeleteCommand.Duration("quietFor", 24*time.Hour, "select empty volumes with no recent writes, avoid newly created ones")
	if err = volDeleteCommand.Parse(args); err != nil {
		return nil
	}

	// collect topology information
	topologyInfo, _, err := collectTopologyInfo(commandEnv)
	if err != nil {
		return err
	}

	quietSeconds := int64(*quietPeriod / time.Second)
	nowUnixSeconds := time.Now().Unix()

	eachDataNode(topologyInfo, func(dc string, rack RackId, dn *master_pb.DataNodeInfo) {
		for _, diskInfo := range dn.DiskInfos {
			for _, v := range diskInfo.VolumeInfos {
				if v.Size <= 8 && v.ModifiedAtSecond + quietSeconds < nowUnixSeconds {
					log.Printf("deleting empty volume %d from %s", v.Id, dn.Id)
					if deleteErr := deleteVolume(commandEnv.option.GrpcDialOption, needle.VolumeId(v.Id), dn.Id); deleteErr != nil {
						err = deleteErr
					}
				}
			}
		}
	})

	return
}
<commit_msg>Add force option in volume.deleteEmpty command<commit_after>package shell

import (
	"flag"
	"github.com/chrislusf/seaweedfs/weed/pb/master_pb"
	"github.com/chrislusf/seaweedfs/weed/storage/needle"
	"io"
	"log"
	"time"
)

func init() {
	Commands = append(Commands, &commandVolumeDeleteEmpty{})
}

type commandVolumeDeleteEmpty struct {
}

func (c *commandVolumeDeleteEmpty) Name() string {
	return "volume.deleteEmpty"
}

func (c *commandVolumeDeleteEmpty) Help() string {
	return `delete empty volumes from all volume servers

	volume.deleteEmpty -quietFor=24h -force

	This command deletes all empty volumes from one volume server.

`
}

func (c *commandVolumeDeleteEmpty) Do(args []string, commandEnv *CommandEnv, writer io.Writer) (err error) {

	if err = commandEnv.confirmIsLocked(); err != nil {
		return
	}

	volDeleteCommand := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
	quietPeriod := volDeleteCommand.Duration("quietFor", 24*time.Hour, "select empty volumes with no recent writes, avoid newly created ones")
	applyBalancing := volDeleteCommand.Bool("force", false, "apply to delete empty volumes")
	if err = volDeleteCommand.Parse(args); err != nil {
		return nil
	}

	// collect topology information
	topologyInfo, _, err := collectTopologyInfo(commandEnv)
	if err != nil {
		return err
	}

	quietSeconds := int64(*quietPeriod / time.Second)
	nowUnixSeconds := time.Now().Unix()

	eachDataNode(topologyInfo, func(dc string, rack RackId, dn *master_pb.DataNodeInfo) {
		for _, diskInfo := range dn.DiskInfos {
			for _, v := range diskInfo.VolumeInfos {
				if v.Size <= 8 && v.ModifiedAtSecond+quietSeconds < nowUnixSeconds {
					if *applyBalancing {
						log.Printf("deleting empty volume %d from %s", v.Id, dn.Id)
						if deleteErr := deleteVolume(commandEnv.option.GrpcDialOption, needle.VolumeId(v.Id), dn.Id); deleteErr != nil {
							err = deleteErr
						}
						continue
					} else {
						log.Printf("empty volume %d from %s", v.Id, dn.Id)
					}
				}
			}
		}
	})

	return
}
<|endoftext|>


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

package usb

// #include <libusb-1.0/libusb.h>
import "C"

type Descriptor struct {
	// Bus information
	Bus     uint8 // The bus on which the device was detected
	Address uint8 // The address of the device on the bus

	// Version information
	Spec   BCD // USB Specification Release Number
	Device BCD // The device version

	// Product information
	Vendor  ID // The Vendor identifer
	Product ID // The Product identifier

	// Protocol information
	Class    uint8 // The class of this device
	SubClass uint8 // The sub-class (within the class) of this device
	Protocol uint8 // The protocol (within the sub-class) of this device

	// Configuration information
	Configs []ConfigInfo

	// libusb_device
	dev *C.libusb_device
}

func newDescriptor(dev *C.libusb_device) (*Descriptor, error) {
	var desc C.struct_libusb_device_descriptor
	if errno := C.libusb_get_device_descriptor(dev, &desc); errno < 0 {
		return nil, usbError(errno)
	}

	// Enumerate configurations
	var cfgs []ConfigInfo
	for i := 0; i < int(desc.bNumConfigurations); i++ {
		var cfg *C.struct_libusb_config_descriptor
		if errno := C.libusb_get_config_descriptor(dev, C.uint8_t(i), &cfg); errno < 0 {
			return nil, usbError(errno)
		}
		cfgs = append(cfgs, newConfig(dev, cfg))
		C.libusb_free_config_descriptor(cfg)
	}

	return &Descriptor{
		Bus:      uint8(C.libusb_get_bus_number(dev)),
		Address:  uint8(C.libusb_get_device_address(dev)),
		Spec:     BCD(desc.bcdUSB),
		Device:   BCD(desc.bcdDevice),
		Vendor:   ID(desc.idVendor),
		Product:  ID(desc.idProduct),
		Class:    uint8(desc.bDeviceClass),
		SubClass: uint8(desc.bDeviceSubClass),
		Protocol: uint8(desc.bDeviceProtocol),
		Configs:  cfgs,
		dev:      dev,
	}, nil
}

// Opens the device and returns a new Device instance
func (d *Descriptor) Open() (*Device, error) {
	var handle *C.libusb_device_handle
	if errno := C.libusb_open(d.dev, &handle); errno != 0 {
		return nil, usbError(errno)
	}
	return newDevice(handle, d), nil
}
<commit_msg>Add code to retrieve device serial number.<commit_after>// Copyright 2013 Google Inc.  All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package usb

// #include <libusb-1.0/libusb.h>
import "C"

type Descriptor struct {
	// Bus information
	Bus     uint8 // The bus on which the device was detected
	Address uint8 // The address of the device on the bus

	// Version information
	Spec   BCD // USB Specification Release Number
	Device BCD // The device version

	// Product information
	Vendor  ID // The Vendor identifer
	Product ID // The Product identifier

	// Protocol information
	Class    uint8 // The class of this device
	SubClass uint8 // The sub-class (within the class) of this device
	Protocol uint8 // The protocol (within the sub-class) of this device

	// Configuration information
	Configs []ConfigInfo

	// libusb_device
	dev *C.libusb_device
}

func newDescriptor(dev *C.libusb_device) (*Descriptor, error) {
	var desc C.struct_libusb_device_descriptor
	if errno := C.libusb_get_device_descriptor(dev, &desc); errno < 0 {
		return nil, usbError(errno)
	}

	// Enumerate configurations
	var cfgs []ConfigInfo
	for i := 0; i < int(desc.bNumConfigurations); i++ {
		var cfg *C.struct_libusb_config_descriptor
		if errno := C.libusb_get_config_descriptor(dev, C.uint8_t(i), &cfg); errno < 0 {
			return nil, usbError(errno)
		}
		cfgs = append(cfgs, newConfig(dev, cfg))
		C.libusb_free_config_descriptor(cfg)
	}

	return &Descriptor{
		Bus:          uint8(C.libusb_get_bus_number(dev)),
		Address:      uint8(C.libusb_get_device_address(dev)),
		Spec:         BCD(desc.bcdUSB),
		Device:       BCD(desc.bcdDevice),
		Vendor:       ID(desc.idVendor),
		Product:      ID(desc.idProduct),
		Class:        uint8(desc.bDeviceClass),
		SubClass:     uint8(desc.bDeviceSubClass),
		Protocol:     uint8(desc.bDeviceProtocol),
		SerialNumber: getSerialNumber(dev, desc.iSerialNumber),
		Configs:      cfgs,
		dev:          dev,
	}, nil
}

// Opens the device and returns a new Device instance
func (d *Descriptor) Open() (*Device, error) {
	var handle *C.libusb_device_handle
	if errno := C.libusb_open(d.dev, &handle); errno != 0 {
		return nil, usbError(errno)
	}
	return newDevice(handle, d), nil
}

func getSerialNumber(dev *C.libusb_device, index C.uint8_t) string {
	data := make([]byte, 1024)
	var devHandle *C.libusb_device_handle
	C.libusb_open(dev, &devHandle)
	C.libusb_get_string_descriptor_ascii(devHandle, index, (*C.uchar)(unsafe.Pointer(&data[0])), C.int(len(data)))
	C.libusb_close(devHandle)
	return C.GoString((*C.char)(unsafe.Pointer(&data[0])))
}
<|endoftext|>


<commit_before>package usecases

import (
	"encoding/json"
	"net/http"
	"net/url"

	"github.com/digital-ocean-service/domain"
)

type DOInteractor struct {
}

const authURL = "https://cloud.digitalocean.com/v1/oauth/authorize"

func (interactor DOInteractor) GetOauthURL(id, redirectURI, scope string) string {
	u, _ := url.Parse(authURL)
	q := u.Query()
	q.Set("client_id", id)
	q.Set("redirect_uri", redirectURI)
	q.Set("scope", scope)
	q.Set("response_type", "code")

	u.RawQuery = q.Encode()

	return u.String()
}

func (interactor DOInteractor) GetToken(code, id, secret, redirectURL string) (*domain.DOToken, error) {
	u, _ := url.Parse("https://cloud.digitalocean.com/v1/oauth/token")
	q := u.Query()

	q.Set("grant_type", "authorization_code")
	q.Set("code", code)
	q.Set("client_id", id)
	q.Set("client_secret", secret)
	q.Set("redirect_uri", redirectURL)

	u.RawQuery = q.Encode()

	res, err := http.Post(u.String(), "", nil)
	if err != nil {
		return nil, err
	}

	defer res.Body.Close()

	decoder := json.NewDecoder(res.Body)

	accessToken := domain.DOToken{}

	err = decoder.Decode(&accessToken)
	if err != nil {
		return nil, err
	}

	return &accessToken, nil
}
<commit_msg>Modify the way to get the OAUTH URI<commit_after>package usecases

import (
	"encoding/json"
	"net/http"
	"net/url"
	"strings"

	"github.com/digital-ocean-service/domain"
)

type DOInteractor struct {
}

const authURL = "https://cloud.digitalocean.com/v1/oauth/authorize"

func (interactor DOInteractor) GetOauthURL(id, redirectURI string, scope []string) string {

	scp := strings.Join(scope, " ")

	u, _ := url.Parse(authURL)
	q := u.Query()
	q.Set("client_id", id)
	q.Set("redirect_uri", redirectURI)
	q.Set("scope", scp)
	q.Set("response_type", "code")

	u.RawQuery = q.Encode()

	return u.String()
}

func (interactor DOInteractor) GetToken(code, id, secret, redirectURL string) (*domain.DOToken, error) {
	u, _ := url.Parse("https://cloud.digitalocean.com/v1/oauth/token")
	q := u.Query()

	q.Set("grant_type", "authorization_code")
	q.Set("code", code)
	q.Set("client_id", id)
	q.Set("client_secret", secret)
	q.Set("redirect_uri", redirectURL)

	u.RawQuery = q.Encode()

	res, err := http.Post(u.String(), "", nil)
	if err != nil {
		return nil, err
	}

	defer res.Body.Close()

	decoder := json.NewDecoder(res.Body)

	accessToken := domain.DOToken{}

	err = decoder.Decode(&accessToken)
	if err != nil {
		return nil, err
	}

	return &accessToken, nil
}
<|endoftext|>