<commit_before>package main

import (
	"bufio"
	"fmt"
	"os/exec"
	"runtime"
	"strings"

	termbox "github.com/nsf/termbox-go"
)

type Terminal struct {
	Links         []Link
	ViewFullURL   bool
	ViewFullHelp  bool
	Selected      int
	Width, Height int
}

const (
	help_mini string = "h: help   q: quit"
	help_full string = `

h:           toggle help (press again to return to menu)
tab:         toggle full url
j/C-n:       move down
k/C-p:       move up
return/C-o:  open url
q/C-c:       quit`
)

var (
	EventChan    = make(chan termbox.Event)
	KeyTab       = termbox.KeyTab
	KeyEnter     = termbox.KeyEnter
	KeyArrowUp   = termbox.KeyArrowUp
	KeyArrowDown = termbox.KeyArrowDown
	KeyCtrlP     = termbox.KeyCtrlP
	KeyCtrlN     = termbox.KeyCtrlN
	KeyCtrlO     = termbox.KeyCtrlO
	KeyCtrlC     = termbox.KeyCtrlC
)

func PollEvent() {
	EventChan <- termbox.PollEvent()
}

func NewTerminal(links *[]Link) *Terminal {
	term := Terminal{
		Links:    *links,
		Selected: 0,
		Width:    0,
		Height:   0,
	}

	return &term
}

func (t *Terminal) Start() error {
	err := termbox.Init()
	if err != nil {
		return err
	}

	return nil
}

func (t *Terminal) Close() {
	termbox.Close()
}

func (t *Terminal) HandleEvent(e termbox.Event) (bool, error) {
	if e.Type == termbox.EventResize {
		t.SetSize()
		t.Render()
	}

	var err error
	if e.Type == termbox.EventKey {
		if e.Ch == 0 {
			switch e.Key {
			case KeyArrowDown:
				t.MoveSelection("down")
				t.Render()
			case KeyCtrlN:
				t.MoveSelection("down")
				t.Render()
			case KeyArrowUp:
				t.MoveSelection("up")
				t.Render()
			case KeyCtrlP:
				t.MoveSelection("up")
				t.Render()
			case KeyTab:
				if !t.ViewFullURL {
					t.ShowFullLink()
				} else {
					t.Render()
					t.ViewFullURL = false
				}
			case KeyEnter:
				err = t.Select()
			case KeyCtrlO:
				err = t.Select()
			case KeyCtrlC:
				return true, nil
			}
		} else {
			switch e.Ch {
			case 'j':
				t.MoveSelection("down")
				t.Render()
			case 'k':
				t.MoveSelection("up")
				t.Render()
			case 'h':
				if !t.ViewFullHelp {
					t.ShowFullHelp()
				} else {
					t.Render()
					t.ViewFullHelp = false
				}
			case 'q':
				return true, nil
			}
		}
	}

	return false, err
}

func (t *Terminal) Println(x int, y int, s string) {
	for col, char := range s {
		termbox.SetCell(col+x, y, char, termbox.ColorDefault, termbox.ColorDefault)
	}
}

func (t *Terminal) PrintHeader() {
	t.Println(0, 0, help_mini)
	t.Println(len(help_mini)+3, 0, fmt.Sprintf("(%d of %d)", t.Selected+1, len(t.Links)))
}

func (t *Terminal) ShowFullHelp() {
	t.ViewFullHelp = true
	termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)

	t.Println(0, 0, help_mini)
	scanner := bufio.NewScanner(strings.NewReader(help_full))
	row := 0
	for scanner.Scan() {
		t.Println(0, row, scanner.Text())
		row++
	}

	termbox.Flush()
}

func (t *Terminal) ShowFullLink() {
	t.ViewFullURL = true
	termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)

	t.PrintHeader()

	url := t.Links[t.Selected].URL
	row := 2
	col := 0
	for _, char := range url {
		if col >= t.Width {
			row++
			col = 0
		}
		termbox.SetCell(col, row, char, termbox.ColorDefault, termbox.ColorDefault)
		col++
	}

	termbox.Flush()
}

func (t *Terminal) Render() {
	termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)

	t.PrintHeader()

	url := t.Links[t.Selected].URL
	t.Println(0, 2, url)

	var start int
	offset := t.Selected - t.Height + 6
	if t.Selected > t.Height-6 {
		start = offset
	}

	for i := start; i < len(t.Links); i++ {
		if t.Selected > t.Height-6 {
			t.Println(0, t.Height-2, "->")
			t.Println(3, i+4-offset, t.Links[i].Text)
		} else {
			t.Println(0, t.Selected+4, "->")
			t.Println(3, i+4, t.Links[i].Text)
		}
	}

	termbox.Flush()
}

func (t *Terminal) SetSize() {
	t.Width, t.Height = termbox.Size()
}

func (t *Terminal) MoveSelection(direction string) {
	switch direction {
	case "up":
		t.Selected--
	case "down":
		t.Selected++
	}

	if t.Selected >= len(t.Links) {
		t.Selected = len(t.Links) - 1
	}

	if t.Selected < 0 {
		t.Selected = 0
	}
}

func (t *Terminal) Select() error {
	var err error
	url := t.Links[t.Selected].URL

	switch runtime.GOOS {
	case "linux":
		err = exec.Command("xdg-open", url).Start()
	case "windows":
		err = exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start()
	case "darwin":
		err = exec.Command("open", url).Start()
	default:
		err = fmt.Errorf("can't open browser: unsupported platform")
	}

	if err != nil {
		return err
	}

	return nil
}
<commit_msg>Add GoToTop and GoToBottom functions and key bindings<commit_after>package main

import (
	"bufio"
	"fmt"
	"os/exec"
	"runtime"
	"strings"

	termbox "github.com/nsf/termbox-go"
)

type Terminal struct {
	Links         []Link
	ViewFullURL   bool
	ViewFullHelp  bool
	Selected      int
	Width, Height int
}

const (
	help_mini string = "h: help   q: quit"
	help_full string = `

h:           toggle help (press again to return to menu)
tab:         toggle full url
g:           go to top
G:           go to bottom
j/C-n:       move down
k/C-p:       move up
return/C-o:  open url
q/C-c:       quit`
)

var (
	EventChan    = make(chan termbox.Event)
	KeyTab       = termbox.KeyTab
	KeyEnter     = termbox.KeyEnter
	KeyArrowUp   = termbox.KeyArrowUp
	KeyArrowDown = termbox.KeyArrowDown
	KeyCtrlP     = termbox.KeyCtrlP
	KeyCtrlN     = termbox.KeyCtrlN
	KeyCtrlO     = termbox.KeyCtrlO
	KeyCtrlC     = termbox.KeyCtrlC
)

func PollEvent() {
	EventChan <- termbox.PollEvent()
}

func NewTerminal(links *[]Link) *Terminal {
	term := Terminal{
		Links:    *links,
		Selected: 0,
		Width:    0,
		Height:   0,
	}

	return &term
}

func (t *Terminal) Start() error {
	err := termbox.Init()
	if err != nil {
		return err
	}

	return nil
}

func (t *Terminal) Close() {
	termbox.Close()
}

func (t *Terminal) HandleEvent(e termbox.Event) (bool, error) {
	if e.Type == termbox.EventResize {
		t.SetSize()
		t.Render()
	}

	var err error
	if e.Type == termbox.EventKey {
		if e.Ch == 0 {
			switch e.Key {
			case KeyArrowDown:
				t.MoveSelection("down")
				t.Render()
			case KeyCtrlN:
				t.MoveSelection("down")
				t.Render()
			case KeyArrowUp:
				t.MoveSelection("up")
				t.Render()
			case KeyCtrlP:
				t.MoveSelection("up")
				t.Render()
			case KeyTab:
				if !t.ViewFullURL {
					t.ShowFullLink()
				} else {
					t.Render()
					t.ViewFullURL = false
				}
			case KeyEnter:
				err = t.Select()
			case KeyCtrlO:
				err = t.Select()
			case KeyCtrlC:
				return true, nil
			}
		} else {
			switch e.Ch {
			case 'G':
				t.GoToBottom()
				t.Render()
			case 'g':
				t.GoToTop()
				t.Render()
			case 'j':
				t.MoveSelection("down")
				t.Render()
			case 'k':
				t.MoveSelection("up")
				t.Render()
			case 'h':
				if !t.ViewFullHelp {
					t.ShowFullHelp()
				} else {
					t.Render()
					t.ViewFullHelp = false
				}
			case 'q':
				return true, nil
			}
		}
	}

	return false, err
}

func (t *Terminal) Println(x int, y int, s string) {
	for col, char := range s {
		termbox.SetCell(col+x, y, char, termbox.ColorDefault, termbox.ColorDefault)
	}
}

func (t *Terminal) PrintHeader() {
	t.Println(0, 0, help_mini)
	t.Println(len(help_mini)+3, 0, fmt.Sprintf("(%d of %d)", t.Selected+1, len(t.Links)))
}

func (t *Terminal) ShowFullHelp() {
	t.ViewFullHelp = true
	termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)

	t.Println(0, 0, help_mini)
	scanner := bufio.NewScanner(strings.NewReader(help_full))
	row := 0
	for scanner.Scan() {
		t.Println(0, row, scanner.Text())
		row++
	}

	termbox.Flush()
}

func (t *Terminal) ShowFullLink() {
	t.ViewFullURL = true
	termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)

	t.PrintHeader()

	url := t.Links[t.Selected].URL
	row := 2
	col := 0
	for _, char := range url {
		if col >= t.Width {
			row++
			col = 0
		}
		termbox.SetCell(col, row, char, termbox.ColorDefault, termbox.ColorDefault)
		col++
	}

	termbox.Flush()
}

func (t *Terminal) GoToTop() {
	t.Selected = 0
}

func (t *Terminal) GoToBottom() {
	t.Selected = len(t.Links) - 1
}

func (t *Terminal) Render() {
	termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)

	t.PrintHeader()

	url := t.Links[t.Selected].URL
	t.Println(0, 2, url)

	var start int
	offset := t.Selected - t.Height + 6
	if t.Selected > t.Height-6 {
		start = offset
	}

	for i := start; i < len(t.Links); i++ {
		if t.Selected > t.Height-6 {
			t.Println(0, t.Height-2, "->")
			t.Println(3, i+4-offset, t.Links[i].Text)
		} else {
			t.Println(0, t.Selected+4, "->")
			t.Println(3, i+4, t.Links[i].Text)
		}
	}

	termbox.Flush()
}

func (t *Terminal) SetSize() {
	t.Width, t.Height = termbox.Size()
}

func (t *Terminal) MoveSelection(direction string) {
	switch direction {
	case "up":
		t.Selected--
	case "down":
		t.Selected++
	}

	if t.Selected >= len(t.Links) {
		t.Selected = len(t.Links) - 1
	}

	if t.Selected < 0 {
		t.Selected = 0
	}
}

func (t *Terminal) Select() error {
	var err error
	url := t.Links[t.Selected].URL

	switch runtime.GOOS {
	case "linux":
		err = exec.Command("xdg-open", url).Start()
	case "windows":
		err = exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start()
	case "darwin":
		err = exec.Command("open", url).Start()
	default:
		err = fmt.Errorf("can't open browser: unsupported platform")
	}

	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>// Package core provides common definitions and functionalities of V2Ray.
package core

import (
	"fmt"

	"github.com/v2ray/v2ray-core/common/platform"
)

var (
	version  = "0.10"
	build    = "Custom"
	codename = "Post Apocalypse"
	intro    = "A stable and unbreakable connection for everyone."
)

func PrintVersion() {
	fmt.Printf("V2Ray %s (%s) %s%s", version, codename, build, platform.LineSeparator())
	fmt.Printf("%s%s", intro, platform.LineSeparator())
}
<commit_msg>Update version for next release<commit_after>// Package core provides common definitions and functionalities of V2Ray.
package core

import (
	"fmt"

	"github.com/v2ray/v2ray-core/common/platform"
)

var (
	version  = "0.11"
	build    = "Custom"
	codename = "Post Apocalypse"
	intro    = "A stable and unbreakable connection for everyone."
)

func PrintVersion() {
	fmt.Printf("V2Ray %s (%s) %s%s", version, codename, build, platform.LineSeparator())
	fmt.Printf("%s%s", intro, platform.LineSeparator())
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math"
)

var CoreFuncs = map[string]interface{}{
	// Arithmetic
	"+":   Add,
	"-":   Sub,
	"*":   Mul,
	"/":   Div,
	"rem": Rem,
	"mod": Mod,
	"inc": Inc,
	"dec": Dec,

	// Relational
	">":  Gt,
	">=": Ge,
	"=":  Eq,
	"!=": Ne,
	"<=": Le,
	"<":  Lt,

	// Logic
	"not": Not,

	// Test
	"nil?":    IsNil,
	"zero?":   IsZero,
	"pos?":    IsPos,
	"neg?":    IsNeg,
	"empty?":  IsEmpty,
	"number?": IsNumber,
	"bool?":   IsBool,
	"string?": IsString,
	"list?":   IsList,
	"symbol?": IsSymbol,

	// List
	"first": First,
	"next":  Next,
	"cons":  Cons,

	// IO
	"print": Print,
	//"printf": Printf,
	"println": Println,
	"newline": Newline,
	//"readline": Readline,
}

////////////////////////////////////////////////////////////////////////////////
// Arithmetic

func Add(args ...Object) Object {
	res := args[0].(*Number).Value

	for _, arg := range args[1:] {
		res += arg.(*Number).Value
	}

	return NewNumber(res)
}

func Sub(args ...Object) Object {
	if len(args) == 1 {
		return NewNumber(-args[0].(*Number).Value)
	}

	res := args[0].(*Number).Value

	for _, arg := range args[1:] {
		res -= arg.(*Number).Value
	}

	return NewNumber(res)
}

func Mul(args ...Object) Object {
	res := args[0].(*Number).Value

	for _, arg := range args[1:] {
		res *= arg.(*Number).Value
	}

	return NewNumber(res)
}

func Div(args ...Object) Object {
	if len(args) == 1 {
		return NewNumber(1.0 / args[0].(*Number).Value)
	}

	res := args[0].(*Number).Value

	for _, arg := range args[1:] {
		res /= arg.(*Number).Value
	}

	return NewNumber(res)
}

func Rem(num Object, div Object) Object {
	return NewNumber(math.Remainder(num.(*Number).Value, div.(*Number).Value))
}

func Mod(num Object, div Object) Object {
	return NewNumber(math.Mod(num.(*Number).Value, div.(*Number).Value))
}

func Inc(x Object) Object {
	return NewNumber(x.(*Number).Value + 1.0)
}

func Dec(x Object) Object {
	return NewNumber(x.(*Number).Value - 1.0)
}

////////////////////////////////////////////////////////////////////////////////
// Relational

func Gt(args ...Object) Object {
	x := args[0].(*Number).Value

	for _, arg := range args[1:] {
		y := arg.(*Number).Value
		if x <= y {
			return NewBool(false)
		}
		x = y
	}

	return NewBool(true)
}

func Ge(args ...Object) Object {
	x := args[0].(*Number).Value

	for _, arg := range args[1:] {
		y := arg.(*Number).Value
		if x < y {
			return NewBool(false)
		}
		x = y
	}

	return NewBool(true)
}

func Eq(args ...Object) Object {
	x := args[0]

	for _, arg := range args[1:] {
		y := arg
		if !x.Equals(y) {
			return NewBool(false)
		}
		x = y
	}

	return NewBool(true)
}

func Ne(args ...Object) Object {
	return NewBool(!Eq(args...).(*Bool).Value)
}

func Le(args ...Object) Object {
	x := args[0].(*Number).Value

	for _, arg := range args[1:] {
		y := arg.(*Number).Value
		if x > y {
			return NewBool(false)
		}
		x = y
	}

	return NewBool(true)
}

func Lt(args ...Object) Object {
	x := args[0].(*Number).Value

	for _, arg := range args[1:] {
		y := arg.(*Number).Value
		if x >= y {
			return NewBool(false)
		}
		x = y
	}

	return NewBool(true)
}

////////////////////////////////////////////////////////////////////////////////
// Logic

func Not(x Object) Object {
	return NewBool(x.Equals(&falsecons))
}

////////////////////////////////////////////////////////////////////////////////
// Tests

func IsNil(x Object) Object {
	return NewBool(x.Nil())
}

func IsZero(x Object) Object {
	return NewBool(x.(*Number).Value == 0.0)
}

func IsPos(x Object) Object {
	return NewBool(x.(*Number).Value > 0)
}

func IsNeg(x Object) Object {
	return NewBool(x.(*Number).Value < 0)
}

func IsEmpty(ls Object) Object {
	return NewBool(ls.(List).First().Nil())
}

func IsNumber(x Object) Object {
	_, ok := x.(*Number)
	return NewBool(ok)
}

func IsBool(x Object) Object {
	_, ok := x.(*Bool)
	return NewBool(ok)
}

func IsString(x Object) Object {
	_, ok := x.(*String)
	return NewBool(ok)
}

func IsList(x Object) Object {
	_, ok := x.(*Cell)
	return NewBool(ok)
}

func IsSymbol(x Object) Object {
	_, ok := x.(*Symbol)
	return NewBool(ok)
}

////////////////////////////////////////////////////////////////////////////////
// List

func First(ls Object) Object {
	return ls.(List).First()
}

func Next(ls Object) Object {
	return ls.(List).Next()
}

func Cons(x Object, ls Object) Object {
	return ls.(List).Cons(x)
}

////////////////////////////////////////////////////////////////////////////////
// IO

func Print(args ...Object) Object {
	l := len(args)
	for i, arg := range args {
		fmt.Print(arg)
		if i < l-1 {
			fmt.Print(" ")
		}
	}
	return nil
}

func Println(args ...Object) Object {
	Print(args...)
	fmt.Println()
	return nil
}

func Newline() Object {
	fmt.Println()
	return nil
}
<commit_msg>Refactor core library<commit_after>package main

import (
	"fmt"
	"math"
)

var CoreFuncs = map[string]interface{}{
	// Arithmetic
	"+":   Add,
	"-":   Sub,
	"*":   Mul,
	"/":   Div,
	"rem": Rem,
	"mod": Mod,
	"inc": Inc,
	"dec": Dec,

	// Relational
	">":  Gt,
	">=": Ge,
	"=":  Eq,
	"!=": Ne,
	"<=": Le,
	"<":  Lt,

	// Logic
	"not": Not,

	// Test
	"bool?":   IsBool,
	"list?":   IsList,
	"neg?":    IsNeg,
	"nil?":    IsNil,
	"number?": IsNumber,
	"pos?":    IsPos,
	"string?": IsString,
	"symbol?": IsSymbol,
	"zero?":   IsZero,

	// List
	"cons":   Cons,
	"empty?": IsEmpty,
	"first":  First,
	"next":   Next,

	// IO
	"print": Print,
	//"printf": Printf,
	"println": Println,
	"newline": Newline,
	//"readline": Readline,
}

////////////////////////////////////////////////////////////////////////////////
// Arithmetic

func Add(nums ...Object) Object {
	res := nums[0].(*Number).Value

	for _, arg := range nums[1:] {
		res += arg.(*Number).Value
	}

	return NewNumber(res)
}

func Sub(nums ...Object) Object {
	if len(nums) == 1 {
		return NewNumber(-nums[0].(*Number).Value)
	}

	res := nums[0].(*Number).Value

	for _, arg := range nums[1:] {
		res -= arg.(*Number).Value
	}

	return NewNumber(res)
}

func Mul(nums ...Object) Object {
	res := nums[0].(*Number).Value

	for _, arg := range nums[1:] {
		res *= arg.(*Number).Value
	}

	return NewNumber(res)
}

func Div(nums ...Object) Object {
	if len(nums) == 1 {
		return NewNumber(1.0 / nums[0].(*Number).Value)
	}

	res := nums[0].(*Number).Value

	for _, arg := range nums[1:] {
		res /= arg.(*Number).Value
	}

	return NewNumber(res)
}

func Rem(num Object, div Object) Object {
	return NewNumber(math.Remainder(num.(*Number).Value, div.(*Number).Value))
}

func Mod(num Object, div Object) Object {
	return NewNumber(math.Mod(num.(*Number).Value, div.(*Number).Value))
}

func Inc(num Object) Object {
	return NewNumber(num.(*Number).Value + 1.0)
}

func Dec(num Object) Object {
	return NewNumber(num.(*Number).Value - 1.0)
}

////////////////////////////////////////////////////////////////////////////////
// Relational

func Gt(nums ...Object) Object {
	x := nums[0].(*Number).Value

	for _, arg := range nums[1:] {
		y := arg.(*Number).Value
		if x <= y {
			return NewBool(false)
		}
		x = y
	}

	return NewBool(true)
}

func Ge(nums ...Object) Object {
	x := nums[0].(*Number).Value

	for _, arg := range nums[1:] {
		y := arg.(*Number).Value
		if x < y {
			return NewBool(false)
		}
		x = y
	}

	return NewBool(true)
}

func Eq(objs ...Object) Object {
	x := objs[0]

	for _, arg := range objs[1:] {
		if !x.Equals(arg) {
			return NewBool(false)
		}
	}

	return NewBool(true)
}

func Ne(objs ...Object) Object {
	return Not(Eq(objs...))
}

func Le(nums ...Object) Object {
	x := nums[0].(*Number).Value

	for _, arg := range nums[1:] {
		y := arg.(*Number).Value
		if x > y {
			return NewBool(false)
		}
		x = y
	}

	return NewBool(true)
}

func Lt(nums ...Object) Object {
	x := nums[0].(*Number).Value

	for _, arg := range nums[1:] {
		y := arg.(*Number).Value
		if x >= y {
			return NewBool(false)
		}
		x = y
	}

	return NewBool(true)
}

////////////////////////////////////////////////////////////////////////////////
// Logic

func Not(x Object) Object {
	if x == nil {
		return NewBool(true)
	}
	return NewBool(x.Equals(&falsecons))
}

////////////////////////////////////////////////////////////////////////////////
// Tests

func IsNil(x Object) Object {
	return NewBool(x.Nil())
}

func IsZero(x Object) Object {
	return NewBool(x.(*Number).Value == 0.0)
}

func IsPos(x Object) Object {
	return NewBool(x.(*Number).Value > 0)
}

func IsNeg(x Object) Object {
	return NewBool(x.(*Number).Value < 0)
}

func IsNumber(x Object) Object {
	_, ok := x.(*Number)
	return NewBool(ok)
}

func IsBool(x Object) Object {
	_, ok := x.(*Bool)
	return NewBool(ok)
}

func IsString(x Object) Object {
	_, ok := x.(*String)
	return NewBool(ok)
}

func IsList(x Object) Object {
	_, ok := x.(*Cell)
	return NewBool(ok)
}

func IsSymbol(x Object) Object {
	_, ok := x.(*Symbol)
	return NewBool(ok)
}

////////////////////////////////////////////////////////////////////////////////
// List

func Cons(x Object, ls Object) Object {
	return ls.(List).Cons(x)
}

func IsEmpty(ls Object) Object {
	if ls == nil {
		return nil
	}
	return NewBool(ls.(List).IsEmpty())
}

func First(ls Object) Object {
	if ls == nil {
		return nil
	}
	return ls.(List).First()
}

func Next(ls Object) Object {
	if ls == nil {
		return nil
	}
	return ls.(List).Next()
}

////////////////////////////////////////////////////////////////////////////////
// IO

func Print(objs ...Object) Object {
	l := len(objs)
	for i, arg := range objs {
		fmt.Print(arg)
		if i < l-1 {
			fmt.Print(" ")
		}
	}
	return nil
}

func Println(objs ...Object) Object {
	Print(objs...)
	fmt.Println()
	return nil
}

func Newline() Object {
	fmt.Println()
	return nil
}
<|endoftext|>


<commit_before>package mailjet

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"reflect"
	"runtime"
	"strconv"
	"strings"
)

// DebugLevel defines the verbosity of the debug
//		LevelNone: No debug
//		LevelDebug: Debug without body
//		LevelDebugFull: Debug with body
var DebugLevel int

// NbAttempt defines the number of attempt for a request as long as StatusCode == 500
var NbAttempt = 5

const (
	LevelNone = iota
	LevelDebug
	LevelDebugFull
)

var debugOut io.Writer = os.Stderr

const (
	apiBase                 = "https://api.mailjet.com/v3"
	apiPath                 = "REST"
	dataPath                = "DATA"
	MailjetUserAgentBase    = "mailjet-api-v3-go"
	MailjetUserAgentVersion = "1.0.0"
)

// createRequest is the main core function.
func createRequest(method string, url string,
	payload interface{}, onlyFields []string,
	options ...MailjetOptions) (req *http.Request, err error) {

	body, err := convertPayload(payload, onlyFields)
	if err != nil {
		return req, fmt.Errorf("creating request: %s\n", err)
	}
	req, err = http.NewRequest(method, url, bytes.NewBuffer(body))
	if err != nil {
		return req, fmt.Errorf("creating request: %s\n", err)
	}
	for _, option := range options {
		option(req)
	}
	userAgent(req)
	req.Header.Add("Accept", "application/json")
	return req, err
}

// converPayload returns payload casted in []byte.
// If the payload is a structure, it's encoded to JSON.
func convertPayload(payload interface{}, onlyFields []string) (body []byte, err error) {
	if payload != nil {
		switch t := payload.(type) {
		case string:
			body = []byte(t)
		case []byte:
			body = t
		default:
			v := reflect.Indirect(reflect.ValueOf(payload))
			if v.Kind() == reflect.Ptr {
				return convertPayload(v.Interface(), onlyFields)
			} else if v.Kind() == reflect.Struct {
				body, err = json.Marshal(buildMap(v, onlyFields))
				if err != nil {
					return body, err
				}
			}
		}
		if DebugLevel == LevelDebugFull {
			log.Println("Body:", string(body))
		}
	}
	return body, err
}

// buildMap returns a map with fields specified in onlyFields (all fields if nil)
// and without the read_only fields.
func buildMap(v reflect.Value, onlyFields []string) map[string]interface{} {
	res := make(map[string]interface{})
	if onlyFields != nil {
		for _, onlyField := range onlyFields {
			fieldType, exist := v.Type().FieldByName(onlyField)
			if exist {
				addFieldToMap(true, fieldType, v.FieldByName(onlyField), res)
			}
		}
	} else {
		for i := 0; i < v.NumField(); i++ {
			addFieldToMap(false, v.Type().Field(i), v.Field(i), res)
		}
	}
	return res
}

func addFieldToMap(onlyField bool, fieldType reflect.StructField,
	fieldValue reflect.Value, res map[string]interface{}) {
	if fieldType.Tag.Get("mailjet") != "read_only" {
		name, second := parseTag(fieldType.Tag.Get("json"))
		if name == "" {
			name = fieldType.Name
		}
		if !onlyField && second == "omitempty" &&
			isEmptyValue(fieldValue) {
			return
		}
		res[name] = fieldValue.Interface()
	}
}

func parseTag(tag string) (string, string) {
	if idx := strings.Index(tag, ","); idx != -1 {
		return tag[:idx], tag[idx+1:]
	}
	return tag, ""
}

func isEmptyValue(v reflect.Value) bool {
	switch v.Kind() {
	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
		return v.Len() == 0
	case reflect.Bool:
		return !v.Bool()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return v.Int() == 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return v.Uint() == 0
	case reflect.Float32, reflect.Float64:
		return v.Float() == 0
	case reflect.Interface, reflect.Ptr:
		return v.IsNil()
	}
	return false
}

// userAgent add the User-Agent value to the request header.
func userAgent(req *http.Request) {
	ua := fmt.Sprintf("%s/%s;%s",
		MailjetUserAgentBase,
		MailjetUserAgentVersion,
		runtime.Version(),
	)
	req.Header.Add("User-Agent", ua)
}

func buildUrl(info *MailjetRequest) string {
	tokens := []string{apiBase, apiPath, info.Resource}
	if info.ID != 0 {
		id := strconv.FormatInt(info.ID, 10)
		tokens = append(tokens, id)
	} else if info.AltID != "" {
		tokens = append(tokens, string(info.AltID))
	}
	if info.Action != "" {
		tokens = append(tokens, info.Action)
	}
	if info.ActionID != 0 {
		actionID := strconv.FormatInt(info.ActionID, 10)
		tokens = append(tokens, actionID)
	}
	return strings.Join(tokens, "/")
}

func buildDataUrl(info *MailjetDataRequest) string {
	tokens := []string{apiBase, dataPath, info.SourceType}
	if info.SourceTypeID != 0 {
		id := strconv.FormatInt(info.SourceTypeID, 10)
		tokens = append(tokens, id)
	}
	if info.DataType != "" {
		tokens = append(tokens, info.DataType)
		if info.MimeType != "" {
			tokens = append(tokens, info.MimeType)
		}
	}
	if info.DataTypeID != 0 {
		DataTypeID := strconv.FormatInt(info.DataTypeID, 10)
		tokens = append(tokens, DataTypeID)
	} else if info.LastID == true {
		tokens = append(tokens, "LAST")
	}
	return strings.Join(tokens, "/")
}

// readJsonResult decodes the API response, returns Count and Total values
// and stores the Data in the value pointed to by data.
func readJsonResult(r io.Reader, data interface{}) (int, int, error) {
	if DebugLevel == LevelDebugFull {
		r = io.TeeReader(r, debugOut)
		log.Print("Body: ")
		defer fmt.Fprintln(debugOut)
	}

	var res MailjetResult
	res.Data = &data
	err := json.NewDecoder(r).Decode(&res)
	if err != nil {
		return 0, 0, fmt.Errorf("Error decoding API response: %s", err)
	}
	return res.Count, res.Total, nil
}

// doRequest is called to execute the request. Authentification is set
// with the public key and the secret key specified in MailjetClient.
func (m *MailjetClient) doRequest(req *http.Request) (resp *http.Response, err error) {
	debugRequest(req) //DEBUG
	req.SetBasicAuth(m.apiKeyPublic, m.apiKeyPrivate)
	for attempt := 0; err == nil && resp.StatusCode == 500 && attempt < NbAttempt; attempt++ {
		resp, err = m.client.Do(req)
	}
	defer debugResponse(resp) //DEBUG
	if err != nil {
		return nil, fmt.Errorf("Error getting %s: %s", req.URL, err)
	}
	err = checkResponseError(resp)
	return resp, err
}

// checkResponseError returns response error if the statuscode is < 200 or >= 400.
func checkResponseError(resp *http.Response) error {
	if resp.StatusCode < 200 || resp.StatusCode >= 400 {
		var mailjet_err MailjetError
		err := json.NewDecoder(resp.Body).Decode(&mailjet_err)
		if err != nil {
			return fmt.Errorf("Unexpected server response code: %d: %s", resp.StatusCode, err)
		} else {
			return fmt.Errorf("Unexpected server response code: %d: %s (%s)",
				resp.StatusCode, mailjet_err.ErrorMessage, mailjet_err.ErrorInfo)
		}
	}
	return nil
}

// debugRequest is a custom dump of the request.
// Method used, final URl called, and Header content are logged.
func debugRequest(req *http.Request) {
	if DebugLevel > LevelNone && req != nil {
		log.Printf("Method used is: %s\n", req.Method)
		log.Printf("Final URL is: %s\n", req.URL)
		log.Printf("Header is: %s\n", req.Header)
	}
}

// debugResponse is a custom dump of the response.
// Status and Header content are logged.
func debugResponse(resp *http.Response) {
	if DebugLevel > LevelNone && resp != nil {
		log.Printf("Status is: %s\n", resp.Status)
		log.Printf("Header is: %s\n", resp.Header)
	}
}
<commit_msg>handle 500: rewritten<commit_after>package mailjet

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"reflect"
	"runtime"
	"strconv"
	"strings"
)

// DebugLevel defines the verbosity of the debug
//		LevelNone: No debug
//		LevelDebug: Debug without body
//		LevelDebugFull: Debug with body
var DebugLevel int

// NbAttempt defines the number of attempt for a request as long as StatusCode == 500
var NbAttempt = 5

const (
	LevelNone = iota
	LevelDebug
	LevelDebugFull
)

var debugOut io.Writer = os.Stderr

const (
	apiBase                 = "https://api.mailjet.com/v3"
	apiPath                 = "REST"
	dataPath                = "DATA"
	MailjetUserAgentBase    = "mailjet-api-v3-go"
	MailjetUserAgentVersion = "1.0.0"
)

// createRequest is the main core function.
func createRequest(method string, url string,
	payload interface{}, onlyFields []string,
	options ...MailjetOptions) (req *http.Request, err error) {

	body, err := convertPayload(payload, onlyFields)
	if err != nil {
		return req, fmt.Errorf("creating request: %s\n", err)
	}
	req, err = http.NewRequest(method, url, bytes.NewBuffer(body))
	if err != nil {
		return req, fmt.Errorf("creating request: %s\n", err)
	}
	for _, option := range options {
		option(req)
	}
	userAgent(req)
	req.Header.Add("Accept", "application/json")
	return req, err
}

// converPayload returns payload casted in []byte.
// If the payload is a structure, it's encoded to JSON.
func convertPayload(payload interface{}, onlyFields []string) (body []byte, err error) {
	if payload != nil {
		switch t := payload.(type) {
		case string:
			body = []byte(t)
		case []byte:
			body = t
		default:
			v := reflect.Indirect(reflect.ValueOf(payload))
			if v.Kind() == reflect.Ptr {
				return convertPayload(v.Interface(), onlyFields)
			} else if v.Kind() == reflect.Struct {
				body, err = json.Marshal(buildMap(v, onlyFields))
				if err != nil {
					return body, err
				}
			}
		}
		if DebugLevel == LevelDebugFull {
			log.Println("Body:", string(body))
		}
	}
	return body, err
}

// buildMap returns a map with fields specified in onlyFields (all fields if nil)
// and without the read_only fields.
func buildMap(v reflect.Value, onlyFields []string) map[string]interface{} {
	res := make(map[string]interface{})
	if onlyFields != nil {
		for _, onlyField := range onlyFields {
			fieldType, exist := v.Type().FieldByName(onlyField)
			if exist {
				addFieldToMap(true, fieldType, v.FieldByName(onlyField), res)
			}
		}
	} else {
		for i := 0; i < v.NumField(); i++ {
			addFieldToMap(false, v.Type().Field(i), v.Field(i), res)
		}
	}
	return res
}

func addFieldToMap(onlyField bool, fieldType reflect.StructField,
	fieldValue reflect.Value, res map[string]interface{}) {
	if fieldType.Tag.Get("mailjet") != "read_only" {
		name, second := parseTag(fieldType.Tag.Get("json"))
		if name == "" {
			name = fieldType.Name
		}
		if !onlyField && second == "omitempty" &&
			isEmptyValue(fieldValue) {
			return
		}
		res[name] = fieldValue.Interface()
	}
}

func parseTag(tag string) (string, string) {
	if idx := strings.Index(tag, ","); idx != -1 {
		return tag[:idx], tag[idx+1:]
	}
	return tag, ""
}

func isEmptyValue(v reflect.Value) bool {
	switch v.Kind() {
	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
		return v.Len() == 0
	case reflect.Bool:
		return !v.Bool()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return v.Int() == 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return v.Uint() == 0
	case reflect.Float32, reflect.Float64:
		return v.Float() == 0
	case reflect.Interface, reflect.Ptr:
		return v.IsNil()
	}
	return false
}

// userAgent add the User-Agent value to the request header.
func userAgent(req *http.Request) {
	ua := fmt.Sprintf("%s/%s;%s",
		MailjetUserAgentBase,
		MailjetUserAgentVersion,
		runtime.Version(),
	)
	req.Header.Add("User-Agent", ua)
}

func buildUrl(info *MailjetRequest) string {
	tokens := []string{apiBase, apiPath, info.Resource}
	if info.ID != 0 {
		id := strconv.FormatInt(info.ID, 10)
		tokens = append(tokens, id)
	} else if info.AltID != "" {
		tokens = append(tokens, string(info.AltID))
	}
	if info.Action != "" {
		tokens = append(tokens, info.Action)
	}
	if info.ActionID != 0 {
		actionID := strconv.FormatInt(info.ActionID, 10)
		tokens = append(tokens, actionID)
	}
	return strings.Join(tokens, "/")
}

func buildDataUrl(info *MailjetDataRequest) string {
	tokens := []string{apiBase, dataPath, info.SourceType}
	if info.SourceTypeID != 0 {
		id := strconv.FormatInt(info.SourceTypeID, 10)
		tokens = append(tokens, id)
	}
	if info.DataType != "" {
		tokens = append(tokens, info.DataType)
		if info.MimeType != "" {
			tokens = append(tokens, info.MimeType)
		}
	}
	if info.DataTypeID != 0 {
		DataTypeID := strconv.FormatInt(info.DataTypeID, 10)
		tokens = append(tokens, DataTypeID)
	} else if info.LastID == true {
		tokens = append(tokens, "LAST")
	}
	return strings.Join(tokens, "/")
}

// readJsonResult decodes the API response, returns Count and Total values
// and stores the Data in the value pointed to by data.
func readJsonResult(r io.Reader, data interface{}) (int, int, error) {
	if DebugLevel == LevelDebugFull {
		r = io.TeeReader(r, debugOut)
		log.Print("Body: ")
		defer fmt.Fprintln(debugOut)
	}

	var res MailjetResult
	res.Data = &data
	err := json.NewDecoder(r).Decode(&res)
	if err != nil {
		return 0, 0, fmt.Errorf("Error decoding API response: %s", err)
	}
	return res.Count, res.Total, nil
}

// doRequest is called to execute the request. Authentification is set
// with the public key and the secret key specified in MailjetClient.
func (m *MailjetClient) doRequest(req *http.Request) (resp *http.Response, err error) {
	debugRequest(req) //DEBUG
	req.SetBasicAuth(m.apiKeyPublic, m.apiKeyPrivate)
	for attempt := 0; attempt < NbAttempt; attempt++ {
		resp, err = m.client.Do(req)
		if err != nil || (resp != nil && resp.StatusCode != 500) {
			break
		}
	}
	defer debugResponse(resp) //DEBUG
	if err != nil {
		return nil, fmt.Errorf("Error getting %s: %s", req.URL, err)
	}
	err = checkResponseError(resp)
	return resp, err
}

// checkResponseError returns response error if the statuscode is < 200 or >= 400.
func checkResponseError(resp *http.Response) error {
	if resp.StatusCode < 200 || resp.StatusCode >= 400 {
		var mailjet_err MailjetError
		err := json.NewDecoder(resp.Body).Decode(&mailjet_err)
		if err != nil {
			return fmt.Errorf("Unexpected server response code: %d: %s", resp.StatusCode, err)
		} else {
			return fmt.Errorf("Unexpected server response code: %d: %s (%s)",
				resp.StatusCode, mailjet_err.ErrorMessage, mailjet_err.ErrorInfo)
		}
	}
	return nil
}

// debugRequest is a custom dump of the request.
// Method used, final URl called, and Header content are logged.
func debugRequest(req *http.Request) {
	if DebugLevel > LevelNone && req != nil {
		log.Printf("Method used is: %s\n", req.Method)
		log.Printf("Final URL is: %s\n", req.URL)
		log.Printf("Header is: %s\n", req.Header)
	}
}

// debugResponse is a custom dump of the response.
// Status and Header content are logged.
func debugResponse(resp *http.Response) {
	if DebugLevel > LevelNone && resp != nil {
		log.Printf("Status is: %s\n", resp.Status)
		log.Printf("Header is: %s\n", resp.Header)
	}
}
<|endoftext|>


<commit_before>// package editor implements a full-feature line editor.
package editor

import (
	"os"
	"fmt"
	"bufio"
	"unicode"
	"unicode/utf8"
	"./tty"
)

type cell struct {
	rune
	width byte
}

type buffer [][]cell

type Editor struct {
	savedTermios *tty.Termios
	file *os.File
	oldBuf, buf buffer
	line, col, width, indent int
}

type LineRead struct {
	Line string
	Eof bool
	Err error
}

var savedTermios *tty.Termios

func Init(fd int) (*Editor, error) {
	term, err := tty.NewTermiosFromFd(fd)
	if err != nil {
		return nil, fmt.Errorf("Can't get terminal attribute: %s", err)
	}

	editor := &Editor{
		savedTermios: term.Copy(),
		file: os.NewFile(uintptr(fd), "<line editor terminal>"),
		oldBuf: [][]cell{[]cell{}},
	}

	term.SetIcanon(false)
	term.SetEcho(false)
	term.SetMin(1)
	term.SetTime(0)

	err = term.ApplyToFd(fd)
	if err != nil {
		return nil, fmt.Errorf("Can't set up terminal attribute: %s", err)
	}

	fmt.Fprint(editor.file, "\033[?7l")
	return editor, nil
}

func (ed *Editor) Cleanup() error {
	fmt.Fprint(ed.file, "\033[?7h")

	fd := int(ed.file.Fd())
	err := ed.savedTermios.ApplyToFd(fd)
	if err != nil {
		return fmt.Errorf("Can't restore terminal attribute of stdin: %s", err)
	}
	ed.savedTermios = nil
	return nil
}

func (ed *Editor) beep() {
}

func (ed *Editor) tip(s string) {
	fmt.Fprintf(ed.file, "\n%s\033[A", s)
}

func (ed *Editor) tipf(format string, a ...interface{}) {
	ed.tip(fmt.Sprintf(format, a...))
}

func (ed *Editor) clearTip() {
	fmt.Fprintf(ed.file, "\n\033[K\033[A")
}

func (ed *Editor) startBuffer() {
	ed.line = 0
	ed.col = 0
	ed.width = int(tty.GetWinsize(int(ed.file.Fd())).Col)
	ed.buf = [][]cell{make([]cell, ed.width)}
}

func (ed *Editor) commitBuffer() error {
	newlines := len(ed.oldBuf) - 1
	if newlines > 0 {
		fmt.Fprintf(ed.file, "\033[%dA", newlines)
	}
	fmt.Fprintf(ed.file, "\r\033[J")

	for _, line := range ed.buf {
		for _, c := range line {
			_, err := ed.file.WriteString(string(c.rune))
			if err != nil {
				return err
			}
		}
	}
	ed.oldBuf = ed.buf
	return nil
}

func (ed *Editor) appendToLine(c cell) {
	ed.buf[ed.line] = append(ed.buf[ed.line], c)
	ed.col += int(c.width)
}

func (ed *Editor) newline() {
	ed.buf[ed.line] = append(ed.buf[ed.line], cell{rune: '\n'})
	ed.buf = append(ed.buf, make([]cell, ed.width))
	ed.line++
	ed.col = 0
	if ed.indent > 0 {
		for i := 0; i < ed.indent; i++ {
			ed.appendToLine(cell{rune: ' '})
		}
	}
}

func (ed *Editor) write(r rune) {
	wd := wcwidth(r)
	c := cell{r, byte(wd)}

	if ed.col + wd > ed.width {
		ed.newline()
		ed.appendToLine(c)
	} else if ed.col + wd == ed.width {
		ed.appendToLine(c)
		ed.newline()
	} else {
		ed.appendToLine(c)
	}
}

func (ed *Editor) refresh(prompt, text string) error {
	ed.startBuffer()

	for _, r := range prompt {
		ed.write(r)
	}

	if ed.col * 2 < ed.width {
		ed.indent = ed.col
	}

	for _, r := range text {
		ed.write(r)
	}

	return ed.commitBuffer()
}

func (ed *Editor) ReadLine(prompt string) (lr LineRead) {
	stdin := bufio.NewReaderSize(ed.file, 0)
	line := ""

	for {
		err := ed.refresh(prompt, line)
		if err != nil {
			return LineRead{Err: err}
		}

		r, _, err := stdin.ReadRune()
		if err != nil {
			return LineRead{Err: err}
		}

		switch {
		case r == '\n':
			ed.clearTip()
			fmt.Fprintln(ed.file)
			return LineRead{Line: line}
		case r == 0x7f: // Backspace
			if l := len(line); l > 0 {
				_, w := utf8.DecodeLastRuneInString(line)
				line = line[:l-w]
			} else {
				ed.beep()
			}
		case r == 0x15: // ^U
			line = ""
		case r == 0x4 && len(line) == 0: // ^D
			return LineRead{Eof: true}
		case r == 0x2: // ^B
			fmt.Fprintf(ed.file, "\033[D")
		case r == 0x6: // ^F
			fmt.Fprintf(ed.file, "\033[C")
		case unicode.IsGraphic(r):
			line += string(r)
		default:
			ed.tipf("Non-graphic: %#x", r)
		}
	}

	panic("unreachable")
}
<commit_msg>libdasc/editor: Fix a quirky cell literal<commit_after>// package editor implements a full-feature line editor.
package editor

import (
	"os"
	"fmt"
	"bufio"
	"unicode"
	"unicode/utf8"
	"./tty"
)

type cell struct {
	rune
	width byte
}

type buffer [][]cell

type Editor struct {
	savedTermios *tty.Termios
	file *os.File
	oldBuf, buf buffer
	line, col, width, indent int
}

type LineRead struct {
	Line string
	Eof bool
	Err error
}

var savedTermios *tty.Termios

func Init(fd int) (*Editor, error) {
	term, err := tty.NewTermiosFromFd(fd)
	if err != nil {
		return nil, fmt.Errorf("Can't get terminal attribute: %s", err)
	}

	editor := &Editor{
		savedTermios: term.Copy(),
		file: os.NewFile(uintptr(fd), "<line editor terminal>"),
		oldBuf: [][]cell{[]cell{}},
	}

	term.SetIcanon(false)
	term.SetEcho(false)
	term.SetMin(1)
	term.SetTime(0)

	err = term.ApplyToFd(fd)
	if err != nil {
		return nil, fmt.Errorf("Can't set up terminal attribute: %s", err)
	}

	fmt.Fprint(editor.file, "\033[?7l")
	return editor, nil
}

func (ed *Editor) Cleanup() error {
	fmt.Fprint(ed.file, "\033[?7h")

	fd := int(ed.file.Fd())
	err := ed.savedTermios.ApplyToFd(fd)
	if err != nil {
		return fmt.Errorf("Can't restore terminal attribute of stdin: %s", err)
	}
	ed.savedTermios = nil
	return nil
}

func (ed *Editor) beep() {
}

func (ed *Editor) tip(s string) {
	fmt.Fprintf(ed.file, "\n%s\033[A", s)
}

func (ed *Editor) tipf(format string, a ...interface{}) {
	ed.tip(fmt.Sprintf(format, a...))
}

func (ed *Editor) clearTip() {
	fmt.Fprintf(ed.file, "\n\033[K\033[A")
}

func (ed *Editor) startBuffer() {
	ed.line = 0
	ed.col = 0
	ed.width = int(tty.GetWinsize(int(ed.file.Fd())).Col)
	ed.buf = [][]cell{make([]cell, ed.width)}
}

func (ed *Editor) commitBuffer() error {
	newlines := len(ed.oldBuf) - 1
	if newlines > 0 {
		fmt.Fprintf(ed.file, "\033[%dA", newlines)
	}
	fmt.Fprintf(ed.file, "\r\033[J")

	for _, line := range ed.buf {
		for _, c := range line {
			_, err := ed.file.WriteString(string(c.rune))
			if err != nil {
				return err
			}
		}
	}
	ed.oldBuf = ed.buf
	return nil
}

func (ed *Editor) appendToLine(c cell) {
	ed.buf[ed.line] = append(ed.buf[ed.line], c)
	ed.col += int(c.width)
}

func (ed *Editor) newline() {
	ed.buf[ed.line] = append(ed.buf[ed.line], cell{rune: '\n'})
	ed.buf = append(ed.buf, make([]cell, ed.width))
	ed.line++
	ed.col = 0
	if ed.indent > 0 {
		for i := 0; i < ed.indent; i++ {
			ed.appendToLine(cell{rune: ' ', width: 1})
		}
	}
}

func (ed *Editor) write(r rune) {
	wd := wcwidth(r)
	c := cell{r, byte(wd)}

	if ed.col + wd > ed.width {
		ed.newline()
		ed.appendToLine(c)
	} else if ed.col + wd == ed.width {
		ed.appendToLine(c)
		ed.newline()
	} else {
		ed.appendToLine(c)
	}
}

func (ed *Editor) refresh(prompt, text string) error {
	ed.startBuffer()

	for _, r := range prompt {
		ed.write(r)
	}

	if ed.col * 2 < ed.width {
		ed.indent = ed.col
	}

	for _, r := range text {
		ed.write(r)
	}

	return ed.commitBuffer()
}

func (ed *Editor) ReadLine(prompt string) (lr LineRead) {
	stdin := bufio.NewReaderSize(ed.file, 0)
	line := ""

	for {
		err := ed.refresh(prompt, line)
		if err != nil {
			return LineRead{Err: err}
		}

		r, _, err := stdin.ReadRune()
		if err != nil {
			return LineRead{Err: err}
		}

		switch {
		case r == '\n':
			ed.clearTip()
			fmt.Fprintln(ed.file)
			return LineRead{Line: line}
		case r == 0x7f: // Backspace
			if l := len(line); l > 0 {
				_, w := utf8.DecodeLastRuneInString(line)
				line = line[:l-w]
			} else {
				ed.beep()
			}
		case r == 0x15: // ^U
			line = ""
		case r == 0x4 && len(line) == 0: // ^D
			return LineRead{Eof: true}
		case r == 0x2: // ^B
			fmt.Fprintf(ed.file, "\033[D")
		case r == 0x6: // ^F
			fmt.Fprintf(ed.file, "\033[C")
		case unicode.IsGraphic(r):
			line += string(r)
		default:
			ed.tipf("Non-graphic: %#x", r)
		}
	}

	panic("unreachable")
}
<|endoftext|>


<commit_before>// +build windows

package overseer

import (
	"fmt"
	"os"
	"time"

	ps "github.com/mitchellh/go-ps"
)

func (sp *slave) watchParent() error {
	sp.masterPid = os.Getppid()
	proc, err := os.FindProcess(sp.masterPid)
	if err != nil {
		return fmt.Errorf("master process: %s", err)
	}
	sp.masterProc = proc
	go func() {
		//check process exists
		for {
			//should not error as long as the process is alive
			if _, err := ps.FindProcess(sp.masterPid); err != nil {
				os.Exit(1)
			}
			time.Sleep(2 * time.Second)
		}
	}()
	return nil
}
<commit_msg>Another attempt to fix watchParent()<commit_after>// +build windows

package overseer

import (
	"context"
	"fmt"
	"github.com/StackExchange/wmi"
	"os"
	"time"
)

var (
	Timeout = 3 * time.Second
)

type Win32_Process struct {
	Name                  string
	ExecutablePath        *string
	CommandLine           *string
	Priority              uint32
	CreationDate          *time.Time
	ProcessID             uint32
	ThreadCount           uint32
	Status                *string
	ReadOperationCount    uint64
	ReadTransferCount     uint64
	WriteOperationCount   uint64
	WriteTransferCount    uint64
	CSCreationClassName   string
	CSName                string
	Caption               *string
	CreationClassName     string
	Description           *string
	ExecutionState        *uint16
	HandleCount           uint32
	KernelModeTime        uint64
	MaximumWorkingSetSize *uint32
	MinimumWorkingSetSize *uint32
	OSCreationClassName   string
	OSName                string
	OtherOperationCount   uint64
	OtherTransferCount    uint64
	PageFaults            uint32
	PageFileUsage         uint32
	ParentProcessID       uint32
	PeakPageFileUsage     uint32
	PeakVirtualSize       uint64
	PeakWorkingSetSize    uint32
	PrivatePageCount      uint64
	TerminationDate       *time.Time
	UserModeTime          uint64
	WorkingSetSize        uint64
}

func (sp *slave) watchParent() error {
	sp.masterPid = os.Getppid()
	proc, err := os.FindProcess(sp.masterPid)
	if err != nil {
		return fmt.Errorf("master process: %s", err)
	}
	sp.masterProc = proc
	go func() {
		//send signal 0 to master process forever
		for {
			//should not error as long as the process is alive
			if _, err := GetWin32Proc(int32(sp.masterPid)); err != nil {
				os.Exit(1)
			}
			time.Sleep(2 * time.Second)
		}
	}()
	return nil
}

func (sp *slave) triggerRestart() {
	//FIXME: This does not work
	if err := sp.masterProc.Signal(sp.Config.RestartSignal); err != nil {
		os.Exit(1)
	}
}

func GetWin32Proc(pid int32) ([]Win32_Process, error) {
	return GetWin32ProcWithContext(context.Background(), pid)
}

func GetWin32ProcWithContext(ctx context.Context, pid int32) ([]Win32_Process, error) {
	var dst []Win32_Process
	query := fmt.Sprintf("WHERE ProcessId = %d", pid)
	q := wmi.CreateQuery(&dst, query)
	err := WMIQueryWithContext(ctx, q, &dst)
	if err != nil {
		return []Win32_Process{}, fmt.Errorf("could not get win32Proc: %s", err)
	}

	if len(dst) == 0 {
		return []Win32_Process{}, fmt.Errorf("could not get win32Proc: empty")
	}

	return dst, nil
}

func WMIQueryWithContext(ctx context.Context, query string, dst interface{}, connectServerArgs ...interface{}) error {
	if _, ok := ctx.Deadline(); !ok {
		ctxTimeout, cancel := context.WithTimeout(ctx, Timeout)
		defer cancel()
		ctx = ctxTimeout
	}

	errChan := make(chan error, 1)
	go func() {
		errChan <- wmi.Query(query, dst, connectServerArgs...)
	}()

	select {
	case <-ctx.Done():
		return ctx.Err()
	case err := <-errChan:
		return err
	}
}
<|endoftext|>


<commit_before>package cors

import (
	"errors"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
)

type Config struct {
	AllowAllOrigins bool

	// AllowedOrigins is a list of origins a cross-domain request can be executed from.
	// If the special "*" value is present in the list, all origins will be allowed.
	// Default value is ["*"]
	AllowOrigins []string

	// AllowOriginFunc is a custom function to validate the origin. It take the origin
	// as argument and returns true if allowed or false otherwise. If this option is
	// set, the content of AllowedOrigins is ignored.
	AllowOriginFunc func(origin string) bool

	// AllowedMethods is a list of methods the client is allowed to use with
	// cross-domain requests. Default value is simple methods (GET and POST)
	AllowMethods []string

	// AllowedHeaders is list of non simple headers the client is allowed to use with
	// cross-domain requests.
	// If the special "*" value is present in the list, all headers will be allowed.
	// Default value is [] but "Origin" is always appended to the list.
	AllowHeaders []string

	// AllowCredentials indicates whether the request can include user credentials like
	// cookies, HTTP authentication or client side SSL certificates.
	AllowCredentials bool

	// ExposedHeaders indicates which headers are safe to expose to the API of a CORS
	// API specification
	ExposeHeaders []string

	// MaxAge indicates how long (in seconds) the results of a preflight request
	// can be cached
	MaxAge time.Duration
}

func (c *Config) AddAllowMethods(methods ...string) {
	c.AllowMethods = append(c.AllowMethods, methods...)
}

func (c *Config) AddAllowHeaders(headers ...string) {
	c.AllowHeaders = append(c.AllowHeaders, headers...)
}

func (c *Config) AddExposeHeaders(headers ...string) {
	c.ExposeHeaders = append(c.ExposeHeaders, headers...)
}

func (c Config) Validate() error {
	if c.AllowAllOrigins && (c.AllowOriginFunc != nil || len(c.AllowOrigins) > 0) {
		return errors.New("conflict settings: all origins are allowed. AllowOriginFunc or AllowedOrigins is not needed")
	}
	if !c.AllowAllOrigins && c.AllowOriginFunc == nil && len(c.AllowOrigins) == 0 {
		return errors.New("conflict settings: all origins disabled")
	}
	for _, origin := range c.AllowOrigins {
		if !strings.HasPrefix(origin, "http://") && !strings.HasPrefix(origin, "https://") {
			return errors.New("bad origin: origins must include http:// or https://")
		}
	}
	return nil
}

func DefaultConfig() Config {
	return Config{
		AllowMethods:     []string{"GET", "POST", "PUT", "HEAD"},
		AllowHeaders:     []string{"Origin", "Content-Length", "Content-Type"},
		AllowCredentials: false,
		MaxAge:           12 * time.Hour,
	}
}

func Default() gin.HandlerFunc {
	config := DefaultConfig()
	config.AllowAllOrigins = true
	return New(config)
}

func New(config Config) gin.HandlerFunc {
	cors := newCors(config)
	return func(c *gin.Context) {
		cors.applyCors(c)
	}
}
<commit_msg>fix golint error.<commit_after>package cors

import (
	"errors"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
)

// Config represents all available options for the middleware.
type Config struct {
	AllowAllOrigins bool

	// AllowedOrigins is a list of origins a cross-domain request can be executed from.
	// If the special "*" value is present in the list, all origins will be allowed.
	// Default value is ["*"]
	AllowOrigins []string

	// AllowOriginFunc is a custom function to validate the origin. It take the origin
	// as argument and returns true if allowed or false otherwise. If this option is
	// set, the content of AllowedOrigins is ignored.
	AllowOriginFunc func(origin string) bool

	// AllowedMethods is a list of methods the client is allowed to use with
	// cross-domain requests. Default value is simple methods (GET and POST)
	AllowMethods []string

	// AllowedHeaders is list of non simple headers the client is allowed to use with
	// cross-domain requests.
	// If the special "*" value is present in the list, all headers will be allowed.
	// Default value is [] but "Origin" is always appended to the list.
	AllowHeaders []string

	// AllowCredentials indicates whether the request can include user credentials like
	// cookies, HTTP authentication or client side SSL certificates.
	AllowCredentials bool

	// ExposedHeaders indicates which headers are safe to expose to the API of a CORS
	// API specification
	ExposeHeaders []string

	// MaxAge indicates how long (in seconds) the results of a preflight request
	// can be cached
	MaxAge time.Duration
}

// AddAllowMethods is allowed to add custom methods
func (c *Config) AddAllowMethods(methods ...string) {
	c.AllowMethods = append(c.AllowMethods, methods...)
}

// AddAllowHeaders is allowed to add custom headers
func (c *Config) AddAllowHeaders(headers ...string) {
	c.AllowHeaders = append(c.AllowHeaders, headers...)
}

// AddExposeHeaders is allowed to add custom expose headers
func (c *Config) AddExposeHeaders(headers ...string) {
	c.ExposeHeaders = append(c.ExposeHeaders, headers...)
}

// Validate is check configuration of user defined.
func (c Config) Validate() error {
	if c.AllowAllOrigins && (c.AllowOriginFunc != nil || len(c.AllowOrigins) > 0) {
		return errors.New("conflict settings: all origins are allowed. AllowOriginFunc or AllowedOrigins is not needed")
	}
	if !c.AllowAllOrigins && c.AllowOriginFunc == nil && len(c.AllowOrigins) == 0 {
		return errors.New("conflict settings: all origins disabled")
	}
	for _, origin := range c.AllowOrigins {
		if !strings.HasPrefix(origin, "http://") && !strings.HasPrefix(origin, "https://") {
			return errors.New("bad origin: origins must include http:// or https://")
		}
	}
	return nil
}

// DefaultConfig returns a generic default configuration mapped to localhost.
func DefaultConfig() Config {
	return Config{
		AllowMethods:     []string{"GET", "POST", "PUT", "HEAD"},
		AllowHeaders:     []string{"Origin", "Content-Length", "Content-Type"},
		AllowCredentials: false,
		MaxAge:           12 * time.Hour,
	}
}

// Default returns the location middleware with default configuration.
func Default() gin.HandlerFunc {
	config := DefaultConfig()
	config.AllowAllOrigins = true
	return New(config)
}

// New returns the location middleware with user-defined custom configuration.
func New(config Config) gin.HandlerFunc {
	cors := newCors(config)
	return func(c *gin.Context) {
		cors.applyCors(c)
	}
}
<|endoftext|>


<commit_before>package handlers

import (
	"net/http"
	"strconv"
	"strings"
)

// CORSOption represents a functional option for configuring the CORS middleware.
type CORSOption func(*cors) error

type cors struct {
	h                      http.Handler
	allowedHeaders         []string
	allowedMethods         []string
	allowedOrigins         []string
	allowedOriginValidator originValidator
	exposedHeaders         []string
	maxAge                 int
	ignoreOptions          bool
	allowCredentials       bool
}

// originValidator takes an origin string and returns whether or not that origin is allowed.
type originValidator func(string) bool

var (
	defaultCorsMethods = []string{"GET", "HEAD", "POST"}
	defaultCorsHeaders = []string{"Accept", "Accept-Language", "Content-Language"}
)

const (
	corsOptionMethod           string = "OPTIONS"
	corsAllowOriginHeader      string = "Access-Control-Allow-Origin"
	corsExposeHeadersHeader    string = "Access-Control-Expose-Headers"
	corsMaxAgeHeader           string = "Access-Control-Max-Age"
	corsAllowMethodsHeader     string = "Access-Control-Allow-Methods"
	corsAllowHeadersHeader     string = "Access-Control-Allow-Headers"
	corsAllowCredentialsHeader string = "Access-Control-Allow-Credentials"
	corsRequestMethodHeader    string = "Access-Control-Request-Method"
	corsRequestHeadersHeader   string = "Access-Control-Request-Headers"
	corsOriginHeader           string = "Origin"
	corsVaryHeader             string = "Vary"
	corsOriginMatchAll         string = "*"
)

func (ch *cors) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	origin := r.Header.Get(corsOriginHeader)
	if !ch.isOriginAllowed(origin) {
		ch.h.ServeHTTP(w, r)
		return
	}

	if r.Method == corsOptionMethod {
		if ch.ignoreOptions {
			ch.h.ServeHTTP(w, r)
			return
		}

		if _, ok := r.Header[corsRequestMethodHeader]; !ok {
			w.WriteHeader(http.StatusBadRequest)
			return
		}

		method := r.Header.Get(corsRequestMethodHeader)
		if !ch.isMatch(method, ch.allowedMethods) {
			w.WriteHeader(http.StatusMethodNotAllowed)
			return
		}

		requestHeaders := strings.Split(r.Header.Get(corsRequestHeadersHeader), ",")
		allowedHeaders := []string{}
		for _, v := range requestHeaders {
			canonicalHeader := http.CanonicalHeaderKey(strings.TrimSpace(v))
			if canonicalHeader == "" || ch.isMatch(canonicalHeader, defaultCorsHeaders) {
				continue
			}

			if !ch.isMatch(canonicalHeader, ch.allowedHeaders) {
				w.WriteHeader(http.StatusForbidden)
				return
			}

			allowedHeaders = append(allowedHeaders, canonicalHeader)
		}

		if len(allowedHeaders) > 0 {
			w.Header().Set(corsAllowHeadersHeader, strings.Join(allowedHeaders, ","))
		}

		if ch.maxAge > 0 {
			w.Header().Set(corsMaxAgeHeader, strconv.Itoa(ch.maxAge))
		}

		if !ch.isMatch(method, defaultCorsMethods) {
			w.Header().Set(corsAllowMethodsHeader, method)
		}
	} else {
		if len(ch.exposedHeaders) > 0 {
			w.Header().Set(corsExposeHeadersHeader, strings.Join(ch.exposedHeaders, ","))
		}
	}

	if ch.allowCredentials {
		w.Header().Set(corsAllowCredentialsHeader, "true")
	}

	if len(ch.allowedOrigins) > 1 {
		w.Header().Set(corsVaryHeader, corsOriginHeader)
	}

	w.Header().Set(corsAllowOriginHeader, origin)

	ch.h.ServeHTTP(w, r)
}

// CORS provides Cross-Origin Resource Sharing middleware.
// Example:
//
//  import (
//      "net/http"
//
//      "github.com/gorilla/handlers"
//      "github.com/gorilla/mux"
//  )
//
//  func main() {
//      r := mux.NewRouter()
//      r.HandleFunc("/users", UserEndpoint)
//      r.HandleFunc("/projects", ProjectEndpoint)
//
//      // Apply the CORS middleware to our top-level router, with the defaults.
//      http.ListenAndServe(":8000", handlers.CORS()(r))
//  }
//
func CORS(opts ...CORSOption) func(http.Handler) http.Handler {
	return func(h http.Handler) http.Handler {
		ch := parseCORSOptions(opts...)
		ch.h = h
		return ch
	}
}

func parseCORSOptions(opts ...CORSOption) *cors {
	ch := &cors{
		allowedMethods: defaultCorsMethods,
		allowedHeaders: defaultCorsHeaders,
		allowedOrigins: []string{corsOriginMatchAll},
	}

	for _, option := range opts {
		option(ch)
	}

	return ch
}

//
// Functional options for configuring CORS.
//

// AllowedHeaders adds the provided headers to the list of allowed headers in a
// CORS request.
// This is an append operation so the headers Accept, Accept-Language,
// and Content-Language are always allowed.
// Content-Type must be explicitly declared if accepting Content-Types other than
// application/x-www-form-urlencoded, multipart/form-data, or text/plain.
func AllowedHeaders(headers []string) CORSOption {
	return func(ch *cors) error {
		for _, v := range headers {
			normalizedHeader := http.CanonicalHeaderKey(strings.TrimSpace(v))
			if normalizedHeader == "" {
				continue
			}

			if !ch.isMatch(normalizedHeader, ch.allowedHeaders) {
				ch.allowedHeaders = append(ch.allowedHeaders, normalizedHeader)
			}
		}

		return nil
	}
}

// AllowedMethods can be used to explicitly allow methods in the
// Access-Control-Allow-Methods header.
// This is a replacement operation so you must also
// pass GET, HEAD, and POST if you wish to support those methods.
func AllowedMethods(methods []string) CORSOption {
	return func(ch *cors) error {
		ch.allowedMethods = []string{}
		for _, v := range methods {
			normalizedMethod := strings.ToUpper(strings.TrimSpace(v))
			if normalizedMethod == "" {
				continue
			}

			if !ch.isMatch(normalizedMethod, ch.allowedMethods) {
				ch.allowedMethods = append(ch.allowedMethods, normalizedMethod)
			}
		}

		return nil
	}
}

// AllowedOrigins sets the allowed origins for CORS requests, as used in the
// 'Allow-Access-Control-Origin' HTTP header.
// Note: Passing in a []string{"*"} will allow any domain.
func AllowedOrigins(origins []string) CORSOption {
	return func(ch *cors) error {
		for _, v := range origins {
			if v == corsOriginMatchAll {
				ch.allowedOrigins = []string{corsOriginMatchAll}
				return nil
			}
		}

		ch.allowedOrigins = origins
		return nil
	}
}

// AllowedOriginValidator sets a function for evaluating allowed origins in CORS requests, represented by the
// 'Allow-Access-Control-Origin' HTTP header.
func AllowedOriginValidator(fn originValidator) CORSOption {
	return func(ch *cors) error {
		ch.allowedOriginValidator = fn
		return nil
	}
}

// ExposeHeaders can be used to specify headers that are available
// and will not be stripped out by the user-agent.
func ExposedHeaders(headers []string) CORSOption {
	return func(ch *cors) error {
		ch.exposedHeaders = []string{}
		for _, v := range headers {
			normalizedHeader := http.CanonicalHeaderKey(strings.TrimSpace(v))
			if normalizedHeader == "" {
				continue
			}

			if !ch.isMatch(normalizedHeader, ch.exposedHeaders) {
				ch.exposedHeaders = append(ch.exposedHeaders, normalizedHeader)
			}
		}

		return nil
	}
}

// MaxAge determines the maximum age (in seconds) between preflight requests. A
// maximum of 10 minutes is allowed. An age above this value will default to 10
// minutes.
func MaxAge(age int) CORSOption {
	return func(ch *cors) error {
		// Maximum of 10 minutes.
		if age > 600 {
			age = 600
		}

		ch.maxAge = age
		return nil
	}
}

// IgnoreOptions causes the CORS middleware to ignore OPTIONS requests, instead
// passing them through to the next handler. This is useful when your application
// or framework has a pre-existing mechanism for responding to OPTIONS requests.
func IgnoreOptions() CORSOption {
	return func(ch *cors) error {
		ch.ignoreOptions = true
		return nil
	}
}

// AllowCredentials can be used to specify that the user agent may pass
// authentication details along with the request.
func AllowCredentials() CORSOption {
	return func(ch *cors) error {
		ch.allowCredentials = true
		return nil
	}
}

func (ch *cors) isOriginAllowed(origin string) bool {
	if origin == "" {
		return false
	}

	if ch.allowedOriginValidator != nil {
		return ch.allowedOriginValidator(origin)
	}

	for _, allowedOrigin := range ch.allowedOrigins {
		if allowedOrigin == origin || allowedOrigin == corsOriginMatchAll {
			return true
		}
	}

	return false
}

func (ch *cors) isMatch(needle string, haystack []string) bool {
	for _, v := range haystack {
		if v == needle {
			return true
		}
	}

	return false
}
<commit_msg>adding Origin as a standard whitelisted request header<commit_after>package handlers

import (
	"net/http"
	"strconv"
	"strings"
)

// CORSOption represents a functional option for configuring the CORS middleware.
type CORSOption func(*cors) error

type cors struct {
	h                      http.Handler
	allowedHeaders         []string
	allowedMethods         []string
	allowedOrigins         []string
	allowedOriginValidator originValidator
	exposedHeaders         []string
	maxAge                 int
	ignoreOptions          bool
	allowCredentials       bool
}

// originValidator takes an origin string and returns whether or not that origin is allowed.
type originValidator func(string) bool

var (
	defaultCorsMethods = []string{"GET", "HEAD", "POST"}
	defaultCorsHeaders = []string{"Accept", "Accept-Language", "Content-Language", "Origin"}
)

const (
	corsOptionMethod           string = "OPTIONS"
	corsAllowOriginHeader      string = "Access-Control-Allow-Origin"
	corsExposeHeadersHeader    string = "Access-Control-Expose-Headers"
	corsMaxAgeHeader           string = "Access-Control-Max-Age"
	corsAllowMethodsHeader     string = "Access-Control-Allow-Methods"
	corsAllowHeadersHeader     string = "Access-Control-Allow-Headers"
	corsAllowCredentialsHeader string = "Access-Control-Allow-Credentials"
	corsRequestMethodHeader    string = "Access-Control-Request-Method"
	corsRequestHeadersHeader   string = "Access-Control-Request-Headers"
	corsOriginHeader           string = "Origin"
	corsVaryHeader             string = "Vary"
	corsOriginMatchAll         string = "*"
)

func (ch *cors) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	origin := r.Header.Get(corsOriginHeader)
	if !ch.isOriginAllowed(origin) {
		ch.h.ServeHTTP(w, r)
		return
	}

	if r.Method == corsOptionMethod {
		if ch.ignoreOptions {
			ch.h.ServeHTTP(w, r)
			return
		}

		if _, ok := r.Header[corsRequestMethodHeader]; !ok {
			w.WriteHeader(http.StatusBadRequest)
			return
		}

		method := r.Header.Get(corsRequestMethodHeader)
		if !ch.isMatch(method, ch.allowedMethods) {
			w.WriteHeader(http.StatusMethodNotAllowed)
			return
		}

		requestHeaders := strings.Split(r.Header.Get(corsRequestHeadersHeader), ",")
		allowedHeaders := []string{}
		for _, v := range requestHeaders {
			canonicalHeader := http.CanonicalHeaderKey(strings.TrimSpace(v))
			if canonicalHeader == "" || ch.isMatch(canonicalHeader, defaultCorsHeaders) {
				continue
			}

			if !ch.isMatch(canonicalHeader, ch.allowedHeaders) {
				w.WriteHeader(http.StatusForbidden)
				return
			}

			allowedHeaders = append(allowedHeaders, canonicalHeader)
		}

		if len(allowedHeaders) > 0 {
			w.Header().Set(corsAllowHeadersHeader, strings.Join(allowedHeaders, ","))
		}

		if ch.maxAge > 0 {
			w.Header().Set(corsMaxAgeHeader, strconv.Itoa(ch.maxAge))
		}

		if !ch.isMatch(method, defaultCorsMethods) {
			w.Header().Set(corsAllowMethodsHeader, method)
		}
	} else {
		if len(ch.exposedHeaders) > 0 {
			w.Header().Set(corsExposeHeadersHeader, strings.Join(ch.exposedHeaders, ","))
		}
	}

	if ch.allowCredentials {
		w.Header().Set(corsAllowCredentialsHeader, "true")
	}

	if len(ch.allowedOrigins) > 1 {
		w.Header().Set(corsVaryHeader, corsOriginHeader)
	}

	w.Header().Set(corsAllowOriginHeader, origin)

	ch.h.ServeHTTP(w, r)
}

// CORS provides Cross-Origin Resource Sharing middleware.
// Example:
//
//  import (
//      "net/http"
//
//      "github.com/gorilla/handlers"
//      "github.com/gorilla/mux"
//  )
//
//  func main() {
//      r := mux.NewRouter()
//      r.HandleFunc("/users", UserEndpoint)
//      r.HandleFunc("/projects", ProjectEndpoint)
//
//      // Apply the CORS middleware to our top-level router, with the defaults.
//      http.ListenAndServe(":8000", handlers.CORS()(r))
//  }
//
func CORS(opts ...CORSOption) func(http.Handler) http.Handler {
	return func(h http.Handler) http.Handler {
		ch := parseCORSOptions(opts...)
		ch.h = h
		return ch
	}
}

func parseCORSOptions(opts ...CORSOption) *cors {
	ch := &cors{
		allowedMethods: defaultCorsMethods,
		allowedHeaders: defaultCorsHeaders,
		allowedOrigins: []string{corsOriginMatchAll},
	}

	for _, option := range opts {
		option(ch)
	}

	return ch
}

//
// Functional options for configuring CORS.
//

// AllowedHeaders adds the provided headers to the list of allowed headers in a
// CORS request.
// This is an append operation so the headers Accept, Accept-Language,
// and Content-Language are always allowed.
// Content-Type must be explicitly declared if accepting Content-Types other than
// application/x-www-form-urlencoded, multipart/form-data, or text/plain.
func AllowedHeaders(headers []string) CORSOption {
	return func(ch *cors) error {
		for _, v := range headers {
			normalizedHeader := http.CanonicalHeaderKey(strings.TrimSpace(v))
			if normalizedHeader == "" {
				continue
			}

			if !ch.isMatch(normalizedHeader, ch.allowedHeaders) {
				ch.allowedHeaders = append(ch.allowedHeaders, normalizedHeader)
			}
		}

		return nil
	}
}

// AllowedMethods can be used to explicitly allow methods in the
// Access-Control-Allow-Methods header.
// This is a replacement operation so you must also
// pass GET, HEAD, and POST if you wish to support those methods.
func AllowedMethods(methods []string) CORSOption {
	return func(ch *cors) error {
		ch.allowedMethods = []string{}
		for _, v := range methods {
			normalizedMethod := strings.ToUpper(strings.TrimSpace(v))
			if normalizedMethod == "" {
				continue
			}

			if !ch.isMatch(normalizedMethod, ch.allowedMethods) {
				ch.allowedMethods = append(ch.allowedMethods, normalizedMethod)
			}
		}

		return nil
	}
}

// AllowedOrigins sets the allowed origins for CORS requests, as used in the
// 'Allow-Access-Control-Origin' HTTP header.
// Note: Passing in a []string{"*"} will allow any domain.
func AllowedOrigins(origins []string) CORSOption {
	return func(ch *cors) error {
		for _, v := range origins {
			if v == corsOriginMatchAll {
				ch.allowedOrigins = []string{corsOriginMatchAll}
				return nil
			}
		}

		ch.allowedOrigins = origins
		return nil
	}
}

// AllowedOriginValidator sets a function for evaluating allowed origins in CORS requests, represented by the
// 'Allow-Access-Control-Origin' HTTP header.
func AllowedOriginValidator(fn originValidator) CORSOption {
	return func(ch *cors) error {
		ch.allowedOriginValidator = fn
		return nil
	}
}

// ExposeHeaders can be used to specify headers that are available
// and will not be stripped out by the user-agent.
func ExposedHeaders(headers []string) CORSOption {
	return func(ch *cors) error {
		ch.exposedHeaders = []string{}
		for _, v := range headers {
			normalizedHeader := http.CanonicalHeaderKey(strings.TrimSpace(v))
			if normalizedHeader == "" {
				continue
			}

			if !ch.isMatch(normalizedHeader, ch.exposedHeaders) {
				ch.exposedHeaders = append(ch.exposedHeaders, normalizedHeader)
			}
		}

		return nil
	}
}

// MaxAge determines the maximum age (in seconds) between preflight requests. A
// maximum of 10 minutes is allowed. An age above this value will default to 10
// minutes.
func MaxAge(age int) CORSOption {
	return func(ch *cors) error {
		// Maximum of 10 minutes.
		if age > 600 {
			age = 600
		}

		ch.maxAge = age
		return nil
	}
}

// IgnoreOptions causes the CORS middleware to ignore OPTIONS requests, instead
// passing them through to the next handler. This is useful when your application
// or framework has a pre-existing mechanism for responding to OPTIONS requests.
func IgnoreOptions() CORSOption {
	return func(ch *cors) error {
		ch.ignoreOptions = true
		return nil
	}
}

// AllowCredentials can be used to specify that the user agent may pass
// authentication details along with the request.
func AllowCredentials() CORSOption {
	return func(ch *cors) error {
		ch.allowCredentials = true
		return nil
	}
}

func (ch *cors) isOriginAllowed(origin string) bool {
	if origin == "" {
		return false
	}

	if ch.allowedOriginValidator != nil {
		return ch.allowedOriginValidator(origin)
	}

	for _, allowedOrigin := range ch.allowedOrigins {
		if allowedOrigin == origin || allowedOrigin == corsOriginMatchAll {
			return true
		}
	}

	return false
}

func (ch *cors) isMatch(needle string, haystack []string) bool {
	for _, v := range haystack {
		if v == needle {
			return true
		}
	}

	return false
}
<|endoftext|>


<commit_before>package cpan

import (
  "archive/tar"
  "compress/gzip"
  "fmt"
  "strings"
//  "github.com/mattn/go-sqlite3"
  "gopkg.in/yaml.v1"
  "io"
  "io/ioutil"
  "net/http"
  "os"
  "os/exec"
  "path"
  "path/filepath"
  "sync"
)

type Dependency struct {
  Name    string
  Version string
  Success bool
  Error   error
}

type Request struct {
  *Dependency
  Wait *sync.WaitGroup
}

type Client struct {
  Queue chan *Request
  Dependencies map[string]*sync.WaitGroup
}

func NewClient() *Client {
  c := &Client {
    make(chan *Request, 1),
    make(map[string]*sync.WaitGroup),
  }
  go c.ProcessQueue()
  return c
}

func (c *Client) Install(d *Dependency) error {
  wg := &sync.WaitGroup {}
  wg.Add(1)
  c.install(d, wg)
  wg.Wait()

  if d.Success {
    return nil
  }

  return d.Error
}

func (c *Client) install(d *Dependency, wg *sync.WaitGroup) {
  c.Queue <-&Request { d, wg }
}

func (c *Client) ProcessQueue() {
  for r := range c.Queue {
    if r.Name == "perl" {
      fmt.Fprintf(os.Stderr, "%s is not supported, skipping\n", r.Name)
      r.Wait.Done()
      continue
    }
    if _, ok := c.Dependencies[r.Name]; ok {
//      fmt.Fprintf(os.Stderr, "%s has already been requested, skipping\n", r.Name)
      r.Wait.Done()
      continue
    }
    fmt.Printf("Processing %s\n", r.Name)
    c.Dependencies[r.Name] = r.Wait
    go c.ProcessDependency(r)
  }
}

func (c *Client) ProcessDependency(r *Request) {
  name, err := c.ResolveDistributionName(r.Name)
  if err != nil {
    c.Dependencies[r.Name].Done()
    return
  }

  c.Fetch(name)

  d := NewDistribution(name)
  if err = d.Install(c); err != nil {
    fmt.Printf("failed to install %s: %s\n", name, err)
  } else {
    r.Success = true
  }

  fmt.Printf("DONE: %s\n", name)
  c.Dependencies[r.Name].Done()
}

func (c *Client) Fetch(path string) {
}

func (c *Client) ResolveDistributionName(name string) (string, error) {
  res, err := http.Get("http://cpanmetadb.plackperl.org/v1.0/package/" + name)
  if err != nil {
    return "", err
  }

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    return  "", err
  }

  var result map[string]string
  err = yaml.Unmarshal([]byte(body), &result)
  if err != nil {
    return "", err
  }
  return result["distfile"], nil
}

type Distribution struct {
  Path    string
  WorkDir string
  Meta    *Distmeta
}

func NewDistribution(path string) *Distribution {
  return &Distribution {
    path,
    "",
    nil,
  }
}

func (d *Distribution) Save(r io.Reader) error {
  dir := path.Dir(d.Path)
  if _, err := os.Stat(dir); err != nil {
    if err = os.MkdirAll(dir, 0777); err != nil {
      return err
    }
  }

  fh, err := os.OpenFile(d.Path, os.O_CREATE|os.O_WRONLY, 0777)
  if err != nil {
    return err
  }
  defer fh.Close()

  if _, err = io.Copy(fh, r); err != nil {
    return err
  }

  return nil
}

func (d *Distribution) Install(c *Client) error {
  _, err := os.Stat(d.Path)
  if err != nil {
    fmt.Printf("Installing %s...\n", d.Path)
    res, err := http.Get("http://cpan.metacpan.org/authors/id/" + d.Path)
    if err != nil {
      return err
    }

    d.Save(res.Body)
    _, err = os.Stat(d.Path)
    if err != nil {
      return err
    }
  }

  if err = d.Unpack(); err != nil {
    return fmt.Errorf("error during unpack: %s", err)
  }

  if err = d.ParseMeta(); err != nil {
    return err
  }

  wg := &sync.WaitGroup {}
  if br := d.Meta.BuildRequires; br != nil {
    for _, dep := range br.List {
      wg.Add(1)
      c.install(dep, wg)
    }
  }

  if cr := d.Meta.ConfigureRequires; cr != nil {
    for _, dep := range cr.List {
      wg.Add(1)
      c.install(dep, wg)
    }
  }

  if r := d.Meta.Requires; r != nil {
    for _, dep := range r.List {
      wg.Add(1)
      c.install(dep, wg)
    }
  }
  wg.Wait()

  waitch := make(chan struct{})
  go func() {
    defer func() { waitch <- struct{}{} }()
    fmt.Printf("CMD: cpanm %s\n", d.WorkDir)
    cmd := exec.Command("cpanm", "-n", "-L", "local", d.WorkDir)
    output, _ := cmd.CombinedOutput()
    os.Stdout.Write(output)
  }();
  <-waitch

  return nil
}

func (d *Distribution) Unpack()  error {
  fmt.Printf("Unpacking %s\n", d.Path)
  done := false
  root := ""
  defer func() {
    if ! done && root != "" {
      os.RemoveAll(root)
    }
  }()

  fh, err := os.Open(d.Path)
  if err != nil {
    return err
  }
  defer fh.Close()

  gzr, err := gzip.NewReader(fh)
  if err != nil {
    return err
  }

  tr := tar.NewReader(gzr)
  for {
    hdr, err := tr.Next()
    if err == io.EOF {
      break
    }

    if err != nil {
      return err
    }

    if root == "" {
      if i := strings.IndexRune(hdr.Name, os.PathSeparator); i > -1 {
        root = hdr.Name[0:i]
      }
    }

    switch hdr.Typeflag {
    case tar.TypeDir:
      if _, err := os.Stat(hdr.Name); err != nil {
        err = os.MkdirAll(hdr.Name, 0777)
        if err != nil {
          return err
        }
      }
    case tar.TypeReg:
      out, err := os.OpenFile(hdr.Name, os.O_CREATE|os.O_WRONLY, 0644)
      if err != nil {
        return err
      }

      if _, err := io.Copy(out, tr); err != nil {
        out.Close()
        return err
      }
      out.Close()
    default:
      return fmt.Errorf("unknown type: %s", err)
    }
  }

fmt.Printf("Unpack -> root = %s\n", root)
  done = true
  abspath, err := filepath.Abs(root)
  if err != nil {
    return err
  }
  d.WorkDir = abspath
  return nil
}

func (d *Distribution) ParseMeta() error {
  metayml := filepath.Join(d.WorkDir, "META.yml")
  meta, err := LoadDistmetaFromFile(metayml)
  if err != nil {
    return fmt.Errorf("failed to load file %s for %s: %s", metayml, d.Path, err)
  }
  d.Meta = meta
  return nil
}

func (d *Distribution) Cleanup() {
  os.RemoveAll(d.WorkDir)
}
<commit_msg>various tweaks<commit_after>package cpan

import (
  "archive/tar"
  "compress/gzip"
  "fmt"
  "strings"
//  "github.com/mattn/go-sqlite3"
  "gopkg.in/yaml.v1"
  "io"
  "io/ioutil"
  "net/http"
  "os"
  "os/exec"
  "path"
  "path/filepath"
  "sync"
)

type Dependency struct {
  Name    string
  Version string
  Success bool
  Error   error
}

type Request struct {
  *Dependency
  Wait *sync.WaitGroup
}

type Client struct {
  Queue chan *Request
  Dependencies map[string]*sync.WaitGroup
  DistributionNames map[string]string
  WorkDir string
}

func NewClient() *Client {
  tmpdir, err := ioutil.TempDir("", "go-cpan-")
  if err != nil {
    panic(err.Error())
  }

  c := &Client {
    make(chan *Request, 1),
    make(map[string]*sync.WaitGroup),
    make(map[string]string),
    tmpdir,
  }
  go c.ProcessQueue()
  return c
}

func (c *Client) Install(d *Dependency) error {
  wd, err := os.Getwd()
  if err != nil {
    return err
  }

  err = os.Chdir(c.WorkDir)
  if err != nil {
    return err
  }
  defer os.Chdir(wd)

  wg := &sync.WaitGroup {}
  wg.Add(1)
  c.install(d, wg)
  wg.Wait()

  if d.Success {
    return nil
  }

  return d.Error
}

func (c *Client) install(d *Dependency, wg *sync.WaitGroup) {
  c.Queue <-&Request { d, wg }
}

func (c *Client) ProcessQueue() {
  for r := range c.Queue {
fmt.Printf("---> r.Name = %s\n", r.Name)
    if r.Name == "perl" {
      fmt.Fprintf(os.Stderr, "%s is not supported, skipping\n", r.Name)
      r.Wait.Done()
      continue
    }
    if _, ok := c.Dependencies[r.Name]; ok {
//      fmt.Fprintf(os.Stderr, "%s has already been requested, skipping\n", r.Name)
      r.Wait.Done()
      continue
    }
    fmt.Printf("Processing %s\n", r.Name)
    c.Dependencies[r.Name] = r.Wait
    go c.ProcessDependency(r)
  }
}

func (c *Client) ProcessDependency(r *Request) {
  name, err := c.ResolveDistributionName(r.Name)
  if err != nil {
    c.Dependencies[r.Name].Done()
    return
  }

  if strings.Index(name, "/perl-5.") > -1 {
    // skip perl
    c.Dependencies[r.Name].Done()
    return
  }

  d := NewDistribution(name)
  if err = d.Install(c); err != nil {
    fmt.Printf("failed to install %s: %s\n", name, err)
  } else {
    r.Success = true
  }

  fmt.Printf("DONE: %s\n", name)
  c.Dependencies[r.Name].Done()
}

func (c *Client) ResolveDistributionName(name string) (distfile string, err error) {
  defer func () {
    if err == nil {
      fmt.Printf("cpanmetadb says we can get %s from %s\n", name, distfile)
    }
  }()

  distfile, ok := c.DistributionNames[name]
  if ok {
    return
  }

  res, err := http.Get("http://cpanmetadb.plackperl.org/v1.0/package/" + name)
  if err != nil {
    return "", err
  }

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    return  "", err
  }

  var result map[string]string
  err = yaml.Unmarshal([]byte(body), &result)
  if err != nil {
    return "", err
  }

  distfile, ok = result["distfile"]
  if ! ok {
    return "", fmt.Errorf("could not find where %s can be found", name)
  }

  return distfile, nil
}

type Distribution struct {
  Path    string
  WorkDir string
  Meta    *Distmeta
}

func NewDistribution(path string) *Distribution {
  return &Distribution {
    path,
    "",
    nil,
  }
}

func (c *Client) Fetch(d *Distribution) error {
  fullpath := filepath.Join(c.WorkDir, d.Path)
  _, err := os.Stat(fullpath)
  if err == nil { // cache found
    return nil
  }

  url := "http://cpan.metacpan.org/authors/id/" + d.Path
  fmt.Printf("Fetching %s...\n", url)

  var rdr io.Reader
  for i := 0; i < 5; i++ {
    res, err := http.Get(url)
    if err != nil {
      fmt.Fprintf(os.Stderr, "failed to download from %s: %s", url, err)
      continue
    }
    if res.StatusCode != 200 {
      fmt.Fprintf(os.Stderr, "failed to download from %s: status code = %d", url, res.StatusCode)
      continue
    }

    rdr = res.Body
    break
  }

  if rdr == nil {
    return fmt.Errorf("Failed to download from %s", url)
  }

  dir := path.Dir(fullpath)
  if _, err := os.Stat(dir); err != nil {
    if err = os.MkdirAll(dir, 0777); err != nil {
      return err
    }
  }

  fh, err := os.OpenFile(fullpath, os.O_CREATE|os.O_WRONLY, 0777)
  if err != nil {
    return err
  }
  defer fh.Close()

  if _, err = io.Copy(fh, rdr); err != nil {
    return err
  }

  return nil
}

func (d *Distribution) Install(c *Client) error {
  fmt.Printf("Installing %s...\n", d.Path)
  if err := c.Fetch(d); err != nil {
    return err
  }

  if err := d.Unpack(); err != nil {
    return fmt.Errorf("error during unpack: %s", err)
  }

  if err := d.ParseMeta(); err != nil {
    return err
  }

  wg := &sync.WaitGroup {}
  if br := d.Meta.BuildRequires; br != nil {
    for _, dep := range br.List {
      wg.Add(1)
fmt.Printf("%s depends on %s\n", d.Path, dep.Name)
      c.install(dep, wg)
    }
  }

  if cr := d.Meta.ConfigureRequires; cr != nil {
    for _, dep := range cr.List {
      wg.Add(1)
fmt.Printf("%s depends on %s\n", d.Path, dep.Name)
      c.install(dep, wg)
    }
  }

  if r := d.Meta.Requires; r != nil {
    for _, dep := range r.List {
      wg.Add(1)
fmt.Printf("%s depends on %s\n", d.Path, dep.Name)
      c.install(dep, wg)
    }
  }
  wg.Wait()

  waitch := make(chan struct{})
  go func() {
    defer func() { waitch <- struct{}{} }()
    fmt.Printf("CMD: cpanm %s\n", d.WorkDir)
    cmd := exec.Command("cpanm", "-n", "-L", "local", d.WorkDir)
    output, _ := cmd.CombinedOutput()
    os.Stdout.Write(output)
  }();
  <-waitch

  return nil
}

func (d *Distribution) Unpack()  error {
  fmt.Printf("Unpacking %s\n", d.Path)
  done := false
  root := ""
  defer func() {
    if ! done && root != "" {
      os.RemoveAll(root)
    }
  }()

  fh, err := os.Open(d.Path)
  if err != nil {
    return err
  }
  defer fh.Close()

  gzr, err := gzip.NewReader(fh)
  if err != nil {
    return err
  }

  tr := tar.NewReader(gzr)
  for {
    hdr, err := tr.Next()
    if err == io.EOF {
      break
    }

    if err != nil {
      return err
    }

    if root == "" {
      if i := strings.IndexRune(hdr.Name, os.PathSeparator); i > -1 {
        root = hdr.Name[0:i]
      }
    }

    switch hdr.Typeflag {
    case tar.TypeDir:
      if _, err := os.Stat(hdr.Name); err != nil {
        err = os.MkdirAll(hdr.Name, 0777)
        if err != nil {
          return err
        }
      }
    case tar.TypeReg:
      out, err := os.OpenFile(hdr.Name, os.O_CREATE|os.O_WRONLY, 0644)
      if err != nil {
        return err
      }

      if _, err := io.Copy(out, tr); err != nil {
        out.Close()
        return err
      }
      out.Close()
    default:
      return fmt.Errorf("unknown type: %s", err)
    }
  }

fmt.Printf("Unpack -> root = %s\n", root)
  done = true
  abspath, err := filepath.Abs(root)
  if err != nil {
    return err
  }
  d.WorkDir = abspath
  return nil
}

func (d *Distribution) ParseMeta() error {
  metayml := filepath.Join(d.WorkDir, "META.yml")
  meta, err := LoadDistmetaFromFile(metayml)
  if err != nil {
    return fmt.Errorf("failed to load file %s for %s: %s", metayml, d.Path, err)
  }
  d.Meta = meta
  return nil
}

func (d *Distribution) Cleanup() {
  os.RemoveAll(d.WorkDir)
}
<|endoftext|>


<commit_before>package web

import (
	"flag"
	"github.com/gorilla/schema"
	"github.com/zenazn/goji"
	"net/http"
)

var (
	defaults *config
	decoder  = schema.NewDecoder()
)

func start(conf *config) {
	defaults = conf
	flag.Set("bind", conf.Address) // Uh, I guess that's a bit strange

	register("/head/:player", serveHeadNormal)
	register("/head/:size/:player", serveHeadWithSize)

	register("/face/:player", serveFaceNormal)
	register("/face/:size/:player", serveFaceWithSize)

	goji.Get("/*", http.FileServer(http.Dir("www"))) // TODO: How to find the correct dir?

	goji.Serve()
}

func register(pattern string, handler interface{}) {
	goji.Get(pattern, handler)
	goji.Get(pattern+".png", handler)
}
<commit_msg>Swap route registration order to make it work again<commit_after>package web

import (
	"flag"
	"github.com/gorilla/schema"
	"github.com/zenazn/goji"
	"net/http"
)

var (
	defaults *config
	decoder  = schema.NewDecoder()
)

func start(conf *config) {
	defaults = conf
	flag.Set("bind", conf.Address) // Uh, I guess that's a bit strange

	register("/head/:size/:player", serveHeadWithSize)
	register("/head/:player", serveHeadNormal)

	register("/face/:size/:player", serveFaceWithSize)
	register("/face/:player", serveFaceNormal)

	goji.Get("/*", http.FileServer(http.Dir("www"))) // TODO: How to find the correct dir?

	goji.Serve()
}

func register(pattern string, handler interface{}) {
	goji.Get(pattern+".png", handler)
	goji.Get(pattern, handler)
}
<|endoftext|>


<commit_before>/*
Copyright 2015 All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"testing"
	"time"
)

func TestIsAudience(t *testing.T) {
	user := &userContext{
		audience: "test",
	}
	if !user.isAudience("test") {
		t.Errorf("return should not have been false")
	}
	if user.isAudience("test1") {
		t.Errorf("return should not have been true")
	}
}

func TestGetROles(t *testing.T) {
	user := &userContext{
		roles: []string{"1","2","3"},
	}
	if user.getRoles() != "1,2,3" {
		t.Errorf("we should have received a true resposne")
	}
	if user.getRoles() == "nothing" {
		t.Errorf("we should have recieved a false response")
	}
}

func TestIsExpired(t *testing.T) {
	user := &userContext{
		expiresAt: time.Now(),
	}
	if !user.isExpired() {
		t.Errorf("we should have been false")
	}
}<commit_msg>- fixing the formating of the code<commit_after>/*
Copyright 2015 All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"testing"
	"time"
)

func TestIsAudience(t *testing.T) {
	user := &userContext{
		audience: "test",
	}
	if !user.isAudience("test") {
		t.Errorf("return should not have been false")
	}
	if user.isAudience("test1") {
		t.Errorf("return should not have been true")
	}
}

func TestGetROles(t *testing.T) {
	user := &userContext{
		roles: []string{"1", "2", "3"},
	}
	if user.getRoles() != "1,2,3" {
		t.Errorf("we should have received a true resposne")
	}
	if user.getRoles() == "nothing" {
		t.Errorf("we should have recieved a false response")
	}
}

func TestIsExpired(t *testing.T) {
	user := &userContext{
		expiresAt: time.Now(),
	}
	if !user.isExpired() {
		t.Errorf("we should have been false")
	}
}
<|endoftext|>


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

package main

import (
	"fmt"
	"io"
	"os"
	"time"

	"github.com/cheggaaa/pb"
	"github.com/codegangsta/cli"
)

// TODO
//   - <S3Path> <S3Path>
//   - <S3Path> <S3Bucket>

func startBar(size int64) *pb.ProgressBar {
	bar := pb.New(int(size))
	bar.SetUnits(pb.U_BYTES)
	bar.SetRefreshRate(time.Millisecond * 10)
	bar.NotPrint = true
	bar.ShowSpeed = true
	bar.Callback = func(s string) {
		// Colorize
		infoCallback(s)
	}
	// Feels like wget
	bar.Format("[=> ]")
	return bar
}

func doFsCopy(c *cli.Context) {
	s3c, err := getNewClient(c)
	if err != nil {
		fatal(err.Error())
	}

	if len(c.Args()) != 2 {
		fatal("Invalid number of args")
	}

	var fsoptions *fsOptions
	fsoptions, err = parseOptions(c)
	if err != nil {
		fatal(err.Error())
	}

	switch true {
	case fsoptions.isput == true:
		stat, err := os.Stat(fsoptions.body)
		if os.IsNotExist(err) {
			fatal(err.Error())
		}
		if stat.IsDir() {
			fatal("Is a directory")
		}
		size := stat.Size()
		bodyFile, err := os.Open(fsoptions.body)
		defer bodyFile.Close()
		if err != nil {
			fatal(err.Error())
		}

		// s3://<bucket> is specified without key
		if fsoptions.key == "" {
			fsoptions.key = fsoptions.body
		}

		err = s3c.Put(fsoptions.bucket, fsoptions.key, size, bodyFile)
		if err != nil {
			fatal(err.Error())
		}
		msg := fmt.Sprintf("%s uploaded -- to bucket:(%s)", fsoptions.key, fsoptions.bucket)
		info(msg)
	case fsoptions.isget == true:
		var objectReader io.ReadCloser
		var objectSize, downloadedSize int64
		var bodyFile *os.File
		var err error
		var st os.FileInfo

		// Send HEAD request to validate if file exists.
		objectSize, _, err = s3c.Stat(fsoptions.key, fsoptions.bucket)
		if err != nil {
			fatal(err.Error())
		}
		// get progress bar
		bar := startBar(objectSize)

		// Check if the object already exists
		st, err = os.Stat(fsoptions.body)
		switch os.IsNotExist(err) {
		case true:
			// Create if it doesn't exist
			bodyFile, err = os.Create(fsoptions.body)
			defer bodyFile.Close()
			if err != nil {
				fatal(err.Error())
			}
			objectReader, _, err = s3c.Get(fsoptions.bucket, fsoptions.key)
			if err != nil {
				fatal(err.Error())
			}
		case false:
			downloadedSize = st.Size()
			// Verify if file is already downloaded
			if downloadedSize == objectSize {
				msg := fmt.Sprintf("%s object has been already downloaded", fsoptions.body)
				fatal(msg)
			}

			bodyFile, err = os.OpenFile(fsoptions.body, os.O_RDWR, 0600)
			defer bodyFile.Close()

			if err != nil {
				fatal(err.Error())
			}

			_, err := bodyFile.Seek(downloadedSize, os.SEEK_SET)
			if err != nil {
				fatal(err.Error())
			}

			remainingSize := objectSize - downloadedSize
			objectReader, objectSize, err = s3c.GetPartial(fsoptions.bucket, fsoptions.key, downloadedSize, remainingSize)
			if err != nil {
				fatal(err.Error())
			}
			bar.Set(int(downloadedSize))
		}
		// Start the bar now
		bar.Start()

		// create multi writer to feed data
		writer := io.MultiWriter(bodyFile, bar)
		_, err = io.CopyN(writer, objectReader, objectSize)
		if err != nil {
			fatal(err.Error())
		}

		bar.Finish()
		info("Success!")
	}
}
<commit_msg>disable progress-bar for --quiet flag<commit_after>/*
 * Mini Object Storage, (C) 2014,2015 Minio, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package main

import (
	"fmt"
	"io"
	"os"
	"time"

	"github.com/cheggaaa/pb"
	"github.com/codegangsta/cli"
)

// TODO
//   - <S3Path> <S3Path>
//   - <S3Path> <S3Bucket>

func startBar(size int64) *pb.ProgressBar {
	bar := pb.New(int(size))
	bar.SetUnits(pb.U_BYTES)
	bar.SetRefreshRate(time.Millisecond * 10)
	bar.NotPrint = true
	bar.ShowSpeed = true
	bar.Callback = func(s string) {
		// Colorize
		infoCallback(s)
	}
	// Feels like wget
	bar.Format("[=> ]")
	return bar
}

func doFsCopy(c *cli.Context) {
	s3c, err := getNewClient(c)
	if err != nil {
		fatal(err.Error())
	}

	if len(c.Args()) != 2 {
		fatal("Invalid number of args")
	}

	var fsoptions *fsOptions
	fsoptions, err = parseOptions(c)
	if err != nil {
		fatal(err.Error())
	}

	switch true {
	case fsoptions.isput == true:
		stat, err := os.Stat(fsoptions.body)
		if os.IsNotExist(err) {
			fatal(err.Error())
		}
		if stat.IsDir() {
			fatal("Is a directory")
		}
		size := stat.Size()
		bodyFile, err := os.Open(fsoptions.body)
		defer bodyFile.Close()
		if err != nil {
			fatal(err.Error())
		}

		// s3://<bucket> is specified without key
		if fsoptions.key == "" {
			fsoptions.key = fsoptions.body
		}

		err = s3c.Put(fsoptions.bucket, fsoptions.key, size, bodyFile)
		if err != nil {
			fatal(err.Error())
		}
		msg := fmt.Sprintf("%s uploaded -- to bucket:(%s)", fsoptions.key, fsoptions.bucket)
		info(msg)
	case fsoptions.isget == true:
		var objectReader io.ReadCloser
		var objectSize, downloadedSize int64
		var bodyFile *os.File
		var err error
		var st os.FileInfo

		// Send HEAD request to validate if file exists.
		objectSize, _, err = s3c.Stat(fsoptions.key, fsoptions.bucket)
		if err != nil {
			fatal(err.Error())
		}

		var bar *pb.ProgressBar
		if !c.GlobalBool("quiet") {
			// get progress bar
			bar = startBar(objectSize)
		}

		// Check if the object already exists
		st, err = os.Stat(fsoptions.body)
		switch os.IsNotExist(err) {
		case true:
			// Create if it doesn't exist
			bodyFile, err = os.Create(fsoptions.body)
			defer bodyFile.Close()
			if err != nil {
				fatal(err.Error())
			}
			objectReader, _, err = s3c.Get(fsoptions.bucket, fsoptions.key)
			if err != nil {
				fatal(err.Error())
			}
		case false:
			downloadedSize = st.Size()
			// Verify if file is already downloaded
			if downloadedSize == objectSize {
				msg := fmt.Sprintf("%s object has been already downloaded", fsoptions.body)
				fatal(msg)
			}

			bodyFile, err = os.OpenFile(fsoptions.body, os.O_RDWR, 0600)
			defer bodyFile.Close()

			if err != nil {
				fatal(err.Error())
			}

			_, err := bodyFile.Seek(downloadedSize, os.SEEK_SET)
			if err != nil {
				fatal(err.Error())
			}

			remainingSize := objectSize - downloadedSize
			objectReader, objectSize, err = s3c.GetPartial(fsoptions.bucket, fsoptions.key, downloadedSize, remainingSize)
			if err != nil {
				fatal(err.Error())
			}

			if !c.GlobalBool("quiet") {
				bar.Set(int(downloadedSize))
			}
		}

		writer := io.Writer(bodyFile)
		if !c.GlobalBool("quiet") {
			// Start the bar now
			bar.Start()
			// create multi writer to feed data
			writer = io.MultiWriter(bodyFile, bar)
		}
		_, err = io.CopyN(writer, objectReader, objectSize)
		if err != nil {
			fatal(err.Error())
		}

		bar.Finish()
		info("Success!")
	}
}
<|endoftext|>


<commit_before>package nsinit

import (
	"encoding/json"
	"fmt"
	"github.com/dotcloud/docker/pkg/libcontainer"
	"io/ioutil"
	"os"
)

// SyncPipe allows communication to and from the child processes
// to it's parent and allows the two independent processes to
// syncronize their state.
type SyncPipe struct {
	parent, child *os.File
}

func NewSyncPipe() (s *SyncPipe, err error) {
	s = &SyncPipe{}
	s.child, s.parent, err = os.Pipe()
	if err != nil {
		return nil, err
	}
	return s, nil
}

func NewSyncPipeFromFd(parendFd, childFd uintptr) (*SyncPipe, error) {
	s := &SyncPipe{}
	if parendFd > 0 {
		s.parent = os.NewFile(parendFd, "parendPipe")
	} else if childFd > 0 {
		s.child = os.NewFile(childFd, "childPipe")
	} else {
		return nil, fmt.Errorf("no valid sync pipe fd specified")
	}
	return s, nil
}

func (s *SyncPipe) SendToChild(context libcontainer.Context) error {
	data, err := json.Marshal(context)
	if err != nil {
		return err
	}
	s.parent.Write(data)
	return nil
}

func (s *SyncPipe) ReadFromParent() (libcontainer.Context, error) {
	data, err := ioutil.ReadAll(s.child)
	if err != nil {
		return nil, fmt.Errorf("error reading from sync pipe %s", err)
	}
	var context libcontainer.Context
	if len(data) > 0 {
		if err := json.Unmarshal(data, &context); err != nil {
			return nil, err
		}
	}
	return context, nil

}

func (s *SyncPipe) Close() error {
	if s.parent != nil {
		s.parent.Close()
	}
	if s.child != nil {
		s.child.Close()
	}
	return nil
}
<commit_msg>Export syncpipe fields Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)<commit_after>package nsinit

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"

	"github.com/dotcloud/docker/pkg/libcontainer"
)

// SyncPipe allows communication to and from the child processes
// to it's parent and allows the two independent processes to
// syncronize their state.
type SyncPipe struct {
	parent, child *os.File
}

func NewSyncPipe() (s *SyncPipe, err error) {
	s = &SyncPipe{}
	s.child, s.parent, err = os.Pipe()
	if err != nil {
		return nil, err
	}
	return s, nil
}

func NewSyncPipeFromFd(parendFd, childFd uintptr) (*SyncPipe, error) {
	s := &SyncPipe{}
	if parendFd > 0 {
		s.parent = os.NewFile(parendFd, "parendPipe")
	} else if childFd > 0 {
		s.child = os.NewFile(childFd, "childPipe")
	} else {
		return nil, fmt.Errorf("no valid sync pipe fd specified")
	}
	return s, nil
}

func (s *SyncPipe) Child() *os.File {
	return s.child
}

func (s *SyncPipe) Parent() *os.File {
	return s.parent
}

func (s *SyncPipe) SendToChild(context libcontainer.Context) error {
	data, err := json.Marshal(context)
	if err != nil {
		return err
	}
	s.parent.Write(data)
	return nil
}

func (s *SyncPipe) ReadFromParent() (libcontainer.Context, error) {
	data, err := ioutil.ReadAll(s.child)
	if err != nil {
		return nil, fmt.Errorf("error reading from sync pipe %s", err)
	}
	var context libcontainer.Context
	if len(data) > 0 {
		if err := json.Unmarshal(data, &context); err != nil {
			return nil, err
		}
	}
	return context, nil

}

func (s *SyncPipe) Close() error {
	if s.parent != nil {
		s.parent.Close()
	}
	if s.child != nil {
		s.child.Close()
	}
	return nil
}
<|endoftext|>